aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2010-09-17 15:54:40 +0000
commit3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f (patch)
tree0bbe07708f7571f8b5291f6d7b96c102b7c99dee
parenta0482fa4e7fa27b01184f938097f0666b78016dd (diff)
downloadsrc-3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f.tar.gz
src-3d1dcd9bfdb15c49ee34d576a065079ac5c4d29f.zip
Vendor import of clang r114020 (from the release_28 branch):vendor/clang/clang-r114020
Notes
Notes: svn path=/vendor/clang/dist/; revision=212795 svn path=/vendor/clang/clang-r114020/; revision=212796; tag=vendor/clang/clang-r114020
-rw-r--r--clang.xcodeproj/project.pbxproj469
-rw-r--r--docs/InternalsManual.html57
-rw-r--r--docs/LanguageExtensions.html22
-rw-r--r--docs/UsersManual.html54
-rw-r--r--docs/tools/clang.pod6
-rw-r--r--examples/CMakeLists.txt1
-rw-r--r--examples/Makefile2
-rw-r--r--examples/PrintFunctionNames/Makefile11
-rw-r--r--examples/PrintFunctionNames/PrintFunctionNames.cpp22
-rw-r--r--examples/PrintFunctionNames/PrintFunctionNames.exports1
-rw-r--r--examples/clang-interpreter/CMakeLists.txt2
-rw-r--r--examples/clang-interpreter/Makefile6
-rw-r--r--examples/clang-interpreter/main.cpp8
-rw-r--r--examples/wpa/CMakeLists.txt1
-rw-r--r--examples/wpa/Makefile4
-rw-r--r--examples/wpa/clang-wpa.cpp13
-rw-r--r--include/clang-c/Index.h554
-rw-r--r--include/clang/AST/ASTConsumer.h14
-rw-r--r--include/clang/AST/ASTContext.h81
-rw-r--r--include/clang/AST/ASTImporter.h2
-rw-r--r--include/clang/AST/Attr.h607
-rw-r--r--include/clang/AST/CMakeLists.txt6
-rw-r--r--include/clang/AST/CanonicalType.h9
-rw-r--r--include/clang/AST/Decl.h238
-rw-r--r--include/clang/AST/DeclBase.h181
-rw-r--r--include/clang/AST/DeclCXX.h279
-rw-r--r--include/clang/AST/DeclContextInternals.h160
-rw-r--r--include/clang/AST/DeclFriend.h16
-rw-r--r--include/clang/AST/DeclGroup.h1
-rw-r--r--include/clang/AST/DeclObjC.h150
-rw-r--r--include/clang/AST/DeclTemplate.h679
-rw-r--r--include/clang/AST/DeclarationName.h147
-rw-r--r--include/clang/AST/Expr.h748
-rw-r--r--include/clang/AST/ExprCXX.h405
-rw-r--r--include/clang/AST/ExternalASTSource.h93
-rw-r--r--include/clang/AST/FullExpr.h1
-rw-r--r--include/clang/AST/Makefile8
-rw-r--r--include/clang/AST/NestedNameSpecifier.h2
-rw-r--r--include/clang/AST/OperationKinds.h158
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h318
-rw-r--r--include/clang/AST/Redeclarable.h3
-rw-r--r--include/clang/AST/Stmt.h37
-rw-r--r--include/clang/AST/StmtCXX.h38
-rw-r--r--include/clang/AST/StmtVisitor.h107
-rw-r--r--include/clang/AST/Type.h143
-rw-r--r--include/clang/AST/TypeLoc.h4
-rw-r--r--include/clang/AST/TypeOrdering.h21
-rw-r--r--include/clang/Analysis/Analyses/FormatString.h595
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h5
-rw-r--r--include/clang/Analysis/Analyses/PrintfFormatString.h445
-rw-r--r--include/clang/Analysis/Analyses/PseudoConstantAnalysis.h45
-rw-r--r--include/clang/Analysis/AnalysisContext.h53
-rw-r--r--include/clang/Analysis/CFG.h19
-rw-r--r--include/clang/Analysis/CFGStmtMap.h52
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowSolver.h17
-rw-r--r--include/clang/Analysis/ProgramPoint.h39
-rw-r--r--include/clang/Analysis/Visitors/CFGStmtVisitor.h4
-rw-r--r--include/clang/Basic/Attr.td90
-rw-r--r--include/clang/Basic/Builtins.def149
-rw-r--r--include/clang/Basic/Builtins.h5
-rw-r--r--include/clang/Basic/BuiltinsARM.def14
-rw-r--r--include/clang/Basic/BuiltinsX86.def221
-rw-r--r--include/clang/Basic/DeclNodes.td5
-rw-r--r--include/clang/Basic/Diagnostic.h71
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--include/clang/Basic/DiagnosticGroups.td27
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td26
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td20
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td150
-rw-r--r--include/clang/Basic/IdentifierTable.h74
-rw-r--r--include/clang/Basic/LangOptions.h3
-rw-r--r--include/clang/Basic/Linkage.h11
-rw-r--r--include/clang/Basic/Makefile1
-rw-r--r--include/clang/Basic/OnDiskHashTable.h83
-rw-r--r--include/clang/Basic/SourceManager.h48
-rw-r--r--include/clang/Basic/Specifiers.h62
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Basic/TargetInfo.h43
-rw-r--r--include/clang/Basic/TargetOptions.h8
-rw-r--r--include/clang/Basic/TokenKinds.def13
-rw-r--r--include/clang/Basic/arm_neon.td2
-rw-r--r--include/clang/CMakeLists.txt1
-rw-r--r--include/clang/Checker/BugReporter/BugReporter.h3
-rw-r--r--include/clang/Checker/PathSensitive/AnalysisManager.h52
-rw-r--r--include/clang/Checker/PathSensitive/Checker.h31
-rw-r--r--include/clang/Checker/PathSensitive/CheckerHelpers.h40
-rw-r--r--include/clang/Checker/PathSensitive/ConstraintManager.h3
-rw-r--r--include/clang/Checker/PathSensitive/Environment.h8
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h168
-rw-r--r--include/clang/Checker/PathSensitive/GRExprEngine.h196
-rw-r--r--include/clang/Checker/PathSensitive/GRState.h99
-rw-r--r--include/clang/Checker/PathSensitive/GRSubEngine.h33
-rw-r--r--include/clang/Checker/PathSensitive/GRTransferFuncs.h6
-rw-r--r--include/clang/Checker/PathSensitive/GRWorkList.h10
-rw-r--r--include/clang/Checker/PathSensitive/MemRegion.h127
-rw-r--r--include/clang/Checker/PathSensitive/SVals.h27
-rw-r--r--include/clang/Checker/PathSensitive/Store.h41
-rw-r--r--include/clang/Checker/PathSensitive/SymbolManager.h79
-rw-r--r--include/clang/Checker/PathSensitive/ValueManager.h3
-rw-r--r--include/clang/Driver/CC1Options.td45
-rw-r--r--include/clang/Driver/Compilation.h2
-rw-r--r--include/clang/Driver/Driver.h29
-rw-r--r--include/clang/Driver/HostInfo.h9
-rw-r--r--include/clang/Driver/Job.h34
-rw-r--r--include/clang/Driver/OptParser.td3
-rw-r--r--include/clang/Driver/OptTable.h11
-rw-r--r--include/clang/Driver/Option.h10
-rw-r--r--include/clang/Driver/Options.td13
-rw-r--r--include/clang/Driver/Tool.h4
-rw-r--r--include/clang/Driver/ToolChain.h18
-rw-r--r--include/clang/Frontend/ASTConsumers.h9
-rw-r--r--include/clang/Frontend/ASTUnit.h341
-rw-r--r--include/clang/Frontend/AnalyzerOptions.h3
-rw-r--r--include/clang/Frontend/CodeGenOptions.h15
-rw-r--r--include/clang/Frontend/CompilerInstance.h59
-rw-r--r--include/clang/Frontend/DeclXML.def20
-rw-r--r--include/clang/Frontend/DiagnosticOptions.h2
-rw-r--r--include/clang/Frontend/DocumentXML.h1
-rw-r--r--include/clang/Frontend/FrontendAction.h14
-rw-r--r--include/clang/Frontend/FrontendActions.h33
-rw-r--r--include/clang/Frontend/FrontendOptions.h16
-rw-r--r--include/clang/Frontend/HeaderSearchOptions.h20
-rw-r--r--include/clang/Frontend/PCHDeserializationListener.h36
-rw-r--r--include/clang/Frontend/PreprocessorOptions.h67
-rw-r--r--include/clang/Frontend/PreprocessorOutputOptions.h16
-rw-r--r--include/clang/Frontend/StmtXML.def99
-rw-r--r--include/clang/Frontend/TypeXML.def8
-rw-r--r--include/clang/Frontend/Utils.h7
-rw-r--r--include/clang/FrontendTool/Utils.h30
-rw-r--r--include/clang/Index/TranslationUnit.h2
-rw-r--r--include/clang/Index/Utils.h36
-rw-r--r--include/clang/Lex/CodeCompletionHandler.h67
-rw-r--r--include/clang/Lex/ExternalPreprocessorSource.h2
-rw-r--r--include/clang/Lex/HeaderSearch.h2
-rw-r--r--include/clang/Lex/Lexer.h29
-rw-r--r--include/clang/Lex/MacroInfo.h37
-rw-r--r--include/clang/Lex/PPCallbacks.h10
-rw-r--r--include/clang/Lex/PTHLexer.h2
-rw-r--r--include/clang/Lex/PreprocessingRecord.h3
-rw-r--r--include/clang/Lex/Preprocessor.h73
-rw-r--r--include/clang/Lex/Token.h1
-rw-r--r--include/clang/Makefile2
-rw-r--r--include/clang/Parse/Action.h3309
-rw-r--r--include/clang/Parse/Ownership.h845
-rw-r--r--include/clang/Parse/ParseAST.h (renamed from include/clang/Sema/ParseAST.h)8
-rw-r--r--include/clang/Parse/Parser.h509
-rw-r--r--include/clang/Rewrite/FixItRewriter.h11
-rw-r--r--include/clang/Rewrite/FrontendActions.h4
-rw-r--r--include/clang/Sema/AnalysisBasedWarnings.h (renamed from lib/Sema/AnalysisBasedWarnings.h)11
-rw-r--r--include/clang/Sema/AttributeList.h (renamed from include/clang/Parse/AttributeList.h)30
-rw-r--r--include/clang/Sema/CXXFieldCollector.h (renamed from lib/Sema/CXXFieldCollector.h)0
-rw-r--r--include/clang/Sema/CodeCompleteConsumer.h495
-rw-r--r--include/clang/Sema/DeclSpec.h (renamed from include/clang/Parse/DeclSpec.h)127
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h168
-rw-r--r--include/clang/Sema/Designator.h (renamed from include/clang/Parse/Designator.h)79
-rw-r--r--include/clang/Sema/ExternalSemaSource.h2
-rw-r--r--include/clang/Sema/IdentifierResolver.h (renamed from lib/Sema/IdentifierResolver.h)29
-rw-r--r--include/clang/Sema/Initialization.h (renamed from lib/Sema/SemaInit.h)41
-rw-r--r--include/clang/Sema/Lookup.h (renamed from lib/Sema/Lookup.h)79
-rw-r--r--include/clang/Sema/ObjCMethodList.h38
-rw-r--r--include/clang/Sema/Overload.h (renamed from lib/Sema/SemaOverload.h)37
-rw-r--r--include/clang/Sema/Ownership.h462
-rw-r--r--include/clang/Sema/ParsedTemplate.h (renamed from include/clang/Parse/Template.h)43
-rw-r--r--include/clang/Sema/PrettyDeclStackTrace.h46
-rw-r--r--include/clang/Sema/Scope.h (renamed from include/clang/Parse/Scope.h)26
-rw-r--r--include/clang/Sema/ScopeInfo.h137
-rw-r--r--include/clang/Sema/Sema.h (renamed from lib/Sema/Sema.h)3192
-rw-r--r--include/clang/Sema/SemaInternal.h30
-rw-r--r--include/clang/Sema/Template.h (renamed from lib/Sema/SemaTemplate.h)95
-rw-r--r--include/clang/Sema/TemplateDeduction.h111
-rw-r--r--include/clang/Serialization/ASTBitCodes.h (renamed from include/clang/Frontend/PCHBitCodes.h)193
-rw-r--r--include/clang/Serialization/ASTDeserializationListener.h49
-rw-r--r--include/clang/Serialization/ASTReader.h (renamed from include/clang/Frontend/PCHReader.h)667
-rw-r--r--include/clang/Serialization/ASTWriter.h (renamed from include/clang/Frontend/PCHWriter.h)257
-rw-r--r--include/clang/Serialization/CMakeLists.txt12
-rw-r--r--include/clang/Serialization/Makefile19
-rw-r--r--lib/AST/ASTConsumer.cpp3
-rw-r--r--lib/AST/ASTContext.cpp595
-rw-r--r--lib/AST/ASTDiagnostic.cpp11
-rw-r--r--lib/AST/ASTImporter.cpp104
-rw-r--r--lib/AST/AttrImpl.cpp196
-rw-r--r--lib/AST/CMakeLists.txt4
-rw-r--r--lib/AST/CXXABI.h39
-rw-r--r--lib/AST/Decl.cpp272
-rw-r--r--lib/AST/DeclBase.cpp251
-rw-r--r--lib/AST/DeclCXX.cpp109
-rw-r--r--lib/AST/DeclGroup.cpp6
-rw-r--r--lib/AST/DeclObjC.cpp183
-rw-r--r--lib/AST/DeclPrinter.cpp19
-rw-r--r--lib/AST/DeclTemplate.cpp174
-rw-r--r--lib/AST/DeclarationName.cpp116
-rw-r--r--lib/AST/Expr.cpp589
-rw-r--r--lib/AST/ExprCXX.cpp329
-rw-r--r--lib/AST/ExprClassification.cpp34
-rw-r--r--lib/AST/ExprConstant.cpp505
-rw-r--r--lib/AST/FullExpr.cpp13
-rw-r--r--lib/AST/ItaniumCXXABI.cpp52
-rw-r--r--lib/AST/Makefile1
-rw-r--r--lib/AST/MicrosoftCXXABI.cpp48
-rw-r--r--lib/AST/NestedNameSpecifier.cpp5
-rw-r--r--lib/AST/ParentMap.cpp2
-rw-r--r--lib/AST/RecordLayout.cpp4
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp113
-rw-r--r--lib/AST/Stmt.cpp94
-rw-r--r--lib/AST/StmtDumper.cpp38
-rw-r--r--lib/AST/StmtPrinter.cpp92
-rw-r--r--lib/AST/StmtProfile.cpp107
-rw-r--r--lib/AST/TemplateBase.cpp17
-rw-r--r--lib/AST/Type.cpp157
-rw-r--r--lib/AST/TypeLoc.cpp14
-rw-r--r--lib/AST/TypePrinter.cpp9
-rw-r--r--lib/Analysis/AnalysisContext.cpp45
-rw-r--r--lib/Analysis/CFG.cpp164
-rw-r--r--lib/Analysis/CFGStmtMap.cpp88
-rw-r--r--lib/Analysis/CMakeLists.txt4
-rw-r--r--lib/Analysis/FormatString.cpp474
-rw-r--r--lib/Analysis/FormatStringParsing.h72
-rw-r--r--lib/Analysis/LiveVariables.cpp24
-rw-r--r--lib/Analysis/Makefile1
-rw-r--r--lib/Analysis/PrintfFormatString.cpp572
-rw-r--r--lib/Analysis/PseudoConstantAnalysis.cpp238
-rw-r--r--lib/Analysis/ReachableCode.cpp2
-rw-r--r--lib/Analysis/ScanfFormatString.cpp221
-rw-r--r--lib/Analysis/UninitializedValues.cpp4
-rw-r--r--lib/Basic/Builtins.cpp20
-rw-r--r--lib/Basic/Diagnostic.cpp64
-rw-r--r--lib/Basic/FileManager.cpp16
-rw-r--r--lib/Basic/IdentifierTable.cpp12
-rw-r--r--lib/Basic/Makefile1
-rw-r--r--lib/Basic/SourceManager.cpp34
-rw-r--r--lib/Basic/TargetInfo.cpp22
-rw-r--r--lib/Basic/Targets.cpp84
-rw-r--r--lib/Basic/Version.cpp2
-rw-r--r--lib/CMakeLists.txt2
-rw-r--r--lib/Checker/AdjustedReturnValueChecker.cpp3
-rw-r--r--lib/Checker/AggExprVisitor.cpp11
-rw-r--r--lib/Checker/AnalysisConsumer.cpp12
-rw-r--r--lib/Checker/AnalysisManager.cpp31
-rw-r--r--lib/Checker/ArrayBoundChecker.cpp2
-rw-r--r--lib/Checker/BasicObjCFoundationChecks.cpp5
-rw-r--r--lib/Checker/BasicStore.cpp63
-rw-r--r--lib/Checker/BasicValueFactory.cpp32
-rw-r--r--lib/Checker/BugReporter.cpp51
-rw-r--r--lib/Checker/BugReporterVisitors.cpp49
-rw-r--r--lib/Checker/CFRefCount.cpp202
-rw-r--r--lib/Checker/CMakeLists.txt4
-rw-r--r--lib/Checker/CStringChecker.cpp594
-rw-r--r--lib/Checker/CallAndMessageChecker.cpp2
-rw-r--r--lib/Checker/CallInliner.cpp54
-rw-r--r--lib/Checker/CastSizeChecker.cpp4
-rw-r--r--lib/Checker/CheckDeadStores.cpp4
-rw-r--r--lib/Checker/CheckSecuritySyntaxOnly.cpp16
-rw-r--r--lib/Checker/CheckerHelpers.cpp80
-rw-r--r--lib/Checker/CocoaConventions.cpp5
-rw-r--r--lib/Checker/DivZeroChecker.cpp8
-rw-r--r--lib/Checker/Environment.cpp41
-rw-r--r--lib/Checker/FixedAddressChecker.cpp2
-rw-r--r--lib/Checker/FlatStore.cpp82
-rw-r--r--lib/Checker/GRCXXExprEngine.cpp34
-rw-r--r--lib/Checker/GRCoreEngine.cpp154
-rw-r--r--lib/Checker/GRExprEngine.cpp678
-rw-r--r--lib/Checker/GRExprEngineExperimentalChecks.cpp16
-rw-r--r--lib/Checker/GRExprEngineExperimentalChecks.h5
-rw-r--r--lib/Checker/GRState.cpp224
-rw-r--r--lib/Checker/IdempotentOperationChecker.cpp673
-rw-r--r--lib/Checker/LLVMConventionsChecker.cpp1
-rw-r--r--lib/Checker/Makefile1
-rw-r--r--lib/Checker/MallocChecker.cpp251
-rw-r--r--lib/Checker/MemRegion.cpp69
-rw-r--r--lib/Checker/OSAtomicChecker.cpp8
-rw-r--r--lib/Checker/PointerArithChecker.cpp3
-rw-r--r--lib/Checker/PointerSubChecker.cpp2
-rw-r--r--lib/Checker/RangeConstraintManager.cpp1
-rw-r--r--lib/Checker/RegionStore.cpp356
-rw-r--r--lib/Checker/ReturnPointerRangeChecker.cpp2
-rw-r--r--lib/Checker/ReturnUndefChecker.cpp1
-rw-r--r--lib/Checker/SVals.cpp7
-rw-r--r--lib/Checker/SValuator.cpp4
-rw-r--r--lib/Checker/SimpleConstraintManager.cpp70
-rw-r--r--lib/Checker/SimpleConstraintManager.h4
-rw-r--r--lib/Checker/SimpleSValuator.cpp284
-rw-r--r--lib/Checker/StackAddrLeakChecker.cpp2
-rw-r--r--lib/Checker/Store.cpp41
-rw-r--r--lib/Checker/StreamChecker.cpp197
-rw-r--r--lib/Checker/SymbolManager.cpp139
-rw-r--r--lib/Checker/UndefBranchChecker.cpp17
-rw-r--r--lib/Checker/UndefinedAssignmentChecker.cpp12
-rw-r--r--lib/Checker/UnixAPIChecker.cpp2
-rw-r--r--lib/Checker/UnreachableCodeChecker.cpp226
-rw-r--r--lib/Checker/VLASizeChecker.cpp2
-rw-r--r--lib/Checker/ValueManager.cpp17
-rw-r--r--lib/CodeGen/ABIInfo.h106
-rw-r--r--lib/CodeGen/CGBlocks.cpp197
-rw-r--r--lib/CodeGen/CGBlocks.h18
-rw-r--r--lib/CodeGen/CGBuiltin.cpp388
-rw-r--r--lib/CodeGen/CGCXX.cpp190
-rw-r--r--lib/CodeGen/CGCXXABI.h200
-rw-r--r--lib/CodeGen/CGCall.cpp481
-rw-r--r--lib/CodeGen/CGClass.cpp450
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp477
-rw-r--r--lib/CodeGen/CGDebugInfo.h51
-rw-r--r--lib/CodeGen/CGDecl.cpp164
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp72
-rw-r--r--lib/CodeGen/CGException.cpp578
-rw-r--r--lib/CodeGen/CGException.h313
-rw-r--r--lib/CodeGen/CGExpr.cpp501
-rw-r--r--lib/CodeGen/CGExprAgg.cpp201
-rw-r--r--lib/CodeGen/CGExprCXX.cpp860
-rw-r--r--lib/CodeGen/CGExprComplex.cpp4
-rw-r--r--lib/CodeGen/CGExprConstant.cpp125
-rw-r--r--lib/CodeGen/CGExprScalar.cpp463
-rw-r--r--lib/CodeGen/CGObjC.cpp15
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp64
-rw-r--r--lib/CodeGen/CGObjCMac.cpp993
-rw-r--r--lib/CodeGen/CGObjCRuntime.h13
-rw-r--r--lib/CodeGen/CGRTTI.cpp192
-rw-r--r--lib/CodeGen/CGRecordLayout.h28
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp81
-rw-r--r--lib/CodeGen/CGStmt.cpp131
-rw-r--r--lib/CodeGen/CGTemporaries.cpp86
-rw-r--r--lib/CodeGen/CGVTT.cpp3
-rw-r--r--lib/CodeGen/CGVTables.cpp92
-rw-r--r--lib/CodeGen/CGValue.h71
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp1125
-rw-r--r--lib/CodeGen/CodeGenFunction.h321
-rw-r--r--lib/CodeGen/CodeGenModule.cpp454
-rw-r--r--lib/CodeGen/CodeGenModule.h77
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp39
-rw-r--r--lib/CodeGen/CodeGenTypes.h28
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp992
-rw-r--r--lib/CodeGen/Makefile1
-rw-r--r--lib/CodeGen/Mangle.cpp120
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp37
-rw-r--r--lib/CodeGen/TargetInfo.cpp1183
-rw-r--r--lib/CodeGen/TargetInfo.h10
-rw-r--r--lib/Driver/Compilation.cpp12
-rw-r--r--lib/Driver/Driver.cpp126
-rw-r--r--lib/Driver/HostInfo.cpp177
-rw-r--r--lib/Driver/InputInfo.h15
-rw-r--r--lib/Driver/Job.cpp12
-rw-r--r--lib/Driver/Makefile1
-rw-r--r--lib/Driver/OptTable.cpp2
-rw-r--r--lib/Driver/Option.cpp2
-rw-r--r--lib/Driver/ToolChain.cpp140
-rw-r--r--lib/Driver/ToolChains.cpp265
-rw-r--r--lib/Driver/ToolChains.h50
-rw-r--r--lib/Driver/Tools.cpp500
-rw-r--r--lib/Driver/Tools.h95
-rw-r--r--lib/Frontend/ASTConsumers.cpp2
-rw-r--r--lib/Frontend/ASTMerge.cpp8
-rw-r--r--lib/Frontend/ASTUnit.cpp1586
-rw-r--r--lib/Frontend/CMakeLists.txt8
-rw-r--r--lib/Frontend/CacheTokens.cpp13
-rw-r--r--lib/Frontend/CompilerInstance.cpp127
-rw-r--r--lib/Frontend/CompilerInvocation.cpp111
-rw-r--r--lib/Frontend/DependencyFile.cpp1
-rw-r--r--lib/Frontend/DiagChecker.cpp2
-rw-r--r--lib/Frontend/FrontendAction.cpp36
-rw-r--r--lib/Frontend/FrontendActions.cpp88
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp42
-rw-r--r--lib/Frontend/InitPreprocessor.cpp33
-rw-r--r--lib/Frontend/Makefile1
-rw-r--r--lib/Frontend/PrintParserCallbacks.cpp852
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp59
-rw-r--r--lib/Frontend/StmtXML.cpp4
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp46
-rw-r--r--lib/Frontend/VerifyDiagnosticsClient.cpp14
-rw-r--r--lib/FrontendTool/CMakeLists.txt5
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp155
-rw-r--r--lib/FrontendTool/Makefile13
-rw-r--r--lib/Headers/CMakeLists.txt3
-rw-r--r--lib/Headers/Makefile1
-rw-r--r--lib/Headers/altivec.h4512
-rw-r--r--lib/Headers/avxintrin.h1156
-rw-r--r--lib/Headers/emmintrin.h9
-rw-r--r--lib/Headers/immintrin.h59
-rw-r--r--lib/Headers/mmintrin.h58
-rw-r--r--lib/Headers/nmmintrin.h44
-rw-r--r--lib/Headers/smmintrin.h12
-rw-r--r--lib/Headers/stddef.h3
-rw-r--r--lib/Headers/x86intrin.h31
-rw-r--r--lib/Headers/xmmintrin.h51
-rw-r--r--lib/Index/CMakeLists.txt1
-rw-r--r--lib/Index/Entity.cpp4
-rw-r--r--lib/Index/Makefile1
-rw-r--r--lib/Index/ResolveLocation.cpp602
-rw-r--r--lib/Lex/Lexer.cpp292
-rw-r--r--lib/Lex/LiteralSupport.cpp44
-rw-r--r--lib/Lex/MacroInfo.cpp19
-rw-r--r--lib/Lex/Makefile1
-rw-r--r--lib/Lex/PPDirectives.cpp51
-rw-r--r--lib/Lex/PPExpressions.cpp19
-rw-r--r--lib/Lex/PPMacroExpansion.cpp24
-rw-r--r--lib/Lex/PTHLexer.cpp30
-rw-r--r--lib/Lex/Pragma.cpp270
-rw-r--r--lib/Lex/PreprocessingRecord.cpp3
-rw-r--r--lib/Lex/Preprocessor.cpp29
-rw-r--r--lib/Lex/TokenLexer.cpp18
-rwxr-xr-xlib/Makefile2
-rw-r--r--lib/Parse/CMakeLists.txt6
-rw-r--r--lib/Parse/Makefile1
-rw-r--r--lib/Parse/MinimalAction.cpp281
-rw-r--r--lib/Parse/ParseAST.cpp (renamed from lib/Sema/ParseAST.cpp)69
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp24
-rw-r--r--lib/Parse/ParseDecl.cpp369
-rw-r--r--lib/Parse/ParseDeclCXX.cpp308
-rw-r--r--lib/Parse/ParseExpr.cpp323
-rw-r--r--lib/Parse/ParseExprCXX.cpp180
-rw-r--r--lib/Parse/ParseInit.cpp48
-rw-r--r--lib/Parse/ParseObjc.cpp420
-rw-r--r--lib/Parse/ParsePragma.cpp120
-rw-r--r--lib/Parse/ParsePragma.h39
-rw-r--r--lib/Parse/ParseStmt.cpp282
-rw-r--r--lib/Parse/ParseTemplate.cpp121
-rw-r--r--lib/Parse/ParseTentative.cpp37
-rw-r--r--lib/Parse/Parser.cpp149
-rw-r--r--lib/Rewrite/CMakeLists.txt6
-rw-r--r--lib/Rewrite/DeltaTree.cpp10
-rw-r--r--lib/Rewrite/FixItRewriter.cpp29
-rw-r--r--lib/Rewrite/FrontendActions.cpp21
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp3
-rw-r--r--lib/Rewrite/Makefile1
-rw-r--r--lib/Rewrite/RewriteObjC.cpp388
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp39
-rw-r--r--lib/Sema/AttributeList.cpp (renamed from lib/Parse/AttributeList.cpp)12
-rw-r--r--lib/Sema/CMakeLists.txt3
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp233
-rw-r--r--lib/Sema/DeclSpec.cpp (renamed from lib/Parse/DeclSpec.cpp)110
-rw-r--r--lib/Sema/IdentifierResolver.cpp35
-rw-r--r--lib/Sema/JumpDiagnostics.cpp29
-rw-r--r--lib/Sema/Makefile1
-rw-r--r--lib/Sema/Sema.cpp261
-rw-r--r--lib/Sema/SemaAccess.cpp218
-rw-r--r--lib/Sema/SemaAttr.cpp135
-rw-r--r--lib/Sema/SemaCXXCast.cpp183
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp42
-rw-r--r--lib/Sema/SemaChecking.cpp870
-rw-r--r--lib/Sema/SemaCodeComplete.cpp2077
-rw-r--r--lib/Sema/SemaDecl.cpp1400
-rw-r--r--lib/Sema/SemaDeclAttr.cpp453
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1068
-rw-r--r--lib/Sema/SemaDeclObjC.cpp442
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp10
-rw-r--r--lib/Sema/SemaExpr.cpp1704
-rw-r--r--lib/Sema/SemaExprCXX.cpp604
-rw-r--r--lib/Sema/SemaExprObjC.cpp136
-rw-r--r--lib/Sema/SemaInit.cpp383
-rw-r--r--lib/Sema/SemaLookup.cpp168
-rw-r--r--lib/Sema/SemaObjCProperty.cpp175
-rw-r--r--lib/Sema/SemaOverload.cpp1374
-rw-r--r--lib/Sema/SemaStmt.cpp382
-rw-r--r--lib/Sema/SemaTemplate.cpp550
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp191
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp87
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp397
-rw-r--r--lib/Sema/SemaType.cpp154
-rw-r--r--lib/Sema/TargetAttributesSema.cpp17
-rw-r--r--lib/Sema/TargetAttributesSema.h2
-rw-r--r--lib/Sema/TreeTransform.h2028
-rw-r--r--lib/Serialization/ASTCommon.cpp69
-rw-r--r--lib/Serialization/ASTCommon.h50
-rw-r--r--lib/Serialization/ASTReader.cpp (renamed from lib/Frontend/PCHReader.cpp)2206
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp (renamed from lib/Frontend/PCHReaderDecl.cpp)892
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp (renamed from lib/Frontend/PCHReaderStmt.cpp)611
-rw-r--r--lib/Serialization/ASTWriter.cpp (renamed from lib/Frontend/PCHWriter.cpp)1677
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp (renamed from lib/Frontend/PCHWriterDecl.cpp)542
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp (renamed from lib/Frontend/PCHWriterStmt.cpp)520
-rw-r--r--lib/Serialization/CMakeLists.txt23
-rw-r--r--lib/Serialization/GeneratePCH.cpp (renamed from lib/Frontend/GeneratePCH.cpp)43
-rw-r--r--lib/Serialization/Makefile19
-rw-r--r--test/Analysis/additive-folding.c14
-rw-r--r--test/Analysis/array-struct-region.c47
-rw-r--r--test/Analysis/bstring.c37
-rw-r--r--test/Analysis/constant-folding.c74
-rw-r--r--test/Analysis/dead-stores.c32
-rw-r--r--test/Analysis/flat-store.c11
-rw-r--r--test/Analysis/idempotent-operations.c203
-rw-r--r--test/Analysis/idempotent-operations.cpp15
-rw-r--r--test/Analysis/malloc.c124
-rw-r--r--test/Analysis/misc-ps-region-store.cpp27
-rw-r--r--test/Analysis/misc-ps-region-store.m101
-rw-r--r--test/Analysis/misc-ps.m58
-rw-r--r--test/Analysis/null-deref-ps.c9
-rw-r--r--test/Analysis/outofbound.c24
-rw-r--r--test/Analysis/plist-output.m2
-rw-r--r--test/Analysis/retain-release-region-store.m27
-rw-r--r--test/Analysis/retain-release.m9
-rw-r--r--test/Analysis/stack-addr-ps.cpp8
-rw-r--r--test/Analysis/stream.c38
-rw-r--r--test/Analysis/string.c240
-rw-r--r--test/Analysis/uninit-vals-ps-region.m4
-rw-r--r--test/Analysis/unreachable-code-path.c104
-rw-r--r--test/CMakeLists.txt6
-rw-r--r--test/CXX/class.access/class.protected/p1.cpp69
-rw-r--r--test/CXX/class.access/p4.cpp25
-rw-r--r--test/CXX/class.access/p6.cpp20
-rw-r--r--test/CXX/class/class.mem/p1.cpp64
-rw-r--r--test/CXX/class/class.static/class.static.data/p4.cpp25
-rw-r--r--test/CXX/conv/conv.ptr/p2.cpp6
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp9
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp13
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp97
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp1
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp15
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp10
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp7
-rw-r--r--test/CXX/dcl.decl/dcl.init/p5.cpp20
-rw-r--r--test/CXX/expr/expr.unary/expr.unary.op/p4.cpp45
-rw-r--r--test/CXX/special/class.dtor/p9.cpp85
-rw-r--r--test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp20
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p4.cpp18
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp27
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp18
-rw-r--r--test/CXX/temp/temp.param/p4.cpp3
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p3.cpp27
-rw-r--r--test/CodeCompletion/enum-switch-case.c21
-rw-r--r--test/CodeCompletion/functions.cpp2
-rw-r--r--test/CodeGen/2009-04-23-dbg.c2
-rw-r--r--test/CodeGen/2009-10-20-GlobalDebug.c2
-rw-r--r--test/CodeGen/2010-08-10-DbgConstant.c5
-rw-r--r--test/CodeGen/_Bool-conversion.c12
-rw-r--r--test/CodeGen/address-space-field1.c26
-rw-r--r--test/CodeGen/address-space-field2.c46
-rw-r--r--test/CodeGen/address-space-field3.c42
-rw-r--r--test/CodeGen/address-space-field4.c55
-rw-r--r--test/CodeGen/asm-errors.c2
-rw-r--r--test/CodeGen/asm-inout.c19
-rw-r--r--test/CodeGen/asm.c22
-rw-r--r--test/CodeGen/asm_arm.c22
-rw-r--r--test/CodeGen/atomic.c15
-rw-r--r--test/CodeGen/available-externally-suppress.c15
-rw-r--r--test/CodeGen/bitfield-2.c8
-rw-r--r--test/CodeGen/block-decl-merging.c20
-rw-r--r--test/CodeGen/blockstret.c4
-rw-r--r--test/CodeGen/builtin-expect.c11
-rw-r--r--test/CodeGen/builtins-arm.c2
-rw-r--r--test/CodeGen/builtins-ppc-altivec.c987
-rw-r--r--test/CodeGen/builtins-x86.c117
-rw-r--r--test/CodeGen/const-arithmetic.c4
-rw-r--r--test/CodeGen/const-init.c7
-rw-r--r--test/CodeGen/debug-info-enum.c11
-rw-r--r--test/CodeGen/debug-info-scope.c14
-rw-r--r--test/CodeGen/designated-initializers.c27
-rw-r--r--test/CodeGen/enum2.c8
-rw-r--r--test/CodeGen/exprs.c7
-rw-r--r--test/CodeGen/fold-const-declref.c9
-rw-r--r--test/CodeGen/func-in-block.c1
-rw-r--r--test/CodeGen/lineno-dbginfo.c3
-rw-r--r--test/CodeGen/packed-structure.c89
-rw-r--r--test/CodeGen/palignr.c2
-rw-r--r--test/CodeGen/pragma-visibility.c24
-rw-r--r--test/CodeGen/statements.c9
-rw-r--r--test/CodeGen/struct-passing.c12
-rw-r--r--test/CodeGen/thread-specifier.c1
-rw-r--r--test/CodeGen/trapv.c47
-rw-r--r--test/CodeGen/unwind-attr.c24
-rw-r--r--test/CodeGen/vector.c17
-rw-r--r--test/CodeGen/x86_32-arguments.c16
-rw-r--r--test/CodeGen/x86_64-arguments.c122
-rw-r--r--test/CodeGenCXX/anonymous-namespaces.cpp38
-rw-r--r--test/CodeGenCXX/anonymous-union-member-initializer.cpp12
-rw-r--r--test/CodeGenCXX/arm.cpp274
-rw-r--r--test/CodeGenCXX/condition.cpp16
-rw-r--r--test/CodeGenCXX/copy-constructor-elim-2.cpp26
-rw-r--r--test/CodeGenCXX/debug-info-byval.cpp31
-rw-r--r--test/CodeGenCXX/debug-info-class.cpp12
-rw-r--r--test/CodeGenCXX/debug-info-ctor.cpp14
-rw-r--r--test/CodeGenCXX/debug-info-enum.cpp8
-rw-r--r--test/CodeGenCXX/debug-info-friend.cpp11
-rw-r--r--test/CodeGenCXX/debug-info-template.cpp9
-rw-r--r--test/CodeGenCXX/debug-info.cpp5
-rw-r--r--test/CodeGenCXX/delete.cpp50
-rw-r--r--test/CodeGenCXX/dependent-type-member-pointer.cpp18
-rw-r--r--test/CodeGenCXX/destructors.cpp56
-rw-r--r--test/CodeGenCXX/dyncast.cpp76
-rw-r--r--test/CodeGenCXX/eh.cpp165
-rw-r--r--test/CodeGenCXX/exceptions-no-rtti.cpp9
-rw-r--r--test/CodeGenCXX/explicit-instantiation.cpp31
-rw-r--r--test/CodeGenCXX/expr.cpp21
-rw-r--r--test/CodeGenCXX/global-init.cpp48
-rw-r--r--test/CodeGenCXX/key-function-vtable.cpp4
-rw-r--r--test/CodeGenCXX/mangle-exprs.cpp2
-rw-r--r--test/CodeGenCXX/mangle.cpp117
-rw-r--r--test/CodeGenCXX/member-function-pointers.cpp79
-rw-r--r--test/CodeGenCXX/member-functions.cpp2
-rw-r--r--test/CodeGenCXX/member-qual-debug-info.cpp20
-rw-r--r--test/CodeGenCXX/new.cpp65
-rw-r--r--test/CodeGenCXX/nonconst-init.cpp5
-rw-r--r--test/CodeGenCXX/operator-new.cpp16
-rw-r--r--test/CodeGenCXX/pointers-to-data-members.cpp30
-rw-r--r--test/CodeGenCXX/pragma-visibility.cpp72
-rw-r--r--test/CodeGenCXX/reference-cast.cpp170
-rw-r--r--test/CodeGenCXX/rtti-fundamental.cpp114
-rw-r--r--test/CodeGenCXX/rtti-linkage.cpp24
-rw-r--r--test/CodeGenCXX/static-init-2.cpp2
-rw-r--r--test/CodeGenCXX/template-anonymous-types.cpp37
-rw-r--r--test/CodeGenCXX/threadsafe-statics-exceptions.cpp2
-rw-r--r--test/CodeGenCXX/thunks.cpp14
-rw-r--r--test/CodeGenCXX/uncode-string.cpp6
-rw-r--r--test/CodeGenCXX/value-init.cpp89
-rw-r--r--test/CodeGenCXX/virt-template-vtable.cpp9
-rw-r--r--test/CodeGenCXX/volatile.cpp35
-rw-r--r--test/CodeGenCXX/vtable-linkage.cpp28
-rw-r--r--test/CodeGenCXX/vtt-layout.cpp6
-rw-r--r--test/CodeGenCXX/x86_32-arguments.cpp2
-rw-r--r--test/CodeGenCXX/x86_64-arguments.cpp74
-rw-r--r--test/CodeGenObjC/bitfield-access.m43
-rw-r--r--test/CodeGenObjC/block-var-layout.m123
-rw-r--r--test/CodeGenObjC/debug-info-linkagename.m3
-rw-r--r--test/CodeGenObjC/exceptions.m102
-rw-r--r--test/CodeGenObjC/for-in.m4
-rw-r--r--test/CodeGenObjC/fpret.m38
-rw-r--r--test/CodeGenObjC/gnu-exceptions.m29
-rw-r--r--test/CodeGenObjC/ivar-layout-nonfragile-abi2.m51
-rw-r--r--test/CodeGenObjC/property-dbg.m2
-rw-r--r--test/CodeGenObjC/return-objc-object.mm19
-rw-r--r--test/CodeGenObjC/super-dotsyntax-struct-property.m47
-rw-r--r--test/CodeGenObjC/synchronized.m56
-rw-r--r--test/CodeGenObjC/unwind-fn.m2
-rw-r--r--test/CodeGenObjC/x86_64-struct-return-gc.m2
-rw-r--r--test/CodeGenObjCXX/exceptions.mm17
-rw-r--r--test/CodeGenObjCXX/property-objects.mm8
-rw-r--r--test/CodeGenObjCXX/references.mm20
-rw-r--r--test/CodeGenObjCXX/rtti.mm52
-rw-r--r--test/Coverage/parse-callbacks.c4
-rw-r--r--test/Coverage/parse-callbacks.m4
-rw-r--r--test/Driver/at_file.c30
-rw-r--r--test/Driver/at_file.c.args11
-rw-r--r--test/Driver/bindings.c6
-rw-r--r--test/Driver/cxx-pth.cpp12
-rw-r--r--test/Driver/darwin-as.c10
-rw-r--r--test/Driver/darwin-cc.c4
-rw-r--r--test/Driver/darwin-debug-flags.c2
-rw-r--r--test/Driver/darwin-ld.c37
-rw-r--r--test/Driver/darwin-xarch.c8
-rw-r--r--test/Driver/freebsd.c26
-rw-r--r--test/Driver/gcc_forward.c13
-rw-r--r--test/Driver/rewrite-objc.m6
-rw-r--r--test/FixIt/fixit.c3
-rw-r--r--test/Frontend/Inputs/lit.local.cfg1
-rw-r--r--test/Frontend/Inputs/test.h1
-rw-r--r--test/Frontend/Inputs/test2.h1
-rw-r--r--test/Frontend/Inputs/test3.h1
-rw-r--r--test/Frontend/print-header-includes.c8
-rw-r--r--test/Headers/x86-intrinsics-headers.c29
-rw-r--r--test/Index/Inputs/crash-recovery-code-complete-remap.c12
-rw-r--r--test/Index/Inputs/crash-recovery-reparse-remap.c11
-rw-r--r--test/Index/Inputs/preamble-reparse-1.c2
-rw-r--r--test/Index/Inputs/preamble-reparse-2.c1
-rw-r--r--test/Index/Inputs/preamble.h6
-rw-r--r--test/Index/Inputs/prefix.h4
-rw-r--r--test/Index/TestClassDecl.m2
-rw-r--r--test/Index/annotate-tokens-pp.c131
-rw-r--r--test/Index/annotate-tokens.c15
-rw-r--r--test/Index/annotate-tokens.cpp23
-rw-r--r--test/Index/annotate-tokens.m106
-rw-r--r--test/Index/c-index-api-loadTU-test.m13
-rw-r--r--test/Index/cindex-from-source.m3
-rw-r--r--test/Index/code-completion.cpp28
-rw-r--r--test/Index/complete-at-exprstmt.m18
-rw-r--r--test/Index/complete-blocks.m24
-rw-r--r--test/Index/complete-ctor-inits.cpp40
-rw-r--r--test/Index/complete-declarators.cpp39
-rw-r--r--test/Index/complete-declarators.m45
-rw-r--r--test/Index/complete-exprs.c31
-rw-r--r--test/Index/complete-hiding.c29
-rw-r--r--test/Index/complete-macros.c3
-rw-r--r--test/Index/complete-memfunc-cvquals.cpp86
-rw-r--r--test/Index/complete-method-decls.m116
-rw-r--r--test/Index/complete-natural.m56
-rw-r--r--test/Index/complete-objc-message-id.m12
-rw-r--r--test/Index/complete-objc-message.m97
-rw-r--r--test/Index/complete-pch.m12
-rw-r--r--test/Index/complete-preprocessor.m80
-rw-r--r--test/Index/complete-recovery.m2
-rw-r--r--test/Index/complete-super.cpp33
-rw-r--r--test/Index/complete-super.m55
-rw-r--r--test/Index/complete-templates.cpp19
-rw-r--r--test/Index/complete-unterminated.c30
-rw-r--r--test/Index/crash-recovery-code-complete.c10
-rw-r--r--test/Index/crash-recovery-reparse.c10
-rw-r--r--test/Index/crash-recovery.c7
-rw-r--r--test/Index/index-templates.cpp147
-rw-r--r--test/Index/invalid-rdar-8236270.cpp11
-rw-r--r--test/Index/load-classes.cpp28
-rw-r--r--test/Index/load-decls.c16
-rw-r--r--test/Index/load-namespaces.cpp50
-rw-r--r--test/Index/load-stmts.cpp105
-rw-r--r--test/Index/local-symbols.m18
-rw-r--r--test/Index/preamble-reparse.c2
-rw-r--r--test/Index/preamble.c28
-rw-r--r--test/Index/print-typekind.c27
-rw-r--r--test/Index/rdar-8288645-invalid-code.mm8
-rw-r--r--test/Index/usrs.cpp53
-rw-r--r--test/Index/usrs.m61
-rw-r--r--test/Lexer/c90.c16
-rw-r--r--test/Lexer/constants.c3
-rw-r--r--test/Lexer/has_feature_cxx0x.cpp10
-rw-r--r--test/Lexer/ms-extensions.c (renamed from test/Lexer/constants-ms.c)16
-rw-r--r--test/Lexer/preamble.c37
-rw-r--r--test/Makefile4
-rw-r--r--test/PCH/Inputs/chain-cxx1.h19
-rw-r--r--test/PCH/Inputs/chain-cxx2.h32
-rw-r--r--test/PCH/Inputs/chain-decls1.h11
-rw-r--r--test/PCH/Inputs/chain-decls2.h12
-rw-r--r--test/PCH/Inputs/chain-ext_vector1.h3
-rw-r--r--test/PCH/Inputs/chain-ext_vector2.h3
-rw-r--r--test/PCH/Inputs/chain-external-defs1.h13
-rw-r--r--test/PCH/Inputs/chain-external-defs2.h11
-rw-r--r--test/PCH/Inputs/chain-macro-override1.h4
-rw-r--r--test/PCH/Inputs/chain-macro-override2.h4
-rw-r--r--test/PCH/Inputs/chain-macro1.h1
-rw-r--r--test/PCH/Inputs/chain-macro2.h1
-rw-r--r--test/PCH/Inputs/chain-selectors1.h12
-rw-r--r--test/PCH/Inputs/chain-selectors2.h11
-rw-r--r--test/PCH/Inputs/chain-trivial1.h0
-rw-r--r--test/PCH/Inputs/chain-trivial2.h0
-rw-r--r--test/PCH/Inputs/preamble.h1
-rw-r--r--test/PCH/chain-cxx.cpp28
-rw-r--r--test/PCH/chain-decls.c27
-rw-r--r--test/PCH/chain-ext_vector.c11
-rw-r--r--test/PCH/chain-external-defs.c54
-rw-r--r--test/PCH/chain-macro-override.c13
-rw-r--r--test/PCH/chain-macro.c9
-rw-r--r--test/PCH/chain-predecl.h3
-rw-r--r--test/PCH/chain-predecl.m16
-rw-r--r--test/PCH/chain-selectors.m24
-rw-r--r--test/PCH/chain-trivial.c4
-rw-r--r--test/PCH/cxx-offsetof-base.cpp2
-rw-r--r--test/PCH/cxx-offsetof-base.h5
-rw-r--r--test/PCH/cxx-required-decls.cpp10
-rw-r--r--test/PCH/cxx-required-decls.h12
-rw-r--r--test/PCH/cxx-static_assert.cpp11
-rw-r--r--test/PCH/cxx-static_assert.h9
-rw-r--r--test/PCH/cxx-templates.cpp14
-rw-r--r--test/PCH/cxx-templates.h37
-rw-r--r--test/PCH/cxx-traits.cpp8
-rw-r--r--test/PCH/cxx-traits.h11
-rw-r--r--test/PCH/cxx-typeid.cpp9
-rw-r--r--test/PCH/cxx-typeid.h3
-rw-r--r--test/PCH/namespaces.cpp7
-rw-r--r--test/PCH/objcxx-ivar-class.h15
-rw-r--r--test/PCH/objcxx-ivar-class.mm15
-rw-r--r--test/PCH/pragma-weak.c10
-rw-r--r--test/PCH/pragma-weak.h10
-rw-r--r--test/PCH/preamble.c21
-rw-r--r--test/PCH/pth.c7
-rw-r--r--test/PCH/pth.h12
-rw-r--r--test/PCH/reinclude.cpp8
-rw-r--r--test/PCH/reinclude1.h4
-rw-r--r--test/PCH/reinclude2.h1
-rw-r--r--test/PCH/selector-warning.h24
-rw-r--r--test/PCH/selector-warning.m19
-rwxr-xr-xtest/Parser/2008-10-31-parse-noop-failure.c4
-rw-r--r--test/Parser/MicrosoftExtensions.c4
-rw-r--r--test/Parser/asm-constraints-pr7869.c45
-rw-r--r--test/Parser/asm.c3
-rw-r--r--test/Parser/block-block-storageclass.c4
-rw-r--r--test/Parser/block-pointer-decl.c4
-rw-r--r--test/Parser/cxx-altivec.cpp35
-rw-r--r--test/Parser/cxx-ambig-decl-expr-xfail.cpp16
-rw-r--r--test/Parser/cxx-ambig-decl-expr.cpp10
-rw-r--r--test/Parser/cxx-attributes.cpp18
-rw-r--r--test/Parser/cxx-condition.cpp4
-rw-r--r--test/Parser/cxx-decl.cpp7
-rw-r--r--test/Parser/cxx-default-args.cpp7
-rw-r--r--test/Parser/cxx-namespace-alias.cpp7
-rw-r--r--test/Parser/cxx-typeof.cpp6
-rw-r--r--test/Parser/declarators.c3
-rw-r--r--test/Parser/expressions.c30
-rw-r--r--test/Parser/expressions.m2
-rw-r--r--test/Parser/method-prototype-1.m2
-rw-r--r--test/Parser/objc-messaging-1.m27
-rw-r--r--test/Parser/pragma-options.c10
-rw-r--r--test/Parser/pragma-visibility.c9
-rw-r--r--test/Parser/selector-1.m2
-rw-r--r--test/Parser/typeof.c7
-rw-r--r--test/Parser/types.c2
-rw-r--r--test/Preprocessor/dump-macros-undef.c8
-rw-r--r--test/Preprocessor/init.c10
-rw-r--r--test/Preprocessor/macro_fn_comma_swallow.c23
-rw-r--r--test/Preprocessor/macro_paste_msextensions.c (renamed from test/Preprocessor/macro_paste_mscomment.c)8
-rw-r--r--test/Preprocessor/pragma-pushpop-macro.c33
-rw-r--r--test/Preprocessor/pragma_diagnostic.c3
-rw-r--r--test/Preprocessor/pragma_microsoft.c20
-rw-r--r--test/Preprocessor/pushable-diagnostics.c2
-rw-r--r--test/Rewriter/rewrite-block-consts.mm19
-rw-r--r--test/Rewriter/rewrite-constructor-init.mm24
-rw-r--r--test/Sema/altivec-init.c19
-rw-r--r--test/Sema/array-init.c8
-rw-r--r--test/Sema/array-size-64.c7
-rw-r--r--test/Sema/array-size.c10
-rw-r--r--test/Sema/block-misc.c5
-rw-r--r--test/Sema/builtins-arm.c11
-rw-r--r--test/Sema/builtins.c20
-rw-r--r--test/Sema/cast-incomplete.c14
-rw-r--r--test/Sema/compound-literal.c2
-rw-r--r--test/Sema/const-eval.c8
-rw-r--r--test/Sema/enum.c6
-rw-r--r--test/Sema/expr-comma-c89.c6
-rw-r--r--test/Sema/expr-comma.c8
-rw-r--r--test/Sema/exprs.c5
-rw-r--r--test/Sema/ext_vector_casts.c2
-rw-r--r--test/Sema/format-strings-scanf.c34
-rw-r--r--test/Sema/format-strings.c17
-rw-r--r--test/Sema/knr-def-call.c11
-rw-r--r--test/Sema/overloadable.c11
-rw-r--r--test/Sema/pragma-align-packed.c7
-rw-r--r--test/Sema/recover-goto.c3
-rw-r--r--test/Sema/scope-check.c32
-rw-r--r--test/Sema/switch.c6
-rw-r--r--test/Sema/typedef-variable-type.c7
-rw-r--r--test/Sema/vector-ops.c25
-rw-r--r--test/Sema/warn-cast-align.c41
-rw-r--r--test/Sema/warn-unused-function.c12
-rw-r--r--test/Sema/warn-write-strings.c6
-rw-r--r--test/SemaCXX/MicrosoftExtensions.cpp44
-rw-r--r--test/SemaCXX/abstract.cpp71
-rw-r--r--test/SemaCXX/access-member-pointer.cpp11
-rw-r--r--test/SemaCXX/addr-of-overloaded-function.cpp10
-rw-r--r--test/SemaCXX/altivec.cpp18
-rw-r--r--test/SemaCXX/anonymous-struct.cpp11
-rw-r--r--test/SemaCXX/attr-unavailable.cpp6
-rw-r--r--test/SemaCXX/blocks.cpp27
-rw-r--r--test/SemaCXX/borland-extensions.cpp26
-rw-r--r--test/SemaCXX/constructor-initializer.cpp14
-rw-r--r--test/SemaCXX/conversion-function.cpp122
-rw-r--r--test/SemaCXX/copy-assignment.cpp12
-rw-r--r--test/SemaCXX/crash-PR7625.cpp6
-rw-r--r--test/SemaCXX/decltype.cpp18
-rw-r--r--test/SemaCXX/default-constructor-initializers.cpp8
-rw-r--r--test/SemaCXX/destructor.cpp16
-rw-r--r--test/SemaCXX/enum.cpp5
-rw-r--r--test/SemaCXX/exception-spec.cpp12
-rw-r--r--test/SemaCXX/expressions.cpp7
-rw-r--r--test/SemaCXX/flexible-array-test.cpp10
-rw-r--r--test/SemaCXX/i-c-e-cxx.cpp2
-rw-r--r--test/SemaCXX/increment-decrement.cpp (renamed from test/SemaCXX/inc-decrement-qualifiers.cpp)5
-rw-r--r--test/SemaCXX/linkage-spec.cpp32
-rw-r--r--test/SemaCXX/member-expr.cpp14
-rw-r--r--test/SemaCXX/member-pointer-ms.cpp14
-rw-r--r--test/SemaCXX/member-pointer.cpp102
-rw-r--r--test/SemaCXX/new-delete.cpp44
-rw-r--r--test/SemaCXX/offsetof.cpp13
-rw-r--r--test/SemaCXX/overload-call-copycon.cpp28
-rw-r--r--test/SemaCXX/qualified-member-enum.cpp10
-rw-r--r--test/SemaCXX/return-noreturn.cpp5
-rw-r--r--test/SemaCXX/return-stack-addr.cpp11
-rw-r--r--test/SemaCXX/scope-check.cpp30
-rw-r--r--test/SemaCXX/switch.cpp3
-rw-r--r--test/SemaCXX/type-traits.cpp130
-rw-r--r--test/SemaCXX/unary-real-imag.cpp6
-rw-r--r--test/SemaCXX/unreachable-code.cpp17
-rw-r--r--test/SemaCXX/vector-no-lax.cpp9
-rw-r--r--test/SemaCXX/vector.cpp14
-rw-r--r--test/SemaCXX/virtual-base-used.cpp42
-rw-r--r--test/SemaCXX/warn-cast-align.cpp45
-rw-r--r--test/SemaCXX/warn-for-var-in-else.cpp45
-rw-r--r--test/SemaCXX/warn-global-constructors.cpp81
-rw-r--r--test/SemaCXX/warn-unused-filescoped.cpp56
-rw-r--r--test/SemaObjC/block-type-safety.m17
-rw-r--r--test/SemaObjC/compare-qualified-class.m30
-rw-r--r--test/SemaObjC/comptypes-5.m4
-rw-r--r--test/SemaObjC/conflict-nonfragile-abi2.m34
-rw-r--r--test/SemaObjC/crash-label.m11
-rw-r--r--test/SemaObjC/default-synthesize-1.m116
-rw-r--r--test/SemaObjC/deref-interface.m2
-rw-r--r--test/SemaObjC/iboutletcollection-attr.m30
-rw-r--r--test/SemaObjC/method-lookup-3.m5
-rw-r--r--test/SemaObjC/method-no-context.m3
-rw-r--r--test/SemaObjC/nonnull.m2
-rw-r--r--test/SemaObjC/property-and-ivar-use.m36
-rw-r--r--test/SemaObjC/property-not-lvalue.m6
-rw-r--r--test/SemaObjC/protocol-attribute.m6
-rw-r--r--test/SemaObjC/protocols.m4
-rw-r--r--test/SemaObjC/static-ivar-ref-1.m18
-rw-r--r--test/SemaObjC/synth-provisional-ivars.m50
-rw-r--r--test/SemaObjC/warn-strict-selector-match.m75
-rw-r--r--test/SemaObjCXX/conversion-to-objc-pointer-2.mm3
-rw-r--r--test/SemaObjCXX/cxxoperator-selector.mm24
-rw-r--r--test/SemaObjCXX/deduction.mm7
-rw-r--r--test/SemaObjCXX/exceptions-fragile.mm12
-rw-r--r--test/SemaObjCXX/expr-objcxx.mm4
-rw-r--r--test/SemaObjCXX/foreach-block.mm14
-rw-r--r--test/SemaObjCXX/instantiate-stmt.mm1
-rw-r--r--test/SemaObjCXX/message.mm2
-rw-r--r--test/SemaObjCXX/objc-decls-inside-namespace.mm5
-rw-r--r--test/SemaObjCXX/pointer-to-objc-pointer-conv.mm28
-rw-r--r--test/SemaObjCXX/references.mm36
-rw-r--r--test/SemaObjCXX/warn-strict-selector-match.mm18
-rw-r--r--test/SemaTemplate/class-template-id.cpp4
-rw-r--r--test/SemaTemplate/crash-8204126.cpp6
-rw-r--r--test/SemaTemplate/current-instantiation.cpp35
-rw-r--r--test/SemaTemplate/deduction-crash.cpp2
-rw-r--r--test/SemaTemplate/deduction.cpp29
-rw-r--r--test/SemaTemplate/dependent-base-member-init.cpp9
-rw-r--r--test/SemaTemplate/dependent-class-member-operator.cpp11
-rw-r--r--test/SemaTemplate/dependent-expr.cpp5
-rw-r--r--test/SemaTemplate/inject-templated-friend-post.cpp72
-rw-r--r--test/SemaTemplate/inject-templated-friend.cpp48
-rw-r--r--test/SemaTemplate/instantiate-anonymous-union.cpp19
-rw-r--r--test/SemaTemplate/instantiate-attr.cpp13
-rw-r--r--test/SemaTemplate/instantiate-clang.cpp2
-rw-r--r--test/SemaTemplate/instantiate-declref.cpp10
-rw-r--r--test/SemaTemplate/instantiate-expr-3.cpp10
-rw-r--r--test/SemaTemplate/instantiate-expr-4.cpp2
-rw-r--r--test/SemaTemplate/instantiate-function-1.cpp6
-rw-r--r--test/SemaTemplate/instantiate-member-template.cpp14
-rw-r--r--test/SemaTemplate/member-access-expr.cpp11
-rw-r--r--test/SemaTemplate/member-template-access-expr.cpp19
-rw-r--r--test/SemaTemplate/nested-name-spec-template.cpp11
-rw-r--r--test/SemaTemplate/recovery-crash.cpp19
-rw-r--r--test/SemaTemplate/temp.cpp18
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp40
-rw-r--r--test/SemaTemplate/temp_arg_template.cpp18
-rw-r--r--test/SemaTemplate/temp_arg_type.cpp4
-rw-r--r--test/lit.cfg6
-rw-r--r--tools/c-index-test/CMakeLists.txt3
-rw-r--r--tools/c-index-test/Makefile5
-rw-r--r--tools/c-index-test/c-index-test.c268
-rw-r--r--tools/driver/CMakeLists.txt5
-rw-r--r--tools/driver/Info.plist.in18
-rw-r--r--tools/driver/Makefile33
-rw-r--r--tools/driver/cc1_main.cpp149
-rw-r--r--tools/driver/cc1as_main.cpp41
-rw-r--r--tools/driver/driver.cpp160
-rw-r--r--tools/libclang/CIndex.cpp1131
-rw-r--r--tools/libclang/CIndexCXX.cpp124
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp306
-rw-r--r--tools/libclang/CIndexDiagnostic.cpp27
-rw-r--r--tools/libclang/CIndexUSRs.cpp237
-rw-r--r--tools/libclang/CMakeLists.txt27
-rw-r--r--tools/libclang/CXCursor.cpp98
-rw-r--r--tools/libclang/CXCursor.h28
-rw-r--r--tools/libclang/CXType.cpp (renamed from tools/libclang/CXTypes.cpp)13
-rw-r--r--tools/libclang/CXType.h29
-rw-r--r--tools/libclang/Makefile26
-rw-r--r--tools/libclang/libclang.darwin.exports19
-rw-r--r--tools/libclang/libclang.exports19
-rw-r--r--www/analyzer/latest_checker.html.incl2
-rw-r--r--www/compatibility.html75
-rw-r--r--www/cxx_status.html4
-rw-r--r--www/get_started.html2
-rw-r--r--www/hacking.html5
-rw-r--r--www/menu.html.incl2
947 files changed, 63717 insertions, 33921 deletions
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index 40c1f5f458cd..2a256450887b 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -9,15 +9,11 @@
/* Begin PBXBuildFile section */
03F50AC60D416EAA00B9CF60 /* Targets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F50AC50D416EAA00B9CF60 /* Targets.cpp */; };
1A2193CE0F45EEB700C0713D /* Mangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2193CC0F45EEB700C0713D /* Mangle.cpp */; };
- 1A2A54B50FD1DD1C00F4CE45 /* AnalysisConsumer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A40FD1DD1C00F4CE45 /* AnalysisConsumer.cpp */; };
1A2A54B60FD1DD1C00F4CE45 /* ASTConsumers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */; };
1A2A54B80FD1DD1C00F4CE45 /* CacheTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */; };
1A2A54B90FD1DD1C00F4CE45 /* DependencyFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */; };
1A2A54BA0FD1DD1C00F4CE45 /* DiagChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */; };
1A2A54BB0FD1DD1C00F4CE45 /* DocumentXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AA0FD1DD1C00F4CE45 /* DocumentXML.cpp */; };
- 1A2A54BC0FD1DD1C00F4CE45 /* GeneratePCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AB0FD1DD1C00F4CE45 /* GeneratePCH.cpp */; };
- 1A2A54BD0FD1DD1C00F4CE45 /* HTMLPrint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */; };
- 1A2A54BE0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */; };
1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */; };
1A2A54C40FD1DD1C00F4CE45 /* StmtXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B30FD1DD1C00F4CE45 /* StmtXML.cpp */; };
1A2A54C50FD1DD1C00F4CE45 /* Warnings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A2A54B40FD1DD1C00F4CE45 /* Warnings.cpp */; };
@@ -93,12 +89,9 @@
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
1AF1B50F109A4FB800AFAFAC /* CGException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AF1B50E109A4FB800AFAFAC /* CGException.cpp */; };
1AFDD8721161085D00AE030A /* ASTMerge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFDD8701161085D00AE030A /* ASTMerge.cpp */; };
- 1AFDD8731161085D00AE030A /* CodeGenAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFDD8711161085D00AE030A /* CodeGenAction.cpp */; };
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
- 352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; };
- 352246EA0F5C6BE000D0D279 /* PlistDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */; };
352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */; };
352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */; };
352712510DAFE54700C76352 /* IdentifierResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352712500DAFE54700C76352 /* IdentifierResolver.cpp */; };
@@ -142,10 +135,16 @@
35EFEFB60DB67ED60020783D /* GRTransferFuncs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35EFEFB50DB67ED60020783D /* GRTransferFuncs.cpp */; };
35F2A01E0E36AFF100D17527 /* CheckObjCUnusedIVars.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35F2A01D0E36AFF100D17527 /* CheckObjCUnusedIVars.cpp */; };
35F8D0D60D9B82CD00D91C5E /* BasicObjCFoundationChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35F8D0D50D9B82CD00D91C5E /* BasicObjCFoundationChecks.cpp */; };
+ 57AA9250121C8B9400B4AA6C /* ASTReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57AA924D121C8B9400B4AA6C /* ASTReader.cpp */; };
+ 57AA9251121C8B9400B4AA6C /* ASTReaderDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57AA924E121C8B9400B4AA6C /* ASTReaderDecl.cpp */; };
+ 57AA9252121C8B9400B4AA6C /* ASTReaderStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57AA924F121C8B9400B4AA6C /* ASTReaderStmt.cpp */; };
+ 57EB566A121B034300ECA335 /* GeneratePCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57EB5662121B034300ECA335 /* GeneratePCH.cpp */; };
+ 57EB566B121B034300ECA335 /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 57EB5663121B034300ECA335 /* Makefile */; };
+ 57F66612121B4DE600DCE3B7 /* ASTWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57F6660F121B4DE600DCE3B7 /* ASTWriter.cpp */; };
+ 57F66613121B4DE600DCE3B7 /* ASTWriterDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57F66610121B4DE600DCE3B7 /* ASTWriterDecl.cpp */; };
+ 57F66614121B4DE600DCE3B7 /* ASTWriterStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57F66611121B4DE600DCE3B7 /* ASTWriterStmt.cpp */; };
72D16C1F0D9975C400E6DA4A /* HTMLRewrite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 72D16C1E0D9975C400E6DA4A /* HTMLRewrite.cpp */; };
84AF36A10CB17A3B00C820A5 /* DeclObjC.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84AF36A00CB17A3B00C820A5 /* DeclObjC.h */; };
- 84D9A8880C1A57E100AC7ABC /* AttributeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */; };
- 84D9A88C0C1A581300AC7ABC /* AttributeList.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84D9A88B0C1A581300AC7ABC /* AttributeList.h */; };
9012911D1048068D0083456D /* ASTUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9012911C1048068D0083456D /* ASTUnit.cpp */; };
90129121104812F90083456D /* CIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9012911F104812F90083456D /* CIndex.cpp */; };
906BF4B00F83BA2E001071FA /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 906BF4AF0F83BA2E001071FA /* ConvertUTF.c */; };
@@ -159,7 +158,6 @@
90FD6D81103C3D49005F5B73 /* Indexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D75103C3D49005F5B73 /* Indexer.cpp */; };
90FD6D82103C3D49005F5B73 /* IndexProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D76103C3D49005F5B73 /* IndexProvider.cpp */; };
90FD6D83103C3D49005F5B73 /* Program.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D77103C3D49005F5B73 /* Program.cpp */; };
- 90FD6D84103C3D49005F5B73 /* ResolveLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D79103C3D49005F5B73 /* ResolveLocation.cpp */; };
90FD6D85103C3D49005F5B73 /* SelectorMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6D7A103C3D49005F5B73 /* SelectorMap.cpp */; };
90FD6DB6103D977E005F5B73 /* index-test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90FD6DB5103D977E005F5B73 /* index-test.cpp */; };
BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */; };
@@ -168,6 +166,20 @@
BF89C3F911595A01001C2D68 /* SemaType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3F811595A01001C2D68 /* SemaType.cpp */; };
BF89C3FB11595A37001C2D68 /* SemaCodeComplete.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3FA11595A37001C2D68 /* SemaCodeComplete.cpp */; };
BF89C3FD11595A5D001C2D68 /* SemaExceptionSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF89C3FC11595A5D001C2D68 /* SemaExceptionSpec.cpp */; };
+ BF9FEDF91225E67B003A8B71 /* Action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDF81225E67B003A8B71 /* Action.cpp */; };
+ BF9FEDFB1225E6A9003A8B71 /* AttributeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDFA1225E6A9003A8B71 /* AttributeList.cpp */; };
+ BF9FEDFD1225E6C6003A8B71 /* DeclSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDFC1225E6C6003A8B71 /* DeclSpec.cpp */; };
+ BF9FEDFF1225E6DD003A8B71 /* TargetAttributesSema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEDFE1225E6DD003A8B71 /* TargetAttributesSema.cpp */; };
+ BF9FEE021225E73F003A8B71 /* ExprClassification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE011225E73F003A8B71 /* ExprClassification.cpp */; };
+ BF9FEE041225E759003A8B71 /* ItaniumCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE031225E759003A8B71 /* ItaniumCXXABI.cpp */; };
+ BF9FEE061225E770003A8B71 /* MicrosoftCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE051225E770003A8B71 /* MicrosoftCXXABI.cpp */; };
+ BF9FEE2C1225E7EA003A8B71 /* BackendUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE2B1225E7EA003A8B71 /* BackendUtil.cpp */; };
+ BF9FEE311225E86C003A8B71 /* CodeGenAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE301225E86C003A8B71 /* CodeGenAction.cpp */; };
+ BF9FEE331225E898003A8B71 /* ItaniumCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE321225E898003A8B71 /* ItaniumCXXABI.cpp */; };
+ BF9FEE351225E8B1003A8B71 /* MicrosoftCXXABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE341225E8B1003A8B71 /* MicrosoftCXXABI.cpp */; };
+ BF9FEE381225E925003A8B71 /* BoostConAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE371225E925003A8B71 /* BoostConAction.cpp */; };
+ BF9FEE521226FE9F003A8B71 /* ParseAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEE511226FE9F003A8B71 /* ParseAST.cpp */; };
+ BF9FEEF2122D8068003A8B71 /* PreprocessingRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BF9FEEF1122D8068003A8B71 /* PreprocessingRecord.cpp */; };
BFE2F6AB11DA955A0007EDC0 /* DeltaTree.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F67D11DA95590007EDC0 /* DeltaTree.d */; };
BFE2F6AC11DA955A0007EDC0 /* DeltaTree.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F67E11DA955A0007EDC0 /* DeltaTree.o */; };
BFE2F6AD11DA955A0007EDC0 /* FixItRewriter.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F67F11DA955A0007EDC0 /* FixItRewriter.d */; };
@@ -179,15 +191,8 @@
BFE2F6B311DA955A0007EDC0 /* HTMLRewrite.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F68511DA955A0007EDC0 /* HTMLRewrite.d */; };
BFE2F6B411DA955A0007EDC0 /* HTMLRewrite.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F68611DA955A0007EDC0 /* HTMLRewrite.o */; };
BFE2F6B511DA955A0007EDC0 /* RewriteMacros.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F68711DA955A0007EDC0 /* RewriteMacros.d */; };
- BFE2F6B611DA955A0007EDC0 /* RewriteMacros.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F68811DA955A0007EDC0 /* RewriteMacros.o */; };
BFE2F6B711DA955A0007EDC0 /* RewriteObjC.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F68911DA955A0007EDC0 /* RewriteObjC.d */; };
- BFE2F6B811DA955A0007EDC0 /* RewriteObjC.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F68A11DA955A0007EDC0 /* RewriteObjC.o */; };
BFE2F6B911DA955A0007EDC0 /* Rewriter.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F68B11DA955A0007EDC0 /* Rewriter.d */; };
- BFE2F6BA11DA955A0007EDC0 /* Rewriter.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F68C11DA955A0007EDC0 /* Rewriter.o */; };
- BFE2F6BB11DA955A0007EDC0 /* RewriteRope.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F68D11DA955A0007EDC0 /* RewriteRope.d */; };
- BFE2F6BC11DA955A0007EDC0 /* RewriteRope.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F68E11DA955A0007EDC0 /* RewriteRope.o */; };
- BFE2F6BD11DA955A0007EDC0 /* RewriteTest.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F68F11DA955A0007EDC0 /* RewriteTest.d */; };
- BFE2F6BE11DA955A0007EDC0 /* RewriteTest.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F69011DA955A0007EDC0 /* RewriteTest.o */; };
BFE2F6BF11DA955A0007EDC0 /* TokenRewriter.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69111DA955A0007EDC0 /* TokenRewriter.d */; };
BFE2F6C011DA955A0007EDC0 /* TokenRewriter.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F69211DA955A0007EDC0 /* TokenRewriter.o */; };
BFE2F6C111DA955A0007EDC0 /* DeltaTree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69311DA955A0007EDC0 /* DeltaTree.cpp */; };
@@ -201,9 +206,6 @@
BFE2F6C911DA955A0007EDC0 /* HTMLRewrite.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69D11DA955A0007EDC0 /* HTMLRewrite.d */; };
BFE2F6CA11DA955A0007EDC0 /* HTMLRewrite.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F69E11DA955A0007EDC0 /* HTMLRewrite.o */; };
BFE2F6CB11DA955A0007EDC0 /* Rewriter.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F69F11DA955A0007EDC0 /* Rewriter.d */; };
- BFE2F6CC11DA955A0007EDC0 /* Rewriter.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F6A011DA955A0007EDC0 /* Rewriter.o */; };
- BFE2F6CD11DA955A0007EDC0 /* RewriteRope.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A111DA955A0007EDC0 /* RewriteRope.d */; };
- BFE2F6CE11DA955A0007EDC0 /* RewriteRope.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F6A211DA955A0007EDC0 /* RewriteRope.o */; };
BFE2F6CF11DA955A0007EDC0 /* TokenRewriter.d in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A311DA955A0007EDC0 /* TokenRewriter.d */; };
BFE2F6D011DA955A0007EDC0 /* TokenRewriter.o in Frameworks */ = {isa = PBXBuildFile; fileRef = BFE2F6A411DA955A0007EDC0 /* TokenRewriter.o */; };
BFE2F6D111DA955A0007EDC0 /* RewriteMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BFE2F6A511DA955A0007EDC0 /* RewriteMacros.cpp */; };
@@ -215,12 +217,8 @@
DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE01DA480B12ADA300AC22CE /* PPCallbacks.h */; };
DE06756C0C051CFE00EBBFD8 /* ParseExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */; };
DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06B73D0A8307640050E87E /* LangOptions.h */; };
- DE06BECB0A854E4B0050E87E /* Scope.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06BECA0A854E4B0050E87E /* Scope.h */; };
DE06D4310A8BB52D0050E87E /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06D42F0A8BB52D0050E87E /* Parser.cpp */; };
- DE06E8140A8FF9330050E87E /* Action.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06E8130A8FF9330050E87E /* Action.h */; };
DE0FCA630A95859D00248FD5 /* Expr.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE0FCA620A95859D00248FD5 /* Expr.h */; };
- DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE17336D0B068DC20080B521 /* DeclSpec.cpp */; };
- DE1733700B068DC60080B521 /* DeclSpec.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE17336F0B068DC60080B521 /* DeclSpec.h */; };
DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; };
DE224FF80C7AA98800D370A5 /* CGExprComplex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */; };
DE2252700C7E82D000D370A5 /* CGExprScalar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE22526F0C7E82D000D370A5 /* CGExprScalar.cpp */; };
@@ -231,13 +229,11 @@
DE3450D70AEB543100DBC861 /* DirectoryLookup.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3450D60AEB543100DBC861 /* DirectoryLookup.h */; };
DE3452810AEF1B1800DBC861 /* Stmt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3452800AEF1B1800DBC861 /* Stmt.h */; };
DE345C1A0AFC658B00DBC861 /* StmtVisitor.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE345C190AFC658B00DBC861 /* StmtVisitor.h */; };
- DE345F220AFD347900DBC861 /* StmtNodes.def in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE345F210AFD347900DBC861 /* StmtNodes.def */; };
DE3460000AFDCC1900DBC861 /* ParseObjc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE345FFF0AFDCC1900DBC861 /* ParseObjc.cpp */; };
DE3460050AFDCC6500DBC861 /* ParseInit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3460040AFDCC6500DBC861 /* ParseInit.cpp */; };
DE34600B0AFDCCBF00DBC861 /* ParseStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34600A0AFDCCBF00DBC861 /* ParseStmt.cpp */; };
DE34600F0AFDCCCE00DBC861 /* ParseDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE34600E0AFDCCCE00DBC861 /* ParseDecl.cpp */; };
DE3460130AFDCCDA00DBC861 /* ParseExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */; };
- DE3461270AFE68BE00DBC861 /* MinimalAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */; };
DE3464220B03040900DBC861 /* Type.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE3464210B03040900DBC861 /* Type.h */; };
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE37252D0FE481AD00CF2CC2 /* Builtins.cpp */; };
DE38CD500D794D0100A273B6 /* CGObjCGNU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */; };
@@ -261,10 +257,7 @@
DE67E70F0C020ECF00F66BC5 /* SemaExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */; };
DE67E7110C020ED400F66BC5 /* SemaExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */; };
DE67E7130C020ED900F66BC5 /* SemaDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */; };
- DE67E7150C020EDF00F66BC5 /* Sema.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE67E7140C020EDF00F66BC5 /* Sema.h */; };
DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7160C020EE400F66BC5 /* Sema.cpp */; };
- DE67E71A0C020F4F00F66BC5 /* ParseAST.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7190C020F4F00F66BC5 /* ParseAST.cpp */; };
- DE67E7280C02109800F66BC5 /* ParseAST.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE67E7270C02109800F66BC5 /* ParseAST.h */; };
DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE6951C60C4D1F5D00A5826B /* RecordLayout.h */; };
DE6954640C5121BD00A5826B /* Token.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE6954630C5121BD00A5826B /* Token.h */; };
DE704B260D0FBEBE009C7762 /* SemaDeclObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE704B250D0FBEBE009C7762 /* SemaDeclObjC.cpp */; };
@@ -290,10 +283,6 @@
DECAB0D00DB3C84200E13CCB /* RewriteRope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECAB0CF0DB3C84200E13CCB /* RewriteRope.cpp */; };
DECB6D650F9AE26600F5FBC7 /* JumpDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB6D640F9AE26600F5FBC7 /* JumpDiagnostics.cpp */; };
DECB6F070F9D93A800F5FBC7 /* InitPreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */; };
- DECB77130FA5752300F5FBC7 /* PCHReaderStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */; };
- DECB77790FA579B000F5FBC7 /* PCHReaderDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */; };
- DECB77F70FA5850200F5FBC7 /* PCHWriterDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB77F60FA5850200F5FBC7 /* PCHWriterDecl.cpp */; };
- DECB78170FA5882F00F5FBC7 /* PCHWriterStmt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DECB78160FA5882F00F5FBC7 /* PCHWriterStmt.cpp */; };
DED626C90AE0C065001E80A4 /* TargetInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED626C80AE0C065001E80A4 /* TargetInfo.cpp */; };
DED7D7410A524295003AD0FB /* Diagnostic.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7310A524295003AD0FB /* Diagnostic.h */; };
DED7D7430A524295003AD0FB /* FileManager.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7330A524295003AD0FB /* FileManager.h */; };
@@ -336,9 +325,6 @@
DEEBBD440C19C5D200A9FE82 /* TODO.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEEBBD430C19C5D200A9FE82 /* TODO.txt */; };
DEEBC3BA0C2363B800A9FE82 /* CodeGenTypes.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */; };
DEEBC3BC0C2363BC00A9FE82 /* CodeGenTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */; };
- DEF165710F8FB34D0098507F /* PCHWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF165700F8FB34D0098507F /* PCHWriter.cpp */; };
- DEF165750F8FB3510098507F /* PCHReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF165740F8FB3510098507F /* PCHReader.cpp */; };
- DEF168400F9548DC0098507F /* FixItRewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF1683F0F9548DC0098507F /* FixItRewriter.cpp */; };
DEF2E95F0C5FBD74000C4259 /* InternalsManual.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEF2E95E0C5FBD74000C4259 /* InternalsManual.html */; };
DEF2EFF30C6CDD74000C4259 /* CGExprAgg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */; };
DEF2F0100C6CFED5000C4259 /* SemaChecking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEF2F00F0C6CFED5000C4259 /* SemaChecking.cpp */; };
@@ -371,8 +357,6 @@
DEAEED4B0A5AF89A0045101B /* NOTES.txt in CopyFiles */,
DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */,
DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */,
- DE06BECB0A854E4B0050E87E /* Scope.h in CopyFiles */,
- DE06E8140A8FF9330050E87E /* Action.h in CopyFiles */,
DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */,
DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */,
DE0FCA630A95859D00248FD5 /* Expr.h in CopyFiles */,
@@ -381,20 +365,15 @@
DE3450D70AEB543100DBC861 /* DirectoryLookup.h in CopyFiles */,
DE3452810AEF1B1800DBC861 /* Stmt.h in CopyFiles */,
DE345C1A0AFC658B00DBC861 /* StmtVisitor.h in CopyFiles */,
- DE345F220AFD347900DBC861 /* StmtNodes.def in CopyFiles */,
DE3464220B03040900DBC861 /* Type.h in CopyFiles */,
DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */,
- DE1733700B068DC60080B521 /* DeclSpec.h in CopyFiles */,
DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */,
1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */,
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */,
- DE67E7150C020EDF00F66BC5 /* Sema.h in CopyFiles */,
- DE67E7280C02109800F66BC5 /* ParseAST.h in CopyFiles */,
DE928B200C0565B000231DA4 /* ModuleBuilder.h in CopyFiles */,
DE928B7D0C0A615100231DA4 /* CodeGenModule.h in CopyFiles */,
DE928B810C0A615B00231DA4 /* CodeGenFunction.h in CopyFiles */,
DEEBBD440C19C5D200A9FE82 /* TODO.txt in CopyFiles */,
- 84D9A88C0C1A581300AC7ABC /* AttributeList.h in CopyFiles */,
DEEBC3BA0C2363B800A9FE82 /* CodeGenTypes.h in CopyFiles */,
DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */,
DE6954640C5121BD00A5826B /* Token.h in CopyFiles */,
@@ -422,15 +401,11 @@
1A2193CB0F45EEB700C0713D /* ABIInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ABIInfo.h; path = lib/CodeGen/ABIInfo.h; sourceTree = "<group>"; tabWidth = 2; };
1A2193CC0F45EEB700C0713D /* Mangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Mangle.cpp; path = lib/CodeGen/Mangle.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A2193CD0F45EEB700C0713D /* Mangle.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Mangle.h; path = lib/CodeGen/Mangle.h; sourceTree = "<group>"; tabWidth = 2; };
- 1A2A54A40FD1DD1C00F4CE45 /* AnalysisConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnalysisConsumer.cpp; path = lib/Frontend/AnalysisConsumer.cpp; sourceTree = "<group>"; };
1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ASTConsumers.cpp; path = lib/Frontend/ASTConsumers.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CacheTokens.cpp; path = lib/Frontend/CacheTokens.cpp; sourceTree = "<group>"; };
1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DependencyFile.cpp; path = lib/Frontend/DependencyFile.cpp; sourceTree = "<group>"; };
1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DiagChecker.cpp; path = lib/Frontend/DiagChecker.cpp; sourceTree = "<group>"; };
1A2A54AA0FD1DD1C00F4CE45 /* DocumentXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DocumentXML.cpp; path = lib/Frontend/DocumentXML.cpp; sourceTree = "<group>"; };
- 1A2A54AB0FD1DD1C00F4CE45 /* GeneratePCH.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GeneratePCH.cpp; path = lib/Frontend/GeneratePCH.cpp; sourceTree = "<group>"; };
- 1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLPrint.cpp; path = lib/Frontend/HTMLPrint.cpp; sourceTree = "<group>"; };
- 1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintParserCallbacks.cpp; path = lib/Frontend/PrintParserCallbacks.cpp; sourceTree = "<group>"; };
1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintPreprocessedOutput.cpp; path = lib/Frontend/PrintPreprocessedOutput.cpp; sourceTree = "<group>"; };
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>"; };
@@ -455,7 +430,6 @@
1A649E1E0F9599DA005B965E /* CGCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGCXX.h; path = lib/CodeGen/CGCXX.h; sourceTree = "<group>"; tabWidth = 2; };
1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CodeCompleteConsumer.cpp; path = lib/Sema/CodeCompleteConsumer.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaCodeComplete.cpp; path = lib/Sema/SemaCodeComplete.cpp; sourceTree = "<group>"; tabWidth = 2; };
- 1A6B6CD310693FC900BB4A8F /* SemaTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = SemaTemplate.h; path = lib/Sema/SemaTemplate.h; sourceTree = "<group>"; tabWidth = 2; };
1A6B6E991069833600BB4A8F /* CGExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprCXX.cpp; path = lib/CodeGen/CGExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6C01F6108128710072DEE4 /* CGRTTI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRTTI.cpp; path = lib/CodeGen/CGRTTI.cpp; sourceTree = "<group>"; tabWidth = 2; };
1A6FE7080FD6F85800E00CA9 /* CGTemporaries.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGTemporaries.cpp; path = lib/CodeGen/CGTemporaries.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -532,15 +506,11 @@
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; };
1AF1B50E109A4FB800AFAFAC /* CGException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGException.cpp; path = lib/CodeGen/CGException.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AFDD8701161085D00AE030A /* ASTMerge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTMerge.cpp; path = lib/Frontend/ASTMerge.cpp; sourceTree = "<group>"; };
- 1AFDD8711161085D00AE030A /* CodeGenAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenAction.cpp; path = lib/Frontend/CodeGenAction.cpp; sourceTree = "<group>"; };
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckObjCInstMethSignature.cpp; path = lib/Analysis/CheckObjCInstMethSignature.cpp; sourceTree = "<group>"; };
- 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLDiagnostics.cpp; path = lib/Frontend/HTMLDiagnostics.cpp; sourceTree = "<group>"; };
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitHeaderSearch.cpp; path = lib/Frontend/InitHeaderSearch.cpp; sourceTree = "<group>"; };
- 352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlistDiagnostics.cpp; path = lib/Frontend/PlistDiagnostics.cpp; sourceTree = "<group>"; };
352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticBuffer.cpp; path = lib/Frontend/TextDiagnosticBuffer.cpp; sourceTree = "<group>"; };
352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticPrinter.cpp; path = lib/Frontend/TextDiagnosticPrinter.cpp; sourceTree = "<group>"; };
- 3527124F0DAFE54700C76352 /* IdentifierResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = IdentifierResolver.h; path = lib/Sema/IdentifierResolver.h; sourceTree = "<group>"; tabWidth = 2; };
352712500DAFE54700C76352 /* IdentifierResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = IdentifierResolver.cpp; path = lib/Sema/IdentifierResolver.cpp; sourceTree = "<group>"; tabWidth = 2; };
352C19DC0CA321C80045DB98 /* CFGRecStmtDeclVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFGRecStmtDeclVisitor.h; path = clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h; sourceTree = "<group>"; };
352C19DD0CA321C80045DB98 /* CFGRecStmtVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFGRecStmtVisitor.h; path = clang/Analysis/Visitors/CFGRecStmtVisitor.h; sourceTree = "<group>"; };
@@ -561,7 +531,6 @@
355106880E9A851B006A4E44 /* MemRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MemRegion.h; path = clang/Analysis/PathSensitive/MemRegion.h; sourceTree = "<group>"; };
3551068A0E9A8546006A4E44 /* ParsePragma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParsePragma.cpp; path = lib/Parse/ParsePragma.cpp; sourceTree = "<group>"; tabWidth = 2; };
3551068B0E9A8546006A4E44 /* ParseTentative.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseTentative.cpp; path = lib/Parse/ParseTentative.cpp; sourceTree = "<group>"; tabWidth = 2; };
- 3551068E0E9A855F006A4E44 /* AccessSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AccessSpecifier.h; path = clang/Parse/AccessSpecifier.h; sourceTree = "<group>"; tabWidth = 2; };
3551068F0E9A857C006A4E44 /* ParsePragma.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ParsePragma.h; path = lib/Parse/ParsePragma.h; sourceTree = "<group>"; tabWidth = 2; };
3552E7540E520D80003A8CA5 /* PPCaching.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCaching.cpp; sourceTree = "<group>"; };
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjCMac.cpp; path = lib/CodeGen/CGObjCMac.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -570,9 +539,7 @@
35544B860F5C7FD700D92AA9 /* SimpleConstraintManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SimpleConstraintManager.cpp; path = lib/Analysis/SimpleConstraintManager.cpp; sourceTree = "<group>"; };
35544B870F5C7FD700D92AA9 /* SimpleConstraintManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SimpleConstraintManager.h; path = lib/Analysis/SimpleConstraintManager.h; sourceTree = "<group>"; };
35544B8B0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiate.cpp; path = lib/Sema/SemaTemplateInstantiate.cpp; sourceTree = "<group>"; tabWidth = 2; };
- 35585DBD0EAFBC4500D0A97A /* CXXFieldCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CXXFieldCollector.h; path = lib/Sema/CXXFieldCollector.h; sourceTree = "<group>"; tabWidth = 2; };
35585DBE0EAFBC4500D0A97A /* SemaOverload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaOverload.cpp; path = lib/Sema/SemaOverload.cpp; sourceTree = "<group>"; tabWidth = 2; };
- 35585DBF0EAFBC4500D0A97A /* SemaOverload.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = SemaOverload.h; path = lib/Sema/SemaOverload.h; sourceTree = "<group>"; tabWidth = 2; };
3558F76C0E267C8300A5B0DF /* BasicStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BasicStore.cpp; path = lib/Analysis/BasicStore.cpp; sourceTree = "<group>"; };
3558F76F0E267C9A00A5B0DF /* Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Store.h; path = clang/Analysis/PathSensitive/Store.h; sourceTree = "<group>"; };
355CF6820C90A8B600A08AA3 /* LocalCheckers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LocalCheckers.h; path = clang/Analysis/LocalCheckers.h; sourceTree = "<group>"; };
@@ -626,11 +593,20 @@
35F8D0D50D9B82CD00D91C5E /* BasicObjCFoundationChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BasicObjCFoundationChecks.cpp; path = lib/Analysis/BasicObjCFoundationChecks.cpp; sourceTree = "<group>"; };
35F9B1550D1C6B2E00DDFDAE /* LiveVariables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LiveVariables.h; path = clang/Analysis/Analyses/LiveVariables.h; sourceTree = "<group>"; };
35F9B1560D1C6B2E00DDFDAE /* UninitializedValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UninitializedValues.h; path = clang/Analysis/Analyses/UninitializedValues.h; sourceTree = "<group>"; };
+ 574F4C25121B4EF000AEAC20 /* ASTWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTWriter.h; path = clang/Serialization/ASTWriter.h; sourceTree = "<group>"; };
+ 57AA924D121C8B9400B4AA6C /* ASTReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTReader.cpp; sourceTree = "<group>"; };
+ 57AA924E121C8B9400B4AA6C /* ASTReaderDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTReaderDecl.cpp; sourceTree = "<group>"; };
+ 57AA924F121C8B9400B4AA6C /* ASTReaderStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTReaderStmt.cpp; sourceTree = "<group>"; };
+ 57E15B21121C8D2B0051C2CC /* ASTDeserializationListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTDeserializationListener.h; path = clang/Serialization/ASTDeserializationListener.h; sourceTree = "<group>"; };
+ 57E15B22121C8D2B0051C2CC /* ASTReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTReader.h; path = clang/Serialization/ASTReader.h; sourceTree = "<group>"; };
+ 57EB5661121B034300ECA335 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
+ 57EB5662121B034300ECA335 /* GeneratePCH.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeneratePCH.cpp; sourceTree = "<group>"; };
+ 57EB5663121B034300ECA335 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
+ 57F6660F121B4DE600DCE3B7 /* ASTWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTWriter.cpp; sourceTree = "<group>"; };
+ 57F66610121B4DE600DCE3B7 /* ASTWriterDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTWriterDecl.cpp; sourceTree = "<group>"; };
+ 57F66611121B4DE600DCE3B7 /* ASTWriterStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASTWriterStmt.cpp; sourceTree = "<group>"; };
72D16C1E0D9975C400E6DA4A /* HTMLRewrite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLRewrite.cpp; path = lib/Rewrite/HTMLRewrite.cpp; sourceTree = "<group>"; };
- 7F270AFE107A90010031B377 /* CodeCompleteConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeCompleteConsumer.h; path = clang/Sema/CodeCompleteConsumer.h; sourceTree = "<group>"; };
84AF36A00CB17A3B00C820A5 /* DeclObjC.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = DeclObjC.h; path = clang/AST/DeclObjC.h; sourceTree = "<group>"; tabWidth = 2; };
- 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = lib/Parse/AttributeList.cpp; sourceTree = "<group>"; tabWidth = 2; };
- 84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; tabWidth = 2; };
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
9012911510470FCE0083456D /* Index.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Index.h; path = "clang-c/Index.h"; sourceTree = "<group>"; };
9012911C1048068D0083456D /* ASTUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTUnit.cpp; path = lib/Frontend/ASTUnit.cpp; sourceTree = "<group>"; };
@@ -642,8 +618,6 @@
9047537D1096376F00CBDDDD /* TypeLocNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text; name = TypeLocNodes.def; path = clang/AST/TypeLocNodes.def; sourceTree = "<group>"; tabWidth = 2; };
9047537E1096376F00CBDDDD /* TypeLocVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TypeLocVisitor.h; path = clang/AST/TypeLocVisitor.h; sourceTree = "<group>"; tabWidth = 2; };
9047537F1096376F00CBDDDD /* TypeVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = TypeVisitor.h; path = clang/AST/TypeVisitor.h; sourceTree = "<group>"; tabWidth = 2; };
- 9063F2210F9E8BDF002F7251 /* ExternalSemaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExternalSemaSource.h; path = clang/Sema/ExternalSemaSource.h; sourceTree = "<group>"; };
- 9063F2220F9E8BDF002F7251 /* SemaConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaConsumer.h; path = clang/Sema/SemaConsumer.h; sourceTree = "<group>"; };
9063F2280F9E911F002F7251 /* OnDiskHashTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnDiskHashTable.h; sourceTree = "<group>"; };
9063F2290F9E911F002F7251 /* SourceManagerInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceManagerInternals.h; sourceTree = "<group>"; };
9063F22A0F9E911F002F7251 /* TemplateKinds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemplateKinds.h; sourceTree = "<group>"; };
@@ -678,10 +652,8 @@
90FD6D76103C3D49005F5B73 /* IndexProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IndexProvider.cpp; path = lib/Index/IndexProvider.cpp; sourceTree = "<group>"; };
90FD6D77103C3D49005F5B73 /* Program.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Program.cpp; path = lib/Index/Program.cpp; sourceTree = "<group>"; };
90FD6D78103C3D49005F5B73 /* ProgramImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProgramImpl.h; path = lib/Index/ProgramImpl.h; sourceTree = "<group>"; };
- 90FD6D79103C3D49005F5B73 /* ResolveLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ResolveLocation.cpp; path = lib/Index/ResolveLocation.cpp; sourceTree = "<group>"; };
90FD6D7A103C3D49005F5B73 /* SelectorMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SelectorMap.cpp; path = lib/Index/SelectorMap.cpp; sourceTree = "<group>"; };
90FD6D86103C3D80005F5B73 /* Analyses.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Analyses.def; path = clang/Frontend/Analyses.def; sourceTree = "<group>"; };
- 90FD6D87103C3D80005F5B73 /* AnalysisConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisConsumer.h; path = clang/Frontend/AnalysisConsumer.h; sourceTree = "<group>"; };
90FD6D88103C3D80005F5B73 /* ASTConsumers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTConsumers.h; path = clang/Frontend/ASTConsumers.h; sourceTree = "<group>"; };
90FD6D89103C3D80005F5B73 /* ASTUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTUnit.h; path = clang/Frontend/ASTUnit.h; sourceTree = "<group>"; };
90FD6D8A103C3D80005F5B73 /* CommandLineSourceLoc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandLineSourceLoc.h; path = clang/Frontend/CommandLineSourceLoc.h; sourceTree = "<group>"; };
@@ -693,16 +665,104 @@
90FD6D90103C3D80005F5B73 /* TypeXML.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TypeXML.def; path = clang/Frontend/TypeXML.def; sourceTree = "<group>"; };
90FD6D91103C3D80005F5B73 /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = clang/Frontend/Utils.h; sourceTree = "<group>"; };
90FD6DB5103D977E005F5B73 /* index-test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "index-test.cpp"; path = "tools/index-test/index-test.cpp"; sourceTree = "<group>"; };
+ BD59A948121496B9003A5A02 /* AnalysisBasedWarnings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisBasedWarnings.h; path = clang/Sema/AnalysisBasedWarnings.h; sourceTree = "<group>"; };
+ BD59A949121496B9003A5A02 /* CodeCompleteConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeCompleteConsumer.h; path = clang/Sema/CodeCompleteConsumer.h; sourceTree = "<group>"; };
+ BD59A94A121496B9003A5A02 /* CXXFieldCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CXXFieldCollector.h; path = clang/Sema/CXXFieldCollector.h; sourceTree = "<group>"; };
+ BD59A94B121496B9003A5A02 /* ExternalSemaSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExternalSemaSource.h; path = clang/Sema/ExternalSemaSource.h; sourceTree = "<group>"; };
+ BD59A94C121496B9003A5A02 /* IdentifierResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IdentifierResolver.h; path = clang/Sema/IdentifierResolver.h; sourceTree = "<group>"; };
+ BD59A94D121496B9003A5A02 /* Initialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Initialization.h; path = clang/Sema/Initialization.h; sourceTree = "<group>"; };
+ BD59A94E121496B9003A5A02 /* Lookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Lookup.h; path = clang/Sema/Lookup.h; sourceTree = "<group>"; };
+ BD59A94F121496B9003A5A02 /* Overload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Overload.h; path = clang/Sema/Overload.h; sourceTree = "<group>"; };
+ BD59A951121496B9003A5A02 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = clang/Sema/Sema.h; sourceTree = "<group>"; };
+ BD59A952121496B9003A5A02 /* SemaConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaConsumer.h; path = clang/Sema/SemaConsumer.h; sourceTree = "<group>"; };
+ BD59A953121496B9003A5A02 /* SemaDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaDiagnostic.h; path = clang/Sema/SemaDiagnostic.h; sourceTree = "<group>"; };
+ BD59A954121496B9003A5A02 /* Template.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Template.h; path = clang/Sema/Template.h; sourceTree = "<group>"; };
BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateDeduction.cpp; path = lib/Sema/SemaTemplateDeduction.cpp; sourceTree = "<group>"; tabWidth = 2; };
- BF89C3E0115957FF001C2D68 /* AnalysisBasedWarnings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisBasedWarnings.h; path = lib/Sema/AnalysisBasedWarnings.h; sourceTree = "<group>"; };
BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnalysisBasedWarnings.cpp; path = lib/Sema/AnalysisBasedWarnings.cpp; sourceTree = "<group>"; };
- BF89C3E311595835001C2D68 /* Lookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Lookup.h; path = lib/Sema/Lookup.h; sourceTree = "<group>"; };
- BF89C3E411595855001C2D68 /* SemaInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaInit.h; path = lib/Sema/SemaInit.h; sourceTree = "<group>"; };
BF89C3E5115958A1001C2D68 /* TargetAttributesSema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TargetAttributesSema.h; path = lib/Sema/TargetAttributesSema.h; sourceTree = "<group>"; };
BF89C3E81159594A001C2D68 /* SemaObjCProperty.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaObjCProperty.cpp; path = lib/Sema/SemaObjCProperty.cpp; sourceTree = "<group>"; };
BF89C3F811595A01001C2D68 /* SemaType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaType.cpp; path = lib/Sema/SemaType.cpp; sourceTree = "<group>"; };
BF89C3FA11595A37001C2D68 /* SemaCodeComplete.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaCodeComplete.cpp; path = lib/Sema/SemaCodeComplete.cpp; sourceTree = "<group>"; };
BF89C3FC11595A5D001C2D68 /* SemaExceptionSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExceptionSpec.cpp; path = lib/Sema/SemaExceptionSpec.cpp; sourceTree = "<group>"; };
+ BF9FED6E1225DF55003A8B71 /* TemplateDeduction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemplateDeduction.h; path = clang/Sema/TemplateDeduction.h; sourceTree = "<group>"; };
+ BF9FED6F1225DF7F003A8B71 /* Action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Sema/Action.h; sourceTree = "<group>"; };
+ BF9FED701225DFA1003A8B71 /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Sema/AttributeList.h; sourceTree = "<group>"; };
+ BF9FED711225DFD9003A8B71 /* DeclSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeclSpec.h; path = clang/Sema/DeclSpec.h; sourceTree = "<group>"; };
+ BF9FED721225DFD9003A8B71 /* Designator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Designator.h; path = clang/Sema/Designator.h; sourceTree = "<group>"; };
+ BF9FED731225E005003A8B71 /* Ownership.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Ownership.h; path = clang/Sema/Ownership.h; sourceTree = "<group>"; };
+ BF9FED741225E005003A8B71 /* ParsedTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParsedTemplate.h; path = clang/Sema/ParsedTemplate.h; sourceTree = "<group>"; };
+ BF9FED751225E005003A8B71 /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Sema/Scope.h; sourceTree = "<group>"; };
+ BF9FED761225E005003A8B71 /* ScopeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScopeInfo.h; path = clang/Sema/ScopeInfo.h; sourceTree = "<group>"; };
+ BF9FED771225E032003A8B71 /* ObjCMethodList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCMethodList.h; path = clang/Sema/ObjCMethodList.h; sourceTree = "<group>"; };
+ BF9FED781225E041003A8B71 /* SemaInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaInternal.h; path = clang/Sema/SemaInternal.h; sourceTree = "<group>"; };
+ BF9FEDB21225E1D2003A8B71 /* CodeCompletionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeCompletionHandler.h; sourceTree = "<group>"; };
+ BF9FEDB31225E1E1003A8B71 /* ExternalPreprocessorSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExternalPreprocessorSource.h; sourceTree = "<group>"; };
+ BF9FEDB41225E1F3003A8B71 /* PreprocessingRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreprocessingRecord.h; sourceTree = "<group>"; };
+ BF9FEDB51225E213003A8B71 /* ParseAST.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ParseAST.h; path = clang/Parse/ParseAST.h; sourceTree = "<group>"; };
+ BF9FEDB61225E252003A8B71 /* OperationKinds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OperationKinds.h; path = clang/AST/OperationKinds.h; sourceTree = "<group>"; };
+ BF9FEDB71225E26A003A8B71 /* RecursiveASTVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecursiveASTVisitor.h; path = clang/AST/RecursiveASTVisitor.h; sourceTree = "<group>"; };
+ BF9FEDB81225E2DE003A8B71 /* BackendUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BackendUtil.h; path = clang/CodeGen/BackendUtil.h; sourceTree = "<group>"; };
+ BF9FEDB91225E2DE003A8B71 /* CodeGenAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeGenAction.h; path = clang/CodeGen/CodeGenAction.h; sourceTree = "<group>"; };
+ BF9FEDBA1225E30E003A8B71 /* ASTBitCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTBitCodes.h; path = clang/Serialization/ASTBitCodes.h; sourceTree = "<group>"; };
+ BF9FEDBB1225E34B003A8B71 /* FixItRewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FixItRewriter.h; path = clang/Rewrite/FixItRewriter.h; sourceTree = "<group>"; };
+ BF9FEDBC1225E34B003A8B71 /* FrontendActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendActions.h; path = clang/Rewrite/FrontendActions.h; sourceTree = "<group>"; };
+ BF9FEDBD1225E35F003A8B71 /* Rewriters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Rewriters.h; path = clang/Rewrite/Rewriters.h; sourceTree = "<group>"; };
+ BF9FEDBE1225E373003A8B71 /* ASTConsumers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTConsumers.h; path = clang/Rewrite/ASTConsumers.h; sourceTree = "<group>"; };
+ BF9FEDBF1225E392003A8B71 /* AnalyzerOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalyzerOptions.h; path = clang/Frontend/AnalyzerOptions.h; sourceTree = "<group>"; };
+ BF9FEDC01225E3AB003A8B71 /* ChainedDiagnosticClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChainedDiagnosticClient.h; path = clang/Frontend/ChainedDiagnosticClient.h; sourceTree = "<group>"; };
+ BF9FEDC11225E3AB003A8B71 /* CodeGenOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CodeGenOptions.h; path = clang/Frontend/CodeGenOptions.h; sourceTree = "<group>"; };
+ BF9FEDC21225E3C2003A8B71 /* CompilerInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompilerInstance.h; path = clang/Frontend/CompilerInstance.h; sourceTree = "<group>"; };
+ BF9FEDC31225E3C2003A8B71 /* CompilerInvocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompilerInvocation.h; path = clang/Frontend/CompilerInvocation.h; sourceTree = "<group>"; };
+ BF9FEDC41225E3DA003A8B71 /* DependencyOutputOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DependencyOutputOptions.h; path = clang/Frontend/DependencyOutputOptions.h; sourceTree = "<group>"; };
+ BF9FEDC51225E3DA003A8B71 /* DiagnosticOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DiagnosticOptions.h; path = clang/Frontend/DiagnosticOptions.h; sourceTree = "<group>"; };
+ BF9FEDC61225E3F6003A8B71 /* FrontendAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendAction.h; path = clang/Frontend/FrontendAction.h; sourceTree = "<group>"; };
+ BF9FEDC71225E3F6003A8B71 /* FrontendActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendActions.h; path = clang/Frontend/FrontendActions.h; sourceTree = "<group>"; };
+ BF9FEDC81225E40A003A8B71 /* FrontendOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendOptions.h; path = clang/Frontend/FrontendOptions.h; sourceTree = "<group>"; };
+ BF9FEDC91225E40A003A8B71 /* FrontendPluginRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendPluginRegistry.h; path = clang/Frontend/FrontendPluginRegistry.h; sourceTree = "<group>"; };
+ BF9FEDCA1225E40A003A8B71 /* HeaderSearchOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HeaderSearchOptions.h; path = clang/Frontend/HeaderSearchOptions.h; sourceTree = "<group>"; };
+ BF9FEDCB1225E40A003A8B71 /* LangStandard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LangStandard.h; path = clang/Frontend/LangStandard.h; sourceTree = "<group>"; };
+ BF9FEDCC1225E41D003A8B71 /* PreprocessorOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreprocessorOptions.h; path = clang/Frontend/PreprocessorOptions.h; sourceTree = "<group>"; };
+ BF9FEDCD1225E41D003A8B71 /* PreprocessorOutputOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreprocessorOutputOptions.h; path = clang/Frontend/PreprocessorOutputOptions.h; sourceTree = "<group>"; };
+ BF9FEDCE1225E42C003A8B71 /* VerifyDiagnosticsClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VerifyDiagnosticsClient.h; path = clang/Frontend/VerifyDiagnosticsClient.h; sourceTree = "<group>"; };
+ BF9FEDCF1225E443003A8B71 /* LangStandards.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LangStandards.def; path = clang/Frontend/LangStandards.def; sourceTree = "<group>"; };
+ BF9FEDE71225E488003A8B71 /* CC1AsOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CC1AsOptions.h; path = clang/Driver/CC1AsOptions.h; sourceTree = "<group>"; };
+ BF9FEDE81225E49D003A8B71 /* CC1Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CC1Options.h; path = clang/Driver/CC1Options.h; sourceTree = "<group>"; };
+ BF9FEDE91225E4BD003A8B71 /* OptSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptSpecifier.h; path = clang/Driver/OptSpecifier.h; sourceTree = "<group>"; };
+ BF9FEDEA1225E4BD003A8B71 /* OptTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptTable.h; path = clang/Driver/OptTable.h; sourceTree = "<group>"; };
+ BF9FEDEB1225E4F2003A8B71 /* AttrKinds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttrKinds.h; sourceTree = "<group>"; };
+ BF9FEDEC1225E514003A8B71 /* Version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Version.h; sourceTree = "<group>"; };
+ BF9FEDED1225E52F003A8B71 /* arm_neon.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = arm_neon.td; sourceTree = "<group>"; };
+ BF9FEDEE1225E52F003A8B71 /* Attr.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Attr.td; sourceTree = "<group>"; };
+ BF9FEDEF1225E55C003A8B71 /* BuiltinsARM.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BuiltinsARM.def; sourceTree = "<group>"; };
+ BF9FEDF01225E574003A8B71 /* Specifiers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Specifiers.h; sourceTree = "<group>"; };
+ BF9FEDF11225E574003A8B71 /* StmtNodes.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StmtNodes.td; sourceTree = "<group>"; };
+ BF9FEDF21225E58B003A8B71 /* TargetOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetOptions.h; sourceTree = "<group>"; };
+ BF9FEDF31225E5B6003A8B71 /* DeclNodes.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DeclNodes.td; sourceTree = "<group>"; };
+ BF9FEDF41225E5D5003A8B71 /* Linkage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Linkage.h; sourceTree = "<group>"; };
+ BF9FEDF51225E5D5003A8B71 /* MacroBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroBuilder.h; sourceTree = "<group>"; };
+ BF9FEDF61225E5FB003A8B71 /* Version.inc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Version.inc.in; sourceTree = "<group>"; };
+ BF9FEDF71225E613003A8B71 /* DiagnosticCategories.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticCategories.td; sourceTree = "<group>"; };
+ BF9FEDF81225E67B003A8B71 /* Action.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Action.cpp; path = lib/Sema/Action.cpp; sourceTree = "<group>"; };
+ BF9FEDFA1225E6A9003A8B71 /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = lib/Sema/AttributeList.cpp; sourceTree = "<group>"; };
+ BF9FEDFC1225E6C6003A8B71 /* DeclSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeclSpec.cpp; path = lib/Sema/DeclSpec.cpp; sourceTree = "<group>"; };
+ BF9FEDFE1225E6DD003A8B71 /* TargetAttributesSema.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TargetAttributesSema.cpp; path = lib/Sema/TargetAttributesSema.cpp; sourceTree = "<group>"; };
+ BF9FEE001225E718003A8B71 /* CXXABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXXABI.h; sourceTree = "<group>"; };
+ BF9FEE011225E73F003A8B71 /* ExprClassification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExprClassification.cpp; sourceTree = "<group>"; };
+ BF9FEE031225E759003A8B71 /* ItaniumCXXABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ItaniumCXXABI.cpp; sourceTree = "<group>"; };
+ BF9FEE051225E770003A8B71 /* MicrosoftCXXABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MicrosoftCXXABI.cpp; sourceTree = "<group>"; };
+ BF9FEE2B1225E7EA003A8B71 /* BackendUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BackendUtil.cpp; path = lib/CodeGen/BackendUtil.cpp; sourceTree = "<group>"; };
+ BF9FEE2D1225E80F003A8B71 /* CGCXXABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGCXXABI.h; path = lib/CodeGen/CGCXXABI.h; sourceTree = "<group>"; };
+ BF9FEE2E1225E82D003A8B71 /* CGException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGException.h; path = lib/CodeGen/CGException.h; sourceTree = "<group>"; };
+ BF9FEE2F1225E854003A8B71 /* CGRecordLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CGRecordLayout.h; path = lib/CodeGen/CGRecordLayout.h; sourceTree = "<group>"; };
+ BF9FEE301225E86C003A8B71 /* CodeGenAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenAction.cpp; path = lib/CodeGen/CodeGenAction.cpp; sourceTree = "<group>"; };
+ BF9FEE321225E898003A8B71 /* ItaniumCXXABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ItaniumCXXABI.cpp; path = lib/CodeGen/ItaniumCXXABI.cpp; sourceTree = "<group>"; };
+ BF9FEE341225E8B1003A8B71 /* MicrosoftCXXABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MicrosoftCXXABI.cpp; path = lib/CodeGen/MicrosoftCXXABI.cpp; sourceTree = "<group>"; };
+ BF9FEE361225E8CF003A8B71 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = lib/CodeGen/README.txt; sourceTree = "<group>"; };
+ BF9FEE371225E925003A8B71 /* BoostConAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BoostConAction.cpp; path = lib/Frontend/BoostConAction.cpp; sourceTree = "<group>"; };
+ BF9FEE451225EA24003A8B71 /* DelayedDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DelayedDiagnostic.h; path = clang/Sema/DelayedDiagnostic.h; sourceTree = "<group>"; };
+ BF9FEE511226FE9F003A8B71 /* ParseAST.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ParseAST.cpp; path = lib/Parse/ParseAST.cpp; sourceTree = "<group>"; };
+ BF9FEE531226FEC1003A8B71 /* RAIIObjectsForParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RAIIObjectsForParser.h; path = lib/Parse/RAIIObjectsForParser.h; sourceTree = "<group>"; };
+ BF9FEEF1122D8068003A8B71 /* PreprocessingRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreprocessingRecord.cpp; sourceTree = "<group>"; };
BFE2F67A11DA95590007EDC0 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
BFE2F67C11DA95590007EDC0 /* .dir */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .dir; sourceTree = "<group>"; };
BFE2F67D11DA95590007EDC0 /* DeltaTree.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = DeltaTree.d; sourceTree = "<group>"; };
@@ -716,15 +776,8 @@
BFE2F68511DA955A0007EDC0 /* HTMLRewrite.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = HTMLRewrite.d; sourceTree = "<group>"; };
BFE2F68611DA955A0007EDC0 /* HTMLRewrite.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = HTMLRewrite.o; sourceTree = "<group>"; };
BFE2F68711DA955A0007EDC0 /* RewriteMacros.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = RewriteMacros.d; sourceTree = "<group>"; };
- BFE2F68811DA955A0007EDC0 /* RewriteMacros.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = RewriteMacros.o; sourceTree = "<group>"; };
BFE2F68911DA955A0007EDC0 /* RewriteObjC.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = RewriteObjC.d; sourceTree = "<group>"; };
- BFE2F68A11DA955A0007EDC0 /* RewriteObjC.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = RewriteObjC.o; sourceTree = "<group>"; };
BFE2F68B11DA955A0007EDC0 /* Rewriter.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = Rewriter.d; sourceTree = "<group>"; };
- BFE2F68C11DA955A0007EDC0 /* Rewriter.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = Rewriter.o; sourceTree = "<group>"; };
- BFE2F68D11DA955A0007EDC0 /* RewriteRope.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = RewriteRope.d; sourceTree = "<group>"; };
- BFE2F68E11DA955A0007EDC0 /* RewriteRope.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = RewriteRope.o; sourceTree = "<group>"; };
- BFE2F68F11DA955A0007EDC0 /* RewriteTest.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = RewriteTest.d; sourceTree = "<group>"; };
- BFE2F69011DA955A0007EDC0 /* RewriteTest.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = RewriteTest.o; sourceTree = "<group>"; };
BFE2F69111DA955A0007EDC0 /* TokenRewriter.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = TokenRewriter.d; sourceTree = "<group>"; };
BFE2F69211DA955A0007EDC0 /* TokenRewriter.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = TokenRewriter.o; sourceTree = "<group>"; };
BFE2F69311DA955A0007EDC0 /* DeltaTree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeltaTree.cpp; sourceTree = "<group>"; };
@@ -739,9 +792,6 @@
BFE2F69D11DA955A0007EDC0 /* HTMLRewrite.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = HTMLRewrite.d; sourceTree = "<group>"; };
BFE2F69E11DA955A0007EDC0 /* HTMLRewrite.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = HTMLRewrite.o; sourceTree = "<group>"; };
BFE2F69F11DA955A0007EDC0 /* Rewriter.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = Rewriter.d; sourceTree = "<group>"; };
- BFE2F6A011DA955A0007EDC0 /* Rewriter.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = Rewriter.o; sourceTree = "<group>"; };
- BFE2F6A111DA955A0007EDC0 /* RewriteRope.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = RewriteRope.d; sourceTree = "<group>"; };
- BFE2F6A211DA955A0007EDC0 /* RewriteRope.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = RewriteRope.o; sourceTree = "<group>"; };
BFE2F6A311DA955A0007EDC0 /* TokenRewriter.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.dtrace; path = TokenRewriter.d; sourceTree = "<group>"; };
BFE2F6A411DA955A0007EDC0 /* TokenRewriter.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = TokenRewriter.o; sourceTree = "<group>"; };
BFE2F6A511DA955A0007EDC0 /* RewriteMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RewriteMacros.cpp; sourceTree = "<group>"; };
@@ -753,13 +803,8 @@
DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = lib/Parse/ParseExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; tabWidth = 2; };
- DE06BECA0A854E4B0050E87E /* Scope.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Scope.h; path = clang/Parse/Scope.h; sourceTree = "<group>"; tabWidth = 2; };
DE06D42F0A8BB52D0050E87E /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = lib/Parse/Parser.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DE06E8130A8FF9330050E87E /* Action.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Action.h; path = clang/Parse/Action.h; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
DE0FCA620A95859D00248FD5 /* Expr.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Expr.h; path = clang/AST/Expr.h; sourceTree = "<group>"; tabWidth = 2; };
- DE1263C20EF2341900F56D2B /* Ownership.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Ownership.h; path = clang/Parse/Ownership.h; sourceTree = "<group>"; tabWidth = 2; };
- DE17336D0B068DC20080B521 /* DeclSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = DeclSpec.cpp; path = lib/Parse/DeclSpec.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DE17336F0B068DC60080B521 /* DeclSpec.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = DeclSpec.h; path = clang/Parse/DeclSpec.h; sourceTree = "<group>"; tabWidth = 2; };
DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = "<group>"; tabWidth = 2; };
DE224FF70C7AA98800D370A5 /* CGExprComplex.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprComplex.cpp; path = lib/CodeGen/CGExprComplex.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE22526F0C7E82D000D370A5 /* CGExprScalar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprScalar.cpp; path = lib/CodeGen/CGExprScalar.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -770,13 +815,11 @@
DE3450D60AEB543100DBC861 /* DirectoryLookup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DirectoryLookup.h; sourceTree = "<group>"; };
DE3452800AEF1B1800DBC861 /* Stmt.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Stmt.h; path = clang/AST/Stmt.h; sourceTree = "<group>"; tabWidth = 2; };
DE345C190AFC658B00DBC861 /* StmtVisitor.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = StmtVisitor.h; path = clang/AST/StmtVisitor.h; sourceTree = "<group>"; tabWidth = 2; };
- DE345F210AFD347900DBC861 /* StmtNodes.def */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = text; name = StmtNodes.def; path = clang/AST/StmtNodes.def; sourceTree = "<group>"; tabWidth = 2; };
DE345FFF0AFDCC1900DBC861 /* ParseObjc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseObjc.cpp; path = lib/Parse/ParseObjc.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE3460040AFDCC6500DBC861 /* ParseInit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseInit.cpp; path = lib/Parse/ParseInit.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE34600A0AFDCCBF00DBC861 /* ParseStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseStmt.cpp; path = lib/Parse/ParseStmt.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE34600E0AFDCCCE00DBC861 /* ParseDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseDecl.cpp; path = lib/Parse/ParseDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExpr.cpp; path = lib/Parse/ParseExpr.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = MinimalAction.cpp; path = lib/Parse/MinimalAction.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE3464210B03040900DBC861 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Type.h; path = clang/AST/Type.h; sourceTree = "<group>"; tabWidth = 2; };
DE37251C0FE4818000CF2CC2 /* Builtins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Builtins.h; sourceTree = "<group>"; };
DE37252A0FE4818F00CF2CC2 /* Builtins.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Builtins.def; sourceTree = "<group>"; };
@@ -788,8 +831,6 @@
DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjCGNU.cpp; path = lib/CodeGen/CGObjCGNU.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE3986EF0CB8D4B300223765 /* IdentifierTable.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = IdentifierTable.h; sourceTree = "<group>"; tabWidth = 2; };
DE3986F30CB8D50C00223765 /* IdentifierTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = IdentifierTable.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DE3B90DE0EAC5EF200D01046 /* ExtensionRAIIObject.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ExtensionRAIIObject.h; path = lib/Parse/ExtensionRAIIObject.h; sourceTree = "<group>"; tabWidth = 2; };
- DE3B92230EB5152000D01046 /* Designator.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Designator.h; path = clang/Parse/Designator.h; sourceTree = "<group>"; tabWidth = 2; };
DE41211D0D7F1BBE0080F80A /* GRWorkList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRWorkList.h; path = clang/Analysis/PathSensitive/GRWorkList.h; sourceTree = "<group>"; };
DE41211E0D7F1BBE0080F80A /* SymbolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolManager.h; path = clang/Analysis/PathSensitive/SymbolManager.h; sourceTree = "<group>"; };
DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRBlockCounter.h; path = clang/Analysis/PathSensitive/GRBlockCounter.h; sourceTree = "<group>"; };
@@ -819,10 +860,7 @@
DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExprCXX.cpp; path = lib/Sema/SemaExprCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaExpr.cpp; path = lib/Sema/SemaExpr.cpp; sourceTree = "<group>"; tabWidth = 2; };
DE67E7120C020ED900F66BC5 /* SemaDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDecl.cpp; path = lib/Sema/SemaDecl.cpp; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
- DE67E7140C020EDF00F66BC5 /* Sema.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Sema.h; path = lib/Sema/Sema.h; sourceTree = "<group>"; tabWidth = 2; };
DE67E7160C020EE400F66BC5 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = lib/Sema/Sema.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DE67E7190C020F4F00F66BC5 /* ParseAST.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = ParseAST.cpp; path = lib/Sema/ParseAST.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DE67E7270C02109800F66BC5 /* ParseAST.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ParseAST.h; path = clang/Sema/ParseAST.h; sourceTree = "<group>"; };
DE6951C60C4D1F5D00A5826B /* RecordLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayout.h; path = clang/AST/RecordLayout.h; sourceTree = "<group>"; tabWidth = 2; };
DE6954630C5121BD00A5826B /* Token.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Token.h; sourceTree = "<group>"; };
DE704B250D0FBEBE009C7762 /* SemaDeclObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaDeclObjC.cpp; path = lib/Sema/SemaDeclObjC.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -849,7 +887,6 @@
DEA09A6E0F31756F000C2258 /* ASTDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ASTDiagnostic.h; path = clang/AST/ASTDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
DEA09A830F3175BF000C2258 /* LexDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LexDiagnostic.h; sourceTree = "<group>"; };
DEA09A860F3175CA000C2258 /* ParseDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ParseDiagnostic.h; path = clang/Parse/ParseDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
- DEA09A890F3175D9000C2258 /* SemaDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaDiagnostic.h; path = clang/Sema/SemaDiagnostic.h; sourceTree = "<group>"; };
DEAABDF70F5F477C0098928A /* PrettyStackTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrettyStackTrace.h; sourceTree = "<group>"; };
DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = "<group>"; };
DEAEED4A0A5AF89A0045101B /* NOTES.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = NOTES.txt; sourceTree = "<group>"; };
@@ -862,14 +899,9 @@
DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = "<group>"; tabWidth = 2; };
DECAB0CF0DB3C84200E13CCB /* RewriteRope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RewriteRope.cpp; path = lib/Rewrite/RewriteRope.cpp; sourceTree = "<group>"; };
DECB6D640F9AE26600F5FBC7 /* JumpDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = JumpDiagnostics.cpp; path = lib/Sema/JumpDiagnostics.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DECB6F030F9D939A00F5FBC7 /* InitPreprocessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InitPreprocessor.h; path = clang/Frontend/InitPreprocessor.h; sourceTree = "<group>"; };
DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitPreprocessor.cpp; path = lib/Frontend/InitPreprocessor.cpp; sourceTree = "<group>"; };
DECB734E0FA3ED8400F5FBC7 /* StmtObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = StmtObjC.h; path = clang/AST/StmtObjC.h; sourceTree = "<group>"; tabWidth = 2; };
DECB73550FA3EE5A00F5FBC7 /* StmtCXX.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = StmtCXX.h; path = clang/AST/StmtCXX.h; sourceTree = "<group>"; tabWidth = 2; };
- DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderStmt.cpp; path = lib/Frontend/PCHReaderStmt.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReaderDecl.cpp; path = lib/Frontend/PCHReaderDecl.cpp; sourceTree = "<group>"; };
- DECB77F60FA5850200F5FBC7 /* PCHWriterDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriterDecl.cpp; path = lib/Frontend/PCHWriterDecl.cpp; sourceTree = "<group>"; };
- DECB78160FA5882F00F5FBC7 /* PCHWriterStmt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriterStmt.cpp; path = lib/Frontend/PCHWriterStmt.cpp; sourceTree = "<group>"; };
DED626C80AE0C065001E80A4 /* TargetInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInfo.cpp; sourceTree = "<group>"; tabWidth = 2; };
DED7D7310A524295003AD0FB /* Diagnostic.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = Diagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
DED7D7330A524295003AD0FB /* FileManager.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = FileManager.h; sourceTree = "<group>"; tabWidth = 2; };
@@ -893,7 +925,6 @@
DED7D7D70A524302003AD0FB /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = "<group>"; };
DED7D9170A52518C003AD0FB /* ScratchBuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScratchBuffer.h; sourceTree = "<group>"; };
DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScratchBuffer.cpp; sourceTree = "<group>"; };
- DEDFE5270F63A9230035BD10 /* DeclNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text; name = DeclNodes.def; path = clang/AST/DeclNodes.def; sourceTree = "<group>"; tabWidth = 2; };
DEDFE5CB0F7206CC0035BD10 /* NestedNameSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = NestedNameSpecifier.h; path = clang/AST/NestedNameSpecifier.h; sourceTree = "<group>"; tabWidth = 2; };
DEDFE6450F7B3B4E0035BD10 /* driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = driver.cpp; path = tools/driver/driver.cpp; sourceTree = "<group>"; };
DEDFE6480F7B3B830035BD10 /* Types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = Types.cpp; path = lib/Driver/Types.cpp; sourceTree = "<group>"; tabWidth = 2; };
@@ -920,11 +951,7 @@
DEEBBD430C19C5D200A9FE82 /* TODO.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TODO.txt; sourceTree = "<group>"; };
DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CodeGenTypes.h; path = lib/CodeGen/CodeGenTypes.h; sourceTree = "<group>"; tabWidth = 2; };
DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenTypes.cpp; path = lib/CodeGen/CodeGenTypes.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DEF1615E0F65C81C0098507F /* InitHeaderSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InitHeaderSearch.h; path = clang/Frontend/InitHeaderSearch.h; sourceTree = "<group>"; };
- DEF1615F0F65C81C0098507F /* ManagerRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ManagerRegistry.h; path = clang/Frontend/ManagerRegistry.h; sourceTree = "<group>"; };
DEF161600F65C81C0098507F /* TextDiagnosticBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextDiagnosticBuffer.h; path = clang/Frontend/TextDiagnosticBuffer.h; sourceTree = "<group>"; };
- DEF161610F65C81C0098507F /* PathDiagnosticClients.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathDiagnosticClients.h; path = clang/Frontend/PathDiagnosticClients.h; sourceTree = "<group>"; };
- DEF161620F65C81C0098507F /* CompileOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompileOptions.h; path = clang/Frontend/CompileOptions.h; sourceTree = "<group>"; };
DEF161630F65C81C0098507F /* TextDiagnosticPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextDiagnosticPrinter.h; path = clang/Frontend/TextDiagnosticPrinter.h; sourceTree = "<group>"; };
DEF165140F8D46980098507F /* Tool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Tool.h; path = clang/Driver/Tool.h; sourceTree = "<group>"; };
DEF165150F8D46980098507F /* Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Types.h; path = clang/Driver/Types.h; sourceTree = "<group>"; };
@@ -942,13 +969,6 @@
DEF165220F8D46980098507F /* Util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Util.h; path = clang/Driver/Util.h; sourceTree = "<group>"; };
DEF165230F8D46980098507F /* Phases.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Phases.h; path = clang/Driver/Phases.h; sourceTree = "<group>"; };
DEF165240F8D46980098507F /* DriverDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DriverDiagnostic.h; path = clang/Driver/DriverDiagnostic.h; sourceTree = "<group>"; };
- DEF165700F8FB34D0098507F /* PCHWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHWriter.cpp; path = lib/Frontend/PCHWriter.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DEF165740F8FB3510098507F /* PCHReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = PCHReader.cpp; path = lib/Frontend/PCHReader.cpp; sourceTree = "<group>"; tabWidth = 2; };
- DEF165780F8FB3690098507F /* PCHWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PCHWriter.h; path = clang/Frontend/PCHWriter.h; sourceTree = "<group>"; };
- DEF1657B0F8FB36E0098507F /* PCHReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PCHReader.h; path = clang/Frontend/PCHReader.h; sourceTree = "<group>"; };
- DEF1657E0F8FB3730098507F /* PCHBitCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PCHBitCodes.h; path = clang/Frontend/PCHBitCodes.h; sourceTree = "<group>"; };
- DEF1683F0F9548DC0098507F /* FixItRewriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FixItRewriter.cpp; path = lib/Frontend/FixItRewriter.cpp; sourceTree = "<group>"; };
- DEF168620F9549250098507F /* FixItRewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FixItRewriter.h; path = clang/Frontend/FixItRewriter.h; sourceTree = "<group>"; };
DEF169220F9645960098507F /* FrontendDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendDiagnostic.h; path = clang/Frontend/FrontendDiagnostic.h; sourceTree = "<group>"; };
DEF1692C0F9645BF0098507F /* AnalysisDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisDiagnostic.h; path = clang/Analysis/AnalysisDiagnostic.h; sourceTree = "<group>"; };
DEF16BE40FA13A5B0098507F /* TypeNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text; name = TypeNodes.def; path = clang/AST/TypeNodes.def; sourceTree = "<group>"; tabWidth = 2; };
@@ -973,16 +993,9 @@
BFE2F6B011DA955A0007EDC0 /* FrontendActions.o in Frameworks */,
BFE2F6B211DA955A0007EDC0 /* HTMLPrint.o in Frameworks */,
BFE2F6B411DA955A0007EDC0 /* HTMLRewrite.o in Frameworks */,
- BFE2F6B611DA955A0007EDC0 /* RewriteMacros.o in Frameworks */,
- BFE2F6B811DA955A0007EDC0 /* RewriteObjC.o in Frameworks */,
- BFE2F6BA11DA955A0007EDC0 /* Rewriter.o in Frameworks */,
- BFE2F6BC11DA955A0007EDC0 /* RewriteRope.o in Frameworks */,
- BFE2F6BE11DA955A0007EDC0 /* RewriteTest.o in Frameworks */,
BFE2F6C011DA955A0007EDC0 /* TokenRewriter.o in Frameworks */,
BFE2F6C811DA955A0007EDC0 /* DeltaTree.o in Frameworks */,
BFE2F6CA11DA955A0007EDC0 /* HTMLRewrite.o in Frameworks */,
- BFE2F6CC11DA955A0007EDC0 /* Rewriter.o in Frameworks */,
- BFE2F6CE11DA955A0007EDC0 /* RewriteRope.o in Frameworks */,
BFE2F6D011DA955A0007EDC0 /* TokenRewriter.o in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1005,6 +1018,7 @@
08FB7795FE84155DC02AAC07 /* Libraries */ = {
isa = PBXGroup;
children = (
+ 57EB5660121B034300ECA335 /* Serialization */,
BFE2F67911DA95590007EDC0 /* Rewrite */,
90FD6D6C103C3D2D005F5B73 /* Index */,
DED7D7500A5242C7003AD0FB /* Basic */,
@@ -1083,11 +1097,10 @@
352246E00F5C6BC000D0D279 /* Frontend */ = {
isa = PBXGroup;
children = (
+ BF9FEE371225E925003A8B71 /* BoostConAction.cpp */,
1AFDD8701161085D00AE030A /* ASTMerge.cpp */,
9012911C1048068D0083456D /* ASTUnit.cpp */,
- 1A2A54A40FD1DD1C00F4CE45 /* AnalysisConsumer.cpp */,
1A2A54A50FD1DD1C00F4CE45 /* ASTConsumers.cpp */,
- 1AFDD8711161085D00AE030A /* CodeGenAction.cpp */,
1A2A54A70FD1DD1C00F4CE45 /* CacheTokens.cpp */,
1ACB57DB1105820D0047B991 /* CompilerInstance.cpp */,
1ACB57DC1105820D0047B991 /* CompilerInvocation.cpp */,
@@ -1095,24 +1108,12 @@
1A2A54A80FD1DD1C00F4CE45 /* DependencyFile.cpp */,
1A2A54A90FD1DD1C00F4CE45 /* DiagChecker.cpp */,
1A2A54AA0FD1DD1C00F4CE45 /* DocumentXML.cpp */,
- DEF1683F0F9548DC0098507F /* FixItRewriter.cpp */,
1ACB57DE1105820D0047B991 /* FrontendAction.cpp */,
1ACB57DF1105820D0047B991 /* FrontendActions.cpp */,
1ACB57E01105820D0047B991 /* FrontendOptions.cpp */,
- 1A2A54AB0FD1DD1C00F4CE45 /* GeneratePCH.cpp */,
- 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */,
- 1A2A54AC0FD1DD1C00F4CE45 /* HTMLPrint.cpp */,
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */,
DECB6F060F9D93A800F5FBC7 /* InitPreprocessor.cpp */,
1ACB57E11105820D0047B991 /* LangStandards.cpp */,
- DEF165740F8FB3510098507F /* PCHReader.cpp */,
- DECB77780FA579B000F5FBC7 /* PCHReaderDecl.cpp */,
- DECB77120FA5752300F5FBC7 /* PCHReaderStmt.cpp */,
- DEF165700F8FB34D0098507F /* PCHWriter.cpp */,
- DECB77F60FA5850200F5FBC7 /* PCHWriterDecl.cpp */,
- DECB78160FA5882F00F5FBC7 /* PCHWriterStmt.cpp */,
- 352246E40F5C6BE000D0D279 /* PlistDiagnostics.cpp */,
- 1A2A54AD0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp */,
1A2A54AE0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp */,
352246E50F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp */,
352246E60F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp */,
@@ -1230,6 +1231,34 @@
name = Analyses;
sourceTree = "<group>";
};
+ 57EB5654121B023900ECA335 /* Serialization */ = {
+ isa = PBXGroup;
+ children = (
+ BF9FEDBA1225E30E003A8B71 /* ASTBitCodes.h */,
+ 57E15B21121C8D2B0051C2CC /* ASTDeserializationListener.h */,
+ 57E15B22121C8D2B0051C2CC /* ASTReader.h */,
+ 574F4C25121B4EF000AEAC20 /* ASTWriter.h */,
+ );
+ name = Serialization;
+ sourceTree = "<group>";
+ };
+ 57EB5660121B034300ECA335 /* Serialization */ = {
+ isa = PBXGroup;
+ children = (
+ 57AA924D121C8B9400B4AA6C /* ASTReader.cpp */,
+ 57AA924E121C8B9400B4AA6C /* ASTReaderDecl.cpp */,
+ 57AA924F121C8B9400B4AA6C /* ASTReaderStmt.cpp */,
+ 57F6660F121B4DE600DCE3B7 /* ASTWriter.cpp */,
+ 57F66610121B4DE600DCE3B7 /* ASTWriterDecl.cpp */,
+ 57F66611121B4DE600DCE3B7 /* ASTWriterStmt.cpp */,
+ 57EB5661121B034300ECA335 /* CMakeLists.txt */,
+ 57EB5662121B034300ECA335 /* GeneratePCH.cpp */,
+ 57EB5663121B034300ECA335 /* Makefile */,
+ );
+ name = Serialization;
+ path = lib/Serialization;
+ sourceTree = "<group>";
+ };
9012911210470FAF0083456D /* clang-c */ = {
isa = PBXGroup;
children = (
@@ -1297,7 +1326,6 @@
90FD6D76103C3D49005F5B73 /* IndexProvider.cpp */,
90FD6D77103C3D49005F5B73 /* Program.cpp */,
90FD6D78103C3D49005F5B73 /* ProgramImpl.h */,
- 90FD6D79103C3D49005F5B73 /* ResolveLocation.cpp */,
90FD6D7A103C3D49005F5B73 /* SelectorMap.cpp */,
);
name = Index;
@@ -1349,15 +1377,8 @@
BFE2F68511DA955A0007EDC0 /* HTMLRewrite.d */,
BFE2F68611DA955A0007EDC0 /* HTMLRewrite.o */,
BFE2F68711DA955A0007EDC0 /* RewriteMacros.d */,
- BFE2F68811DA955A0007EDC0 /* RewriteMacros.o */,
BFE2F68911DA955A0007EDC0 /* RewriteObjC.d */,
- BFE2F68A11DA955A0007EDC0 /* RewriteObjC.o */,
BFE2F68B11DA955A0007EDC0 /* Rewriter.d */,
- BFE2F68C11DA955A0007EDC0 /* Rewriter.o */,
- BFE2F68D11DA955A0007EDC0 /* RewriteRope.d */,
- BFE2F68E11DA955A0007EDC0 /* RewriteRope.o */,
- BFE2F68F11DA955A0007EDC0 /* RewriteTest.d */,
- BFE2F69011DA955A0007EDC0 /* RewriteTest.o */,
BFE2F69111DA955A0007EDC0 /* TokenRewriter.d */,
BFE2F69211DA955A0007EDC0 /* TokenRewriter.o */,
);
@@ -1373,9 +1394,6 @@
BFE2F69D11DA955A0007EDC0 /* HTMLRewrite.d */,
BFE2F69E11DA955A0007EDC0 /* HTMLRewrite.o */,
BFE2F69F11DA955A0007EDC0 /* Rewriter.d */,
- BFE2F6A011DA955A0007EDC0 /* Rewriter.o */,
- BFE2F6A111DA955A0007EDC0 /* RewriteRope.d */,
- BFE2F6A211DA955A0007EDC0 /* RewriteRope.o */,
BFE2F6A311DA955A0007EDC0 /* TokenRewriter.d */,
BFE2F6A411DA955A0007EDC0 /* TokenRewriter.o */,
);
@@ -1396,15 +1414,9 @@
DE1F21F20A7D84E800FBF588 /* Parse */ = {
isa = PBXGroup;
children = (
- 3551068E0E9A855F006A4E44 /* AccessSpecifier.h */,
- 84D9A88B0C1A581300AC7ABC /* AttributeList.h */,
- DE06E8130A8FF9330050E87E /* Action.h */,
- DE17336F0B068DC60080B521 /* DeclSpec.h */,
- DE3B92230EB5152000D01046 /* Designator.h */,
- DE1263C20EF2341900F56D2B /* Ownership.h */,
+ BF9FEDB51225E213003A8B71 /* ParseAST.h */,
DEA09A860F3175CA000C2258 /* ParseDiagnostic.h */,
DE1F22020A7D852A00FBF588 /* Parser.h */,
- DE06BECA0A854E4B0050E87E /* Scope.h */,
);
name = Parse;
sourceTree = "<group>";
@@ -1412,10 +1424,7 @@
DE1F22600A7D8C9B00FBF588 /* Parse */ = {
isa = PBXGroup;
children = (
- 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */,
- DE17336D0B068DC20080B521 /* DeclSpec.cpp */,
- DE3B90DE0EAC5EF200D01046 /* ExtensionRAIIObject.h */,
- DE3461260AFE68BE00DBC861 /* MinimalAction.cpp */,
+ BF9FEE511226FE9F003A8B71 /* ParseAST.cpp */,
DE34600E0AFDCCCE00DBC861 /* ParseDecl.cpp */,
DE2255FB0C8004E600D370A5 /* ParseDeclCXX.cpp */,
DE3460120AFDCCDA00DBC861 /* ParseExpr.cpp */,
@@ -1429,6 +1438,7 @@
353959D40EE5F88A00E82461 /* ParseTemplate.cpp */,
3551068B0E9A8546006A4E44 /* ParseTentative.cpp */,
DE06D42F0A8BB52D0050E87E /* Parser.cpp */,
+ BF9FEE531226FEC1003A8B71 /* RAIIObjectsForParser.h */,
);
name = Parse;
sourceTree = "<group>";
@@ -1461,16 +1471,14 @@
DE67E7070C020EAB00F66BC5 /* Sema */ = {
isa = PBXGroup;
children = (
+ BF9FEDFE1225E6DD003A8B71 /* TargetAttributesSema.cpp */,
+ BF9FEDFC1225E6C6003A8B71 /* DeclSpec.cpp */,
+ BF9FEDFA1225E6A9003A8B71 /* AttributeList.cpp */,
+ BF9FEDF81225E67B003A8B71 /* Action.cpp */,
BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */,
- BF89C3E0115957FF001C2D68 /* AnalysisBasedWarnings.h */,
- 35585DBD0EAFBC4500D0A97A /* CXXFieldCollector.h */,
1A6B6CD110693FC900BB4A8F /* CodeCompleteConsumer.cpp */,
- 3527124F0DAFE54700C76352 /* IdentifierResolver.h */,
352712500DAFE54700C76352 /* IdentifierResolver.cpp */,
DECB6D640F9AE26600F5FBC7 /* JumpDiagnostics.cpp */,
- BF89C3E311595835001C2D68 /* Lookup.h */,
- DE67E7190C020F4F00F66BC5 /* ParseAST.cpp */,
- DE67E7140C020EDF00F66BC5 /* Sema.h */,
DE67E7160C020EE400F66BC5 /* Sema.cpp */,
1A701B630F7C8FE400FEC4D1 /* SemaAccess.cpp */,
DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */,
@@ -1485,17 +1493,14 @@
DE67E7100C020ED400F66BC5 /* SemaExpr.cpp */,
DE47999B0D2EBE1A00706D2D /* SemaExprObjC.cpp */,
DE67E70E0C020ECF00F66BC5 /* SemaExprCXX.cpp */,
- BF89C3E411595855001C2D68 /* SemaInit.h */,
3599299A0DE2425300A8A33E /* SemaInit.cpp */,
357EA27C0F2526F300439B60 /* SemaLookup.cpp */,
1A6B6CD210693FC900BB4A8F /* SemaCodeComplete.cpp */,
35E194680ECB82FB00F21733 /* SemaCXXCast.cpp */,
BF89C3E81159594A001C2D68 /* SemaObjCProperty.cpp */,
35585DBE0EAFBC4500D0A97A /* SemaOverload.cpp */,
- 35585DBF0EAFBC4500D0A97A /* SemaOverload.h */,
DE67E70C0C020ECA00F66BC5 /* SemaStmt.cpp */,
3591853E0EFB1088000039AF /* SemaTemplate.cpp */,
- 1A6B6CD310693FC900BB4A8F /* SemaTemplate.h */,
BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */,
35544B8B0F5C803200D92AA9 /* SemaTemplateInstantiate.cpp */,
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */,
@@ -1509,11 +1514,30 @@
DE67E7260C02108300F66BC5 /* Sema */ = {
isa = PBXGroup;
children = (
- 7F270AFE107A90010031B377 /* CodeCompleteConsumer.h */,
- 9063F2210F9E8BDF002F7251 /* ExternalSemaSource.h */,
- 9063F2220F9E8BDF002F7251 /* SemaConsumer.h */,
- DE67E7270C02109800F66BC5 /* ParseAST.h */,
- DEA09A890F3175D9000C2258 /* SemaDiagnostic.h */,
+ BF9FEE451225EA24003A8B71 /* DelayedDiagnostic.h */,
+ BF9FED781225E041003A8B71 /* SemaInternal.h */,
+ BF9FED771225E032003A8B71 /* ObjCMethodList.h */,
+ BF9FED731225E005003A8B71 /* Ownership.h */,
+ BF9FED741225E005003A8B71 /* ParsedTemplate.h */,
+ BF9FED751225E005003A8B71 /* Scope.h */,
+ BF9FED761225E005003A8B71 /* ScopeInfo.h */,
+ BF9FED711225DFD9003A8B71 /* DeclSpec.h */,
+ BF9FED721225DFD9003A8B71 /* Designator.h */,
+ BF9FED701225DFA1003A8B71 /* AttributeList.h */,
+ BF9FED6F1225DF7F003A8B71 /* Action.h */,
+ BF9FED6E1225DF55003A8B71 /* TemplateDeduction.h */,
+ BD59A948121496B9003A5A02 /* AnalysisBasedWarnings.h */,
+ BD59A949121496B9003A5A02 /* CodeCompleteConsumer.h */,
+ BD59A94A121496B9003A5A02 /* CXXFieldCollector.h */,
+ BD59A94B121496B9003A5A02 /* ExternalSemaSource.h */,
+ BD59A94C121496B9003A5A02 /* IdentifierResolver.h */,
+ BD59A94D121496B9003A5A02 /* Initialization.h */,
+ BD59A94E121496B9003A5A02 /* Lookup.h */,
+ BD59A94F121496B9003A5A02 /* Overload.h */,
+ BD59A951121496B9003A5A02 /* Sema.h */,
+ BD59A952121496B9003A5A02 /* SemaConsumer.h */,
+ BD59A953121496B9003A5A02 /* SemaDiagnostic.h */,
+ BD59A954121496B9003A5A02 /* Template.h */,
);
name = Sema;
sourceTree = "<group>";
@@ -1521,6 +1545,14 @@
DE927FCC0C0557CD00231DA4 /* CodeGen */ = {
isa = PBXGroup;
children = (
+ BF9FEE361225E8CF003A8B71 /* README.txt */,
+ BF9FEE341225E8B1003A8B71 /* MicrosoftCXXABI.cpp */,
+ BF9FEE321225E898003A8B71 /* ItaniumCXXABI.cpp */,
+ BF9FEE301225E86C003A8B71 /* CodeGenAction.cpp */,
+ BF9FEE2F1225E854003A8B71 /* CGRecordLayout.h */,
+ BF9FEE2E1225E82D003A8B71 /* CGException.h */,
+ BF9FEE2D1225E80F003A8B71 /* CGCXXABI.h */,
+ BF9FEE2B1225E7EA003A8B71 /* BackendUtil.cpp */,
1A2193CB0F45EEB700C0713D /* ABIInfo.h */,
1A471AB40F437BC500753CE8 /* CGBlocks.cpp */,
1A649E1D0F9599D9005B965E /* CGBlocks.h */,
@@ -1573,6 +1605,8 @@
DE928B140C05659A00231DA4 /* CodeGen */ = {
isa = PBXGroup;
children = (
+ BF9FEDB81225E2DE003A8B71 /* BackendUtil.h */,
+ BF9FEDB91225E2DE003A8B71 /* CodeGenAction.h */,
DE928B1F0C0565B000231DA4 /* ModuleBuilder.h */,
);
name = CodeGen;
@@ -1581,6 +1615,8 @@
DEC8D98B0A9433BC00353FCA /* AST */ = {
isa = PBXGroup;
children = (
+ BF9FEDB71225E26A003A8B71 /* RecursiveASTVisitor.h */,
+ BF9FEDB61225E252003A8B71 /* OperationKinds.h */,
1A15C407118226980092260D /* ASTImporter.h */,
1A15C408118226980092260D /* ASTVector.h */,
1A15C409118226980092260D /* CharUnits.h */,
@@ -1613,7 +1649,6 @@
84AF36A00CB17A3B00C820A5 /* DeclObjC.h */,
35EE48AD0E0C4CB200715C54 /* DeclCXX.h */,
358D23090E8BEB850003DDCC /* DeclGroup.h */,
- DEDFE5270F63A9230035BD10 /* DeclNodes.def */,
DEB076C90F3A221200F5A2BE /* DeclTemplate.h */,
DE0FCA620A95859D00248FD5 /* Expr.h */,
1A30A9E80B93A4C800201A91 /* ExprCXX.h */,
@@ -1625,7 +1660,6 @@
DE6951C60C4D1F5D00A5826B /* RecordLayout.h */,
DE3452800AEF1B1800DBC861 /* Stmt.h */,
DECB73550FA3EE5A00F5FBC7 /* StmtCXX.h */,
- DE345F210AFD347900DBC861 /* StmtNodes.def */,
DECB734E0FA3ED8400F5FBC7 /* StmtObjC.h */,
DE345C190AFC658B00DBC861 /* StmtVisitor.h */,
35847BE30CC7DB9000C40FFF /* StmtIterator.h */,
@@ -1641,6 +1675,10 @@
DEC8D9920A9433F400353FCA /* AST */ = {
isa = PBXGroup;
children = (
+ BF9FEE051225E770003A8B71 /* MicrosoftCXXABI.cpp */,
+ BF9FEE031225E759003A8B71 /* ItaniumCXXABI.cpp */,
+ BF9FEE011225E73F003A8B71 /* ExprClassification.cpp */,
+ BF9FEE001225E718003A8B71 /* CXXABI.h */,
1ABD23B11182449800A48E65 /* APValue.cpp */,
1ABD23B21182449800A48E65 /* ASTConsumer.cpp */,
1ABD23B31182449800A48E65 /* ASTContext.cpp */,
@@ -1692,6 +1730,7 @@
DE67E7260C02108300F66BC5 /* Sema */,
DE928B140C05659A00231DA4 /* CodeGen */,
356EF9AF0C8F7DA4006650F5 /* Analysis */,
+ 57EB5654121B023900ECA335 /* Serialization */,
90FD6D5E103C3D03005F5B73 /* Index */,
DEF7D9F40C9C8B020001F598 /* Rewrite */,
DEF1615D0F65C7FC0098507F /* Frontend */,
@@ -1704,6 +1743,19 @@
DED7D7300A524295003AD0FB /* Basic */ = {
isa = PBXGroup;
children = (
+ BF9FEDF71225E613003A8B71 /* DiagnosticCategories.td */,
+ BF9FEDF61225E5FB003A8B71 /* Version.inc.in */,
+ BF9FEDF41225E5D5003A8B71 /* Linkage.h */,
+ BF9FEDF51225E5D5003A8B71 /* MacroBuilder.h */,
+ BF9FEDF31225E5B6003A8B71 /* DeclNodes.td */,
+ BF9FEDF21225E58B003A8B71 /* TargetOptions.h */,
+ BF9FEDF01225E574003A8B71 /* Specifiers.h */,
+ BF9FEDF11225E574003A8B71 /* StmtNodes.td */,
+ BF9FEDEF1225E55C003A8B71 /* BuiltinsARM.def */,
+ BF9FEDED1225E52F003A8B71 /* arm_neon.td */,
+ BF9FEDEE1225E52F003A8B71 /* Attr.td */,
+ BF9FEDEC1225E514003A8B71 /* Version.h */,
+ BF9FEDEB1225E4F2003A8B71 /* AttrKinds.h */,
DE37251C0FE4818000CF2CC2 /* Builtins.h */,
DE37252A0FE4818F00CF2CC2 /* Builtins.def */,
DE3725330FE4827200CF2CC2 /* BuiltinsPPC.def */,
@@ -1745,6 +1797,9 @@
DED7D7390A524295003AD0FB /* Lex */ = {
isa = PBXGroup;
children = (
+ BF9FEDB41225E1F3003A8B71 /* PreprocessingRecord.h */,
+ BF9FEDB31225E1E1003A8B71 /* ExternalPreprocessorSource.h */,
+ BF9FEDB21225E1D2003A8B71 /* CodeCompletionHandler.h */,
DE3450D60AEB543100DBC861 /* DirectoryLookup.h */,
DE704BD10D1647E7009C7762 /* HeaderMap.h */,
DE344AB70AE5DF6D00DBC861 /* HeaderSearch.h */,
@@ -1789,6 +1844,7 @@
DED7D78C0A5242E6003AD0FB /* Lex */ = {
isa = PBXGroup;
children = (
+ BF9FEEF1122D8068003A8B71 /* PreprocessingRecord.cpp */,
DE704DD10D1668A4009C7762 /* HeaderMap.cpp */,
DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */,
DED7D79E0A5242E6003AD0FB /* Lexer.cpp */,
@@ -1861,28 +1917,35 @@
DEF1615D0F65C7FC0098507F /* Frontend */ = {
isa = PBXGroup;
children = (
+ BF9FEDCE1225E42C003A8B71 /* VerifyDiagnosticsClient.h */,
+ BF9FEDCC1225E41D003A8B71 /* PreprocessorOptions.h */,
+ BF9FEDCD1225E41D003A8B71 /* PreprocessorOutputOptions.h */,
+ BF9FEDC81225E40A003A8B71 /* FrontendOptions.h */,
+ BF9FEDC91225E40A003A8B71 /* FrontendPluginRegistry.h */,
+ BF9FEDCA1225E40A003A8B71 /* HeaderSearchOptions.h */,
+ BF9FEDCB1225E40A003A8B71 /* LangStandard.h */,
+ BF9FEDC61225E3F6003A8B71 /* FrontendAction.h */,
+ BF9FEDC71225E3F6003A8B71 /* FrontendActions.h */,
+ BF9FEDC41225E3DA003A8B71 /* DependencyOutputOptions.h */,
+ BF9FEDC51225E3DA003A8B71 /* DiagnosticOptions.h */,
+ BF9FEDC21225E3C2003A8B71 /* CompilerInstance.h */,
+ BF9FEDC31225E3C2003A8B71 /* CompilerInvocation.h */,
+ BF9FEDC01225E3AB003A8B71 /* ChainedDiagnosticClient.h */,
+ BF9FEDC11225E3AB003A8B71 /* CodeGenOptions.h */,
+ BF9FEDBF1225E392003A8B71 /* AnalyzerOptions.h */,
90FD6D86103C3D80005F5B73 /* Analyses.def */,
- 90FD6D87103C3D80005F5B73 /* AnalysisConsumer.h */,
90FD6D88103C3D80005F5B73 /* ASTConsumers.h */,
90FD6D89103C3D80005F5B73 /* ASTUnit.h */,
90FD6D8A103C3D80005F5B73 /* CommandLineSourceLoc.h */,
90FD6D8B103C3D80005F5B73 /* DeclContextXML.def */,
90FD6D8C103C3D80005F5B73 /* DeclXML.def */,
90FD6D8D103C3D80005F5B73 /* DocumentXML.def */,
+ BF9FEDCF1225E443003A8B71 /* LangStandards.def */,
90FD6D8E103C3D80005F5B73 /* DocumentXML.h */,
90FD6D8F103C3D80005F5B73 /* StmtXML.def */,
90FD6D90103C3D80005F5B73 /* TypeXML.def */,
90FD6D91103C3D80005F5B73 /* Utils.h */,
- DEF161620F65C81C0098507F /* CompileOptions.h */,
- DEF168620F9549250098507F /* FixItRewriter.h */,
DEF169220F9645960098507F /* FrontendDiagnostic.h */,
- DEF1615E0F65C81C0098507F /* InitHeaderSearch.h */,
- DECB6F030F9D939A00F5FBC7 /* InitPreprocessor.h */,
- DEF1615F0F65C81C0098507F /* ManagerRegistry.h */,
- DEF1657E0F8FB3730098507F /* PCHBitCodes.h */,
- DEF1657B0F8FB36E0098507F /* PCHReader.h */,
- DEF165780F8FB3690098507F /* PCHWriter.h */,
- DEF161610F65C81C0098507F /* PathDiagnosticClients.h */,
DEF161600F65C81C0098507F /* TextDiagnosticBuffer.h */,
DEF161630F65C81C0098507F /* TextDiagnosticPrinter.h */,
);
@@ -1892,6 +1955,10 @@
DEF165020F8D46810098507F /* Driver */ = {
isa = PBXGroup;
children = (
+ BF9FEDE91225E4BD003A8B71 /* OptSpecifier.h */,
+ BF9FEDEA1225E4BD003A8B71 /* OptTable.h */,
+ BF9FEDE81225E49D003A8B71 /* CC1Options.h */,
+ BF9FEDE71225E488003A8B71 /* CC1AsOptions.h */,
DEF165160F8D46980098507F /* Action.h */,
DEF1651D0F8D46980098507F /* ArgList.h */,
DEF1651E0F8D46980098507F /* Arg.h */,
@@ -1919,6 +1986,10 @@
DEF7D9F40C9C8B020001F598 /* Rewrite */ = {
isa = PBXGroup;
children = (
+ BF9FEDBE1225E373003A8B71 /* ASTConsumers.h */,
+ BF9FEDBD1225E35F003A8B71 /* Rewriters.h */,
+ BF9FEDBB1225E34B003A8B71 /* FixItRewriter.h */,
+ BF9FEDBC1225E34B003A8B71 /* FrontendActions.h */,
DEFFECA30DB093D100B4E7C3 /* DeltaTree.h */,
35F2BE7B0DAC2963006E7668 /* HTMLRewrite.h */,
DEF7D9F60C9C8B1A0001F598 /* Rewriter.h */,
@@ -1969,6 +2040,12 @@
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
projectRoot = "";
@@ -2001,8 +2078,6 @@
DE34600B0AFDCCBF00DBC861 /* ParseStmt.cpp in Sources */,
DE34600F0AFDCCCE00DBC861 /* ParseDecl.cpp in Sources */,
DE3460130AFDCCDA00DBC861 /* ParseExpr.cpp in Sources */,
- DE3461270AFE68BE00DBC861 /* MinimalAction.cpp in Sources */,
- DE17336E0B068DC20080B521 /* DeclSpec.cpp in Sources */,
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */,
DE67E70B0C020EC500F66BC5 /* SemaType.cpp in Sources */,
DE67E70D0C020ECA00F66BC5 /* SemaStmt.cpp in Sources */,
@@ -2010,7 +2085,6 @@
DE67E7110C020ED400F66BC5 /* SemaExpr.cpp in Sources */,
DE67E7130C020ED900F66BC5 /* SemaDecl.cpp in Sources */,
DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */,
- DE67E71A0C020F4F00F66BC5 /* ParseAST.cpp in Sources */,
DE06756C0C051CFE00EBBFD8 /* ParseExprCXX.cpp in Sources */,
DE928B130C05659200231DA4 /* ModuleBuilder.cpp in Sources */,
DE928B7F0C0A615600231DA4 /* CodeGenModule.cpp in Sources */,
@@ -2018,7 +2092,6 @@
DE4772FA0C10EAE5002239E8 /* CGStmt.cpp in Sources */,
DE4772FC0C10EAEC002239E8 /* CGExpr.cpp in Sources */,
DE4264FC0C113592005A861D /* CGDecl.cpp in Sources */,
- 84D9A8880C1A57E100AC7ABC /* AttributeList.cpp in Sources */,
DEEBC3BC0C2363BC00A9FE82 /* CodeGenTypes.cpp in Sources */,
DEF2EFF30C6CDD74000C4259 /* CGExprAgg.cpp in Sources */,
DEF2F0100C6CFED5000C4259 /* SemaChecking.cpp in Sources */,
@@ -2096,9 +2169,7 @@
DEB077990F44F97800F5A2BE /* TokenConcatenation.cpp in Sources */,
1A2193CE0F45EEB700C0713D /* Mangle.cpp in Sources */,
DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */,
- 352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */,
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */,
- 352246EA0F5C6BE000D0D279 /* PlistDiagnostics.cpp in Sources */,
352246EB0F5C6BE000D0D279 /* TextDiagnosticBuffer.cpp in Sources */,
352246EC0F5C6BE000D0D279 /* TextDiagnosticPrinter.cpp in Sources */,
35544B880F5C7FD700D92AA9 /* RangeConstraintManager.cpp in Sources */,
@@ -2123,24 +2194,13 @@
DEDFE6680F7B3B830035BD10 /* Driver.cpp in Sources */,
1A701B640F7C8FE400FEC4D1 /* SemaAccess.cpp in Sources */,
906BF4B00F83BA2E001071FA /* ConvertUTF.c in Sources */,
- DEF165710F8FB34D0098507F /* PCHWriter.cpp in Sources */,
- DEF165750F8FB3510098507F /* PCHReader.cpp in Sources */,
- DEF168400F9548DC0098507F /* FixItRewriter.cpp in Sources */,
DECB6D650F9AE26600F5FBC7 /* JumpDiagnostics.cpp in Sources */,
DECB6F070F9D93A800F5FBC7 /* InitPreprocessor.cpp in Sources */,
- DECB77130FA5752300F5FBC7 /* PCHReaderStmt.cpp in Sources */,
- DECB77790FA579B000F5FBC7 /* PCHReaderDecl.cpp in Sources */,
- DECB77F70FA5850200F5FBC7 /* PCHWriterDecl.cpp in Sources */,
- DECB78170FA5882F00F5FBC7 /* PCHWriterStmt.cpp in Sources */,
- 1A2A54B50FD1DD1C00F4CE45 /* AnalysisConsumer.cpp in Sources */,
1A2A54B60FD1DD1C00F4CE45 /* ASTConsumers.cpp in Sources */,
1A2A54B80FD1DD1C00F4CE45 /* CacheTokens.cpp in Sources */,
1A2A54B90FD1DD1C00F4CE45 /* DependencyFile.cpp in Sources */,
1A2A54BA0FD1DD1C00F4CE45 /* DiagChecker.cpp in Sources */,
1A2A54BB0FD1DD1C00F4CE45 /* DocumentXML.cpp in Sources */,
- 1A2A54BC0FD1DD1C00F4CE45 /* GeneratePCH.cpp in Sources */,
- 1A2A54BD0FD1DD1C00F4CE45 /* HTMLPrint.cpp in Sources */,
- 1A2A54BE0FD1DD1C00F4CE45 /* PrintParserCallbacks.cpp in Sources */,
1A2A54BF0FD1DD1C00F4CE45 /* PrintPreprocessedOutput.cpp in Sources */,
1A2A54C40FD1DD1C00F4CE45 /* StmtXML.cpp in Sources */,
1A2A54C50FD1DD1C00F4CE45 /* Warnings.cpp in Sources */,
@@ -2157,7 +2217,6 @@
90FD6D81103C3D49005F5B73 /* Indexer.cpp in Sources */,
90FD6D82103C3D49005F5B73 /* IndexProvider.cpp in Sources */,
90FD6D83103C3D49005F5B73 /* Program.cpp in Sources */,
- 90FD6D84103C3D49005F5B73 /* ResolveLocation.cpp in Sources */,
90FD6D85103C3D49005F5B73 /* SelectorMap.cpp in Sources */,
90FD6DB6103D977E005F5B73 /* index-test.cpp in Sources */,
9012911D1048068D0083456D /* ASTUnit.cpp in Sources */,
@@ -2194,7 +2253,6 @@
BF89C3FB11595A37001C2D68 /* SemaCodeComplete.cpp in Sources */,
BF89C3FD11595A5D001C2D68 /* SemaExceptionSpec.cpp in Sources */,
1AFDD8721161085D00AE030A /* ASTMerge.cpp in Sources */,
- 1AFDD8731161085D00AE030A /* CodeGenAction.cpp in Sources */,
1ABD23D61182449800A48E65 /* APValue.cpp in Sources */,
1ABD23D71182449800A48E65 /* ASTConsumer.cpp in Sources */,
1ABD23D81182449800A48E65 /* ASTContext.cpp in Sources */,
@@ -2239,8 +2297,6 @@
BFE2F6B511DA955A0007EDC0 /* RewriteMacros.d in Sources */,
BFE2F6B711DA955A0007EDC0 /* RewriteObjC.d in Sources */,
BFE2F6B911DA955A0007EDC0 /* Rewriter.d in Sources */,
- BFE2F6BB11DA955A0007EDC0 /* RewriteRope.d in Sources */,
- BFE2F6BD11DA955A0007EDC0 /* RewriteTest.d in Sources */,
BFE2F6BF11DA955A0007EDC0 /* TokenRewriter.d in Sources */,
BFE2F6C111DA955A0007EDC0 /* DeltaTree.cpp in Sources */,
BFE2F6C211DA955A0007EDC0 /* FixItRewriter.cpp in Sources */,
@@ -2251,7 +2307,6 @@
BFE2F6C711DA955A0007EDC0 /* DeltaTree.d in Sources */,
BFE2F6C911DA955A0007EDC0 /* HTMLRewrite.d in Sources */,
BFE2F6CB11DA955A0007EDC0 /* Rewriter.d in Sources */,
- BFE2F6CD11DA955A0007EDC0 /* RewriteRope.d in Sources */,
BFE2F6CF11DA955A0007EDC0 /* TokenRewriter.d in Sources */,
BFE2F6D111DA955A0007EDC0 /* RewriteMacros.cpp in Sources */,
BFE2F6D211DA955A0007EDC0 /* RewriteObjC.cpp in Sources */,
@@ -2259,6 +2314,28 @@
BFE2F6D411DA955A0007EDC0 /* RewriteRope.cpp in Sources */,
BFE2F6D511DA955A0007EDC0 /* RewriteTest.cpp in Sources */,
BFE2F6D611DA955A0007EDC0 /* TokenRewriter.cpp in Sources */,
+ 57EB566A121B034300ECA335 /* GeneratePCH.cpp in Sources */,
+ 57EB566B121B034300ECA335 /* Makefile in Sources */,
+ 57F66612121B4DE600DCE3B7 /* ASTWriter.cpp in Sources */,
+ 57F66613121B4DE600DCE3B7 /* ASTWriterDecl.cpp in Sources */,
+ 57F66614121B4DE600DCE3B7 /* ASTWriterStmt.cpp in Sources */,
+ 57AA9250121C8B9400B4AA6C /* ASTReader.cpp in Sources */,
+ 57AA9251121C8B9400B4AA6C /* ASTReaderDecl.cpp in Sources */,
+ 57AA9252121C8B9400B4AA6C /* ASTReaderStmt.cpp in Sources */,
+ BF9FEDF91225E67B003A8B71 /* Action.cpp in Sources */,
+ BF9FEDFB1225E6A9003A8B71 /* AttributeList.cpp in Sources */,
+ BF9FEDFD1225E6C6003A8B71 /* DeclSpec.cpp in Sources */,
+ BF9FEDFF1225E6DD003A8B71 /* TargetAttributesSema.cpp in Sources */,
+ BF9FEE021225E73F003A8B71 /* ExprClassification.cpp in Sources */,
+ BF9FEE041225E759003A8B71 /* ItaniumCXXABI.cpp in Sources */,
+ BF9FEE061225E770003A8B71 /* MicrosoftCXXABI.cpp in Sources */,
+ BF9FEE2C1225E7EA003A8B71 /* BackendUtil.cpp in Sources */,
+ BF9FEE311225E86C003A8B71 /* CodeGenAction.cpp in Sources */,
+ BF9FEE331225E898003A8B71 /* ItaniumCXXABI.cpp in Sources */,
+ BF9FEE351225E8B1003A8B71 /* MicrosoftCXXABI.cpp in Sources */,
+ BF9FEE381225E925003A8B71 /* BoostConAction.cpp in Sources */,
+ BF9FEE521226FE9F003A8B71 /* ParseAST.cpp in Sources */,
+ BF9FEEF2122D8068003A8B71 /* PreprocessingRecord.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/docs/InternalsManual.html b/docs/InternalsManual.html
index 7aa26e00a4f1..6df26db8cfeb 100644
--- a/docs/InternalsManual.html
+++ b/docs/InternalsManual.html
@@ -707,9 +707,10 @@ above, it would be the location of the "a" identifier.</li>
last token replaced with the annotation token. In the example above, it would
be the location of the "c" identifier.</li>
-<li><b>void* "AnnotationValue"</b> - This contains an opaque object that the
-parser gets from Sema through an Actions module, it is passed around and Sema
-interprets it, based on the type of annotation token.</li>
+<li><b>void* "AnnotationValue"</b> - This contains an opaque object
+that the parser gets from Sema. The parser merely preserves the
+information for Sema to later interpret based on the annotation token
+kind.</li>
<li><b>TokenKind "Kind"</b> - This indicates the kind of Annotation token this
is. See below for the different valid kinds.</li>
@@ -719,21 +720,29 @@ is. See below for the different valid kinds.</li>
<ol>
<li><b>tok::annot_typename</b>: This annotation token represents a
-resolved typename token that is potentially qualified. The AnnotationValue
-field contains a pointer returned by Action::getTypeName(). In the case of the
-Sema actions module, this is a <tt>Decl*</tt> for the type.</li>
-
-<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++ scope
-specifier, such as "A::B::". This corresponds to the grammar productions "::"
-and ":: [opt] nested-name-specifier". The AnnotationValue pointer is returned
-by the Action::ActOnCXXGlobalScopeSpecifier and
-Action::ActOnCXXNestedNameSpecifier callbacks. In the case of Sema, this is a
-<tt>DeclContext*</tt>.</li>
+resolved typename token that is potentially qualified. The
+AnnotationValue field contains the <tt>QualType</tt> returned by
+Sema::getTypeName(), possibly with source location information
+attached.</li>
+
+<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++
+scope specifier, such as "A::B::". This corresponds to the grammar
+productions "::" and ":: [opt] nested-name-specifier". The
+AnnotationValue pointer is a <tt>NestedNameSpecifier*</tt> returned by
+the Sema::ActOnCXXGlobalScopeSpecifier and
+Sema::ActOnCXXNestedNameSpecifier callbacks.</li>
<li><b>tok::annot_template_id</b>: This annotation token represents a
C++ template-id such as "foo&lt;int, 4&gt;", where "foo" is the name
of a template. The AnnotationValue pointer is a pointer to a malloc'd
-TemplateIdAnnotation object. Depending on the context, a parsed template-id that names a type might become a typename annotation token (if all we care about is the named type, e.g., because it occurs in a type specifier) or might remain a template-id token (if we want to retain more source location information or produce a new type, e.g., in a declaration of a class template specialization). template-id annotation tokens that refer to a type can be "upgraded" to typename annotation tokens by the parser.</li>
+TemplateIdAnnotation object. Depending on the context, a parsed
+template-id that names a type might become a typename annotation token
+(if all we care about is the named type, e.g., because it occurs in a
+type specifier) or might remain a template-id token (if we want to
+retain more source location information or produce a new type, e.g.,
+in a declaration of a class template specialization). template-id
+annotation tokens that refer to a type can be "upgraded" to typename
+annotation tokens by the parser.</li>
</ol>
@@ -953,11 +962,12 @@ make sense to you :).</p>
<h3 id="QualType">The QualType class</h3>
<!-- ======================================================================= -->
-<p>The QualType class is designed as a trivial value class that is small,
-passed by-value and is efficient to query. The idea of QualType is that it
-stores the type qualifiers (const, volatile, restrict) separately from the types
-themselves: QualType is conceptually a pair of "Type*" and bits for the type
-qualifiers.</p>
+<p>The QualType class is designed as a trivial value class that is
+small, passed by-value and is efficient to query. The idea of
+QualType is that it stores the type qualifiers (const, volatile,
+restrict, plus some extended qualifiers required by language
+extensions) separately from the types themselves. QualType is
+conceptually a pair of "Type*" and the bits for these type qualifiers.</p>
<p>By storing the type qualifiers as bits in the conceptual pair, it is
extremely efficient to get the set of qualifiers on a QualType (just return the
@@ -972,10 +982,11 @@ both point to the same heap allocated "int" type). This reduces the heap size
used to represent bits and also means we do not have to consider qualifiers when
uniquing types (<a href="#Type">Type</a> does not even contain qualifiers).</p>
-<p>In practice, on hosts where it is safe, the 3 type qualifiers are stored in
-the low bit of the pointer to the Type object. This means that QualType is
-exactly the same size as a pointer, and this works fine on any system where
-malloc'd objects are at least 8 byte aligned.</p>
+<p>In practice, the two most common type qualifiers (const and
+restrict) are stored in the low bits of the pointer to the Type
+object, together with a flag indicating whether extended qualifiers
+are present (which must be heap-allocated). This means that QualType
+is exactly the same size as a pointer.</p>
<!-- ======================================================================= -->
<h3 id="DeclarationName">Declaration names</h3>
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index 838b65f27b81..75a4608993e9 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -40,6 +40,7 @@ td {
<li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li>
<li><a href="#cxx_auto_type">C++0x type inference</a></li>
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
+ <li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
</ul>
<li><a href="#blocks">Blocks</a></li>
<li><a href="#overloading-in-c">Function Overloading in C</a></li>
@@ -301,32 +302,34 @@ not yet implemented will be noted.</p>
<h3 id="cxx_attributes">C++0x attributes</h3>
<p>Use <tt>__has_feature(cxx_attributes)</tt> to determine if support for
-attribute parsing with C++0x's square bracket notation is enabled.
+attribute parsing with C++0x's square bracket notation is enabled.</p>
<h3 id="cxx_deleted_functions">C++0x deleted functions</tt></h3>
<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> to determine if support for
-deleted function definitions (with <tt>= delete</tt>) is enabled.
+deleted function definitions (with <tt>= delete</tt>) is enabled.</p>
<h3 id="cxx_concepts">C++ TR concepts</h3>
<p>Use <tt>__has_feature(cxx_concepts)</tt> to determine if support for
-concepts is enabled. clang does not currently implement this feature.
+concepts is enabled. clang does not currently implement this feature.</p>
<h3 id="cxx_lambdas">C++0x lambdas</h3>
<p>Use <tt>__has_feature(cxx_lambdas)</tt> to determine if support for
-lambdas is enabled. clang does not currently implement this feature.
+lambdas is enabled. clang does not currently implement this feature.</p>
<h3 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3>
<p>Use <tt>__has_feature(cxx_nullptr)</tt> to determine if support for
-<tt>nullptr</tt> is enabled. clang does not yet fully implement this feature.
+<tt>nullptr</tt> is enabled. clang does not yet fully implement this
+feature.</p>
<h3 id="cxx_rvalue_references">C++0x rvalue references</tt></h3>
<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> to determine if support for
-rvalue references is enabled. clang does not yet fully implement this feature.
+rvalue references is enabled. clang does not yet fully implement this
+feature.</p>
<h3 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3>
@@ -339,12 +342,17 @@ compile-time assertions using <tt>static_assert</tt> is enabled.</p>
is supported using the <tt>auto</tt> specifier. If this is disabled,
<tt>auto</tt> will instead be a storage class specifier, as in C or C++98.</p>
-<h3 id="cxx_variadic_templates">C++0x variadic templates</tt></h3>
+<h3 id="cxx_variadic_templates">C++0x variadic templates</h3>
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> to determine if support
for templates taking any number of arguments with the ellipsis notation is
enabled. clang does not yet fully implement this feature.</p>
+<h3 id="cxx_inline_namespaces">C++0x inline namespaces</h3>
+
+<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> to determine if support for
+inline namespaces is enabled.</p>
+
<!-- ======================================================================= -->
<h2 id="blocks">Blocks</h2>
<!-- ======================================================================= -->
diff --git a/docs/UsersManual.html b/docs/UsersManual.html
index 51e699fc32cb..75241610a32d 100644
--- a/docs/UsersManual.html
+++ b/docs/UsersManual.html
@@ -39,6 +39,7 @@ td {
<li><a href="#diagnostics_categories">Diagnostic Categories</a></li>
<li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li>
<li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li>
+ <li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li>
</ul>
<li><a href="#precompiledheaders">Precompiled Headers</a></li>
<li><a href="#codegen">Controlling Code Generation</a></li>
@@ -358,6 +359,18 @@ exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expre
<p>The {}'s are generated by -fdiagnostics-print-source-range-info.</p>
</dd>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<dt id="opt_fdiagnostics-parseable-fixits">
+<b>-fdiagnostics-parseable-fixits</b>:
+Print Fix-Its in a machine parseable form.</dt>
+<dd><p>This option makes Clang print available Fix-Its in a machine parseable format at the end of diagnostics. The following example illustrates the format:</p>
+
+<pre>
+ fix-it:"t.cpp":{7:25-7:29}:"Gamma"
+</pre>
+
+<p>The range printed is a half-open range, so in this example the characters at column 25 up to but not including column 29 on line 7 in t.cpp should be replaced with the string "Gamma". Either the range or the replacement string may be empty (representing strict insertions and strict erasures, respectively). Both the file name and the insertion string escape backslash (as "\\"), tabs (as "\t"), newlines (as "\n"), double quotes(as "\"") and non-printable characters (as octal "\xxx").</p>
+</dd>
</dl>
@@ -579,6 +592,42 @@ GCC do not support the exact same set of warnings, so even when using GCC
compatible #pragmas there is no guarantee that they will have identical behaviour
on both compilers. </p>
+<h4 id="analyzer_diagnositics">Controlling Static Analyzer Diagnostics</h4>
+
+<p>While not strictly part of the compiler, the diagnostics from Clang's <a
+href="http://clang-analyzer.llvm.org">static analyzer</a> can also be influenced
+by the user via changes to the source code. This can be done in two ways:
+
+<ul>
+
+<li id="analyzer_annotations"><b>Annotations</b>: The static analyzer recognizes various GCC-style
+attributes (e.g., <tt>__attribute__((nonnull)))</tt>) that can either suppress
+static analyzer warnings or teach the analyzer about code invariants which
+enable it to find more bugs. While many of these attributes are standard GCC
+attributes, additional ones have added to Clang to specifically support the
+static analyzer. Detailed information on these annotations can be found in the
+<a href="http://clang-analyzer.llvm.org/annotations.html">analyzer's
+documentation</a>.</li>
+
+<li><b><tt>__clang_analyzer__</tt></b>: When the static analyzer is using Clang
+to parse source files, it implicitly defines the preprocessor macro
+<tt>__clang_analyzer__</tt>. While discouraged, code can use this macro to
+selectively exclude code the analyzer examines. Here is an example:
+
+<pre>
+#ifndef __clang_analyzer__
+// Code not to be analyzed
+#endif
+</pre>
+
+In general, this usage is discouraged. Instead, we prefer that users file bugs
+against the analyzer when it flags false positives. There is also active
+discussion of allowing users in the future to selectively silence specific
+analyzer warnings (some which can already be done using <a
+href="analyzer_annotations">annotations</a>).</li>
+
+</ul>
+
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<h3 id="precompiledheaders">Precompiled Headers</h3>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
@@ -789,11 +838,6 @@ soon.</li>
the uses described in the bug, this is likely to be implemented at some
point, at least partially.</li>
-<li>clang does not support #pragma align
-(<a href="http://llvm.org/bugs/show_bug.cgi?id=3811">bug 3811</a>). This is a
-relatively small feature, so it is likely to be implemented relatively
-soon.</li>
-
<li>clang does not support code generation for local variables pinned to
registers (<a href="http://llvm.org/bugs/show_bug.cgi?id=3933">bug 3933</a>).
This is a relatively small feature, so it is likely to be implemented
diff --git a/docs/tools/clang.pod b/docs/tools/clang.pod
index 0c1ab574d535..032efcfcabc5 100644
--- a/docs/tools/clang.pod
+++ b/docs/tools/clang.pod
@@ -168,6 +168,10 @@ Enable support for Pascal-style strings with "\pfoo".
Enable support for Microsoft extensions.
+=item B<-fborland-extensions>
+
+Enable support for Borland extensions.
+
=item B<-fwritable-strings>
Make all string literals default to writable. This disables uniquing of
@@ -395,6 +399,7 @@ Show commands to run and use verbose output.
B<-fshow-source-location>
B<-fcaret-diagnostics>
B<-fdiagnostics-fixit-info>
+B<-fdiagnostics-parseable-fixits>
B<-fdiagnostics-print-source-range-info>
B<-fprint-source-range-info>
B<-fdiagnostics-show-option>
@@ -515,7 +520,6 @@ targets.
=head1 BUGS
-Clang currently does not have C++ support, and this manual page is incomplete.
To report bugs, please visit L<http://llvm.org/bugs/>. Most bug reports should
include preprocessed source files (use the B<-E> option) and the full output of
the compiler, along with information to reproduce.
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index d2738c69035e..9a32ee406523 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,4 +1,3 @@
add_subdirectory(clang-interpreter)
add_subdirectory(PrintFunctionNames)
-add_subdirectory(wpa)
diff --git a/examples/Makefile b/examples/Makefile
index c4af25263398..8cb431d73916 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -9,6 +9,6 @@
CLANG_LEVEL := ..
-PARALLEL_DIRS := clang-interpreter PrintFunctionNames wpa
+PARALLEL_DIRS := clang-interpreter PrintFunctionNames
include $(CLANG_LEVEL)/Makefile
diff --git a/examples/PrintFunctionNames/Makefile b/examples/PrintFunctionNames/Makefile
index 0ff5189437c7..125ac4854ffc 100644
--- a/examples/PrintFunctionNames/Makefile
+++ b/examples/PrintFunctionNames/Makefile
@@ -10,10 +10,15 @@
CLANG_LEVEL := ../..
LIBRARYNAME = PrintFunctionNames
+# If we don't need RTTI or EH, there's no reason to export anything
+# from the plugin.
+ifneq ($(REQUIRES_RTTI), 1)
+ifneq ($(REQUIRES_EH), 1)
+EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/PrintFunctionNames.exports
+endif
+endif
+
LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
-USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
- clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
-
include $(CLANG_LEVEL)/Makefile
diff --git a/examples/PrintFunctionNames/PrintFunctionNames.cpp b/examples/PrintFunctionNames/PrintFunctionNames.cpp
index 397cf843fa7f..cc138f56dbba 100644
--- a/examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ b/examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -15,6 +15,7 @@
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/AST.h"
+#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -29,7 +30,7 @@ public:
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
}
}
-};
+};
class PrintFunctionNamesAction : public PluginASTAction {
protected:
@@ -37,15 +38,26 @@ protected:
return new PrintFunctionsConsumer();
}
- bool ParseArgs(const std::vector<std::string>& args) {
- for (unsigned i=0; i<args.size(); ++i)
+ bool ParseArgs(const CompilerInstance &CI,
+ const std::vector<std::string>& args) {
+ for (unsigned i = 0, e = args.size(); i != e; ++i) {
llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
+
+ // Example error handling.
+ if (args[i] == "-an-error") {
+ Diagnostic &D = CI.getDiagnostics();
+ unsigned DiagID = D.getCustomDiagID(
+ Diagnostic::Error, "invalid argument '" + args[i] + "'");
+ D.Report(DiagID);
+ return false;
+ }
+ }
if (args.size() && args[0] == "help")
PrintHelp(llvm::errs());
return true;
}
- void PrintHelp(llvm::raw_ostream& ros) {
+ void PrintHelp(llvm::raw_ostream& ros) {
ros << "Help for PrintFunctionNames plugin goes here\n";
}
@@ -53,5 +65,5 @@ protected:
}
-FrontendPluginRegistry::Add<PrintFunctionNamesAction>
+static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
X("print-fns", "print function names");
diff --git a/examples/PrintFunctionNames/PrintFunctionNames.exports b/examples/PrintFunctionNames/PrintFunctionNames.exports
new file mode 100644
index 000000000000..0ff590d30d7b
--- /dev/null
+++ b/examples/PrintFunctionNames/PrintFunctionNames.exports
@@ -0,0 +1 @@
+_ZN4llvm8Registry*
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index 1aa9b2b59224..73f28bb7a2e7 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -2,10 +2,12 @@ set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangFrontend
+ clangSerialization
clangDriver
clangCodeGen
clangSema
clangChecker
+ clangIndex
clangAnalysis
clangRewrite
clangAST
diff --git a/examples/clang-interpreter/Makefile b/examples/clang-interpreter/Makefile
index 6fa58d22cbd9..2f5e017af803 100644
--- a/examples/clang-interpreter/Makefile
+++ b/examples/clang-interpreter/Makefile
@@ -17,8 +17,8 @@ TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
selectiondag asmparser
-USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
- clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
- clangParse.a clangLex.a clangBasic.a
+USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
+ clangSema.a clangChecker.a clangAnalysis.a clangRewrite.a \
+ clangAST.a clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp
index ec4e8619829f..2ccba8b24a85 100644
--- a/examples/clang-interpreter/main.cpp
+++ b/examples/clang-interpreter/main.cpp
@@ -66,11 +66,11 @@ int Execute(llvm::Module *Mod, char * const *envp) {
int main(int argc, const char **argv, char * const *envp) {
void *MainAddr = (void*) (intptr_t) GetExecutablePath;
llvm::sys::Path Path = GetExecutablePath(argv[0]);
- TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
+ TextDiagnosticPrinter *DiagClient =
+ new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
- Diagnostic Diags(&DiagClient);
- Driver TheDriver(Path.getBasename(), Path.getDirname(),
- llvm::sys::getHostTriple(),
+ Diagnostic Diags(DiagClient);
+ Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
"a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
Diags);
TheDriver.setTitle("clang interpreter");
diff --git a/examples/wpa/CMakeLists.txt b/examples/wpa/CMakeLists.txt
index c2b2ce63a934..13e4298c1f2e 100644
--- a/examples/wpa/CMakeLists.txt
+++ b/examples/wpa/CMakeLists.txt
@@ -6,6 +6,7 @@ set(LLVM_USED_LIBS
clangDriver
clangSema
clangAnalysis
+ clangSerialization
clangChecker
clangRewrite
clangAST
diff --git a/examples/wpa/Makefile b/examples/wpa/Makefile
index bd6ebfdc9bfe..0a70ea6359c8 100644
--- a/examples/wpa/Makefile
+++ b/examples/wpa/Makefile
@@ -17,7 +17,7 @@ TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := asmparser bitreader mc core
USEDLIBS = clangChecker.a clangIndex.a clangFrontend.a clangDriver.a \
- clangSema.a clangAnalysis.a clangAST.a clangParse.a clangLex.a \
- clangBasic.a
+ clangSema.a clangAnalysis.a clangSerialization.a \
+ clangAST.a clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
diff --git a/examples/wpa/clang-wpa.cpp b/examples/wpa/clang-wpa.cpp
index 74ec368cfbe7..41dca0dc451e 100644
--- a/examples/wpa/clang-wpa.cpp
+++ b/examples/wpa/clang-wpa.cpp
@@ -62,6 +62,10 @@ public:
return AST->getPreprocessor();
}
+ virtual Diagnostic &getDiagnostic() {
+ return AST->getDiagnostics();
+ }
+
virtual DeclReferenceMap &getDeclReferenceMap() {
return DeclRefMap;
}
@@ -87,7 +91,7 @@ int main(int argc, char **argv) {
= CompilerInstance::createDiagnostics(DiagOpts, argc, argv);
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
const std::string &InFile = InputFilenames[i];
- llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, Diags));
+ llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromASTFile(InFile, Diags));
if (!AST)
return 1;
@@ -129,17 +133,18 @@ int main(int argc, char **argv) {
AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
PP.getLangOptions(), /* PathDiagnostic */ 0,
CreateRegionStoreManager,
- CreateRangeConstraintManager,
+ CreateRangeConstraintManager, &Idxer,
/* MaxNodes */ 300000, /* MaxLoop */ 3,
/* VisualizeEG */ false, /* VisualizeEGUbi */ false,
/* PurgeDead */ true, /* EagerlyAssume */ false,
- /* TrimGraph */ false, /* InlineCall */ true);
+ /* TrimGraph */ false, /* InlineCall */ true,
+ /* UseUnoptimizedCFG */ false);
GRTransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false,
AMgr.getLangOptions());
GRExprEngine Eng(AMgr, TF);
- Eng.ExecuteWorkList(AMgr.getStackFrame(FD), AMgr.getMaxNodes());
+ Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
return 0;
}
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index b377b6d5fe2c..4631c65bf05a 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -98,6 +98,27 @@ struct CXUnsavedFile {
};
/**
+ * \brief Describes the availability of a particular entity, which indicates
+ * whether the use of this entity will result in a warning or error due to
+ * it being deprecated or unavailable.
+ */
+enum CXAvailabilityKind {
+ /**
+ * \brief The entity is available.
+ */
+ CXAvailability_Available,
+ /**
+ * \brief The entity is available, but has been deprecated (and its use is
+ * not recommended).
+ */
+ CXAvailability_Deprecated,
+ /**
+ * \brief The entity is not available; any use of it will be an error.
+ */
+ CXAvailability_NotAvailable
+};
+
+/**
* \defgroup CINDEX_STRING String manipulation routines
*
* @{
@@ -624,7 +645,7 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CXIndex CIdx,
const char *source_filename,
int num_clang_command_line_args,
- const char **clang_command_line_args,
+ const char * const *clang_command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files);
@@ -635,11 +656,261 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
const char *ast_filename);
/**
+ * \brief Flags that control the creation of translation units.
+ *
+ * The enumerators in this enumeration type are meant to be bitwise
+ * ORed together to specify which options should be used when
+ * constructing the translation unit.
+ */
+enum CXTranslationUnit_Flags {
+ /**
+ * \brief Used to indicate that no special translation-unit options are
+ * needed.
+ */
+ CXTranslationUnit_None = 0x0,
+
+ /**
+ * \brief Used to indicate that the parser should construct a "detailed"
+ * preprocessing record, including all macro definitions and instantiations.
+ *
+ * Constructing a detailed preprocessing record requires more memory
+ * and time to parse, since the information contained in the record
+ * is usually not retained. However, it can be useful for
+ * applications that require more detailed information about the
+ * behavior of the preprocessor.
+ */
+ CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
+
+ /**
+ * \brief Used to indicate that the translation unit is incomplete.
+ *
+ * When a translation unit is considered "incomplete", semantic
+ * analysis that is typically performed at the end of the
+ * translation unit will be suppressed. For example, this suppresses
+ * the completion of tentative declarations in C and of
+ * instantiation of implicitly-instantiation function templates in
+ * C++. This option is typically used when parsing a header with the
+ * intent of producing a precompiled header.
+ */
+ CXTranslationUnit_Incomplete = 0x02,
+
+ /**
+ * \brief Used to indicate that the translation unit should be built with an
+ * implicit precompiled header for the preamble.
+ *
+ * An implicit precompiled header is used as an optimization when a
+ * particular translation unit is likely to be reparsed many times
+ * when the sources aren't changing that often. In this case, an
+ * implicit precompiled header will be built containing all of the
+ * initial includes at the top of the main file (what we refer to as
+ * the "preamble" of the file). In subsequent parses, if the
+ * preamble or the files in it have not changed, \c
+ * clang_reparseTranslationUnit() will re-use the implicit
+ * precompiled header to improve parsing performance.
+ */
+ CXTranslationUnit_PrecompiledPreamble = 0x04,
+
+ /**
+ * \brief Used to indicate that the translation unit should cache some
+ * code-completion results with each reparse of the source file.
+ *
+ * Caching of code-completion results is a performance optimization that
+ * introduces some overhead to reparsing but improves the performance of
+ * code-completion operations.
+ */
+ CXTranslationUnit_CacheCompletionResults = 0x08
+};
+
+/**
+ * \brief Returns the set of flags that is suitable for parsing a translation
+ * unit that is being edited.
+ *
+ * The set of flags returned provide options for \c clang_parseTranslationUnit()
+ * to indicate that the translation unit is likely to be reparsed many times,
+ * either explicitly (via \c clang_reparseTranslationUnit()) or implicitly
+ * (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag
+ * set contains an unspecified set of optimizations (e.g., the precompiled
+ * preamble) geared toward improving the performance of these routines. The
+ * set of optimizations enabled may change from one version to the next.
+ */
+CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
+
+/**
+ * \brief Parse the given source file and the translation unit corresponding
+ * to that file.
+ *
+ * This routine is the main entry point for the Clang C API, providing the
+ * ability to parse a source file into a translation unit that can then be
+ * queried by other functions in the API. This routine accepts a set of
+ * command-line arguments so that the compilation can be configured in the same
+ * way that the compiler is configured on the command line.
+ *
+ * \param CIdx The index object with which the translation unit will be
+ * associated.
+ *
+ * \param source_filename The name of the source file to load, or NULL if the
+ * source file is included in \p clang_command_line_args.
+ *
+ * \param command_line_args The command-line arguments that would be
+ * passed to the \c clang executable if it were being invoked out-of-process.
+ * These command-line options will be parsed and will affect how the translation
+ * unit is parsed. Note that the following options are ignored: '-c',
+ * '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'.
+ *
+ * \param num_command_line_args The number of command-line arguments in
+ * \p command_line_args.
+ *
+ * \param unsaved_files the files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param num_unsaved_files the number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is managed but not its compilation. This should be a bitwise OR of the
+ * CXTranslationUnit_XXX flags.
+ *
+ * \returns A new translation unit describing the parsed code and containing
+ * any diagnostics produced by the compiler. If there is a failure from which
+ * the compiler cannot recover, returns NULL.
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options);
+
+/**
+ * \brief Flags that control how translation units are saved.
+ *
+ * The enumerators in this enumeration type are meant to be bitwise
+ * ORed together to specify which options should be used when
+ * saving the translation unit.
+ */
+enum CXSaveTranslationUnit_Flags {
+ /**
+ * \brief Used to indicate that no special saving options are needed.
+ */
+ CXSaveTranslationUnit_None = 0x0
+};
+
+/**
+ * \brief Returns the set of flags that is suitable for saving a translation
+ * unit.
+ *
+ * The set of flags returned provide options for
+ * \c clang_saveTranslationUnit() by default. The returned flag
+ * set contains an unspecified set of options that save translation units with
+ * the most commonly-requested data.
+ */
+CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU);
+
+/**
+ * \brief Saves a translation unit into a serialized representation of
+ * that translation unit on disk.
+ *
+ * Any translation unit that was parsed without error can be saved
+ * into a file. The translation unit can then be deserialized into a
+ * new \c CXTranslationUnit with \c clang_createTranslationUnit() or,
+ * if it is an incomplete translation unit that corresponds to a
+ * header, used as a precompiled header when parsing other translation
+ * units.
+ *
+ * \param TU The translation unit to save.
+ *
+ * \param FileName The file to which the translation unit will be saved.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is saved. This should be a bitwise OR of the
+ * CXSaveTranslationUnit_XXX flags.
+ *
+ * \returns Zero if the translation unit was saved successfully, a
+ * non-zero value otherwise.
+ */
+CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
+ const char *FileName,
+ unsigned options);
+
+/**
* \brief Destroy the specified CXTranslationUnit object.
*/
CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
/**
+ * \brief Flags that control the reparsing of translation units.
+ *
+ * The enumerators in this enumeration type are meant to be bitwise
+ * ORed together to specify which options should be used when
+ * reparsing the translation unit.
+ */
+enum CXReparse_Flags {
+ /**
+ * \brief Used to indicate that no special reparsing options are needed.
+ */
+ CXReparse_None = 0x0
+};
+
+/**
+ * \brief Returns the set of flags that is suitable for reparsing a translation
+ * unit.
+ *
+ * The set of flags returned provide options for
+ * \c clang_reparseTranslationUnit() by default. The returned flag
+ * set contains an unspecified set of optimizations geared toward common uses
+ * of reparsing. The set of optimizations enabled may change from one version
+ * to the next.
+ */
+CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
+
+/**
+ * \brief Reparse the source files that produced this translation unit.
+ *
+ * This routine can be used to re-parse the source files that originally
+ * created the given translation unit, for example because those source files
+ * have changed (either on disk or as passed via \p unsaved_files). The
+ * source code will be reparsed with the same command-line options as it
+ * was originally parsed.
+ *
+ * Reparsing a translation unit invalidates all cursors and source locations
+ * that refer into that translation unit. This makes reparsing a translation
+ * unit semantically equivalent to destroying the translation unit and then
+ * creating a new translation unit with the same command-line arguments.
+ * However, it may be more efficient to reparse a translation
+ * unit using this routine.
+ *
+ * \param TU The translation unit whose contents will be re-parsed. The
+ * translation unit must originally have been built with
+ * \c clang_createTranslationUnitFromSourceFile().
+ *
+ * \param num_unsaved_files The number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param unsaved_files The files that have not yet been saved to disk
+ * but may be required for parsing, including the contents of
+ * those files. The contents and name of these files (as specified by
+ * CXUnsavedFile) are copied when necessary, so the client only needs to
+ * guarantee their validity until the call to this function returns.
+ *
+ * \param options A bitset of options composed of the flags in CXReparse_Flags.
+ * The function \c clang_defaultReparseOptions() produces a default set of
+ * options recommended for most uses, based on the translation unit.
+ *
+ * \returns 0 if the sources could be reparsed. A non-zero value will be
+ * returned if reparsing was impossible, such that the translation unit is
+ * invalid. In such cases, the only valid call for \p TU is
+ * \c clang_disposeTranslationUnit(TU).
+ */
+CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options);
+
+/**
* @}
*/
@@ -705,9 +976,33 @@ enum CXCursorKind {
CXCursor_Namespace = 22,
/** \brief A linkage specification, e.g. 'extern "C"'. */
CXCursor_LinkageSpec = 23,
-
+ /** \brief A C++ constructor. */
+ CXCursor_Constructor = 24,
+ /** \brief A C++ destructor. */
+ CXCursor_Destructor = 25,
+ /** \brief A C++ conversion function. */
+ CXCursor_ConversionFunction = 26,
+ /** \brief A C++ template type parameter. */
+ CXCursor_TemplateTypeParameter = 27,
+ /** \brief A C++ non-type template parameter. */
+ CXCursor_NonTypeTemplateParameter = 28,
+ /** \brief A C++ template template parameter. */
+ CXCursor_TemplateTemplateParameter = 29,
+ /** \brief A C++ function template. */
+ CXCursor_FunctionTemplate = 30,
+ /** \brief A C++ class template. */
+ CXCursor_ClassTemplate = 31,
+ /** \brief A C++ class template partial specialization. */
+ CXCursor_ClassTemplatePartialSpecialization = 32,
+ /** \brief A C++ namespace alias declaration. */
+ CXCursor_NamespaceAlias = 33,
+ /** \brief A C++ using directive. */
+ CXCursor_UsingDirective = 34,
+ /** \brief A using declaration. */
+ CXCursor_UsingDeclaration = 35,
+
CXCursor_FirstDecl = CXCursor_UnexposedDecl,
- CXCursor_LastDecl = CXCursor_LinkageSpec,
+ CXCursor_LastDecl = CXCursor_UsingDeclaration,
/* References */
CXCursor_FirstRef = 40, /* Decl references */
@@ -730,7 +1025,17 @@ enum CXCursorKind {
* referenced by the type of size is the typedef for size_type.
*/
CXCursor_TypeRef = 43,
- CXCursor_LastRef = 43,
+ CXCursor_CXXBaseSpecifier = 44,
+ /**
+ * \brief A reference to a class template, function template, or template
+ * template parameter.
+ */
+ CXCursor_TemplateRef = 45,
+ /**
+ * \brief A reference to a namespace or namespace alias.
+ */
+ CXCursor_NamespaceRef = 46,
+ CXCursor_LastRef = CXCursor_NamespaceRef,
/* Error conditions */
CXCursor_FirstInvalid = 70,
@@ -949,6 +1254,16 @@ enum CXLinkageKind {
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
/**
+ * \brief Determine the availability of the entity that this cursor refers to.
+ *
+ * \param cursor The cursor to query.
+ *
+ * \returns The availability of the cursor.
+ */
+CINDEX_LINKAGE enum CXAvailabilityKind
+clang_getCursorAvailability(CXCursor cursor);
+
+/**
* \brief Describe the "language" of the entity referred to by a cursor.
*/
CINDEX_LINKAGE enum CXLanguageKind {
@@ -1023,7 +1338,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
/**
* @}
*/
-
+
/**
* \defgroup CINDEX_TYPES Type information for CXCursors
*
@@ -1152,6 +1467,53 @@ CINDEX_LINKAGE CXType clang_getResultType(CXType T);
CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
/**
+ * \brief Return 1 if the CXType is a POD (plain old data) type, and 0
+ * otherwise.
+ */
+CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
+
+/**
+ * \brief Returns 1 if the base class specified by the cursor with kind
+ * CX_CXXBaseSpecifier is virtual.
+ */
+CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
+
+/**
+ * \brief Represents the C++ access control level to a base class for a
+ * cursor with kind CX_CXXBaseSpecifier.
+ */
+enum CX_CXXAccessSpecifier {
+ CX_CXXInvalidAccessSpecifier,
+ CX_CXXPublic,
+ CX_CXXProtected,
+ CX_CXXPrivate
+};
+
+/**
+ * \brief Returns the access control level for the C++ base specifier
+ * represented by a cursor with kind CX_CXXBaseSpecifier.
+ */
+CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
+
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_ATTRIBUTES Information for attributes
+ *
+ * @{
+ */
+
+
+/**
+ * \brief For cursors representing an iboutletcollection attribute,
+ * this function returns the collection element type.
+ *
+ */
+CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor);
+
+/**
* @}
*/
@@ -1364,11 +1726,61 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
*/
/**
- * \brief Determine if a C++ member function is declared 'static'.
+ * \brief Determine if a C++ member function or member function template is
+ * declared 'static'.
*/
CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
/**
+ * \brief Given a cursor that represents a template, determine
+ * the cursor kind of the specializations would be generated by instantiating
+ * the template.
+ *
+ * This routine can be used to determine what flavor of function template,
+ * class template, or class template partial specialization is stored in the
+ * cursor. For example, it can describe whether a class template cursor is
+ * declared with "struct", "class" or "union".
+ *
+ * \param C The cursor to query. This cursor should represent a template
+ * declaration.
+ *
+ * \returns The cursor kind of the specializations that would be generated
+ * by instantiating the template \p C. If \p C is not a template, returns
+ * \c CXCursor_NoDeclFound.
+ */
+CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
+
+/**
+ * \brief Given a cursor that may represent a specialization or instantiation
+ * of a template, retrieve the cursor that represents the template that it
+ * specializes or from which it was instantiated.
+ *
+ * This routine determines the template involved both for explicit
+ * specializations of templates and for implicit instantiations of the template,
+ * both of which are referred to as "specializations". For a class template
+ * specialization (e.g., \c std::vector<bool>), this routine will return
+ * either the primary template (\c std::vector) or, if the specialization was
+ * instantiated from a class template partial specialization, the class template
+ * partial specialization. For a class template partial specialization and a
+ * function template specialization (including instantiations), this
+ * this routine will return the specialized template.
+ *
+ * For members of a class template (e.g., member functions, member classes, or
+ * static data members), returns the specialized or instantiated member.
+ * Although not strictly "templates" in the C++ language, members of class
+ * templates have the same notions of specializations and instantiations that
+ * templates do, so this routine treats them similarly.
+ *
+ * \param C A cursor that may be a specialization of a template or a member
+ * of a template.
+ *
+ * \returns If the given cursor is a specialization or instantiation of a
+ * template or a member thereof, the template or member that it specializes or
+ * from which it was instantiated. Otherwise, returns a NULL cursor.
+ */
+CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
+
+/**
* @}
*/
@@ -1817,6 +2229,17 @@ CINDEX_LINKAGE unsigned
clang_getCompletionPriority(CXCompletionString completion_string);
/**
+ * \brief Determine the availability of the entity that this code-completion
+ * string refers to.
+ *
+ * \param completion_string The completion string to query.
+ *
+ * \returns The availability of the completion string.
+ */
+CINDEX_LINKAGE enum CXAvailabilityKind
+clang_getCompletionAvailability(CXCompletionString completion_string);
+
+/**
* \brief Contains the results of code-completion.
*
* This data structure contains the results of code completion, as
@@ -1922,7 +2345,7 @@ CINDEX_LINKAGE
CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
- const char **command_line_args,
+ const char * const *command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
const char *complete_filename,
@@ -1930,11 +2353,126 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
unsigned complete_column);
/**
+ * \brief Flags that can be passed to \c clang_codeCompleteAt() to
+ * modify its behavior.
+ *
+ * The enumerators in this enumeration can be bitwise-OR'd together to
+ * provide multiple options to \c clang_codeCompleteAt().
+ */
+enum CXCodeComplete_Flags {
+ /**
+ * \brief Whether to include macros within the set of code
+ * completions returned.
+ */
+ CXCodeComplete_IncludeMacros = 0x01,
+
+ /**
+ * \brief Whether to include code patterns for language constructs
+ * within the set of code completions, e.g., for loops.
+ */
+ CXCodeComplete_IncludeCodePatterns = 0x02
+};
+
+/**
+ * \brief Returns a default set of code-completion options that can be
+ * passed to\c clang_codeCompleteAt().
+ */
+CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
+
+/**
+ * \brief Perform code completion at a given location in a translation unit.
+ *
+ * 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
+ * returned via a new \c CXCodeCompleteResults structure.
+ *
+ * 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-completion
+ * results from the filtering of results on a per-character basis, which must
+ * have a lower latency.
+ *
+ * \param TU The translation unit in which code-completion should
+ * occur. The source files for this translation unit need not be
+ * completely up-to-date (and the contents of those source files may
+ * be overridden via \p unsaved_files). Cursors referring into the
+ * translation unit may be invalidated by this invocation.
+ *
+ * \param complete_filename The name of the source file where code
+ * completion should be performed. This filename may be any file
+ * included in the translation unit.
+ *
+ * \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 unsaved_files the Tiles that have not yet been saved to disk
+ * but may be required for parsing or code completion, including the
+ * contents of those files. The contents and name of these files (as
+ * specified by CXUnsavedFile) are copied when necessary, so the
+ * client only needs to guarantee their validity until the call to
+ * this function returns.
+ *
+ * \param num_unsaved_files The number of unsaved file entries in \p
+ * unsaved_files.
+ *
+ * \param options Extra options that control the behavior of code
+ * completion, expressed as a bitwise OR of the enumerators of the
+ * CXCodeComplete_Flags enumeration. The
+ * \c clang_defaultCodeCompleteOptions() function returns a default set
+ * of code-completion options.
+ *
+ * \returns If successful, a new \c CXCodeCompleteResults structure
+ * containing code-completion results, which should eventually be
+ * freed with \c clang_disposeCodeCompleteResults(). If code
+ * completion fails, returns NULL.
+ */
+CINDEX_LINKAGE
+CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options);
+
+/**
+ * \brief Sort the code-completion results in case-insensitive alphabetical
+ * order.
+ *
+ * \param Results The set of results to sort.
+ * \param NumResults The number of results in \p Results.
+ */
+CINDEX_LINKAGE
+void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+ unsigned NumResults);
+
+/**
* \brief Free the given set of code-completion results.
*/
CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
-
+
/**
* \brief Determine the number of diagnostics produced prior to the
* location where code completion was performed.
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index 06113954fc48..84833c099f97 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -18,9 +18,10 @@ namespace clang {
class ASTContext;
class CXXRecordDecl;
class DeclGroupRef;
- class TagDecl;
class HandleTagDeclDefinition;
+ class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
+ class TagDecl;
class VarDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by
@@ -48,6 +49,11 @@ public:
/// elements). Use Decl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(DeclGroupRef D);
+ /// HandleInterestingDecl - Handle the specified interesting declaration. This
+ /// is called by the AST reader when deserializing things that might interest
+ /// the consumer. The default implementation forwards to HandleTopLevelDecl.
+ virtual void HandleInterestingDecl(DeclGroupRef D);
+
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
@@ -80,6 +86,12 @@ public:
/// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
+ /// \brief If the consumer is interested in entities being deserialized from
+ /// AST files, it should return a pointer to a ASTDeserializationListener here
+ ///
+ /// The return type is void* because ASTDS lives in Frontend.
+ virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
+
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {}
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 3799451360f4..ae4ee946fe27 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -18,7 +18,6 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
@@ -50,6 +49,7 @@ namespace clang {
class SelectorTable;
class SourceManager;
class TargetInfo;
+ class CXXABI;
// Decls
class DeclContext;
class CXXMethodDecl;
@@ -198,7 +198,7 @@ class ASTContext {
///
/// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class.
- llvm::DenseMap<const Decl*, Attr*> DeclAttrs;
+ llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
/// \brief Keeps track of the static data member templates from which
/// static data members of class template specializations were instantiated.
@@ -275,13 +275,18 @@ class ASTContext {
/// this ASTContext object.
LangOptions LangOpts;
- /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
- bool FreeMemory;
- llvm::MallocAllocator MallocAlloc;
+ /// \brief The allocator used to create AST objects.
+ ///
+ /// AST objects are never destructed; rather, all memory associated with the
+ /// AST objects will be released when the ASTContext itself is destroyed.
llvm::BumpPtrAllocator BumpAlloc;
/// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
+
+ /// \brief The current C++ ABI.
+ llvm::OwningPtr<CXXABI> ABI;
+ CXXABI *createCXXABI(const TargetInfo &T);
public:
const TargetInfo &Target;
@@ -301,13 +306,9 @@ public:
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) {
- return FreeMemory ? MallocAlloc.Allocate(Size, Align) :
- BumpAlloc.Allocate(Size, Align);
- }
- void Deallocate(void *Ptr) {
- if (FreeMemory)
- MallocAlloc.Deallocate(Ptr);
+ return BumpAlloc.Allocate(Size, Align);
}
+ void Deallocate(void *Ptr) { }
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
@@ -320,10 +321,10 @@ public:
}
/// \brief Retrieve the attributes for the given declaration.
- Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; }
+ AttrVec& getDeclAttrs(const Decl *D);
/// \brief Erase the attributes corresponding to the given declaration.
- void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); }
+ void eraseDeclAttrs(const Decl *D);
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
@@ -393,7 +394,7 @@ public:
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
- bool FreeMemory = true, unsigned size_reserve=0);
+ unsigned size_reserve);
~ASTContext();
@@ -520,7 +521,7 @@ public:
llvm::SmallVectorImpl<const Expr *> &Layout);
/// This builds the struct used for __block variables.
- QualType BuildByRefType(const char *DeclName, QualType Ty);
+ QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty);
/// Returns true iff we need copy/dispose helpers for the given type.
bool BlockRequiresCopying(QualType Ty);
@@ -873,7 +874,8 @@ public:
return getExtQualType(T, Qs);
}
- DeclarationName getNameForTemplate(TemplateName Name);
+ DeclarationNameInfo getNameForTemplate(TemplateName Name,
+ SourceLocation NameLoc);
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
@@ -909,6 +911,11 @@ public:
///
Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
+ /// areCompatibleVectorTypes - Return true if the given vector types either
+ /// are of the same unqualified type or if one is GCC and other - equivalent
+ /// AltiVec vector type.
+ bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
+
/// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set.
bool isObjCNSObjectType(QualType Ty) const;
@@ -1002,13 +1009,12 @@ public:
/// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
- void CollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<FieldDecl*> &Fields);
-
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
- void CollectNonClassIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
+ void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
+ llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@@ -1067,8 +1073,6 @@ public:
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
- /// \brief Retrieves the "canonical" declaration of
-
/// \brief Retrieves the "canonical" nested name specifier for a
/// given nested name specifier.
///
@@ -1218,7 +1222,8 @@ public:
//===--------------------------------------------------------------------===//
/// Compatibility predicates used to check assignment expressions.
- bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
+ bool typesAreCompatible(QualType T1, QualType T2,
+ bool CompareUnqualified = false); // C99 6.2.7p1
bool typesAreBlockPointerCompatible(QualType, QualType);
@@ -1235,6 +1240,8 @@ public:
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare);
+ bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
+
// Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
@@ -1246,10 +1253,13 @@ public:
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
-
+ bool canBindObjCObjectType(QualType To, QualType From);
+
// Functions for calculating composite types
- QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false);
- QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false);
+ QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
+ QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
+ bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType);
@@ -1257,6 +1267,10 @@ public:
/// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
/// and returns the result type of that conversion.
QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
+
+ void ResetObjCLayout(const ObjCContainerDecl *CD) {
+ ObjCLayouts[CD] = 0;
+ }
//===--------------------------------------------------------------------===//
// Integer Predicates
@@ -1337,6 +1351,17 @@ public:
/// when it is called.
void AddDeallocation(void (*Callback)(void*), void *Data);
+ GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD);
+ GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
+
+ /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
+ /// lazily, only when used; this is only relevant for function or file scoped
+ /// var definitions.
+ ///
+ /// \returns true if the function/var must be CodeGen'ed/deserialized even if
+ /// it is not used.
+ bool DeclMustBeEmitted(const Decl *D);
+
//===--------------------------------------------------------------------===//
// Statistics
//===--------------------------------------------------------------------===//
@@ -1386,7 +1411,7 @@ private:
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
-
+
private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index 7975c4378876..9380058118c5 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
-#include "clang/AST/Type.h"
#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 9faa62eef6f7..62ca49fbf3b1 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -15,8 +15,11 @@
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/AttrKinds.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <cstring>
#include <algorithm>
@@ -27,28 +30,39 @@ namespace clang {
class IdentifierInfo;
class ObjCInterfaceDecl;
class Expr;
+ class QualType;
+ class FunctionDecl;
+ class TypeSourceInfo;
}
// Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw ();
+// FIXME: Being forced to not have a default argument here due to redeclaration
+// rules on default arguments sucks
+void *operator new[](size_t Bytes, clang::ASTContext &C,
+ size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw ();
+void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+ throw ();
namespace clang {
/// Attr - This represents one attribute.
class Attr {
private:
- Attr *Next;
- attr::Kind AttrKind;
+ SourceLocation Loc;
+ unsigned AttrKind : 16;
bool Inherited : 1;
protected:
+ virtual ~Attr();
+
void* operator new(size_t bytes) throw() {
assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0;
@@ -57,41 +71,36 @@ protected:
assert(0 && "Attrs cannot be released with regular 'delete'.");
}
-protected:
- Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
- virtual ~Attr() {
- assert(Next == 0 && "Destroy didn't work");
+public:
+ // Forward so that the regular new and delete do not hide global ones.
+ void* operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 16) throw() {
+ return ::operator new(Bytes, C, Alignment);
}
+ void operator delete(void *Ptr, ASTContext &C,
+ size_t Alignment) throw() {
+ return ::operator delete(Ptr, C, Alignment);
+ }
+
+protected:
+ Attr(attr::Kind AK, SourceLocation L)
+ : Loc(L), AttrKind(AK), Inherited(false) {}
+
public:
- virtual void Destroy(ASTContext &C);
/// \brief Whether this attribute should be merged to new
/// declarations.
virtual bool isMerged() const { return true; }
- attr::Kind getKind() const { return AttrKind; }
-
- Attr *getNext() { return Next; }
- const Attr *getNext() const { return Next; }
- void setNext(Attr *next) { Next = next; }
-
- template<typename T> const T *getNext() const {
- for (const Attr *attr = getNext(); attr; attr = attr->getNext())
- if (const T *V = dyn_cast<T>(attr))
- return V;
- return 0;
+ attr::Kind getKind() const {
+ return static_cast<attr::Kind>(AttrKind);
}
- bool isInherited() const { return Inherited; }
- void setInherited(bool value) { Inherited = value; }
-
- void addAttr(Attr *attr) {
- assert((attr != 0) && "addAttr(): attr is null");
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
- // FIXME: This doesn't preserve the order in any way.
- attr->Next = Next;
- Next = attr;
- }
+ bool isInherited() const { return Inherited; }
+ void setInherited(bool I) { Inherited = I; }
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -101,490 +110,112 @@ public:
};
#include "clang/AST/Attrs.inc"
-
-class AttrWithString : public Attr {
-private:
- const char *Str;
- unsigned StrLen;
-protected:
- AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s);
- llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
- void ReplaceString(ASTContext &C, llvm::StringRef newS);
-public:
- virtual void Destroy(ASTContext &C);
-};
-
-#define DEF_SIMPLE_ATTR(ATTR) \
-class ATTR##Attr : public Attr { \
-public: \
- ATTR##Attr() : Attr(attr::ATTR) {} \
- virtual Attr *clone(ASTContext &C) const; \
- static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \
- static bool classof(const ATTR##Attr *A) { return true; } \
-}
-DEF_SIMPLE_ATTR(Packed);
-
-/// \brief Attribute for specifying a maximum field alignment; this is only
-/// valid on record decls.
-class MaxFieldAlignmentAttr : public Attr {
- unsigned Alignment;
-
-public:
- MaxFieldAlignmentAttr(unsigned alignment)
- : Attr(attr::MaxFieldAlignment), Alignment(alignment) {}
+/// AttrVec - A vector of Attr, which is how they are stored on the AST.
+typedef llvm::SmallVector<Attr*, 2> AttrVec;
+typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
- /// getAlignment - The specified alignment in bits.
- unsigned getAlignment() const { return Alignment; }
-
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::MaxFieldAlignment;
- }
- static bool classof(const MaxFieldAlignmentAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AlignMac68k);
-
-/// \brief Atribute for specifying the alignment of a variable or type.
-///
-/// This node will either contain the precise Alignment (in bits, not bytes!)
-/// or will contain the expression for the alignment attribute in the case of
-/// a dependent expression within a class or function template. At template
-/// instantiation time these are transformed into concrete attributes.
-class AlignedAttr : public Attr {
- unsigned Alignment;
- Expr *AlignmentExpr;
-public:
- AlignedAttr(unsigned alignment)
- : Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {}
- AlignedAttr(Expr *E)
- : Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {}
-
- /// getAlignmentExpr - Get a dependent alignment expression if one is present.
- Expr *getAlignmentExpr() const {
- return AlignmentExpr;
- }
-
- /// isDependent - Is the alignment a dependent expression
- bool isDependent() const {
- return getAlignmentExpr();
- }
+/// DestroyAttrs - Destroy the contents of an AttrVec.
+inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
+}
- /// getAlignment - The specified alignment in bits. Requires !isDependent().
- unsigned getAlignment() const {
- assert(!isDependent() && "Cannot get a value dependent alignment");
- return Alignment;
- }
+/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
+/// providing attributes that are of a specifc type.
+template <typename SpecificAttr>
+class specific_attr_iterator {
+ /// Current - The current, underlying iterator.
+ /// In order to ensure we don't dereference an invalid iterator unless
+ /// specifically requested, we don't necessarily advance this all the
+ /// way. Instead, we advance it when an operation is requested; if the
+ /// operation is acting on what should be a past-the-end iterator,
+ /// then we offer no guarantees, but this way we do not dererence a
+ /// past-the-end iterator when we move to a past-the-end position.
+ mutable AttrVec::const_iterator Current;
- /// getMaxAlignment - Get the maximum alignment of attributes on this list.
- unsigned getMaxAlignment() const {
- const AlignedAttr *Next = getNext<AlignedAttr>();
- if (Next)
- return std::max(Next->getMaxAlignment(), getAlignment());
- else
- return getAlignment();
+ void AdvanceToNext() const {
+ while (!llvm::isa<SpecificAttr>(*Current))
+ ++Current;
}
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Aligned;
+ void AdvanceToNext(AttrVec::const_iterator I) const {
+ while (Current != I && !llvm::isa<SpecificAttr>(*Current))
+ ++Current;
}
- static bool classof(const AlignedAttr *A) { return true; }
-};
-class AnnotateAttr : public AttrWithString {
public:
- AnnotateAttr(ASTContext &C, llvm::StringRef ann)
- : AttrWithString(attr::Annotate, C, ann) {}
-
- llvm::StringRef getAnnotation() const { return getString(); }
+ typedef SpecificAttr* value_type;
+ typedef SpecificAttr* reference;
+ typedef SpecificAttr* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
- virtual Attr* clone(ASTContext &C) const;
+ specific_attr_iterator() : Current() { }
+ explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Annotate;
+ reference operator*() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
}
- static bool classof(const AnnotateAttr *A) { return true; }
-};
-
-class AsmLabelAttr : public AttrWithString {
-public:
- AsmLabelAttr(ASTContext &C, llvm::StringRef L)
- : AttrWithString(attr::AsmLabel, C, L) {}
-
- llvm::StringRef getLabel() const { return getString(); }
-
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::AsmLabel;
- }
- static bool classof(const AsmLabelAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AlwaysInline);
-
-class AliasAttr : public AttrWithString {
-public:
- AliasAttr(ASTContext &C, llvm::StringRef aliasee)
- : AttrWithString(attr::Alias, C, aliasee) {}
-
- llvm::StringRef getAliasee() const { return getString(); }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Alias; }
- static bool classof(const AliasAttr *A) { return true; }
-};
-
-class ConstructorAttr : public Attr {
- int priority;
-public:
- ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {}
-
- int getPriority() const { return priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Constructor; }
- static bool classof(const ConstructorAttr *A) { return true; }
-};
-
-class DestructorAttr : public Attr {
- int priority;
-public:
- DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {}
-
- int getPriority() const { return priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Destructor; }
- static bool classof(const DestructorAttr *A) { return true; }
-};
-
-class IBOutletAttr : public Attr {
-public:
- IBOutletAttr() : Attr(attr::IBOutlet) {}
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBOutlet;
- }
- static bool classof(const IBOutletAttr *A) { return true; }
-};
-
-class IBOutletCollectionAttr : public Attr {
- const ObjCInterfaceDecl *D;
-public:
- IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0)
- : Attr(attr::IBOutletCollection), D(d) {}
-
- const ObjCInterfaceDecl *getClass() const { return D; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBOutletCollection;
+ pointer operator->() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
}
- static bool classof(const IBOutletCollectionAttr *A) { return true; }
-};
-
-class IBActionAttr : public Attr {
-public:
- IBActionAttr() : Attr(attr::IBAction) {}
-
- virtual Attr *clone(ASTContext &C) const;
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBAction;
+ specific_attr_iterator& operator++() {
+ ++Current;
+ return *this;
}
- static bool classof(const IBActionAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AnalyzerNoReturn);
-DEF_SIMPLE_ATTR(Deprecated);
-DEF_SIMPLE_ATTR(GNUInline);
-DEF_SIMPLE_ATTR(Malloc);
-DEF_SIMPLE_ATTR(NoReturn);
-DEF_SIMPLE_ATTR(NoInstrumentFunction);
-
-class SectionAttr : public AttrWithString {
-public:
- SectionAttr(ASTContext &C, llvm::StringRef N)
- : AttrWithString(attr::Section, C, N) {}
-
- llvm::StringRef getName() const { return getString(); }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Section;
+ specific_attr_iterator operator++(int) {
+ specific_attr_iterator Tmp(*this);
+ ++(*this);
+ return Tmp;
}
- static bool classof(const SectionAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(Unavailable);
-DEF_SIMPLE_ATTR(Unused);
-DEF_SIMPLE_ATTR(Used);
-DEF_SIMPLE_ATTR(Weak);
-DEF_SIMPLE_ATTR(WeakImport);
-DEF_SIMPLE_ATTR(WeakRef);
-DEF_SIMPLE_ATTR(NoThrow);
-DEF_SIMPLE_ATTR(Const);
-DEF_SIMPLE_ATTR(Pure);
-
-class NonNullAttr : public Attr {
- unsigned* ArgNums;
- unsigned Size;
-public:
- NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
-
- virtual void Destroy(ASTContext &C);
-
- typedef const unsigned *iterator;
- iterator begin() const { return ArgNums; }
- iterator end() const { return ArgNums + Size; }
- unsigned size() const { return Size; }
- bool isNonNull(unsigned arg) const {
- return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
+ friend bool operator==(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ if (Left.Current < Right.Current)
+ Left.AdvanceToNext(Right.Current);
+ else
+ Right.AdvanceToNext(Left.Current);
+ return Left.Current == Right.Current;
}
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; }
- static bool classof(const NonNullAttr *A) { return true; }
-};
-
-class FormatAttr : public AttrWithString {
- int formatIdx, firstArg;
-public:
- FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
- : AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {}
-
- llvm::StringRef getType() const { return getString(); }
- void setType(ASTContext &C, llvm::StringRef type);
- int getFormatIdx() const { return formatIdx; }
- int getFirstArg() const { return firstArg; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Format; }
- static bool classof(const FormatAttr *A) { return true; }
-};
-
-class FormatArgAttr : public Attr {
- int formatIdx;
-public:
- FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {}
- int getFormatIdx() const { return formatIdx; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; }
- static bool classof(const FormatArgAttr *A) { return true; }
-};
-
-class SentinelAttr : public Attr {
- int sentinel, NullPos;
-public:
- SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel),
- sentinel(sentinel_val), NullPos(nullPos) {}
- int getSentinel() const { return sentinel; }
- int getNullPos() const { return NullPos; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; }
- static bool classof(const SentinelAttr *A) { return true; }
-};
-
-class VisibilityAttr : public Attr {
-public:
- /// @brief An enumeration for the kinds of visibility of symbols.
- enum VisibilityTypes {
- DefaultVisibility = 0,
- HiddenVisibility,
- ProtectedVisibility
- };
-private:
- VisibilityTypes VisibilityType;
-public:
- VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility),
- VisibilityType(v) {}
-
- VisibilityTypes getVisibility() const { return VisibilityType; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Visibility; }
- static bool classof(const VisibilityAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(FastCall);
-DEF_SIMPLE_ATTR(StdCall);
-DEF_SIMPLE_ATTR(ThisCall);
-DEF_SIMPLE_ATTR(CDecl);
-DEF_SIMPLE_ATTR(TransparentUnion);
-DEF_SIMPLE_ATTR(ObjCNSObject);
-DEF_SIMPLE_ATTR(ObjCException);
-
-class OverloadableAttr : public Attr {
-public:
- OverloadableAttr() : Attr(attr::Overloadable) { }
-
- virtual bool isMerged() const { return false; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Overloadable; }
- static bool classof(const OverloadableAttr *) { return true; }
-};
-
-class BlocksAttr : public Attr {
-public:
- enum BlocksAttrTypes {
- ByRef = 0
- };
-private:
- BlocksAttrTypes BlocksAttrType;
-public:
- BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {}
-
- BlocksAttrTypes getType() const { return BlocksAttrType; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; }
- static bool classof(const BlocksAttr *A) { return true; }
-};
-
-class FunctionDecl;
-
-class CleanupAttr : public Attr {
- FunctionDecl *FD;
-
-public:
- CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {}
-
- const FunctionDecl *getFunctionDecl() const { return FD; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; }
- static bool classof(const CleanupAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(NoDebug);
-DEF_SIMPLE_ATTR(WarnUnusedResult);
-DEF_SIMPLE_ATTR(NoInline);
-
-class RegparmAttr : public Attr {
- unsigned NumParams;
-
-public:
- RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {}
-
- unsigned getNumParams() const { return NumParams; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; }
- static bool classof(const RegparmAttr *A) { return true; }
-};
-
-class ReqdWorkGroupSizeAttr : public Attr {
- unsigned X, Y, Z;
-public:
- ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
- : Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
-
- unsigned getXDim() const { return X; }
- unsigned getYDim() const { return Y; }
- unsigned getZDim() const { return Z; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::ReqdWorkGroupSize;
+ friend bool operator!=(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ return !(Left == Right);
}
- static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
-class InitPriorityAttr : public Attr {
- unsigned Priority;
-public:
- InitPriorityAttr(unsigned priority)
- : Attr(attr::InitPriority), Priority(priority) {}
-
- virtual void Destroy(ASTContext &C) { Attr::Destroy(C); }
-
- unsigned getPriority() const { return Priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A)
- { return A->getKind() == attr::InitPriority; }
- static bool classof(const InitPriorityAttr *A) { return true; }
-};
-
-// Checker-specific attributes.
-DEF_SIMPLE_ATTR(CFReturnsNotRetained);
-DEF_SIMPLE_ATTR(CFReturnsRetained);
-DEF_SIMPLE_ATTR(NSReturnsNotRetained);
-DEF_SIMPLE_ATTR(NSReturnsRetained);
-
-// Target-specific attributes
-DEF_SIMPLE_ATTR(DLLImport);
-DEF_SIMPLE_ATTR(DLLExport);
-
-class MSP430InterruptAttr : public Attr {
- unsigned Number;
-
-public:
- MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {}
-
- unsigned getNumber() const { return Number; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::MSP430Interrupt; }
- static bool classof(const MSP430InterruptAttr *A) { return true; }
-};
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.begin());
+}
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.end());
+}
-DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
+template <typename T>
+inline bool hasSpecificAttr(const AttrVec& vec) {
+ return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
+}
+template <typename T>
+inline T *getSpecificAttr(const AttrVec& vec) {
+ specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
+ if (i != specific_attr_end<T>(vec))
+ return *i;
+ else
+ return 0;
+}
-#undef DEF_SIMPLE_ATTR
+/// getMaxAlignment - Returns the highest alignment value found among
+/// AlignedAttrs in an AttrVec, or 0 if there are none.
+inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
+ unsigned Align = 0;
+ specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
+ for(; i != e; ++i)
+ Align = std::max(Align, i->getAlignment(Ctx));
+ return Align;
+}
} // end namespace clang
diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt
index 3b090715e083..800c58361b02 100644
--- a/include/clang/AST/CMakeLists.txt
+++ b/include/clang/AST/CMakeLists.txt
@@ -5,6 +5,12 @@ tablegen(Attrs.inc
add_custom_target(ClangAttrClasses
DEPENDS Attrs.inc)
+tablegen(AttrImpl.inc
+ -gen-clang-attr-impl
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrImpl
+ DEPENDS AttrImpl.inc)
+
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
tablegen(StmtNodes.inc
-gen-clang-stmt-nodes)
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 9f97fd8a7aee..dad4dfc926e1 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -273,6 +273,9 @@ public:
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
@@ -700,9 +703,9 @@ inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
template<typename T>
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
CanQual<T> Result;
- Result.Stored.setFromOpaqueValue(Ptr);
- assert((!Result || Result.Stored.isCanonical())
- && "Type is not canonical!");
+ Result.Stored = QualType::getFromOpaquePtr(Ptr);
+ assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
+ Result.Stored.isCanonical()) && "Type is not canonical!");
return Result;
}
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 39cd51f606b5..674925532210 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -118,16 +118,6 @@ public:
return getIdentifier() ? getIdentifier()->getName() : "";
}
- /// getNameAsCString - Get the name of identifier for this declaration as a
- /// C string (const char*). This requires that the declaration have a name
- /// and that it be a simple identifier.
- //
- // FIXME: Deprecated, move clients to getName().
- const char *getNameAsCString() const {
- assert(Name.isIdentifier() && "Name is not a simple identifier");
- return getIdentifier() ? getIdentifier()->getNameStart() : "";
- }
-
/// getNameAsString - Get a human-readable name for the declaration, even if
/// it is one of the special kinds of names (C++ constructor, Objective-C
/// selector, etc). Creating this name requires expensive string
@@ -229,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext {
+ bool IsInline : 1;
+
SourceLocation LBracLoc, RBracLoc;
// For extended namespace definitions:
@@ -239,7 +231,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// there will be one NamespaceDecl for each declaration.
// NextNamespace points to the next extended declaration.
// OrigNamespace points to the original namespace declaration.
- // OrigNamespace of the first namespace decl points to itself.
+ // OrigNamespace of the first namespace decl points to its anonymous namespace
NamespaceDecl *NextNamespace;
/// \brief A pointer to either the original namespace definition for
@@ -258,28 +250,36 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
- NextNamespace(0), OrigOrAnonNamespace(0, true) { }
+ IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
- virtual void Destroy(ASTContext& C);
-
- // \brief Returns true if this is an anonymous namespace declaration.
- //
- // For example:
+ /// \brief Returns true if this is an anonymous namespace declaration.
+ ///
+ /// For example:
/// \code
- // namespace {
- // ...
- // };
- // \endcode
- // q.v. C++ [namespace.unnamed]
+ /// namespace {
+ /// ...
+ /// };
+ /// \endcode
+ /// q.v. C++ [namespace.unnamed]
bool isAnonymousNamespace() const {
return !getIdentifier();
}
- /// \brief Return the next extended namespace declaration or null if this
+ /// \brief Returns true if this is an inline namespace declaration.
+ bool isInline() const {
+ return IsInline;
+ }
+
+ /// \brief Set whether this is an inline namespace declaration.
+ void setInline(bool Inline) {
+ IsInline = Inline;
+ }
+
+ /// \brief Return the next extended namespace declaration or null if there
/// is none.
NamespaceDecl *getNextNamespace() { return NextNamespace; }
const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
@@ -345,8 +345,8 @@ public:
return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// ValueDecl - Represent the declaration of a variable (in which case it is
@@ -392,8 +392,6 @@ struct QualifierInfo {
unsigned NumTPLists,
TemplateParameterList **TPLists);
- void Destroy(ASTContext &Context);
-
private:
// Copy constructor and copy assignment are disabled.
QualifierInfo(const QualifierInfo&);
@@ -421,9 +419,6 @@ protected:
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
public:
- virtual ~DeclaratorDecl();
- virtual void Destroy(ASTContext &C);
-
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? getExtInfo()->TInfo
@@ -507,36 +502,11 @@ struct EvaluatedStmt {
APValue Evaluated;
};
-// \brief Describes the kind of template specialization that a
-// particular template specialization declaration represents.
-enum TemplateSpecializationKind {
- /// This template specialization was formed from a template-id but
- /// has not yet been declared, defined, or instantiated.
- TSK_Undeclared = 0,
- /// This template specialization was implicitly instantiated from a
- /// template. (C++ [temp.inst]).
- TSK_ImplicitInstantiation,
- /// This template specialization was declared or defined by an
- /// explicit specialization (C++ [temp.expl.spec]) or partial
- /// specialization (C++ [temp.class.spec]).
- TSK_ExplicitSpecialization,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation declaration request
- /// (C++0x [temp.explicit]).
- TSK_ExplicitInstantiationDeclaration,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation definition request
- /// (C++ [temp.explicit]).
- TSK_ExplicitInstantiationDefinition
-};
-
/// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
- enum StorageClass {
- None, Auto, Register, Extern, Static, PrivateExtern
- };
+ typedef clang::StorageClass StorageClass;
/// getStorageClassSpecifierString - Return the string used to
/// specify the storage class \arg SC.
@@ -568,10 +538,6 @@ private:
bool ThreadSpecified : 1;
bool HasCXXDirectInit : 1;
- /// DeclaredInCondition - Whether this variable was declared in a
- /// condition, e.g., if (int x = foo()) { ... }.
- bool DeclaredInCondition : 1;
-
/// \brief Whether this variable is the exception variable in a C++ catch
/// or an Objective-C @catch statement.
bool ExceptionVar : 1;
@@ -587,7 +553,7 @@ protected:
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
- DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) {
+ ExceptionVar(false), NRVOVariable(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@@ -609,9 +575,6 @@ public:
QualType T, TypeSourceInfo *TInfo, StorageClass S,
StorageClass SCAsWritten);
- virtual void Destroy(ASTContext& C);
- virtual ~VarDecl();
-
virtual SourceLocation getInnerLocStart() const;
virtual SourceRange getSourceRange() const;
@@ -619,8 +582,14 @@ public:
StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten;
}
- void setStorageClass(StorageClass SC) { SClass = SC; }
- void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; }
+ void setStorageClass(StorageClass SC) {
+ assert(isLegalForVariable(SC));
+ SClass = SC;
+ }
+ void setStorageClassAsWritten(StorageClass SC) {
+ assert(isLegalForVariable(SC));
+ SClassAsWritten = SC;
+ }
void setThreadSpecified(bool T) { ThreadSpecified = T; }
bool isThreadSpecified() const {
@@ -630,25 +599,26 @@ public:
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
- if (getStorageClass() == None)
+ if (getStorageClass() == SC_None)
return !isFileVarDecl();
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern.
- return getStorageClass() <= Register;
+ return getStorageClass() >= SC_Auto;
}
/// isStaticLocal - Returns true if a variable with function scope is a
/// static local variable.
bool isStaticLocal() const {
- return getStorageClass() == Static && !isFileVarDecl();
+ return getStorageClass() == SC_Static && !isFileVarDecl();
}
/// hasExternStorage - Returns true if a variable has extern or
/// __private_extern__ storage.
bool hasExternalStorage() const {
- return getStorageClass() == Extern || getStorageClass() == PrivateExtern;
+ return getStorageClass() == SC_Extern ||
+ getStorageClass() == SC_PrivateExtern;
}
/// hasGlobalStorage - Returns true for all variables that do not
@@ -670,7 +640,7 @@ public:
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
- return DC->getLookupContext()->isFunctionOrMethod();
+ return DC->getRedeclContext()->isFunctionOrMethod();
return false;
}
@@ -679,10 +649,8 @@ public:
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
- if (const DeclContext *DC = getDeclContext())
- return DC->getLookupContext()->isFunctionOrMethod() &&
- DC->getLookupContext()->getDeclKind() != Decl::Block;
- return false;
+ const DeclContext *DC = getDeclContext()->getRedeclContext();
+ return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
}
/// \brief Determines whether this is a static data member.
@@ -696,7 +664,7 @@ public:
/// \endcode
bool isStaticDataMember() const {
// If it wasn't static, it would be a FieldDecl.
- return getDeclContext()->isRecord();
+ return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
}
virtual VarDecl *getCanonicalDecl();
@@ -743,11 +711,10 @@ public:
bool isFileVarDecl() const {
if (getKind() != Decl::Var)
return false;
- if (const DeclContext *Ctx = getDeclContext()) {
- Ctx = Ctx->getLookupContext();
- if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
- return true;
- }
+
+ if (getDeclContext()->getRedeclContext()->isFileContext())
+ return true;
+
if (isStaticDataMember())
return true;
@@ -912,18 +879,6 @@ public:
return HasCXXDirectInit;
}
- /// isDeclaredInCondition - Whether this variable was declared as
- /// part of a condition in an if/switch/while statement, e.g.,
- /// @code
- /// if (int x = foo()) { ... }
- /// @endcode
- bool isDeclaredInCondition() const {
- return DeclaredInCondition;
- }
- void setDeclaredInCondition(bool InCondition) {
- DeclaredInCondition = InCondition;
- }
-
/// \brief Determine whether this variable is the exception variable in a
/// C++ catch statememt or an Objective-C @catch statement.
bool isExceptionVariable() const {
@@ -973,7 +928,7 @@ class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType Tw)
- : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {}
+ : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {}
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -1117,9 +1072,7 @@ public:
class FunctionDecl : public DeclaratorDecl, public DeclContext,
public Redeclarable<FunctionDecl> {
public:
- enum StorageClass {
- None, Extern, Static, PrivateExtern
- };
+ typedef clang::StorageClass StorageClass;
/// \brief The kind of templated function a FunctionDecl can be.
enum TemplatedKind {
@@ -1179,11 +1132,15 @@ private:
DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the DeclaratorDecl base class.
+ DeclarationNameLoc DNLoc;
+
protected:
- FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten, bool isInline)
- : DeclaratorDecl(DK, DC, L, N, T, TInfo),
+ : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
DeclContext(DK),
ParamInfo(0), Body(),
SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline),
@@ -1191,10 +1148,9 @@ protected:
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
IsCopyAssignment(false),
HasImplicitReturnZero(false),
- EndRangeLoc(L), TemplateOrSpecialization() {}
-
- virtual ~FunctionDecl() {}
- virtual void Destroy(ASTContext& C);
+ EndRangeLoc(NameInfo.getEndLoc()),
+ TemplateOrSpecialization(),
+ DNLoc(NameInfo.getInfo()) {}
typedef Redeclarable<FunctionDecl> redeclarable_base;
virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@@ -1211,11 +1167,27 @@ public:
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
TypeSourceInfo *TInfo,
- StorageClass S = None,
- StorageClass SCAsWritten = None,
+ StorageClass S = SC_None,
+ StorageClass SCAsWritten = SC_None,
+ bool isInline = false,
+ bool hasWrittenPrototype = true) {
+ DeclarationNameInfo NameInfo(N, L);
+ return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten,
+ isInline, hasWrittenPrototype);
+ }
+
+ static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S = SC_None,
+ StorageClass SCAsWritten = SC_None,
bool isInline = false,
bool hasWrittenPrototype = true);
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
@@ -1245,7 +1217,7 @@ public:
/// set that function declaration to the actual declaration
/// containing the body (if there is one).
/// NOTE: For checking if there is a body, use hasBody() instead, to avoid
- /// unnecessary PCH de-serialization of the body.
+ /// unnecessary AST de-serialization of the body.
Stmt *getBody(const FunctionDecl *&Definition) const;
virtual Stmt *getBody() const {
@@ -1389,12 +1361,18 @@ public:
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
- void setStorageClass(StorageClass SC) { SClass = SC; }
+ void setStorageClass(StorageClass SC) {
+ assert(isLegalForFunction(SC));
+ SClass = SC;
+ }
StorageClass getStorageClassAsWritten() const {
return StorageClass(SClassAsWritten);
}
- void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; }
+ void setStorageClassAsWritten(StorageClass SC) {
+ assert(isLegalForFunction(SC));
+ SClassAsWritten = SC;
+ }
/// \brief Determine whether the "inline" keyword was specified for this
/// function.
@@ -1632,8 +1610,8 @@ public:
return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
@@ -1705,7 +1683,6 @@ protected:
const llvm::APSInt &V)
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
- virtual ~EnumConstantDecl() {}
public:
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
@@ -1713,8 +1690,6 @@ public:
QualType T, Expr *E,
const llvm::APSInt &V);
- virtual void Destroy(ASTContext& C);
-
const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; }
@@ -1722,6 +1697,8 @@ public:
void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
+ SourceRange getSourceRange() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const EnumConstantDecl *D) { return true; }
@@ -1770,8 +1747,6 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
- virtual ~TypedefDecl();
-
protected:
typedef Redeclarable<TypedefDecl> redeclarable_base;
virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@@ -1832,6 +1807,9 @@ private:
/// it is a declaration ("struct foo;").
bool IsDefinition : 1;
+ /// IsBeingDefined - True if this is currently being defined.
+ bool IsBeingDefined : 1;
+
/// IsEmbeddedInDeclarator - True if this tag declaration is
/// "embedded" (i.e., defined or declared for the very first time)
/// in the syntax of a declarator.
@@ -1873,6 +1851,7 @@ protected:
"EnumDecl not matched with TTK_Enum");
TagDeclKind = TK;
IsDefinition = false;
+ IsBeingDefined = false;
IsEmbeddedInDeclarator = false;
setPreviousDeclaration(PrevDecl);
}
@@ -1881,8 +1860,6 @@ protected:
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public:
- void Destroy(ASTContext &C);
-
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
@@ -1911,11 +1888,22 @@ public:
return const_cast<TagDecl*>(this)->getCanonicalDecl();
}
+ /// isThisDeclarationADefinition() - Return true if this declaration
+ /// defines the type. Provided for consistency.
+ bool isThisDeclarationADefinition() const {
+ return isDefinition();
+ }
+
/// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const {
return IsDefinition;
}
+ /// isBeingDefined - Return true if this decl is currently being defined.
+ bool isBeingDefined() const {
+ return IsBeingDefined;
+ }
+
bool isEmbeddedInDeclarator() const {
return IsEmbeddedInDeclarator;
}
@@ -2003,8 +1991,8 @@ public:
return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
@@ -2037,6 +2025,8 @@ class EnumDecl : public TagDecl {
IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
IntegerType = QualType();
+ NumNegativeBits = 0;
+ NumPositiveBits = 0;
}
public:
EnumDecl *getCanonicalDecl() {
@@ -2058,8 +2048,6 @@ public:
SourceLocation TKL, EnumDecl *PrevDecl);
static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
- virtual void Destroy(ASTContext& C);
-
/// completeDefinition - When created, the EnumDecl corresponds to a
/// forward-declared enum. This method is used to mark the
/// declaration as being defined; it's enumerators have already been
@@ -2167,7 +2155,6 @@ protected:
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
RecordDecl *PrevDecl, SourceLocation TKL);
- virtual ~RecordDecl();
public:
static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -2183,8 +2170,6 @@ public:
return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
}
- virtual void Destroy(ASTContext& C);
-
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
@@ -2307,9 +2292,6 @@ protected:
IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
SignatureAsWritten(0) {}
- virtual ~BlockDecl();
- virtual void Destroy(ASTContext& C);
-
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index be30b8ed296b..1369c2b5955a 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -222,11 +222,13 @@ protected:
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
-
- // PCHLevel - the "level" of precompiled header/AST file from which this
- // declaration was built.
- unsigned PCHLevel : 3;
-
+
+ /// PCHLevel - the "level" of AST file from which this declaration was built.
+ unsigned PCHLevel : 2;
+
+ /// ChangedAfterLoad - if this declaration has changed since being loaded
+ bool ChangedAfterLoad : 1;
+
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 15;
@@ -243,7 +245,7 @@ protected:
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
- Access(AS_none), PCHLevel(0),
+ Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK);
}
@@ -251,7 +253,7 @@ protected:
Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
- Access(AS_none), PCHLevel(0),
+ Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK);
}
@@ -305,24 +307,52 @@ public:
}
bool hasAttrs() const { return HasAttrs; }
- void initAttrs(Attr *attrs);
- void addAttr(Attr *attr);
- const Attr *getAttrs() const {
- if (!HasAttrs) return 0; // common case, no attributes.
- return getAttrsImpl(); // Uncommon case, out of line hash lookup.
+ void setAttrs(const AttrVec& Attrs);
+ AttrVec& getAttrs() {
+ return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
+ const AttrVec &getAttrs() const;
void swapAttrs(Decl *D);
- void invalidateAttrs();
+ void dropAttrs();
+
+ void addAttr(Attr *A) {
+ if (hasAttrs())
+ getAttrs().push_back(A);
+ else
+ setAttrs(AttrVec(1, A));
+ }
+
+ typedef AttrVec::const_iterator attr_iterator;
+
+ // FIXME: Do not rely on iterators having comparable singular values.
+ // Note that this should error out if they do not.
+ attr_iterator attr_begin() const {
+ return hasAttrs() ? getAttrs().begin() : 0;
+ }
+ attr_iterator attr_end() const {
+ return hasAttrs() ? getAttrs().end() : 0;
+ }
- template<typename T> const T *getAttr() const {
- for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
- if (const T *V = dyn_cast<T>(attr))
- return V;
- return 0;
+ template <typename T>
+ specific_attr_iterator<T> specific_attr_begin() const {
+ return specific_attr_iterator<T>(attr_begin());
+ }
+ template <typename T>
+ specific_attr_iterator<T> specific_attr_end() const {
+ return specific_attr_iterator<T>(attr_end());
}
+ template<typename T> T *getAttr() const {
+ return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
+ }
template<typename T> bool hasAttr() const {
- return getAttr<T>() != 0;
+ return hasAttrs() && hasSpecificAttr<T>(getAttrs());
+ }
+
+ /// getMaxAlignment - return the maximum alignment specified by attributes
+ /// on this decl, 0 if there are none.
+ unsigned getMaxAlignment() const {
+ return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
@@ -343,22 +373,21 @@ public:
/// (in addition to the "used" bit set by \c setUsed()) when determining
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
-
+
void setUsed(bool U = true) { Used = U; }
/// \brief Retrieve the level of precompiled header from which this
/// declaration was generated.
///
/// The PCH level of a declaration describes where the declaration originated
- /// from. A PCH level of 0 indicates that the declaration was not from a
- /// precompiled header. A PCH level of 1 indicates that the declaration was
- /// from a top-level precompiled header; 2 indicates that the declaration
- /// comes from a precompiled header on which the top-level precompiled header
- /// depends, and so on.
+ /// from. A PCH level of 0 indicates that the declaration was parsed from
+ /// source. A PCH level of 1 indicates that the declaration was loaded from
+ /// a top-level AST file. A PCH level 2 indicates that the declaration was
+ /// loaded from a PCH file the AST file depends on, and so on.
unsigned getPCHLevel() const { return PCHLevel; }
/// \brief The maximum PCH level that any declaration may have.
- static const unsigned MaxPCHLevel = 7;
+ static const unsigned MaxPCHLevel = 3;
/// \brief Set the PCH level of this declaration.
void setPCHLevel(unsigned Level) {
@@ -366,6 +395,19 @@ public:
PCHLevel = Level;
}
+ /// \brief Query whether this declaration was changed in a significant way
+ /// since being loaded from an AST file.
+ ///
+ /// In an epic violation of layering, what is "significant" is entirely
+ /// up to the serialization system, but implemented in AST and Sema.
+ bool isChangedSinceDeserialization() const { return ChangedAfterLoad; }
+
+ /// \brief Mark this declaration as having changed since deserialization, or
+ /// reset the flag.
+ void setChangedSinceDeserialization(bool Changed) {
+ ChangedAfterLoad = Changed;
+ }
+
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@@ -411,10 +453,10 @@ public:
void setLexicalDeclContext(DeclContext *DC);
- // isDefinedOutsideFunctionOrMethod - This predicate returns true if this
- // scoped decl is defined outside the current function or method. This is
- // roughly global variables and functions, but also handles enums (which could
- // be defined inside or outside a function etc).
+ /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+ /// scoped decl is defined outside the current function or method. This is
+ /// roughly global variables and functions, but also handles enums (which
+ /// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
/// \brief Retrieves the "canonical" declaration of the given declaration.
@@ -572,9 +614,6 @@ public:
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
@@ -603,6 +642,29 @@ public:
virtual void print(llvm::raw_ostream &OS) const;
};
+class DeclContextLookupResult
+ : public std::pair<NamedDecl**,NamedDecl**> {
+public:
+ DeclContextLookupResult(NamedDecl **I, NamedDecl **E)
+ : std::pair<NamedDecl**,NamedDecl**>(I, E) {}
+ DeclContextLookupResult()
+ : std::pair<NamedDecl**,NamedDecl**>() {}
+
+ using std::pair<NamedDecl**,NamedDecl**>::operator=;
+};
+
+class DeclContextLookupConstResult
+ : public std::pair<NamedDecl*const*, NamedDecl*const*> {
+public:
+ DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R)
+ : std::pair<NamedDecl*const*, NamedDecl*const*>(R) {}
+ DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E)
+ : std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {}
+ DeclContextLookupConstResult()
+ : std::pair<NamedDecl*const*, NamedDecl*const*>() {}
+
+ using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=;
+};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes
@@ -654,8 +716,6 @@ protected:
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
LastDecl(0) { }
- void DestroyDecls(ASTContext &C);
-
public:
~DeclContext();
@@ -724,6 +784,8 @@ public:
return DeclKind == Decl::Namespace;
}
+ bool isInlineNamespace() const;
+
/// \brief Determines whether this context is dependent on a
/// template parameter.
bool isDependentContext() const;
@@ -742,19 +804,18 @@ public:
/// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for
- /// C++0x scoped enums), C++ linkage specifications, and C++0x
- /// inline namespaces.
+ /// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
- bool Equals(DeclContext *DC) {
+ bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
/// \brief Determine whether this declaration context encloses the
/// declaration context DC.
- bool Encloses(DeclContext *DC);
+ bool Encloses(const DeclContext *DC) const;
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
@@ -767,13 +828,12 @@ public:
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
- /// getLookupContext - Retrieve the innermost non-transparent
- /// context of this context, which corresponds to the innermost
- /// location from which name lookup can find the entities in this
- /// context.
- DeclContext *getLookupContext();
- const DeclContext *getLookupContext() const {
- return const_cast<DeclContext *>(this)->getLookupContext();
+ /// getRedeclContext - Retrieve the context in which an entity conflicts with
+ /// other entities of the same name, or where it is a redeclaration if the
+ /// two entities are compatible. This skips through transparent contexts.
+ DeclContext *getRedeclContext();
+ const DeclContext *getRedeclContext() const {
+ return const_cast<DeclContext *>(this)->getRedeclContext();
}
/// \brief Retrieve the nearest enclosing namespace context.
@@ -782,6 +842,14 @@ public:
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
}
+ /// \brief Test if this context is part of the enclosing namespace set of
+ /// the context NS, as defined in C++0x [namespace.def]p9. If either context
+ /// isn't a namespace, this is equivalent to Equals().
+ ///
+ /// The enclosing namespace set of a namespace is the namespace and, if it is
+ /// inline, its enclosing namespace, recursively.
+ bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
+
/// getNextContext - If this is a DeclContext that may have other
/// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the
@@ -845,6 +913,12 @@ public:
decl_iterator decls_end() const;
bool decls_empty() const;
+ /// noload_decls_begin/end - Iterate over the declarations stored in this
+ /// context that are currently loaded; don't attempt to retrieve anything
+ /// from an external source.
+ decl_iterator noload_decls_begin() const;
+ decl_iterator noload_decls_end() const;
+
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it). This
@@ -1020,9 +1094,8 @@ public:
/// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator;
- typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
- typedef std::pair<lookup_const_iterator, lookup_const_iterator>
- lookup_const_result;
+ typedef DeclContextLookupResult lookup_result;
+ typedef DeclContextLookupConstResult lookup_const_result;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
@@ -1052,6 +1125,14 @@ public:
/// the declaration chains.
void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
+ /// \brief Deserialize all the visible declarations from external storage.
+ ///
+ /// Name lookup deserializes visible declarations lazily, thus a DeclContext
+ /// may not have a complete name lookup table. This function deserializes
+ /// the rest of visible declarations from the external storage and completes
+ /// the name lookup table.
+ void MaterializeVisibleDeclsFromExternalStorage();
+
/// udir_iterator - Iterates through the using-directives stored
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
@@ -1109,7 +1190,6 @@ public:
private:
void LoadLexicalDeclsFromExternalStorage() const;
- void LoadVisibleDeclsFromExternalStorage() const;
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
@@ -1123,7 +1203,6 @@ inline bool Decl::isTemplateParameter() const {
getKind() == TemplateTemplateParm;
}
-
// Specialization selected when ToTy is not a known subclass of DeclContext.
template <class ToTy,
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 41474ab21e32..a9802bfcaf4e 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -17,6 +17,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -159,7 +160,6 @@ class CXXBaseSpecifier {
/// Range - The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
- // FIXME: Move over to a TypeLoc!
SourceRange Range;
/// Virtual - Whether this is a virtual base class or not.
@@ -177,15 +177,17 @@ class CXXBaseSpecifier {
/// VC++ bug.
unsigned Access : 2;
- /// BaseType - The type of the base class. This will be a class or
- /// struct (or a typedef of such).
- QualType BaseType;
+ /// BaseTypeInfo - The type of the base class. This will be a class or struct
+ /// (or a typedef of such). The source code range does not include the
+ /// "virtual" or access specifier.
+ TypeSourceInfo *BaseTypeInfo;
public:
CXXBaseSpecifier() { }
- CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
- : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
+ CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
+ TypeSourceInfo *TInfo)
+ : Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
@@ -195,7 +197,7 @@ public:
/// class (or not).
bool isVirtual() const { return Virtual; }
- /// \brief Determine whether this base class if a base of a class declared
+ /// \brief Determine whether this base class is a base of a class declared
/// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; }
@@ -221,7 +223,10 @@ public:
/// getType - Retrieves the type of the base class. This type will
/// always be an unqualified class type.
- QualType getType() const { return BaseType; }
+ QualType getType() const { return BaseTypeInfo->getType(); }
+
+ /// getTypeLoc - Retrieves the type and source location of the base class.
+ TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
};
/// CXXRecordDecl - Represents a C++ struct/union/class.
@@ -400,8 +405,6 @@ protected:
CXXRecordDecl *PrevDecl,
SourceLocation TKL = SourceLocation());
- ~CXXRecordDecl();
-
public:
/// base_class_iterator - Iterator that traverses the base classes
/// of a class.
@@ -449,8 +452,6 @@ public:
bool DelayTypeCreation = false);
static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty);
- virtual void Destroy(ASTContext& C);
-
bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0;
}
@@ -1056,29 +1057,30 @@ public:
return true;
}
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class.
class CXXMethodDecl : public FunctionDecl {
protected:
- CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ CXXMethodDecl(Kind DK, CXXRecordDecl *RD,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline)
- : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None),
+ : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None),
SCAsWritten, isInline) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
- QualType T, TypeSourceInfo *TInfo,
- bool isStatic = false,
- StorageClass SCAsWritten = FunctionDecl::None,
- bool isInline = false);
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
+ bool isStatic = false,
+ StorageClass SCAsWritten = SC_None,
+ bool isInline = false);
- bool isStatic() const { return getStorageClass() == Static; }
+ bool isStatic() const { return getStorageClass() == SC_Static; }
bool isInstance() const { return !isStatic(); }
bool isVirtual() const {
@@ -1249,9 +1251,6 @@ public:
VarDecl **Indices,
unsigned NumIndices);
- /// \brief Destroy the base or member initializer.
- void Destroy(ASTContext &Context);
-
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
@@ -1285,7 +1284,7 @@ public:
/// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL.
- FieldDecl *getMember() {
+ FieldDecl *getMember() const {
if (isMemberInitializer())
return BaseOrMember.get<FieldDecl*>();
else
@@ -1363,7 +1362,7 @@ public:
reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
}
- Expr *getInit() { return static_cast<Expr *>(Init); }
+ Expr *getInit() const { return static_cast<Expr *>(Init); }
};
/// CXXConstructorDecl - Represents a C++ constructor within a
@@ -1394,22 +1393,21 @@ class CXXConstructorDecl : public CXXMethodDecl {
CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
unsigned NumBaseOrMemberInitializers;
- CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false,
- FunctionDecl::None, isInline),
+ : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
- virtual void Destroy(ASTContext& C);
public:
static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
@@ -1519,8 +1517,8 @@ public:
static bool classof(const CXXConstructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConstructor; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// CXXDestructorDecl - Represents a C++ destructor within a
@@ -1543,11 +1541,10 @@ class CXXDestructorDecl : public CXXMethodDecl {
FunctionDecl *OperatorDelete;
- CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T,
- bool isInline, bool isImplicitlyDeclared)
- : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false,
- FunctionDecl::None, isInline),
+ CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, bool isInline, bool isImplicitlyDeclared)
+ : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false,
+ SC_None, isInline),
ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
}
@@ -1555,7 +1552,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
public:
static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, bool isInline,
bool isImplicitlyDeclared);
@@ -1585,8 +1582,8 @@ public:
static bool classof(const CXXDestructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXDestructor; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// CXXConversionDecl - Represents a C++ conversion function within a
@@ -1604,17 +1601,17 @@ class CXXConversionDecl : public CXXMethodDecl {
/// explicitly wrote a cast. This is a C++0x feature.
bool IsExplicitSpecified : 1;
- CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
- DeclarationName N, QualType T, TypeSourceInfo *TInfo,
+ CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicitSpecified)
- : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false,
- FunctionDecl::None, isInline),
+ : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false,
+ SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified) { }
public:
static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit);
@@ -1642,8 +1639,8 @@ public:
static bool classof(const CXXConversionDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConversion; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// LinkageSpecDecl - This represents a linkage specification. For example:
@@ -1710,7 +1707,9 @@ public:
// artificial name, for all using-directives in order to store
// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
-
+ /// \brief The location of the "using" keyword.
+ SourceLocation UsingLoc;
+
/// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc;
@@ -1722,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl {
/// name, if any.
NestedNameSpecifier *Qualifier;
- /// IdentLoc - Location of nominated namespace-name identifier.
- // FIXME: We don't store location of scope specifier.
- SourceLocation IdentLoc;
-
/// NominatedNamespace - Namespace nominated by using-directive.
NamedDecl *NominatedNamespace;
@@ -1740,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl {
return DeclarationName::getUsingDirectiveName();
}
- UsingDirectiveDecl(DeclContext *DC, SourceLocation L,
+ UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
- : NamedDecl(UsingDirective, DC, L, getName()),
+ : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
- Qualifier(Qualifier), IdentLoc(IdentLoc),
- NominatedNamespace(Nominated),
+ Qualifier(Qualifier), NominatedNamespace(Nominated),
CommonAncestor(CommonAncestor) {
}
@@ -1759,18 +1753,10 @@ public:
/// that qualifies the namespace name.
SourceRange getQualifierRange() const { return QualifierRange; }
- /// \brief Set the source range of the nested-name-specifier that
- /// qualifies the namespace name.
- void setQualifierRange(SourceRange R) { QualifierRange = R; }
-
/// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
- /// \brief Set the nested-name-specifier that qualifes the name of the
- /// namespace.
- void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
-
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
return NominatedNamespace;
@@ -1783,34 +1769,23 @@ public:
return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
}
- /// setNominatedNamespace - Set the namespace nominataed by the
- /// using-directive.
- void setNominatedNamespace(NamedDecl* NS);
-
/// \brief Returns the common ancestor context of this using-directive and
/// its nominated namespace.
DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; }
- /// \brief Set the common ancestor context of this using-directive and its
- /// nominated namespace.
- void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; }
-
+ /// \brief Return the location of the "using" keyword.
+ SourceLocation getUsingLoc() const { return UsingLoc; }
+
// FIXME: Could omit 'Key' in name.
/// getNamespaceKeyLocation - Returns location of namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
- /// setNamespaceKeyLocation - Set the the location of the namespacekeyword.
- void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; }
-
/// getIdentLocation - Returns location of identifier.
- SourceLocation getIdentLocation() const { return IdentLoc; }
-
- /// setIdentLocation - set the location of the identifier.
- void setIdentLocation(SourceLocation L) { IdentLoc = L; }
+ SourceLocation getIdentLocation() const { return getLocation(); }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ SourceLocation UsingLoc,
SourceLocation NamespaceLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
@@ -1818,12 +1793,18 @@ public:
NamedDecl *Nominated,
DeclContext *CommonAncestor);
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLoc, getLocation());
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDirectiveDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UsingDirective; }
// Friend for getUsingDirectiveName.
friend class DeclContext;
+
+ friend class ASTDeclReader;
};
/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
@@ -1832,7 +1813,8 @@ public:
/// namespace Foo = Bar;
/// @endcode
class NamespaceAliasDecl : public NamedDecl {
- SourceLocation AliasLoc;
+ /// \brief The location of the "namespace" keyword.
+ SourceLocation NamespaceLoc;
/// \brief The source range that covers the nested-name-specifier
/// preceding the namespace name.
@@ -1849,15 +1831,17 @@ class NamespaceAliasDecl : public NamedDecl {
/// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace;
- NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
+ NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, NamedDecl *Namespace)
- : NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
- QualifierRange(QualifierRange), Qualifier(Qualifier),
- IdentLoc(IdentLoc), Namespace(Namespace) { }
+ : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
+ NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
+ Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
+ friend class ASTDeclReader;
+
public:
/// \brief Retrieve the source range of the nested-name-specifier
/// that qualifiers the namespace name.
@@ -1889,41 +1873,31 @@ public:
/// Returns the location of the alias name, i.e. 'foo' in
/// "namespace foo = ns::bar;".
- SourceLocation getAliasLoc() const { return AliasLoc; }
-
- /// Set the location o;f the alias name, e.e., 'foo' in
- /// "namespace foo = ns::bar;".
- void setAliasLoc(SourceLocation L) { AliasLoc = L; }
+ SourceLocation getAliasLoc() const { return getLocation(); }
/// Returns the location of the 'namespace' keyword.
- SourceLocation getNamespaceLoc() const { return getLocation(); }
+ SourceLocation getNamespaceLoc() const { return NamespaceLoc; }
/// Returns the location of the identifier in the named namespace.
SourceLocation getTargetNameLoc() const { return IdentLoc; }
- /// Set the location of the identifier in the named namespace.
- void setTargetNameLoc(SourceLocation L) { IdentLoc = L; }
-
/// \brief Retrieve the namespace that this alias refers to, which
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *getAliasedNamespace() const { return Namespace; }
- /// \brief Set the namespace or namespace alias pointed to by this
- /// alias decl.
- void setAliasedNamespace(NamedDecl *ND) {
- assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) &&
- "expecting namespace or namespace alias decl");
- Namespace = ND;
- }
-
static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceLocation AliasLoc,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Namespace);
+ virtual SourceRange getSourceRange() const {
+ return SourceRange(NamespaceLoc, IdentLoc);
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NamespaceAliasDecl *D) { return true; }
static bool classofKind(Kind K) { return K == NamespaceAlias; }
@@ -2002,6 +1976,10 @@ class UsingDecl : public NamedDecl {
/// \brief Target nested name specifier.
NestedNameSpecifier* TargetNestedName;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
/// \brief The collection of shadow declarations associated with
/// this using declaration. This set can change as a class is
/// processed.
@@ -2010,34 +1988,31 @@ class UsingDecl : public NamedDecl {
// \brief Has 'typename' keyword.
bool IsTypeName;
- UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
+ UsingDecl(DeclContext *DC, SourceRange NNR,
SourceLocation UL, NestedNameSpecifier* TargetNNS,
- DeclarationName Name, bool IsTypeNameArg)
- : NamedDecl(Using, DC, L, Name),
+ const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
+ : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
- IsTypeName(IsTypeNameArg) {
+ DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
}
public:
- // FIXME: Should be const?
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
- SourceRange getNestedNameRange() { return NestedNameRange; }
+ SourceRange getNestedNameRange() const { return NestedNameRange; }
/// \brief Set the source range of the nested-name-specifier.
void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
- // FIXME; Should be const?
// FIXME: Naming is inconsistent with other get*Loc functions.
/// \brief Returns the source location of the "using" keyword.
- SourceLocation getUsingLocation() { return UsingLocation; }
+ SourceLocation getUsingLocation() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLocation(SourceLocation L) { UsingLocation = L; }
-
/// \brief Get the target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameDecl() {
+ NestedNameSpecifier* getTargetNestedNameDecl() const {
return TargetNestedName;
}
@@ -2046,6 +2021,10 @@ public:
TargetNestedName = NNS;
}
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
/// \brief Return true if the using declaration has 'typename'.
bool isTypeName() const { return IsTypeName; }
@@ -2076,15 +2055,21 @@ public:
}
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
- NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
+ SourceRange NNR, SourceLocation UsingL,
+ NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsTypeNameArg);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getNameInfo().getEndLoc());
+ }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Using; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// UnresolvedUsingValueDecl - Represents a dependent using
@@ -2105,14 +2090,18 @@ class UnresolvedUsingValueDecl : public ValueDecl {
NestedNameSpecifier *TargetNestedNameSpecifier;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in the ValueDecl base class.
+ DeclarationNameLoc DNLoc;
+
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
SourceLocation UsingLoc, SourceRange TargetNNR,
NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc,
- DeclarationName TargetName)
- : ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty),
- TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
- TargetNestedNameSpecifier(TargetNNS)
+ const DeclarationNameInfo &NameInfo)
+ : ValueDecl(UnresolvedUsingValue, DC,
+ NameInfo.getLoc(), NameInfo.getName(), Ty),
+ TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+ TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
{ }
public:
@@ -2125,7 +2114,7 @@ public:
void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
/// \brief Get target nested name declaration.
- NestedNameSpecifier* getTargetNestedNameSpecifier() {
+ NestedNameSpecifier* getTargetNestedNameSpecifier() const {
return TargetNestedNameSpecifier;
}
@@ -2140,10 +2129,18 @@ public:
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
+ }
+
static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc, DeclarationName TargetName);
+ const DeclarationNameInfo &NameInfo);
+
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getNameInfo().getEndLoc());
+ }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
@@ -2181,43 +2178,34 @@ class UnresolvedUsingTypenameDecl : public TypeDecl {
TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
{ }
+ friend class ASTDeclReader;
+
public:
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
- /// \brief Set the source range coverting the nested-name-specifier preceding
- /// the namespace name.
- void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
-
/// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameSpecifier() {
return TargetNestedNameSpecifier;
}
- /// \brief Set the nested name declaration.
- void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
- TargetNestedNameSpecifier = NNS;
- }
-
/// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; }
- /// \brief Set the source location of the 'using' keyword.
- void setUsingLoc(SourceLocation L) { UsingLocation = L; }
-
/// \brief Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
- /// \brief Set the source location of the 'typename' keyword.
- void setTypenameLoc(SourceLocation L) { TypenameLocation = L; }
-
static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceLocation TypenameLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
SourceLocation TargetNameLoc, DeclarationName TargetName);
+ SourceRange getSourceRange() const {
+ return SourceRange(UsingLocation, getLocation());
+ }
+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
@@ -2243,12 +2231,11 @@ public:
StringLiteral *getMessage() { return Message; }
const StringLiteral *getMessage() const { return Message; }
- virtual ~StaticAssertDecl();
- virtual void Destroy(ASTContext& C);
-
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(StaticAssertDecl *D) { return true; }
static bool classofKind(Kind K) { return K == StaticAssert; }
+
+ friend class ASTDeclReader;
};
/// Insertion operator for diagnostics. This allows sending AccessSpecifier's
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 9602b677fca5..97da6ca9a1ef 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -29,108 +29,54 @@ class DependentDiagnostic;
/// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry.
struct StoredDeclsList {
- /// The kind of data encoded in this list.
- enum DataKind {
- /// \brief The data is a NamedDecl*.
- DK_Decl = 0,
- /// \brief The data is a declaration ID (an unsigned value),
- /// shifted left by 2 bits.
- DK_DeclID = 1,
- /// \brief The data is a pointer to a vector (of type VectorTy)
- /// that contains declarations.
- DK_Decl_Vector = 2,
- /// \brief The data is a pointer to a vector (of type VectorTy)
- /// that contains declaration ID.
- DK_ID_Vector = 3
- };
-
- /// VectorTy - When in vector form, this is what the Data pointer points to.
- typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
-
- /// \brief The stored data, which will be either a declaration ID, a
- /// pointer to a NamedDecl, or a pointer to a vector.
- uintptr_t Data;
+
+ /// DeclsTy - When in vector form, this is what the Data pointer points to.
+ typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
+
+ /// \brief The stored data, which will be either a pointer to a NamedDecl,
+ /// or a pointer to a vector.
+ llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
public:
- StoredDeclsList() : Data(0) {}
+ StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
- if (VectorTy *RHSVec = RHS.getAsVector()) {
- VectorTy *New = new VectorTy(*RHSVec);
- Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
- }
+ if (DeclsTy *RHSVec = RHS.getAsVector())
+ Data = new DeclsTy(*RHSVec);
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
- if (VectorTy *Vector = getAsVector())
+ if (DeclsTy *Vector = getAsVector())
delete Vector;
}
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
- if (VectorTy *Vector = getAsVector())
+ if (DeclsTy *Vector = getAsVector())
delete Vector;
Data = RHS.Data;
- if (VectorTy *RHSVec = RHS.getAsVector()) {
- VectorTy *New = new VectorTy(*RHSVec);
- Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
- }
+ if (DeclsTy *RHSVec = RHS.getAsVector())
+ Data = new DeclsTy(*RHSVec);
return *this;
}
- bool isNull() const { return (Data & ~0x03) == 0; }
+ bool isNull() const { return Data.isNull(); }
NamedDecl *getAsDecl() const {
- if ((Data & 0x03) != DK_Decl)
- return 0;
-
- return reinterpret_cast<NamedDecl *>(Data & ~0x03);
+ return Data.dyn_cast<NamedDecl *>();
}
- VectorTy *getAsVector() const {
- if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
- return 0;
-
- return reinterpret_cast<VectorTy *>(Data & ~0x03);
+ DeclsTy *getAsVector() const {
+ return Data.dyn_cast<DeclsTy *>();
}
void setOnlyValue(NamedDecl *ND) {
assert(!getAsVector() && "Not inline");
- Data = reinterpret_cast<uintptr_t>(ND);
- }
-
- void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
- if (Vec.size() > 1) {
- VectorTy *Vector = getAsVector();
- if (!Vector) {
- Vector = new VectorTy;
- Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector;
- }
-
- Vector->resize(Vec.size());
- std::copy(Vec.begin(), Vec.end(), Vector->begin());
- return;
- }
-
- if (VectorTy *Vector = getAsVector())
- delete Vector;
-
- if (Vec.empty())
- Data = 0;
- else
- Data = (Vec[0] << 2) | DK_DeclID;
- }
-
- /// \brief Force the stored declarations list to contain actual
- /// declarations.
- ///
- /// This routine will resolve any declaration IDs for declarations
- /// that may not yet have been loaded from external storage.
- void materializeDecls(ASTContext &Context);
-
- bool hasDeclarationIDs() const {
- DataKind DK = (DataKind)(Data & 0x03);
- return DK == DK_DeclID || DK == DK_ID_Vector;
+ Data = ND;
+ // Make sure that Data is a plain NamedDecl* so we can use its address
+ // at getLookupResult.
+ assert(*(NamedDecl **)&Data == ND &&
+ "PointerUnion mangles the NamedDecl pointer!");
}
void remove(NamedDecl *D) {
@@ -138,30 +84,26 @@ public:
if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton");
(void)Singleton;
- Data = 0;
+ Data = (NamedDecl *)0;
return;
}
- VectorTy &Vec = *getAsVector();
- VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
- reinterpret_cast<uintptr_t>(D));
+ DeclsTy &Vec = *getAsVector();
+ DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
assert(I != Vec.end() && "list does not contain decl");
Vec.erase(I);
- assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D))
+ assert(std::find(Vec.begin(), Vec.end(), D)
== Vec.end() && "list still contains decl");
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
- DeclContext::lookup_result getLookupResult(ASTContext &Context) {
+ DeclContext::lookup_result getLookupResult() {
if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
DeclContext::lookup_iterator(0));
- if (hasDeclarationIDs())
- materializeDecls(Context);
-
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
@@ -172,19 +114,15 @@ public:
}
assert(getAsVector() && "Must have a vector at this point");
- VectorTy &Vector = *getAsVector();
+ DeclsTy &Vector = *getAsVector();
// Otherwise, we have a range result.
- return DeclContext::lookup_result((NamedDecl **)&Vector[0],
- (NamedDecl **)&Vector[0]+Vector.size());
+ return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
- bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
- if (hasDeclarationIDs())
- materializeDecls(Context);
-
+ bool HandleRedeclaration(NamedDecl *D) {
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD))
@@ -194,12 +132,12 @@ public:
}
// Determine if this declaration is actually a redeclaration.
- VectorTy &Vec = *getAsVector();
- for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
+ DeclsTy &Vec = *getAsVector();
+ for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) {
- NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
+ NamedDecl *OldD = *OD;
if (D->declarationReplaces(OldD)) {
- *OD = reinterpret_cast<uintptr_t>(D);
+ *OD = D;
return true;
}
}
@@ -211,17 +149,15 @@ public:
/// not a redeclaration to merge it into the appropriate place in our list.
///
void AddSubsequentDecl(NamedDecl *D) {
- assert(!hasDeclarationIDs() && "Must materialize before adding decls");
-
// If this is the second decl added to the list, convert this to vector
// form.
if (NamedDecl *OldD = getAsDecl()) {
- VectorTy *VT = new VectorTy();
- VT->push_back(reinterpret_cast<uintptr_t>(OldD));
- Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
+ DeclsTy *VT = new DeclsTy();
+ VT->push_back(OldD);
+ Data = VT;
}
- VectorTy &Vec = *getAsVector();
+ DeclsTy &Vec = *getAsVector();
// Using directives end up in a special entry which contains only
// other using directives, so all this logic is wasted for them.
@@ -232,32 +168,30 @@ public:
// iterator which points at the first tag will start a span of
// decls that only contains tags.
if (D->hasTagIdentifierNamespace())
- Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ Vec.push_back(D);
// Resolved using declarations go at the front of the list so that
// they won't show up in other lookup results. Unresolved using
// declarations (which are always in IDNS_Using | IDNS_Ordinary)
// follow that so that the using declarations will be contiguous.
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
- VectorTy::iterator I = Vec.begin();
+ DeclsTy::iterator I = Vec.begin();
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
while (I != Vec.end() &&
- reinterpret_cast<NamedDecl *>(*I)
- ->getIdentifierNamespace() == Decl::IDNS_Using)
+ (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
++I;
}
- Vec.insert(I, reinterpret_cast<uintptr_t>(D));
+ Vec.insert(I, D);
// All other declarations go at the end of the list, but before any
// tag declarations. But we can be clever about tag declarations
// because there can only ever be one in a scope.
- } else if (reinterpret_cast<NamedDecl *>(Vec.back())
- ->hasTagIdentifierNamespace()) {
- uintptr_t TagD = Vec.back();
- Vec.back() = reinterpret_cast<uintptr_t>(D);
+ } else if (Vec.back()->hasTagIdentifierNamespace()) {
+ NamedDecl *TagD = Vec.back();
+ Vec.back() = D;
Vec.push_back(TagD);
} else
- Vec.push_back(reinterpret_cast<uintptr_t>(D));
+ Vec.push_back(D);
}
};
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 2807d16379ae..4b5e6fd48bb3 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -68,16 +68,16 @@ public:
SourceLocation FriendL);
static FriendDecl *Create(ASTContext &C, EmptyShell Empty);
- /// If this friend declaration names an (untemplated but
- /// possibly dependent) type, return the type; otherwise
- /// return null. This is used only for C++0x's unelaborated
- /// friend type declarations.
+ /// If this friend declaration names an (untemplated but possibly
+ /// dependent) type, return the type; otherwise return null. This
+ /// is used for elaborated-type-specifiers and, in C++0x, for
+ /// arbitrary friend type declarations.
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
- /// If this friend declaration doesn't name an unelaborated
- /// type, return the inner declaration.
+ /// If this friend declaration doesn't name a type, return the inner
+ /// declaration.
NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl*>();
}
@@ -92,8 +92,8 @@ public:
static bool classof(const FriendDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Decl::Friend; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// An iterator over the friend declarations of a class.
diff --git a/include/clang/AST/DeclGroup.h b/include/clang/AST/DeclGroup.h
index e1fae8f2ae67..030291ea7345 100644
--- a/include/clang/AST/DeclGroup.h
+++ b/include/clang/AST/DeclGroup.h
@@ -34,7 +34,6 @@ private:
public:
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
- void Destroy(ASTContext& C);
unsigned size() const { return NumDecls; }
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index 30f63d895959..ad26748e1343 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -21,7 +21,6 @@ namespace clang {
class Expr;
class Stmt;
class FunctionDecl;
-class AttributeList;
class RecordDecl;
class ObjCIvarDecl;
class ObjCMethodDecl;
@@ -41,12 +40,6 @@ protected:
public:
ObjCListBase() : List(0), NumElts(0) {}
- ~ObjCListBase() {
- assert(List == 0 && "Destroy should have been called before dtor");
- }
-
- void Destroy(ASTContext &Ctx);
-
unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; }
@@ -92,7 +85,6 @@ public:
void set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx);
- void Destroy(ASTContext &Ctx);
};
@@ -128,6 +120,9 @@ private:
// Synthesized declaration method for a property setter/getter
bool IsSynthesized : 1;
+
+ // Method has a definition.
+ bool IsDefined : 1;
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
/// @required/@optional
@@ -171,29 +166,25 @@ private:
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
+ bool isDefined = false,
ImplementationControl impControl = None,
unsigned numSelectorArgs = 0)
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
DeclContext(ObjCMethod),
IsInstance(isInstance), IsVariadic(isVariadic),
IsSynthesized(isSynthesized),
+ IsDefined(isDefined),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
ResultTInfo(ResultTInfo),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
- virtual ~ObjCMethodDecl() {}
-
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
virtual ObjCMethodDecl *getNextRedeclaration();
public:
-
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
static ObjCMethodDecl *Create(ASTContext &C,
SourceLocation beginLoc,
SourceLocation endLoc, Selector SelInfo,
@@ -203,6 +194,7 @@ public:
bool isInstance = true,
bool isVariadic = false,
bool isSynthesized = false,
+ bool isDefined = false,
ImplementationControl impControl = None,
unsigned numSelectorArgs = 0);
@@ -296,6 +288,9 @@ public:
bool isSynthesized() const { return IsSynthesized; }
void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
+
+ bool isDefined() const { return IsDefined; }
+ void setDefined(bool isDefined) { IsDefined = isDefined; }
// Related to protocols declared in @protocol
void setDeclImplementation(ImplementationControl ic) {
@@ -326,21 +321,6 @@ public:
}
};
-/// ObjCMethodList - a linked list of methods with different signatures.
-struct ObjCMethodList {
- ObjCMethodDecl *Method;
- ObjCMethodList *Next;
-
- ObjCMethodList() {
- Method = 0;
- Next = 0;
- }
- ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
- Method = M;
- Next = C;
- }
-};
-
/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
@@ -355,8 +335,6 @@ public:
IdentifierInfo *Id)
: NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
- virtual ~ObjCContainerDecl() {}
-
// Iterator access to properties.
typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
prop_iterator prop_begin() const {
@@ -465,12 +443,19 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// Class's super class.
ObjCInterfaceDecl *SuperClass;
- /// Protocols referenced in interface header declaration
+ /// Protocols referenced in the @interface declaration
ObjCProtocolList ReferencedProtocols;
+
+ /// Protocols reference in both the @interface and class extensions.
+ ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
/// List of categories defined for this class.
/// FIXME: Why is this a linked list??
ObjCCategoryDecl *CategoryList;
+
+ /// IvarList - List of all ivars defined by this class; including class
+ /// extensions and implementation. This list is built lazily.
+ ObjCIvarDecl *IvarList;
bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation
@@ -482,13 +467,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal);
- virtual ~ObjCInterfaceDecl() {}
-
public:
-
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
@@ -513,25 +492,49 @@ public:
}
typedef ObjCProtocolList::iterator protocol_iterator;
- protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
- protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+
+ protocol_iterator protocol_begin() const {
+ return ReferencedProtocols.begin();
+ }
+ protocol_iterator protocol_end() const {
+ return ReferencedProtocols.end();
+ }
+
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+
protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin();
}
+
protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end();
}
- unsigned protocol_size() const { return ReferencedProtocols.size(); }
+
+ typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
+
+ all_protocol_iterator all_referenced_protocol_begin() const {
+ return AllReferencedProtocols.empty() ? protocol_begin()
+ : AllReferencedProtocols.begin();
+ }
+ all_protocol_iterator all_referenced_protocol_end() const {
+ return AllReferencedProtocols.empty() ? protocol_end()
+ : AllReferencedProtocols.end();
+ }
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+
ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+
unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end());
}
+
bool ivar_empty() const { return ivar_begin() == ivar_end(); }
-
+
+ ObjCIvarDecl *all_declared_ivar_begin();
+ void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
+
/// setProtocolList - Set the list of protocols that this interface
/// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
@@ -543,7 +546,6 @@ public:
/// into the protocol list for this class.
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
unsigned Num,
- const SourceLocation *Locs,
ASTContext &C);
bool isForwardDecl() const { return ForwardDecl; }
@@ -625,6 +627,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCInterface; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
@@ -650,21 +655,26 @@ public:
private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id,
- QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW)
+ QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
+ bool synthesized)
: FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
- DeclAccess(ac) {}
+ NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
public:
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo,
- AccessControl ac, Expr *BW = NULL);
+ AccessControl ac, Expr *BW = NULL,
+ bool synthesized=false);
/// \brief Return the class interface that this ivar is logically contained
/// in; this is either the interface where the ivar was declared, or the
/// interface the ivar is conceptually a part of in the case of synthesized
/// ivars.
const ObjCInterfaceDecl *getContainingInterface() const;
+
+ ObjCIvarDecl *getNextIvar() { return NextIvar; }
+ void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
void setAccessControl(AccessControl ac) { DeclAccess = ac; }
@@ -674,13 +684,21 @@ public:
return DeclAccess == None ? Protected : AccessControl(DeclAccess);
}
+ void setSynthesize(bool synth) { Synthesized = synth; }
+ bool getSynthesize() const { return Synthesized; }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCIvarDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCIvar; }
private:
+ /// NextIvar - Next Ivar in the list of ivars declared in class; class's
+ /// extensions and class's implementation
+ ObjCIvarDecl *NextIvar;
+
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
unsigned DeclAccess : 3;
+ unsigned Synthesized : 1;
};
@@ -700,8 +718,6 @@ public:
IdentifierInfo *Id, QualType T,
Expr *BW);
- virtual void Destroy(ASTContext& C);
-
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
@@ -745,15 +761,10 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
isForwardProtoDecl(true) {
}
- virtual ~ObjCProtocolDecl() {}
-
public:
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols;
}
@@ -822,12 +833,7 @@ private:
ObjCClassDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
unsigned nElts, ASTContext &C);
- virtual ~ObjCClassDecl() {}
public:
-
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts = 0,
const SourceLocation *Locs = 0,
@@ -860,7 +866,6 @@ class ObjCForwardProtocolDecl : public Decl {
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts,
const SourceLocation *Locs, ASTContext &C);
- virtual ~ObjCForwardProtocolDecl() {}
public:
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
@@ -874,9 +879,6 @@ public:
return Create(C, DC, L, 0, 0, 0);
}
- /// Destroy - Call destructors and release memory.
- virtual void Destroy(ASTContext& C);
-
typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
@@ -928,6 +930,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory;
+ /// true of class extension has at least one bitfield ivar.
+ bool HasSynthBitfield : 1;
+
/// \brief The location of the '@' in '@interface'
SourceLocation AtLoc;
@@ -938,8 +943,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
- ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc),
- CategoryNameLoc(CategoryNameLoc) {
+ ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false),
+ AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) {
}
public:
@@ -991,6 +996,9 @@ public:
bool IsClassExtension() const { return getIdentifier() == 0; }
const ObjCCategoryDecl *getNextClassExtension() const;
+ bool hasSynthBitfield() const { return HasSynthBitfield; }
+ void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
+
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin());
@@ -1032,8 +1040,6 @@ protected:
ClassInterface(classInterface) {}
public:
- virtual ~ObjCImplDecl() {}
-
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
void setClassInterface(ObjCInterfaceDecl *IFace);
@@ -1165,11 +1171,15 @@ class ObjCImplementationDecl : public ObjCImplDecl {
CXXBaseOrMemberInitializer **IvarInitializers;
unsigned NumIvarInitializers;
+ /// true of class extension has at least one bitfield ivar.
+ bool HasSynthBitfield : 1;
+
ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl)
: ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
- SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {}
+ SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
+ HasSynthBitfield(false) {}
public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -1207,6 +1217,9 @@ public:
void setIvarInitializers(ASTContext &C,
CXXBaseOrMemberInitializer ** initializers,
unsigned numInitializers);
+
+ bool hasSynthBitfield() const { return HasSynthBitfield; }
+ void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
/// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation.
@@ -1262,6 +1275,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCImplementationDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCImplementation; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 135dd3ae78d3..b532668242fd 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -23,6 +23,7 @@ namespace clang {
class TemplateParameterList;
class TemplateDecl;
+class RedeclarableTemplateDecl;
class FunctionTemplateDecl;
class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl;
@@ -193,13 +194,6 @@ public:
TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { }
- /// Used to release the memory associated with a TemplateArgumentList
- /// object. FIXME: This is currently not called anywhere, but the
- /// memory will still be freed when using a BumpPtrAllocator.
- void Destroy(ASTContext &C);
-
- ~TemplateArgumentList();
-
/// \brief Copies the template arguments into a locally new[]'d array.
void init(ASTContext &Context,
const TemplateArgument *Args, unsigned NumArgs);
@@ -255,8 +249,6 @@ protected:
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(Params) { }
public:
- ~TemplateDecl();
-
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@@ -268,6 +260,7 @@ public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateDecl *D) { return true; }
+ static bool classof(const RedeclarableTemplateDecl *D) { return true; }
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
@@ -490,122 +483,179 @@ public:
}
};
-/// Declaration of a template function.
-class FunctionTemplateDecl : public TemplateDecl {
- static void DeallocateCommon(void *Ptr);
-
+/// Declaration of a redeclarable template.
+class RedeclarableTemplateDecl : public TemplateDecl {
+
+ RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
+ return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
+ }
+
+ RedeclarableTemplateDecl *getCanonicalDeclImpl();
+
+ void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
+
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
+ return getCommonPtr()->InstantiatedFromMember.getPointer();
+ }
+
+ void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
+ assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
+ getCommonPtr()->InstantiatedFromMember.setPointer(TD);
+ }
+
protected:
- /// \brief Data that is common to all of the declarations of a given
- /// function template.
- struct Common {
- Common() : InstantiatedFromMember(0, false) { }
+ template <typename EntryType> struct SpecEntryTraits {
+ typedef EntryType DeclType;
- /// \brief The function template specializations for this function
- /// template, including explicit specializations and instantiations.
- llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+ static DeclType *getMostRecentDeclaration(EntryType *D) {
+ return D->getMostRecentDeclaration();
+ }
+ };
+
+ template <typename EntryType,
+ typename _SETraits = SpecEntryTraits<EntryType>,
+ typename _DeclType = typename _SETraits::DeclType>
+ class SpecIterator : public std::iterator<std::forward_iterator_tag,
+ _DeclType*, ptrdiff_t,
+ _DeclType*, _DeclType*> {
+ typedef _SETraits SETraits;
+ typedef _DeclType DeclType;
+
+ typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType;
+
+ SetIteratorType SetIter;
+
+ public:
+ SpecIterator() : SetIter() {}
+ SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {}
+
+ DeclType *operator*() const {
+ return SETraits::getMostRecentDeclaration(&*SetIter);
+ }
+ DeclType *operator->() const { return **this; }
+
+ SpecIterator &operator++() { ++SetIter; return *this; }
+ SpecIterator operator++(int) {
+ SpecIterator tmp(*this);
+ ++(*this);
+ return tmp;
+ }
+
+ bool operator==(SpecIterator Other) const {
+ return SetIter == Other.SetIter;
+ }
+ bool operator!=(SpecIterator Other) const {
+ return SetIter != Other.SetIter;
+ }
+ };
+
+ template <typename EntryType>
+ SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs,
+ bool isEnd) {
+ return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
+ }
+
+ template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
+ findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
+ const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ struct CommonBase {
+ CommonBase() : InstantiatedFromMember(0, false) { }
- /// \brief The member function template from which this was most
+ /// \brief The template from which this was most
/// directly instantiated (or null).
///
- /// The boolean value indicates whether this member function template
+ /// The boolean value indicates whether this template
/// was explicitly specialized.
- llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember;
+ llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
+ InstantiatedFromMember;
+
+ /// \brief The latest declaration of this template.
+ RedeclarableTemplateDecl *Latest;
};
/// \brief A pointer to the previous declaration (if this is a redeclaration)
- /// or to the data that is common to all declarations of this function
- /// template.
- llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
+ /// or to the data that is common to all declarations of this template.
+ llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev;
- /// \brief Retrieves the "common" pointer shared by all
- /// (re-)declarations of the same function template. Calling this routine
- /// may implicitly allocate memory for the common pointer.
- Common *getCommonPtr();
+ /// \brief Retrieves the "common" pointer shared by all (re-)declarations of
+ /// the same template. Calling this routine may implicitly allocate memory
+ /// for the common pointer.
+ CommonBase *getCommonPtr();
- FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params, NamedDecl *Decl)
- : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
- CommonOrPrev((Common*)0) { }
+ virtual CommonBase *newCommon() = 0;
-public:
- void Destroy(ASTContext &C);
+ // Construct a template decl with name, parameters, and templated element.
+ RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
+ DeclarationName Name, TemplateParameterList *Params,
+ NamedDecl *Decl)
+ : TemplateDecl(DK, DC, L, Name, Params, Decl),
+ CommonOrPrev((CommonBase*)0) { }
- /// Get the underlying function declaration of the template.
- FunctionDecl *getTemplatedDecl() const {
- return static_cast<FunctionDecl*>(TemplatedDecl);
- }
+public:
+ template <class decl_type> friend class RedeclarableTemplate;
- /// \brief Retrieve the set of function template specializations of this
- /// function template.
- llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
- return getCommonPtr()->Specializations;
+ RedeclarableTemplateDecl *getCanonicalDecl() {
+ return getCanonicalDeclImpl();
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
- const FunctionTemplateDecl *getPreviousDeclaration() const {
- return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
+ RedeclarableTemplateDecl *getPreviousDeclaration() {
+ return getPreviousDeclarationImpl();
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
- FunctionTemplateDecl *getPreviousDeclaration() {
- return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
+ const RedeclarableTemplateDecl *getPreviousDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration();
}
- /// \brief Set the previous declaration of this function template.
- void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
- if (Prev)
- CommonOrPrev = Prev;
+ /// \brief Retrieve the first declaration of this template, or itself
+ /// if this the first one.
+ RedeclarableTemplateDecl *getFirstDeclaration() {
+ return getCanonicalDecl();
}
- virtual FunctionTemplateDecl *getCanonicalDecl();
+ /// \brief Retrieve the first declaration of this template, or itself
+ /// if this the first one.
+ const RedeclarableTemplateDecl *getFirstDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration();
+ }
- /// \brief Retrieve the member function template that this function template
- /// was instantiated from.
- ///
- /// This routine will return non-NULL for member function templates of
- /// class templates. For example, given:
- ///
- /// \code
- /// template <typename T>
- /// struct X {
- /// template <typename U> void f();
- /// };
- /// \endcode
- ///
- /// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a
- /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
- /// return X<int>::f, a FunctionTemplateDecl (whose parent is again
- /// X<int>) for which getInstantiatedFromMemberTemplate() will return
- /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
- /// ClassTemplateDecl).
- ///
- /// \returns NULL if this is not an instantiation of a member function
- /// template.
- FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
- return getCommonPtr()->InstantiatedFromMember.getPointer();
+ /// \brief Retrieve the most recent declaration of this template, or itself
+ /// if this the most recent one.
+ RedeclarableTemplateDecl *getMostRecentDeclaration() {
+ return getCommonPtr()->Latest;
}
- void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) {
- assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
- getCommonPtr()->InstantiatedFromMember.setPointer(FTD);
+ /// \brief Retrieve the most recent declaration of this template, or itself
+ /// if this the most recent one.
+ const RedeclarableTemplateDecl *getMostRecentDeclaration() const {
+ return
+ const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration();
}
/// \brief Determines whether this template was a specialization of a
/// member template.
///
- /// In the following example, the function template \c X<int>::f is a
- /// member specialization.
+ /// In the following example, the function template \c X<int>::f and the
+ /// member template \c X<int>::Inner are member specializations.
///
/// \code
/// template<typename T>
/// struct X {
/// template<typename U> void f(T, U);
+ /// template<typename U> struct Inner;
/// };
///
/// template<> template<typename T>
/// void X<int>::f(int, T);
+ /// template<> template<typename T>
+ /// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
return getCommonPtr()->InstantiatedFromMember.getInt();
@@ -618,6 +668,197 @@ public:
getCommonPtr()->InstantiatedFromMember.setInt(true);
}
+ /// \brief Retrieve the previous declaration of this template, or
+ /// NULL if no such declaration exists.
+ RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return getInstantiatedFromMemberTemplateImpl();
+ }
+
+ virtual RedeclarableTemplateDecl *getNextRedeclaration();
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classof(const RedeclarableTemplateDecl *D) { return true; }
+ static bool classof(const FunctionTemplateDecl *D) { return true; }
+ static bool classof(const ClassTemplateDecl *D) { return true; }
+ static bool classofKind(Kind K) {
+ return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+template <class decl_type>
+class RedeclarableTemplate {
+ RedeclarableTemplateDecl *thisDecl() {
+ return static_cast<decl_type*>(this);
+ }
+
+public:
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ decl_type *getPreviousDeclaration() {
+ return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl());
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const decl_type *getPreviousDeclaration() const {
+ return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration();
+ }
+
+ /// \brief Set the previous declaration of this function template.
+ void setPreviousDeclaration(decl_type *Prev) {
+ thisDecl()->setPreviousDeclarationImpl(Prev);
+ }
+
+ decl_type *getCanonicalDecl() {
+ return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl());
+ }
+
+ const decl_type *getCanonicalDecl() const {
+ return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the member template that this template was instantiated
+ /// from.
+ ///
+ /// This routine will return non-NULL for member templates of
+ /// class templates. For example, given:
+ ///
+ /// \code
+ /// template <typename T>
+ /// struct X {
+ /// template <typename U> void f();
+ /// template <typename U> struct A {};
+ /// };
+ /// \endcode
+ ///
+ /// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a
+ /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
+ /// return X<int>::f, a FunctionTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
+ /// ClassTemplateDecl).
+ ///
+ /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
+ /// is X<int>, also a CTSD) for which getSpecializedTemplate() will
+ /// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again
+ /// X<int>) for which getInstantiatedFromMemberTemplate() will return
+ /// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD).
+ ///
+ /// \returns NULL if this is not an instantiation of a member template.
+ decl_type *getInstantiatedFromMemberTemplate() {
+ return static_cast<decl_type*>(
+ thisDecl()->getInstantiatedFromMemberTemplateImpl());
+ }
+
+ void setInstantiatedFromMemberTemplate(decl_type *TD) {
+ thisDecl()->setInstantiatedFromMemberTemplateImpl(TD);
+ }
+};
+
+template <> struct RedeclarableTemplateDecl::
+SpecEntryTraits<FunctionTemplateSpecializationInfo> {
+ typedef FunctionDecl DeclType;
+
+ static DeclType *
+ getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) {
+ return I->Function->getMostRecentDeclaration();
+ }
+};
+
+/// Declaration of a template function.
+class FunctionTemplateDecl : public RedeclarableTemplateDecl,
+ public RedeclarableTemplate<FunctionTemplateDecl> {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base;
+
+ /// \brief Data that is common to all of the declarations of a given
+ /// function template.
+ struct Common : CommonBase {
+ /// \brief The function template specializations for this function
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
+ };
+
+ FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
+
+ CommonBase *newCommon();
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+ friend void FunctionDecl::setFunctionTemplateSpecialization(
+ FunctionTemplateDecl *Template,
+ const TemplateArgumentList *TemplateArgs,
+ void *InsertPos,
+ TemplateSpecializationKind TSK,
+ const TemplateArgumentListInfo *TemplateArgsAsWritten,
+ SourceLocation PointOfInstantiation);
+
+ /// \brief Retrieve the set of function template specializations of this
+ /// function template.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
+ return getCommonPtr()->Specializations;
+ }
+
+public:
+ /// Get the underlying function declaration of the template.
+ FunctionDecl *getTemplatedDecl() const {
+ return static_cast<FunctionDecl*>(TemplatedDecl);
+ }
+
+ /// Returns whether this template declaration defines the primary
+ /// pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ FunctionDecl *findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos);
+
+ FunctionTemplateDecl *getCanonicalDecl() {
+ return redeclarable_base::getCanonicalDecl();
+ }
+ const FunctionTemplateDecl *getCanonicalDecl() const {
+ return redeclarable_base::getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ FunctionTemplateDecl *getPreviousDeclaration() {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ /// \brief Retrieve the previous declaration of this function template, or
+ /// NULL if no such declaration exists.
+ const FunctionTemplateDecl *getPreviousDeclaration() const {
+ return redeclarable_base::getPreviousDeclaration();
+ }
+
+ FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return redeclarable_base::getInstantiatedFromMemberTemplate();
+ }
+
+ typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
+
+ spec_iterator spec_begin() {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
/// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -630,8 +871,8 @@ public:
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == FunctionTemplate; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
//===----------------------------------------------------------------------===//
@@ -781,8 +1022,7 @@ class NonTypeTemplateParmDecl
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo)
- : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None,
- VarDecl::None),
+ : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
{ }
@@ -904,13 +1144,20 @@ public:
DefaultArgumentWasInherited = false;
}
+ SourceRange getSourceRange() const {
+ SourceLocation End = getLocation();
+ if (hasDefaultArgument() && !defaultArgumentWasInherited())
+ End = getDefaultArgument().getSourceRange().getEnd();
+ return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// \brief Represents a class template specialization, which refers to
@@ -991,12 +1238,21 @@ public:
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
- virtual void Destroy(ASTContext& C);
-
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
+ ClassTemplateSpecializationDecl *getMostRecentDeclaration() {
+ CXXRecordDecl *Recent
+ = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration());
+ if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
+ // FIXME: Does injected class name need to be in the redeclarations chain?
+ assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration());
+ Recent = Recent->getPreviousDeclaration();
+ }
+ return cast<ClassTemplateSpecializationDecl>(Recent);
+ }
+
/// \brief Retrieve the template that this specialization specializes.
ClassTemplateDecl *getSpecializedTemplate() const;
@@ -1044,7 +1300,8 @@ public:
if (getSpecializationKind() != TSK_ImplicitInstantiation &&
getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
- return (ClassTemplateDecl*)0;
+ return llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>();
if (SpecializedPartialSpecialization *PartialSpec
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
@@ -1123,7 +1380,8 @@ public:
/// \brief Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type.
void setTypeAsWritten(TypeSourceInfo *T) {
- if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = T;
}
/// \brief Gets the type of this specialization as it was written by
@@ -1138,13 +1396,15 @@ public:
}
/// \brief Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
- if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->ExternLoc = Loc;
}
/// \brief Sets the location of the template keyword.
void setTemplateKeywordLoc(SourceLocation Loc) {
- if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
/// \brief Gets the location of the template keyword, if present.
@@ -1242,6 +1502,11 @@ public:
static ClassTemplatePartialSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
+ ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() {
+ return cast<ClassTemplatePartialSpecializationDecl>(
+ ClassTemplateSpecializationDecl::getMostRecentDeclaration());
+ }
+
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@@ -1355,15 +1620,16 @@ public:
};
/// Declaration of a class template.
-class ClassTemplateDecl : public TemplateDecl {
+class ClassTemplateDecl : public RedeclarableTemplateDecl,
+ public RedeclarableTemplate<ClassTemplateDecl> {
static void DeallocateCommon(void *Ptr);
protected:
+ typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
+
/// \brief Data that is common to all of the declarations of a given
/// class template.
- struct Common {
- Common() : InstantiatedFromMember(0, 0) {}
-
+ struct Common : CommonBase {
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@@ -1375,28 +1641,29 @@ protected:
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
-
- /// \brief The templated member class from which this was most
- /// directly instantiated (or null).
- ///
- /// The boolean value indicates whether this member class template
- /// was explicitly specialized.
- llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember;
};
- /// \brief A pointer to the previous declaration (if this is a redeclaration)
- /// or to the data that is common to all declarations of this class template.
- llvm::PointerUnion<Common*, ClassTemplateDecl*> CommonOrPrev;
+ /// \brief Retrieve the set of specializations of this class template.
+ llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
+ return getCommonPtr()->Specializations;
+ }
- /// \brief Retrieves the "common" pointer shared by all
- /// (re-)declarations of the same class template. Calling this routine
- /// may implicitly allocate memory for the common pointer.
- Common *getCommonPtr();
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ getPartialSpecializations() {
+ return getCommonPtr()->PartialSpecializations;
+ }
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
- : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl),
- CommonOrPrev((Common*)0) { }
+ : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
+
+ CommonBase *newCommon();
+
+ Common *getCommonPtr() {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
public:
/// Get the underlying class declarations of the template.
@@ -1404,48 +1671,71 @@ public:
return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
- /// \brief Retrieve the previous declaration of this class template, or
- /// NULL if no such declaration exists.
- const ClassTemplateDecl *getPreviousDeclaration() const {
- return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
+ /// Returns whether this template declaration defines the primary
+ /// class pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
}
- /// \brief Retrieve the previous declaration of this function template, or
+ /// Create a class template node.
+ static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl,
+ ClassTemplateDecl *PrevDecl);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ ClassTemplateSpecializationDecl *
+ findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified specialization knowing that it is not already
+ /// in. InsertPos must be obtained from findSpecialization.
+ void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) {
+ getSpecializations().InsertNode(D, InsertPos);
+ }
+
+ ClassTemplateDecl *getCanonicalDecl() {
+ return redeclarable_base::getCanonicalDecl();
+ }
+ const ClassTemplateDecl *getCanonicalDecl() const {
+ return redeclarable_base::getCanonicalDecl();
+ }
+
+ /// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDeclaration() {
- return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
+ return redeclarable_base::getPreviousDeclaration();
}
- /// \brief Set the previous declaration of this class template.
- void setPreviousDeclaration(ClassTemplateDecl *Prev) {
- if (Prev)
- CommonOrPrev = Prev;
+ /// \brief Retrieve the previous declaration of this class template, or
+ /// NULL if no such declaration exists.
+ const ClassTemplateDecl *getPreviousDeclaration() const {
+ return redeclarable_base::getPreviousDeclaration();
}
- virtual ClassTemplateDecl *getCanonicalDecl();
-
- const ClassTemplateDecl *getCanonicalDecl() const {
- return const_cast<ClassTemplateDecl*>(this)->getCanonicalDecl();
+ ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return redeclarable_base::getInstantiatedFromMemberTemplate();
}
- /// Create a class template node.
- static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName Name,
- TemplateParameterList *Params,
- NamedDecl *Decl,
- ClassTemplateDecl *PrevDecl);
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
- /// \brief Retrieve the set of specializations of this class template.
- llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
- return getCommonPtr()->Specializations;
+ /// \brief Insert the specified partial specialization knowing that it is not
+ /// already in. InsertPos must be obtained from findPartialSpecialization.
+ void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
+ void *InsertPos) {
+ getPartialSpecializations().InsertNode(D, InsertPos);
}
- /// \brief Retrieve the set of partial specializations of this class
- /// template.
- llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
- getPartialSpecializations() {
- return getCommonPtr()->PartialSpecializations;
+ /// \brief Return the next partial specialization sequence number.
+ unsigned getNextPartialSpecSequenceNumber() {
+ return getPartialSpecializations().size();
}
/// \brief Retrieve the partial specializations as an ordered list.
@@ -1455,12 +1745,24 @@ public:
/// \brief Find a class template partial specialization with the given
/// type T.
///
- /// \brief A dependent type that names a specialization of this class
+ /// \param T a dependent type that names a specialization of this class
/// template.
///
/// \returns the class template partial specialization that exactly matches
/// the type \p T, or NULL if no such partial specialization exists.
ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
+
+ /// \brief Find a class template partial specialization which was instantiated
+ /// from the given member partial specialization.
+ ///
+ /// \param D a member class template partial specialization.
+ ///
+ /// \returns the class template partial specialization which was instantiated
+ /// from the given member partial specialization, or NULL if no such partial
+ /// specialization exists.
+ ClassTemplatePartialSpecializationDecl *
+ findPartialSpecInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *D);
/// \brief Retrieve the template specialization type of the
/// injected-class-name for this class template.
@@ -1478,78 +1780,45 @@ public:
/// \endcode
QualType getInjectedClassNameSpecialization();
- /// \brief Retrieve the member class template that this class template was
- /// derived from.
- ///
- /// This routine will return non-NULL for templated member classes of
- /// class templates. For example, given:
- ///
- /// \code
- /// template <typename T>
- /// struct X {
- /// template <typename U> struct A {};
- /// };
- /// \endcode
- ///
- /// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
- /// is X<int>, also a CTSD) for which getSpecializedTemplate() will
- /// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
- /// X<int>) for which getInstantiatedFromMemberTemplate() will return
- /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD).
- ///
- /// \returns null if this is not an instantiation of a member class template.
- ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
- return getCommonPtr()->InstantiatedFromMember.getPointer();
+ typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
+
+ spec_iterator spec_begin() {
+ return makeSpecIterator(getSpecializations(), false);
}
- void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) {
- assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
- getCommonPtr()->InstantiatedFromMember.setPointer(CTD);
+ spec_iterator spec_end() {
+ return makeSpecIterator(getSpecializations(), true);
}
- /// \brief Determines whether this template was a specialization of a
- /// member template.
- ///
- /// In the following example, the member template \c X<int>::Inner is a
- /// member specialization.
- ///
- /// \code
- /// template<typename T>
- /// struct X {
- /// template<typename U> struct Inner;
- /// };
- ///
- /// template<> template<typename T>
- /// struct X<int>::Inner { /* ... */ };
- /// \endcode
- bool isMemberSpecialization() {
- return getCommonPtr()->InstantiatedFromMember.getInt();
+ typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
+ partial_spec_iterator;
+
+ partial_spec_iterator partial_spec_begin() {
+ return makeSpecIterator(getPartialSpecializations(), false);
}
-
- /// \brief Note that this member template is a specialization.
- void setMemberSpecialization() {
- assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
- "Only member templates can be member template specializations");
- getCommonPtr()->InstantiatedFromMember.setInt(true);
+
+ partial_spec_iterator partial_spec_end() {
+ return makeSpecIterator(getPartialSpecializations(), true);
}
-
+
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ClassTemplate; }
- virtual void Destroy(ASTContext& C);
-
- friend class PCHDeclReader;
- friend class PCHDeclWriter;
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
/// Declaration of a friend template. For example:
///
/// template <typename T> class A {
/// friend class MyVector<T>; // not a friend template
-/// template <typename U> friend class B; // friend template
+/// template <typename U> friend class B; // not a friend template
/// template <typename U> friend class Foo<T>::Nested; // friend template
+/// };
+/// NOTE: This class is not currently in use. All of the above
+/// will yield a FriendDecl, not a FriendTemplateDecl.
class FriendTemplateDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
@@ -1580,6 +1849,12 @@ private:
FriendLoc(FriendLoc)
{}
+ FriendTemplateDecl(EmptyShell Empty)
+ : Decl(Decl::FriendTemplate, Empty),
+ NumParams(0),
+ Params(0)
+ {}
+
public:
static FriendTemplateDecl *Create(ASTContext &Context,
DeclContext *DC, SourceLocation Loc,
@@ -1588,6 +1863,8 @@ public:
FriendUnion Friend,
SourceLocation FriendLoc);
+ static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty);
+
/// If this friend declaration names a templated type (or
/// a dependent member type of a templated type), return that
/// type; otherwise return null.
@@ -1620,6 +1897,8 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
static bool classof(const FriendTemplateDecl *D) { return true; }
+
+ friend class ASTDeclReader;
};
/// Implementation of inline functions that require the template declarations
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 8a771d513c42..8bb627597520 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -30,6 +30,7 @@ namespace clang {
class IdentifierInfo;
class MultiKeywordSelector;
class UsingDirectiveDecl;
+ class TypeSourceInfo;
/// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal
@@ -367,6 +368,146 @@ public:
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
};
+/// DeclarationNameLoc - Additional source/type location info
+/// for a declaration name. Needs a DeclarationName in order
+/// to be interpreted correctly.
+struct DeclarationNameLoc {
+ union {
+ // The source location for identifier stored elsewhere.
+ // struct {} Identifier;
+
+ // Type info for constructors, destructors and conversion functions.
+ // Locations (if any) for the tilde (destructor) or operator keyword
+ // (conversion) are stored elsewhere.
+ struct {
+ TypeSourceInfo* TInfo;
+ } NamedType;
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct {
+ unsigned BeginOpNameLoc;
+ unsigned EndOpNameLoc;
+ } CXXOperatorName;
+
+ // The location (if any) of the operator keyword is stored elsewhere.
+ struct {
+ unsigned OpNameLoc;
+ } CXXLiteralOperatorName;
+
+ // struct {} CXXUsingDirective;
+ // struct {} ObjCZeroArgSelector;
+ // struct {} ObjCOneArgSelector;
+ // struct {} ObjCMultiArgSelector;
+ };
+
+ DeclarationNameLoc(DeclarationName Name);
+ // FIXME: this should go away once all DNLocs are properly initialized.
+ DeclarationNameLoc() { NamedType.TInfo = 0; }
+}; // struct DeclarationNameLoc
+
+
+/// DeclarationNameInfo - A collector data type for bundling together
+/// a DeclarationName and the correspnding source/type location info.
+struct DeclarationNameInfo {
+private:
+ /// Name - The declaration name, also encoding name kind.
+ DeclarationName Name;
+ /// Loc - The main source location for the declaration name.
+ SourceLocation NameLoc;
+ /// Info - Further source/type location info for special kinds of names.
+ DeclarationNameLoc LocInfo;
+
+public:
+ // FIXME: remove it.
+ DeclarationNameInfo() {}
+
+ DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
+ : Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
+
+ DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
+ DeclarationNameLoc LocInfo)
+ : Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
+
+ /// getName - Returns the embedded declaration name.
+ DeclarationName getName() const { return Name; }
+ /// setName - Sets the embedded declaration name.
+ void setName(DeclarationName N) { Name = N; }
+
+ /// getLoc - Returns the main location of the declaration name.
+ SourceLocation getLoc() const { return NameLoc; }
+ /// setLoc - Sets the main location of the declaration name.
+ void setLoc(SourceLocation L) { NameLoc = L; }
+
+ const DeclarationNameLoc &getInfo() const { return LocInfo; }
+ DeclarationNameLoc &getInfo() { return LocInfo; }
+ void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
+
+ /// getNamedTypeInfo - Returns the source type info associated to
+ /// the name. Assumes it is a constructor, destructor or conversion.
+ TypeSourceInfo *getNamedTypeInfo() const {
+ assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ return LocInfo.NamedType.TInfo;
+ }
+ /// setNamedTypeInfo - Sets the source type info associated to
+ /// the name. Assumes it is a constructor, destructor or conversion.
+ void setNamedTypeInfo(TypeSourceInfo *TInfo) {
+ assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
+ Name.getNameKind() == DeclarationName::CXXDestructorName ||
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
+ LocInfo.NamedType.TInfo = TInfo;
+ }
+
+ /// getCXXOperatorNameRange - Gets the range of the operator name
+ /// (without the operator keyword). Assumes it is a (non-literal) operator.
+ SourceRange getCXXOperatorNameRange() const {
+ assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ return SourceRange(
+ SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
+ SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
+ );
+ }
+ /// setCXXOperatorNameRange - Sets the range of the operator name
+ /// (without the operator keyword). Assumes it is a C++ operator.
+ void setCXXOperatorNameRange(SourceRange R) {
+ assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
+ LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
+ LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
+ }
+
+ /// getCXXLiteralOperatorNameLoc - Returns the location of the literal
+ /// operator name (not the operator keyword).
+ /// Assumes it is a literal operator.
+ SourceLocation getCXXLiteralOperatorNameLoc() const {
+ assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ return SourceLocation::
+ getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
+ }
+ /// setCXXLiteralOperatorNameLoc - Sets the location of the literal
+ /// operator name (not the operator keyword).
+ /// Assumes it is a literal operator.
+ void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
+ assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
+ LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
+ }
+
+ /// getAsString - Retrieve the human-readable string for this name.
+ std::string getAsString() const;
+
+ /// printName - Print the human-readable name to a stream.
+ void printName(llvm::raw_ostream &OS) const;
+
+ /// getBeginLoc - Retrieve the location of the first token.
+ SourceLocation getBeginLoc() const { return NameLoc; }
+ /// getEndLoc - Retrieve the location of the last token.
+ SourceLocation getEndLoc() const;
+ /// getSourceRange - The range of the declaration name.
+ SourceRange getSourceRange() const {
+ return SourceRange(getBeginLoc(), getEndLoc());
+ }
+};
+
/// Insertion operator for diagnostics. This allows sending DeclarationName's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -385,6 +526,12 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
return PD;
}
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ DeclarationNameInfo DNInfo) {
+ DNInfo.printName(OS);
+ return OS;
+}
+
} // end namespace clang
namespace llvm {
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index ade2b09c80c2..48130becf3b5 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -18,6 +18,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/OperationKinds.h"
#include "clang/AST/ASTVector.h"
#include "clang/AST/UsuallyTinyPtrVector.h"
#include "llvm/ADT/APSInt.h"
@@ -42,7 +43,7 @@ namespace clang {
class TemplateArgumentListInfo;
/// \brief A simple array of base specifiers.
-typedef UsuallyTinyPtrVector<const CXXBaseSpecifier> CXXBaseSpecifierArray;
+typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
/// Expr - This represents one expression. Note that Expr's are subclasses of
/// Stmt. This allows an expression to be transparently used any place a Stmt
@@ -61,8 +62,14 @@ protected:
/// (C++ [temp.dep.constexpr]).
bool ValueDependent : 1;
+ /// ValueKind - The value classification of this expression.
+ /// Only actually used by certain subclasses.
+ unsigned ValueKind : 2;
+
+ enum { BitsRemaining = 28 };
+
Expr(StmtClass SC, QualType T, bool TD, bool VD)
- : Stmt(SC), TypeDependent(TD), ValueDependent(VD) {
+ : Stmt(SC), TypeDependent(TD), ValueDependent(VD), ValueKind(0) {
setType(T);
}
@@ -258,7 +265,6 @@ public:
/// function returning an rvalue reference.
/// lvalues and xvalues are collectively referred to as glvalues, while
/// prvalues and xvalues together form rvalues.
- /// If a
Classification Classify(ASTContext &Ctx) const {
return ClassifyImpl(Ctx, 0);
}
@@ -310,7 +316,7 @@ public:
}
/// isConstantInitializer - Returns true if this expression is a constant
/// initializer, which can be emitted at compile-time.
- bool isConstantInitializer(ASTContext &Ctx) const;
+ bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const;
/// EvalResult is a struct with detailed info about an evaluated expression.
struct EvalResult {
@@ -521,10 +527,14 @@ class DeclRefExpr : public Expr {
// (2) the declaration's name was followed by an explicit template
// argument list.
llvm::PointerIntPair<ValueDecl *, 2> DecoratedD;
-
+
// Loc - The location of the declaration name itself.
SourceLocation Loc;
+ /// DNLoc - Provides source/type location info for the
+ /// declaration name embedded in DecoratedD.
+ DeclarationNameLoc DNLoc;
+
/// \brief Retrieve the qualifier that preceded the declaration name, if any.
NameQualifier *getNameQualifier() {
if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
@@ -537,31 +547,17 @@ class DeclRefExpr : public Expr {
const NameQualifier *getNameQualifier() const {
return const_cast<DeclRefExpr *>(this)->getNameQualifier();
}
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
- if ((DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag) == 0)
- return 0;
-
- if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
- return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
-
- return reinterpret_cast<ExplicitTemplateArgumentList *>(
- getNameQualifier() + 1);
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
- return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgumentList();
- }
-
+
DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
ValueDecl *D, SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs,
QualType T);
+ DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange,
+ ValueDecl *D, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T);
+
/// \brief Construct an empty declaration reference expression.
explicit DeclRefExpr(EmptyShell Empty)
: Expr(DeclRefExprClass, Empty) { }
@@ -584,6 +580,14 @@ public:
QualType T,
const TemplateArgumentListInfo *TemplateArgs = 0);
+ static DeclRefExpr *Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ const DeclarationNameInfo &NameInfo,
+ QualType T,
+ const TemplateArgumentListInfo *TemplateArgs = 0);
+
/// \brief Construct an empty declaration reference expression.
static DeclRefExpr *CreateEmpty(ASTContext &Context,
bool HasQualifier, unsigned NumTemplateArgs);
@@ -592,6 +596,10 @@ public:
const ValueDecl *getDecl() const { return DecoratedD.getPointer(); }
void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); }
+ DeclarationNameInfo getNameInfo() const {
+ return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc);
+ }
+
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
virtual SourceRange getSourceRange() const;
@@ -619,53 +627,77 @@ public:
return getNameQualifier()->NNS;
}
- /// \brief Determines whether this member expression actually had a C++
- /// template argument list explicitly specified, e.g., x.f<int>.
- bool hasExplicitTemplateArgumentList() const {
- return DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag;
+ bool hasExplicitTemplateArgs() const {
+ return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(hasExplicitTemplateArgs());
+
+ if ((DecoratedD.getInt() & HasQualifierFlag) == 0)
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getNameQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that followed the
+ /// member template name.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<DeclRefExpr *>(this)->getExplicitTemplateArgs();
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getExplicitTemplateArgsOpt() const {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- if (hasExplicitTemplateArgumentList())
- getExplicitTemplateArgumentList()->copyInto(List);
+ if (hasExplicitTemplateArgs())
+ getExplicitTemplateArgs().copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
SourceLocation getLAngleLoc() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return SourceLocation();
- return getExplicitTemplateArgumentList()->LAngleLoc;
+ return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgumentList()->getTemplateArgs();
+ return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return 0;
- return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket following the
/// template arguments ('>').
SourceLocation getRAngleLoc() const {
- if (!hasExplicitTemplateArgumentList())
+ if (!hasExplicitTemplateArgs())
return SourceLocation();
- return getExplicitTemplateArgumentList()->RAngleLoc;
+ return getExplicitTemplateArgs().RAngleLoc;
}
static bool classof(const Stmt *T) {
@@ -677,8 +709,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
- friend class PCHStmtWriter;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
@@ -725,28 +757,84 @@ public:
virtual child_iterator child_end();
};
+/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
+/// leaking memory.
+///
+/// For large floats/integers, APFloat/APInt will allocate memory from the heap
+/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
+/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
+/// the APFloat/APInt values will never get freed. APNumericStorage uses
+/// ASTContext's allocator for memory allocation.
+class APNumericStorage {
+ unsigned BitWidth;
+ union {
+ uint64_t VAL; ///< Used to store the <= 64 bits integer value.
+ uint64_t *pVal; ///< Used to store the >64 bits integer value.
+ };
+
+ bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
+
+ APNumericStorage(const APNumericStorage&); // do not implement
+ APNumericStorage& operator=(const APNumericStorage&); // do not implement
+
+protected:
+ APNumericStorage() : BitWidth(0), VAL(0) { }
+
+ llvm::APInt getIntValue() const {
+ unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
+ if (NumWords > 1)
+ return llvm::APInt(BitWidth, NumWords, pVal);
+ else
+ return llvm::APInt(BitWidth, VAL);
+ }
+ void setIntValue(ASTContext &C, const llvm::APInt &Val);
+};
+
+class APIntStorage : public APNumericStorage {
+public:
+ llvm::APInt getValue() const { return getIntValue(); }
+ void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); }
+};
+
+class APFloatStorage : public APNumericStorage {
+public:
+ llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); }
+ void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ setIntValue(C, Val.bitcastToAPInt());
+ }
+};
+
class IntegerLiteral : public Expr {
- llvm::APInt Value;
+ APIntStorage Num;
SourceLocation Loc;
+
+ /// \brief Construct an empty integer literal.
+ explicit IntegerLiteral(EmptyShell Empty)
+ : Expr(IntegerLiteralClass, Empty) { }
+
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
- IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) {
+ IntegerLiteral(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l)
+ : Expr(IntegerLiteralClass, type, false, false), Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
+ setValue(C, V);
}
- /// \brief Construct an empty integer literal.
- explicit IntegerLiteral(EmptyShell Empty)
- : Expr(IntegerLiteralClass, Empty) { }
+ // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
+ // or UnsignedLongLongTy
+ static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l);
+ static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
- const llvm::APInt &getValue() const { return Value; }
+ llvm::APInt getValue() const { return Num.getValue(); }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
/// \brief Retrieve the location of the literal.
SourceLocation getLocation() const { return Loc; }
- void setValue(const llvm::APInt &Val) { Value = Val; }
+ void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); }
void setLocation(SourceLocation Location) { Loc = Location; }
static bool classof(const Stmt *T) {
@@ -795,21 +883,30 @@ public:
};
class FloatingLiteral : public Expr {
- llvm::APFloat Value;
+ APFloatStorage Num;
bool IsExact : 1;
SourceLocation Loc;
-public:
- FloatingLiteral(const llvm::APFloat &V, bool isexact,
+
+ FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L)
- : Expr(FloatingLiteralClass, Type, false, false), Value(V),
- IsExact(isexact), Loc(L) {}
+ : Expr(FloatingLiteralClass, Type, false, false),
+ IsExact(isexact), Loc(L) {
+ setValue(C, V);
+ }
/// \brief Construct an empty floating-point literal.
explicit FloatingLiteral(EmptyShell Empty)
- : Expr(FloatingLiteralClass, Empty), Value(0.0) { }
+ : Expr(FloatingLiteralClass, Empty), IsExact(false) { }
- const llvm::APFloat &getValue() const { return Value; }
- void setValue(const llvm::APFloat &Val) { Value = Val; }
+public:
+ static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L);
+ static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
+
+ llvm::APFloat getValue() const { return Num.getValue(); }
+ void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ Num.setValue(C, Val);
+ }
bool isExact() const { return IsExact; }
void setExact(bool E) { IsExact = E; }
@@ -889,9 +986,6 @@ class StringLiteral : public Expr {
StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {}
-protected:
- virtual void DoDestroy(ASTContext &C);
-
public:
/// This is the "fully general" constructor that allows representation of
/// strings formed from multiple concatenated tokens.
@@ -912,8 +1006,7 @@ public:
llvm::StringRef getString() const {
return llvm::StringRef(StrData, ByteLength);
}
- // FIXME: These are deprecated, replace with StringRef.
- const char *getStrData() const { return StrData; }
+
unsigned getByteLength() const { return ByteLength; }
/// \brief Sets the string data to the given string data.
@@ -1009,40 +1102,27 @@ public:
/// applied to a non-complex value, the former returns its operand and the
/// later returns zero in the type of the operand.
///
-/// __builtin_offsetof(type, a.b[10]) is represented as a unary operator whose
-/// subexpression is a compound literal with the various MemberExpr and
-/// ArraySubscriptExpr's applied to it. (This is only used in C)
-///
class UnaryOperator : public Expr {
public:
- // Note that additions to this should also update the StmtVisitor class.
- enum Opcode {
- PostInc, PostDec, // [C99 6.5.2.4] Postfix increment and decrement operators
- PreInc, PreDec, // [C99 6.5.3.1] Prefix increment and decrement operators.
- AddrOf, Deref, // [C99 6.5.3.2] Address and indirection operators.
- Plus, Minus, // [C99 6.5.3.3] Unary arithmetic operators.
- Not, LNot, // [C99 6.5.3.3] Unary arithmetic operators.
- Real, Imag, // "__real expr"/"__imag expr" Extension.
- Extension, // __extension__ marker.
- OffsetOf // __builtin_offsetof
- };
+ typedef UnaryOperatorKind Opcode;
+
private:
- Stmt *Val;
- Opcode Opc;
+ unsigned Opc : 5;
SourceLocation Loc;
+ Stmt *Val;
public:
UnaryOperator(Expr *input, Opcode opc, QualType type, SourceLocation l)
: Expr(UnaryOperatorClass, type,
- input->isTypeDependent() && opc != OffsetOf,
+ input->isTypeDependent() || type->isDependentType(),
input->isValueDependent()),
- Val(input), Opc(opc), Loc(l) {}
+ Opc(opc), Loc(l), Val(input) {}
/// \brief Build an empty unary operator.
explicit UnaryOperator(EmptyShell Empty)
- : Expr(UnaryOperatorClass, Empty), Opc(AddrOf) { }
+ : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { }
- Opcode getOpcode() const { return Opc; }
+ Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
void setOpcode(Opcode O) { Opc = O; }
Expr *getSubExpr() const { return cast<Expr>(Val); }
@@ -1054,21 +1134,26 @@ public:
/// isPostfix - Return true if this is a postfix operation, like x++.
static bool isPostfix(Opcode Op) {
- return Op == PostInc || Op == PostDec;
+ return Op == UO_PostInc || Op == UO_PostDec;
}
/// isPostfix - Return true if this is a prefix operation, like --x.
static bool isPrefix(Opcode Op) {
- return Op == PreInc || Op == PreDec;
+ return Op == UO_PreInc || Op == UO_PreDec;
}
- bool isPrefix() const { return isPrefix(Opc); }
- bool isPostfix() const { return isPostfix(Opc); }
- bool isIncrementOp() const {return Opc==PreInc || Opc==PostInc; }
- bool isIncrementDecrementOp() const { return Opc>=PostInc && Opc<=PreDec; }
- bool isOffsetOfOp() const { return Opc == OffsetOf; }
- static bool isArithmeticOp(Opcode Op) { return Op >= Plus && Op <= LNot; }
- bool isArithmeticOp() const { return isArithmeticOp(Opc); }
+ bool isPrefix() const { return isPrefix(getOpcode()); }
+ bool isPostfix() const { return isPostfix(getOpcode()); }
+ bool isIncrementOp() const {
+ return Opc == UO_PreInc || Opc == UO_PostInc;
+ }
+ bool isIncrementDecrementOp() const {
+ return Opc <= UO_PreDec;
+ }
+ static bool isArithmeticOp(Opcode Op) {
+ return Op >= UO_Plus && Op <= UO_LNot;
+ }
+ bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); }
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "sizeof" or "[pre]++"
@@ -1310,9 +1395,6 @@ class SizeOfAlignOfExpr : public Expr {
} Argument;
SourceLocation OpLoc, RParenLoc;
-protected:
- virtual void DoDestroy(ASTContext& C);
-
public:
SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo,
QualType resultType, SourceLocation op,
@@ -1485,8 +1567,6 @@ protected:
CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, unsigned numargs,
QualType t, SourceLocation rparenloc);
- virtual void DoDestroy(ASTContext& C);
-
public:
CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, QualType t,
SourceLocation rparenloc);
@@ -1494,8 +1574,6 @@ public:
/// \brief Build an empty call expression.
CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty);
- ~CallExpr() {}
-
const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); }
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
void setCallee(Expr *F) { SubExprs[FN] = F; }
@@ -1594,6 +1672,10 @@ class MemberExpr : public Expr {
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
+ /// MemberDNLoc - Provides source/type location info for the
+ /// declaration name embedded in MemberDecl.
+ DeclarationNameLoc MemberDNLoc;
+
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
@@ -1621,37 +1703,33 @@ class MemberExpr : public Expr {
return const_cast<MemberExpr *>(this)->getMemberQualifier();
}
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
- if (!HasExplicitTemplateArgumentList)
- return 0;
-
- if (!HasQualifierOrFoundDecl)
- return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
-
- return reinterpret_cast<ExplicitTemplateArgumentList *>(
- getMemberQualifier() + 1);
- }
-
- /// \brief Retrieve the explicit template argument list that followed the
- /// member template name, if any.
- const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
- return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
+public:
+ MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
+ const DeclarationNameInfo &NameInfo, QualType ty)
+ : Expr(MemberExprClass, ty,
+ base->isTypeDependent(), base->isValueDependent()),
+ Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()),
+ MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow),
+ HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {
+ assert(memberdecl->getDeclName() == NameInfo.getName());
}
-public:
+ // NOTE: this constructor should be used only when it is known that
+ // the member name can not provide additional syntactic info
+ // (i.e., source locations for C++ operator names or type source info
+ // for constructors, destructors and conversion oeprators).
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
SourceLocation l, QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent(), base->isValueDependent()),
- Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
+ Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(),
+ IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual, SourceRange qualrange,
ValueDecl *memberdecl, DeclAccessPair founddecl,
- SourceLocation l,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs,
QualType ty);
@@ -1700,15 +1778,42 @@ public:
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
- bool hasExplicitTemplateArgumentList() const {
+ bool hasExplicitTemplateArgs() const {
return HasExplicitTemplateArgumentList;
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- if (hasExplicitTemplateArgumentList())
- getExplicitTemplateArgumentList()->copyInto(List);
+ if (hasExplicitTemplateArgs())
+ getExplicitTemplateArgs().copyInto(List);
+ }
+
+ /// \brief Retrieve the explicit template argument list that
+ /// follow the member template name. This must only be called on an
+ /// expression with explicit template arguments.
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
+ assert(HasExplicitTemplateArgumentList);
+ if (!HasQualifierOrFoundDecl)
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(
+ getMemberQualifier() + 1);
+ }
+
+ /// \brief Retrieve the explicit template argument list that
+ /// followed the member template name. This must only be called on
+ /// an expression with explicit template arguments.
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
+ return const_cast<MemberExpr *>(this)->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() const {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
}
/// \brief Retrieve the location of the left angle bracket following the
@@ -1717,7 +1822,7 @@ public:
if (!HasExplicitTemplateArgumentList)
return SourceLocation();
- return getExplicitTemplateArgumentList()->LAngleLoc;
+ return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
@@ -1726,7 +1831,7 @@ public:
if (!HasExplicitTemplateArgumentList)
return 0;
- return getExplicitTemplateArgumentList()->getTemplateArgs();
+ return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
@@ -1735,7 +1840,7 @@ public:
if (!HasExplicitTemplateArgumentList)
return 0;
- return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket following the
@@ -1744,7 +1849,13 @@ public:
if (!HasExplicitTemplateArgumentList)
return SourceLocation();
- return getExplicitTemplateArgumentList()->RAngleLoc;
+ return getExplicitTemplateArgs().RAngleLoc;
+ }
+
+ /// \brief Retrieve the member declaration name info.
+ DeclarationNameInfo getMemberNameInfo() const {
+ return DeclarationNameInfo(MemberDecl->getDeclName(),
+ MemberLoc, MemberDNLoc);
}
bool isArrow() const { return IsArrow; }
@@ -1758,9 +1869,8 @@ public:
virtual SourceRange getSourceRange() const {
// If we have an implicit base (like a C++ implicit this),
// make sure not to return its location
- SourceLocation EndLoc = MemberLoc;
- if (HasExplicitTemplateArgumentList)
- EndLoc = getRAngleLoc();
+ SourceLocation EndLoc = (HasExplicitTemplateArgumentList)
+ ? getRAngleLoc() : getMemberNameInfo().getEndLoc();
SourceLocation BaseLoc = getBase()->getLocStart();
if (BaseLoc.isInvalid())
@@ -1843,110 +1953,13 @@ public:
/// classes).
class CastExpr : public Expr {
public:
- /// CastKind - the kind of cast this represents.
- enum CastKind {
- /// CK_Unknown - Unknown cast kind.
- /// FIXME: The goal is to get rid of this and make all casts have a
- /// kind so that the AST client doesn't have to try to figure out what's
- /// going on.
- CK_Unknown,
-
- /// CK_BitCast - Used for reinterpret_cast.
- CK_BitCast,
-
- /// CK_LValueBitCast - Used for reinterpret_cast of expressions to
- /// a reference type.
- CK_LValueBitCast,
-
- /// 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,
-
- /// CK_UncheckedDerivedToBase - Derived to base class casts that
- /// assume that the derived pointer is not null.
- CK_UncheckedDerivedToBase,
-
- /// CK_Dynamic - Dynamic cast.
- CK_Dynamic,
-
- /// CK_ToUnion - Cast to union (GCC extension).
- CK_ToUnion,
-
- /// CK_ArrayToPointerDecay - Array to pointer decay.
- CK_ArrayToPointerDecay,
-
- // CK_FunctionToPointerDecay - Function to pointer decay.
- CK_FunctionToPointerDecay,
-
- /// CK_NullToMemberPointer - Null pointer to member pointer.
- CK_NullToMemberPointer,
-
- /// CK_BaseToDerivedMemberPointer - Member pointer in base class to
- /// member pointer in derived class.
- CK_BaseToDerivedMemberPointer,
-
- /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
- /// member pointer in base class.
- CK_DerivedToBaseMemberPointer,
-
- /// CK_UserDefinedConversion - Conversion using a user defined type
- /// conversion function.
- CK_UserDefinedConversion,
-
- /// CK_ConstructorConversion - Conversion by constructor
- CK_ConstructorConversion,
-
- /// CK_IntegralToPointer - Integral to pointer
- CK_IntegralToPointer,
-
- /// CK_PointerToIntegral - Pointer to integral
- CK_PointerToIntegral,
-
- /// CK_ToVoid - Cast to void.
- CK_ToVoid,
-
- /// CK_VectorSplat - Casting from an integer/floating type to an extended
- /// vector type with the same element type as the src type. Splats the
- /// src expression into the destination expression.
- CK_VectorSplat,
-
- /// CK_IntegralCast - Casting between integral types of different size.
- CK_IntegralCast,
-
- /// CK_IntegralToFloating - Integral to floating point.
- CK_IntegralToFloating,
-
- /// CK_FloatingToIntegral - Floating point to integral.
- CK_FloatingToIntegral,
-
- /// CK_FloatingCast - Casting between floating types of different size.
- CK_FloatingCast,
-
- /// CK_MemberPointerToBoolean - Member pointer to boolean
- CK_MemberPointerToBoolean,
-
- /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
- /// pointer
- CK_AnyPointerToObjCPointerCast,
- /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
- /// pointer
- CK_AnyPointerToBlockPointerCast
-
- };
+ typedef clang::CastKind CastKind;
private:
- CastKind Kind;
+ unsigned Kind : 5;
+ unsigned BasePathSize : BitsRemaining - 5;
Stmt *Op;
- /// BasePath - For derived-to-base and base-to-derived casts, the base array
- /// contains the inheritance path.
- CXXBaseSpecifierArray BasePath;
-
void CheckBasePath() const {
#ifndef NDEBUG
switch (getCastKind()) {
@@ -1955,7 +1968,7 @@ private:
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerived:
case CK_BaseToDerivedMemberPointer:
- assert(!BasePath.empty() && "Cast kind should have a base path!");
+ assert(!path_empty() && "Cast kind should have a base path!");
break;
// These should not have an inheritance path.
@@ -1981,15 +1994,21 @@ private:
case CK_MemberPointerToBoolean:
case CK_AnyPointerToObjCPointerCast:
case CK_AnyPointerToBlockPointerCast:
- assert(BasePath.empty() && "Cast kind should not have a base path!");
+ case CK_ObjCObjectLValueCast:
+ assert(path_empty() && "Cast kind should not have a base path!");
break;
}
#endif
}
+ const CXXBaseSpecifier * const *path_buffer() const {
+ return const_cast<CastExpr*>(this)->path_buffer();
+ }
+ CXXBaseSpecifier **path_buffer();
+
protected:
CastExpr(StmtClass SC, QualType ty, const CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath) :
+ unsigned BasePathSize) :
Expr(SC, ty,
// Cast expressions are type-dependent if the type is
// dependent (C++ [temp.dep.expr]p3).
@@ -1997,18 +2016,16 @@ protected:
// Cast expressions are value-dependent if the type is
// dependent or if the subexpression is value-dependent.
ty->isDependentType() || (op && op->isValueDependent())),
- Kind(kind), Op(op), BasePath(BasePath) {
- CheckBasePath();
- }
+ Kind(kind), BasePathSize(BasePathSize), Op(op) {
+ CheckBasePath();
+ }
/// \brief Construct an empty cast.
- CastExpr(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty) { }
-
- virtual void DoDestroy(ASTContext &C);
+ CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize)
+ : Expr(SC, Empty), BasePathSize(BasePathSize) { }
public:
- CastKind getCastKind() const { return Kind; }
+ CastKind getCastKind() const { return static_cast<CastKind>(Kind); }
void setCastKind(CastKind K) { Kind = K; }
const char *getCastKindName() const;
@@ -2024,8 +2041,16 @@ public:
return const_cast<CastExpr *>(this)->getSubExprAsWritten();
}
- const CXXBaseSpecifierArray& getBasePath() const { return BasePath; }
- CXXBaseSpecifierArray& getBasePath() { return BasePath; }
+ typedef CXXBaseSpecifier **path_iterator;
+ typedef const CXXBaseSpecifier * const *path_const_iterator;
+ bool path_empty() const { return BasePathSize == 0; }
+ unsigned path_size() const { return BasePathSize; }
+ path_iterator path_begin() { return path_buffer(); }
+ path_iterator path_end() { return path_buffer() + path_size(); }
+ path_const_iterator path_begin() const { return path_buffer(); }
+ path_const_iterator path_end() const { return path_buffer() + path_size(); }
+
+ void setCastPath(const CXXCastPath &Path);
static bool classof(const Stmt *T) {
return T->getStmtClass() >= firstCastExprConstant &&
@@ -2045,38 +2070,57 @@ public:
///
/// In C, implicit casts always produce rvalues. However, in C++, an
/// implicit cast whose result is being bound to a reference will be
-/// an lvalue. For example:
+/// an lvalue or xvalue. For example:
///
/// @code
/// class Base { };
/// class Derived : public Base { };
+/// Derived &&ref();
/// void f(Derived d) {
-/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base
+/// Base& b = d; // initializer is an ImplicitCastExpr
+/// // to an lvalue of type Base
+/// Base&& r = ref(); // initializer is an ImplicitCastExpr
+/// // to an xvalue of type Base
/// }
/// @endcode
class ImplicitCastExpr : public CastExpr {
- /// LvalueCast - Whether this cast produces an lvalue.
- bool LvalueCast;
+private:
+ ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
+ unsigned BasePathLength, ExprValueKind VK)
+ : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePathLength) {
+ ValueKind = VK;
+ }
+
+ /// \brief Construct an empty implicit cast.
+ explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize)
+ : CastExpr(ImplicitCastExprClass, Shell, PathSize) { }
public:
- ImplicitCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, bool Lvalue)
- : CastExpr(ImplicitCastExprClass, ty, kind, op, BasePath),
- LvalueCast(Lvalue) { }
+ enum OnStack_t { OnStack };
+ ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op,
+ ExprValueKind VK)
+ : CastExpr(ImplicitCastExprClass, ty, kind, op, 0) {
+ ValueKind = VK;
+ }
- /// \brief Construct an empty implicit cast.
- explicit ImplicitCastExpr(EmptyShell Shell)
- : CastExpr(ImplicitCastExprClass, Shell) { }
+ static ImplicitCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind Cat);
+
+ static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
virtual SourceRange getSourceRange() const {
return getSubExpr()->getSourceRange();
}
- /// isLvalueCast - Whether this cast produces an lvalue.
- bool isLvalueCast() const { return LvalueCast; }
+ /// getValueKind - The value kind that this cast produces.
+ ExprValueKind getValueKind() const {
+ return static_cast<ExprValueKind>(ValueKind);
+ }
- /// setLvalueCast - Set whether this cast produces an lvalue.
- void setLvalueCast(bool Lvalue) { LvalueCast = Lvalue; }
+ /// setValueKind - Set the value kind this cast produces.
+ void setValueKind(ExprValueKind Cat) { ValueKind = Cat; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ImplicitCastExprClass;
@@ -2098,8 +2142,8 @@ public:
/// actual type of the expression as determined by semantic
/// analysis. These types may differ slightly. For example, in C++ one
/// can cast to a reference type, which indicates that the resulting
-/// expression will be an lvalue. The reference type, however, will
-/// not be used as the type of the expression.
+/// expression will be an lvalue or xvalue. The reference type, however,
+/// will not be used as the type of the expression.
class ExplicitCastExpr : public CastExpr {
/// TInfo - Source type info for the (written) type
/// this expression is casting to.
@@ -2107,13 +2151,12 @@ class ExplicitCastExpr : public CastExpr {
protected:
ExplicitCastExpr(StmtClass SC, QualType exprTy, CastKind kind,
- Expr *op, CXXBaseSpecifierArray BasePath,
- TypeSourceInfo *writtenTy)
- : CastExpr(SC, exprTy, kind, op, BasePath), TInfo(writtenTy) {}
+ Expr *op, unsigned PathSize, TypeSourceInfo *writtenTy)
+ : CastExpr(SC, exprTy, kind, op, PathSize), TInfo(writtenTy) {}
/// \brief Construct an empty explicit cast.
- ExplicitCastExpr(StmtClass SC, EmptyShell Shell)
- : CastExpr(SC, Shell) { }
+ ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : CastExpr(SC, Shell, PathSize) { }
public:
/// getTypeInfoAsWritten - Returns the type source info for the type
@@ -2138,16 +2181,24 @@ public:
class CStyleCastExpr : public ExplicitCastExpr {
SourceLocation LPLoc; // the location of the left paren
SourceLocation RPLoc; // the location of the right paren
-public:
+
CStyleCastExpr(QualType exprTy, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l, SourceLocation r)
- : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, BasePath,
+ : ExplicitCastExpr(CStyleCastExprClass, exprTy, kind, op, PathSize,
writtenTy), LPLoc(l), RPLoc(r) {}
/// \brief Construct an empty C-style explicit cast.
- explicit CStyleCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(CStyleCastExprClass, Shell) { }
+ explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { }
+
+public:
+ static CStyleCastExpr *Create(ASTContext &Context, QualType T, CastKind K,
+ Expr *Op, const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L,
+ SourceLocation R);
+
+ static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize);
SourceLocation getLParenLoc() const { return LPLoc; }
void setLParenLoc(SourceLocation L) { LPLoc = L; }
@@ -2184,33 +2235,14 @@ public:
/// be used to express the computation.
class BinaryOperator : public Expr {
public:
- enum Opcode {
- // Operators listed in order of precedence.
- // Note that additions to this should also update the StmtVisitor class.
- PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators.
- Mul, Div, Rem, // [C99 6.5.5] Multiplicative operators.
- Add, Sub, // [C99 6.5.6] Additive operators.
- Shl, Shr, // [C99 6.5.7] Bitwise shift operators.
- LT, GT, LE, GE, // [C99 6.5.8] Relational operators.
- EQ, NE, // [C99 6.5.9] Equality operators.
- And, // [C99 6.5.10] Bitwise AND operator.
- Xor, // [C99 6.5.11] Bitwise XOR operator.
- Or, // [C99 6.5.12] Bitwise OR operator.
- LAnd, // [C99 6.5.13] Logical AND operator.
- LOr, // [C99 6.5.14] Logical OR operator.
- Assign, MulAssign,// [C99 6.5.16] Assignment operators.
- DivAssign, RemAssign,
- AddAssign, SubAssign,
- ShlAssign, ShrAssign,
- AndAssign, XorAssign,
- OrAssign,
- Comma // [C99 6.5.17] Comma operator.
- };
+ typedef BinaryOperatorKind Opcode;
+
private:
+ unsigned Opc : 6;
+ SourceLocation OpLoc;
+
enum { LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR];
- Opcode Opc;
- SourceLocation OpLoc;
public:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
@@ -2227,12 +2259,12 @@ public:
/// \brief Construct an empty binary operator.
explicit BinaryOperator(EmptyShell Empty)
- : Expr(BinaryOperatorClass, Empty), Opc(Comma) { }
+ : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { }
SourceLocation getOperatorLoc() const { return OpLoc; }
void setOperatorLoc(SourceLocation L) { OpLoc = L; }
- Opcode getOpcode() const { return Opc; }
+ Opcode getOpcode() const { return static_cast<Opcode>(Opc); }
void setOpcode(Opcode O) { Opc = O; }
Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); }
@@ -2248,6 +2280,8 @@ public:
/// corresponds to, e.g. "<<=".
static const char *getOpcodeStr(Opcode Op);
+ const char *getOpcodeStr() const { return getOpcodeStr(getOpcode()); }
+
/// \brief Retrieve the binary opcode that corresponds to the given
/// overloaded operator.
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO);
@@ -2257,30 +2291,34 @@ public:
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc);
/// predicates to categorize the respective opcodes.
- bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; }
- static bool isAdditiveOp(Opcode Opc) { return Opc == Add || Opc == Sub; }
- bool isAdditiveOp() const { return isAdditiveOp(Opc); }
- static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; }
- bool isShiftOp() const { return isShiftOp(Opc); }
+ bool isMultiplicativeOp() const { return Opc >= BO_Mul && Opc <= BO_Rem; }
+ static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; }
+ bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); }
+ static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; }
+ bool isShiftOp() const { return isShiftOp(getOpcode()); }
- static bool isBitwiseOp(Opcode Opc) { return Opc >= And && Opc <= Or; }
- bool isBitwiseOp() const { return isBitwiseOp(Opc); }
+ static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; }
+ bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); }
- static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; }
- bool isRelationalOp() const { return isRelationalOp(Opc); }
+ static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; }
+ bool isRelationalOp() const { return isRelationalOp(getOpcode()); }
- static bool isEqualityOp(Opcode Opc) { return Opc == EQ || Opc == NE; }
- bool isEqualityOp() const { return isEqualityOp(Opc); }
+ static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; }
+ bool isEqualityOp() const { return isEqualityOp(getOpcode()); }
- static bool isComparisonOp(Opcode Opc) { return Opc >= LT && Opc <= NE; }
- bool isComparisonOp() const { return isComparisonOp(Opc); }
+ static bool isComparisonOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_NE; }
+ bool isComparisonOp() const { return isComparisonOp(getOpcode()); }
- static bool isLogicalOp(Opcode Opc) { return Opc == LAnd || Opc == LOr; }
- bool isLogicalOp() const { return isLogicalOp(Opc); }
+ static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; }
+ bool isLogicalOp() const { return isLogicalOp(getOpcode()); }
- bool isAssignmentOp() const { return Opc >= Assign && Opc <= OrAssign; }
- bool isCompoundAssignmentOp() const { return Opc > Assign && Opc <= OrAssign;}
- bool isShiftAssignOp() const { return Opc == ShlAssign || Opc == ShrAssign; }
+ bool isAssignmentOp() const { return Opc >= BO_Assign && Opc <= BO_OrAssign; }
+ bool isCompoundAssignmentOp() const {
+ return Opc > BO_Assign && Opc <= BO_OrAssign;
+ }
+ bool isShiftAssignOp() const {
+ return Opc == BO_ShlAssign || Opc == BO_ShrAssign;
+ }
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstBinaryOperatorConstant &&
@@ -2304,7 +2342,7 @@ protected:
}
BinaryOperator(StmtClass SC, EmptyShell Empty)
- : Expr(SC, Empty), Opc(MulAssign) { }
+ : Expr(SC, Empty), Opc(BO_MulAssign) { }
};
/// CompoundAssignOperator - For compound assignments (e.g. +=), we keep
@@ -2353,10 +2391,11 @@ public:
class ConditionalOperator : public Expr {
enum { COND, LHS, RHS, END_EXPR };
Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides.
+ Stmt* Save;
SourceLocation QuestionLoc, ColonLoc;
public:
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
- SourceLocation CLoc, Expr *rhs, QualType t)
+ SourceLocation CLoc, Expr *rhs, Expr *save, QualType t)
: Expr(ConditionalOperatorClass, t,
// FIXME: the type of the conditional operator doesn't
// depend on the type of the conditional, but the standard
@@ -2370,6 +2409,7 @@ public:
SubExprs[COND] = cond;
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
+ Save = save;
}
/// \brief Build an empty conditional operator.
@@ -2382,25 +2422,31 @@ public:
void setCond(Expr *E) { SubExprs[COND] = E; }
// getTrueExpr - Return the subexpression representing the value of the ?:
- // expression if the condition evaluates to true. In most cases this value
- // will be the same as getLHS() except a GCC extension allows the left
- // subexpression to be omitted, and instead of the condition be returned.
- // e.g: x ?: y is shorthand for x ? x : y, except that the expression "x"
- // is only evaluated once.
+ // expression if the condition evaluates to true.
Expr *getTrueExpr() const {
- return cast<Expr>(SubExprs[LHS] ? SubExprs[LHS] : SubExprs[COND]);
+ return cast<Expr>(!Save ? SubExprs[LHS] : SubExprs[COND]);
}
- // getTrueExpr - Return the subexpression representing the value of the ?:
+ // getFalseExpr - Return the subexpression representing the value of the ?:
// expression if the condition evaluates to false. This is the same as getRHS.
Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); }
-
- Expr *getLHS() const { return cast_or_null<Expr>(SubExprs[LHS]); }
+
+ // getSaveExpr - In most cases this value will be null. Except a GCC extension
+ // allows the left subexpression to be omitted, and instead of that condition
+ // be returned. e.g: x ?: y is shorthand for x ? x : y, except that the
+ // expression "x" is only evaluated once. Under this senario, this function
+ // returns the original, non-converted condition expression for the ?:operator
+ Expr *getSaveExpr() const { return Save? cast<Expr>(Save) : (Expr*)0; }
+
+ Expr *getLHS() const { return Save ? 0 : cast<Expr>(SubExprs[LHS]); }
void setLHS(Expr *E) { SubExprs[LHS] = E; }
Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); }
void setRHS(Expr *E) { SubExprs[RHS] = E; }
+ Expr *getSAVE() const { return Save? cast<Expr>(Save) : (Expr*)0; }
+ void setSAVE(Expr *E) { Save = E; }
+
SourceLocation getQuestionLoc() const { return QuestionLoc; }
void setQuestionLoc(SourceLocation L) { QuestionLoc = L; }
@@ -2500,23 +2546,27 @@ public:
/// expressions) are compatible. The result of this built-in function can be
/// used in integer constant expressions.
class TypesCompatibleExpr : public Expr {
- QualType Type1;
- QualType Type2;
+ TypeSourceInfo *TInfo1;
+ TypeSourceInfo *TInfo2;
SourceLocation BuiltinLoc, RParenLoc;
public:
TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
- QualType t1, QualType t2, SourceLocation RP) :
+ TypeSourceInfo *tinfo1, TypeSourceInfo *tinfo2,
+ SourceLocation RP) :
Expr(TypesCompatibleExprClass, ReturnType, false, false),
- Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {}
+ TInfo1(tinfo1), TInfo2(tinfo2), BuiltinLoc(BLoc), RParenLoc(RP) {}
/// \brief Build an empty __builtin_type_compatible_p expression.
explicit TypesCompatibleExpr(EmptyShell Empty)
: Expr(TypesCompatibleExprClass, Empty) { }
- QualType getArgType1() const { return Type1; }
- void setArgType1(QualType T) { Type1 = T; }
- QualType getArgType2() const { return Type2; }
- void setArgType2(QualType T) { Type2 = T; }
+ TypeSourceInfo *getArgTInfo1() const { return TInfo1; }
+ void setArgTInfo1(TypeSourceInfo *TInfo) { TInfo1 = TInfo; }
+ TypeSourceInfo *getArgTInfo2() const { return TInfo2; }
+ void setArgTInfo2(TypeSourceInfo *TInfo) { TInfo2 = TInfo; }
+
+ QualType getArgType1() const { return TInfo1->getType(); }
+ QualType getArgType2() const { return TInfo2->getType(); }
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -2553,9 +2603,6 @@ class ShuffleVectorExpr : public Expr {
Stmt **SubExprs;
unsigned NumExprs;
-protected:
- virtual void DoDestroy(ASTContext &C);
-
public:
// FIXME: Can a shufflevector be value-dependent? Does type-dependence need
// to be computed differently?
@@ -2588,8 +2635,6 @@ public:
}
static bool classof(const ShuffleVectorExpr *) { return true; }
- ~ShuffleVectorExpr() {}
-
/// getNumSubExprs - Return the size of the SubExprs array. This includes the
/// constant expression, the actual arguments passed in, and the function
/// pointers.
@@ -2716,11 +2761,13 @@ public:
/// VAArgExpr, used for the builtin function __builtin_va_arg.
class VAArgExpr : public Expr {
Stmt *Val;
+ TypeSourceInfo *TInfo;
SourceLocation BuiltinLoc, RParenLoc;
public:
- VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc)
+ VAArgExpr(SourceLocation BLoc, Expr* e, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc, QualType t)
: Expr(VAArgExprClass, t, t->isDependentType(), false),
- Val(e),
+ Val(e), TInfo(TInfo),
BuiltinLoc(BLoc),
RParenLoc(RPLoc) { }
@@ -2731,6 +2778,9 @@ public:
Expr *getSubExpr() { return cast<Expr>(Val); }
void setSubExpr(Expr *E) { Val = E; }
+ TypeSourceInfo *getWrittenTypeInfo() const { return TInfo; }
+ void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo = TI; }
+
SourceLocation getBuiltinLoc() const { return BuiltinLoc; }
void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; }
@@ -2896,12 +2946,18 @@ public:
virtual child_iterator child_end();
typedef InitExprsTy::iterator iterator;
+ typedef InitExprsTy::const_iterator const_iterator;
typedef InitExprsTy::reverse_iterator reverse_iterator;
+ typedef InitExprsTy::const_reverse_iterator const_reverse_iterator;
iterator begin() { return InitExprs.begin(); }
+ const_iterator begin() const { return InitExprs.begin(); }
iterator end() { return InitExprs.end(); }
+ const_iterator end() const { return InitExprs.end(); }
reverse_iterator rbegin() { return InitExprs.rbegin(); }
+ const_reverse_iterator rbegin() const { return InitExprs.rbegin(); }
reverse_iterator rend() { return InitExprs.rend(); }
+ const_reverse_iterator rend() const { return InitExprs.rend(); }
};
/// @brief Represents a C99 designated initializer expression.
@@ -2961,11 +3017,6 @@ private:
: Expr(DesignatedInitExprClass, EmptyShell()),
NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { }
-protected:
- virtual void DoDestroy(ASTContext &C);
-
- void DestroyDesignators(ASTContext &C);
-
public:
/// A field designator, e.g., ".x".
struct FieldDesignator {
@@ -3233,15 +3284,10 @@ class ParenListExpr : public Expr {
unsigned NumExprs;
SourceLocation LParenLoc, RParenLoc;
-protected:
- virtual void DoDestroy(ASTContext& C);
-
public:
ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs,
unsigned numexprs, SourceLocation rparenloc);
- ~ParenListExpr() {}
-
/// \brief Build an empty paren list.
explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { }
@@ -3274,8 +3320,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
- friend class PCHStmtWriter;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index b9553815d8eb..0a9435479d93 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -121,12 +121,12 @@ private:
protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {}
+ : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {}
- explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell)
- : ExplicitCastExpr(SC, Shell) { }
+ explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(SC, Shell, PathSize) { }
public:
const char *getCastName() const;
@@ -158,14 +158,22 @@ public:
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
-public:
CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {}
+ : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize,
+ writtenTy, l) {}
- explicit CXXStaticCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { }
+ explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
+ : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
+
+public:
+ static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L);
+ static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
@@ -180,15 +188,23 @@ public:
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
-public:
CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy,
+ unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath,
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
- explicit CXXDynamicCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { }
+ explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *Written, SourceLocation L);
+
+ static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
@@ -203,15 +219,22 @@ public:
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
-public:
CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
- CXXBaseSpecifierArray BasePath,
+ unsigned pathSize,
TypeSourceInfo *writtenTy, SourceLocation l)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath,
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
- explicit CXXReinterpretCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { }
+ CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
+ : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
+
+public:
+ static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned pathSize);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
@@ -225,14 +248,18 @@ public:
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
-public:
CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op,
- CXXBaseSpecifierArray(), writtenTy, l) {}
+ 0, writtenTy, l) {}
explicit CXXConstCastExpr(EmptyShell Empty)
- : CXXNamedCastExpr(CXXConstCastExprClass, Empty) { }
+ : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
+
+public:
+ static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op,
+ TypeSourceInfo *WrittenTy, SourceLocation L);
+ static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
@@ -479,9 +506,6 @@ class CXXDefaultArgExpr : public Expr {
*reinterpret_cast<Expr **>(this + 1) = SubExpr;
}
-protected:
- virtual void DoDestroy(ASTContext &C);
-
public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
@@ -535,8 +559,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
- friend class PCHStmtWriter;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// CXXTemporary - Represents a C++ temporary.
@@ -546,14 +570,11 @@ class CXXTemporary {
CXXTemporary(const CXXDestructorDecl *destructor)
: Destructor(destructor) { }
- ~CXXTemporary() { }
public:
static CXXTemporary *Create(ASTContext &C,
const CXXDestructorDecl *Destructor);
- void Destroy(ASTContext &Ctx);
-
const CXXDestructorDecl *getDestructor() const { return Destructor; }
};
@@ -579,10 +600,6 @@ class CXXBindTemporaryExpr : public Expr {
CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
: Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false),
Temp(temp), SubExpr(subexpr) { }
- ~CXXBindTemporaryExpr() { }
-
-protected:
- virtual void DoDestroy(ASTContext &C);
public:
CXXBindTemporaryExpr(EmptyShell Empty)
@@ -614,73 +631,6 @@ public:
virtual child_iterator child_end();
};
-/// CXXBindReferenceExpr - Represents binding an expression to a reference.
-/// In the example:
-///
-/// const int &i = 10;
-///
-/// a bind reference expression is inserted to indicate that 10 is bound to
-/// a reference, and that a temporary needs to be created to hold the
-/// value.
-class CXXBindReferenceExpr : public Expr {
- // SubExpr - The expression being bound.
- Stmt *SubExpr;
-
- // ExtendsLifetime - Whether binding this reference extends the lifetime of
- // the expression being bound. FIXME: Add C++ reference.
- bool ExtendsLifetime;
-
- /// RequiresTemporaryCopy - Whether binding the subexpression requires a
- /// temporary copy.
- bool RequiresTemporaryCopy;
-
- CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime,
- bool RequiresTemporaryCopy)
- : Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false),
- SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime),
- RequiresTemporaryCopy(RequiresTemporaryCopy) { }
- ~CXXBindReferenceExpr() { }
-
-protected:
- virtual void DoDestroy(ASTContext &C);
-
-public:
- static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr,
- bool ExtendsLifetime,
- bool RequiresTemporaryCopy);
-
- explicit CXXBindReferenceExpr(EmptyShell Empty)
- : Expr(CXXBindReferenceExprClass, Empty) { }
-
- const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
- Expr *getSubExpr() { return cast<Expr>(SubExpr); }
- void setSubExpr(Expr *E) { SubExpr = E; }
-
- virtual SourceRange getSourceRange() const {
- return SubExpr->getSourceRange();
- }
-
- /// requiresTemporaryCopy - Whether binding the subexpression requires a
- /// temporary copy.
- bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; }
-
- // extendsLifetime - Whether binding this reference extends the lifetime of
- // the expression being bound. FIXME: Add C++ reference.
- bool extendsLifetime() const { return ExtendsLifetime; }
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == CXXBindReferenceExprClass;
- }
- static bool classof(const CXXBindReferenceExpr *) { return true; }
-
- // Iterators
- virtual child_iterator child_begin();
- virtual child_iterator child_end();
-
- friend class PCHStmtReader;
-};
-
/// CXXConstructExpr - Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr {
public:
@@ -707,15 +657,12 @@ protected:
Expr **args, unsigned numargs,
bool ZeroInitialization = false,
ConstructionKind ConstructKind = CK_Complete);
- ~CXXConstructExpr() { }
/// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0),
ConstructKind(0), Args(0), NumArgs(0) { }
- virtual void DoDestroy(ASTContext &C);
-
public:
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
@@ -796,7 +743,7 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
};
/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
@@ -805,17 +752,27 @@ public:
class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
-public:
+
CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind,
- Expr *castExpr, CXXBaseSpecifierArray BasePath,
+ Expr *castExpr, unsigned pathSize,
SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
- BasePath, writtenTy),
+ pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
- explicit CXXFunctionalCastExpr(EmptyShell Shell)
- : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { }
+ explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
+ : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
+
+public:
+ static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
+ TypeSourceInfo *Written,
+ SourceLocation TyBeginLoc,
+ CastKind Kind, Expr *Op,
+ const CXXCastPath *Path,
+ SourceLocation RPLoc);
+ static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
+ unsigned PathSize);
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
@@ -859,8 +816,6 @@ public:
explicit CXXTemporaryObjectExpr(EmptyShell Empty)
: CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { }
- ~CXXTemporaryObjectExpr() { }
-
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -872,7 +827,7 @@ public:
}
static bool classof(const CXXTemporaryObjectExpr *) { return true; }
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
};
/// CXXScalarValueInitExpr - [C++ 5.2.3p2]
@@ -952,7 +907,7 @@ class CXXNewExpr : public Expr {
SourceLocation StartLoc;
SourceLocation EndLoc;
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
public:
CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs,
@@ -967,8 +922,6 @@ public:
void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs,
unsigned numConsArgs);
- virtual void DoDestroy(ASTContext &C);
-
QualType getAllocatedType() const {
assert(getType()->isPointerType());
return getType()->getAs<PointerType>()->getPointeeType();
@@ -1381,7 +1334,7 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
- friend class PCHStmtReader;
+ friend class ASTStmtReader;
};
/// \brief A reference to an overloaded function set, either an
@@ -1395,7 +1348,7 @@ class OverloadExpr : public Expr {
unsigned NumResults;
/// The common name of these declarations.
- DeclarationName Name;
+ DeclarationNameInfo NameInfo;
/// The scope specifier, if any.
NestedNameSpecifier *Qualifier;
@@ -1403,16 +1356,13 @@ class OverloadExpr : public Expr {
/// The source range of the scope specifier.
SourceRange QualifierRange;
- /// The location of the name.
- SourceLocation NameLoc;
-
protected:
/// True if the name was a template-id.
bool HasExplicitTemplateArgs;
OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent,
NestedNameSpecifier *Qualifier, SourceRange QRange,
- DeclarationName Name, SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool HasTemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@@ -1427,19 +1377,38 @@ public:
UnresolvedSetIterator End,
const TemplateArgumentListInfo *Args);
+ struct FindResult {
+ OverloadExpr *Expression;
+ bool IsAddressOfOperand;
+ bool HasFormOfMemberPointer;
+ };
+
/// Finds the overloaded expression in the given expression of
/// OverloadTy.
///
- /// \return the expression (which must be there) and true if it is
- /// within an address-of operator.
- static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) {
+ /// \return the expression (which must be there) and true if it has
+ /// the particular form of a member pointer expression
+ static FindResult find(Expr *E) {
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
- bool op = false;
+ FindResult Result;
+
E = E->IgnoreParens();
- if (isa<UnaryOperator>(E))
- op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
- return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op);
+ if (isa<UnaryOperator>(E)) {
+ assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
+ E = cast<UnaryOperator>(E)->getSubExpr();
+ OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens());
+
+ Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
+ Result.IsAddressOfOperand = true;
+ Result.Expression = Ovl;
+ } else {
+ Result.HasFormOfMemberPointer = false;
+ Result.IsAddressOfOperand = false;
+ Result.Expression = cast<OverloadExpr>(E);
+ }
+
+ return Result;
}
/// Gets the naming class of this lookup, if any.
@@ -1457,13 +1426,17 @@ public:
/// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; }
+ /// Gets the full name info.
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
+
/// Gets the name looked up.
- DeclarationName getName() const { return Name; }
- void setName(DeclarationName N) { Name = N; }
+ DeclarationName getName() const { return NameInfo.getName(); }
+ void setName(DeclarationName N) { NameInfo.setName(N); }
/// Gets the location of the name.
- SourceLocation getNameLoc() const { return NameLoc; }
- void setNameLoc(SourceLocation Loc) { NameLoc = Loc; }
+ SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
+ void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); }
/// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
@@ -1483,10 +1456,12 @@ public:
return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
}
- ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
- if (hasExplicitTemplateArgs())
- return &getExplicitTemplateArgs();
- return 0;
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
}
static bool classof(const Stmt *T) {
@@ -1526,11 +1501,11 @@ class UnresolvedLookupExpr : public OverloadExpr {
UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, SourceRange QRange,
- DeclarationName Name, SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool RequiresADL, bool Overloaded, bool HasTemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End)
: OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier,
- QRange, Name, NameLoc, HasTemplateArgs, Begin, End),
+ QRange, NameInfo, HasTemplateArgs, Begin, End),
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
{}
@@ -1545,16 +1520,15 @@ public:
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool ADL, bool Overloaded,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
return new(C) UnresolvedLookupExpr(C,
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, NamingClass,
- Qualifier, QualifierRange,
- Name, NameLoc, ADL, Overloaded, false,
+ Qualifier, QualifierRange, NameInfo,
+ ADL, Overloaded, false,
Begin, End);
}
@@ -1563,8 +1537,7 @@ public:
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool ADL,
const TemplateArgumentListInfo &Args,
UnresolvedSetIterator Begin,
@@ -1603,6 +1576,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
@@ -1626,7 +1607,7 @@ public:
}
virtual SourceRange getSourceRange() const {
- SourceRange Range(getNameLoc());
+ SourceRange Range(getNameInfo().getSourceRange());
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range;
@@ -1657,10 +1638,7 @@ public:
/// declaration can be found.
class DependentScopeDeclRefExpr : public Expr {
/// The name of the entity we will be referencing.
- DeclarationName Name;
-
- /// Location of the name of the declaration we're referencing.
- SourceLocation Loc;
+ DeclarationNameInfo NameInfo;
/// QualifierRange - The source range that covers the
/// nested-name-specifier.
@@ -1676,12 +1654,10 @@ class DependentScopeDeclRefExpr : public Expr {
DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool HasExplicitTemplateArgs)
: Expr(DependentScopeDeclRefExprClass, T, true, true),
- Name(Name), Loc(NameLoc),
- QualifierRange(QualifierRange), Qualifier(Qualifier),
+ NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
HasExplicitTemplateArgs(HasExplicitTemplateArgs)
{}
@@ -1689,20 +1665,23 @@ public:
static DependentScopeDeclRefExpr *Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs = 0);
static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
unsigned NumTemplateArgs);
/// \brief Retrieve the name that this expression refers to.
- DeclarationName getDeclName() const { return Name; }
- void setDeclName(DeclarationName N) { Name = N; }
+ const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
+ void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
+
+ /// \brief Retrieve the name that this expression refers to.
+ DeclarationName getDeclName() const { return NameInfo.getName(); }
+ void setDeclName(DeclarationName N) { NameInfo.setName(N); }
/// \brief Retrieve the location of the name within the expression.
- SourceLocation getLocation() const { return Loc; }
- void setLocation(SourceLocation L) { Loc = L; }
+ SourceLocation getLocation() const { return NameInfo.getLoc(); }
+ void setLocation(SourceLocation L) { NameInfo.setLoc(L); }
/// \brief Retrieve the source range of the nested-name-specifier.
SourceRange getQualifierRange() const { return QualifierRange; }
@@ -1731,6 +1710,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
@@ -1777,10 +1764,6 @@ class CXXExprWithTemporaries : public Expr {
CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps,
unsigned NumTemps);
- ~CXXExprWithTemporaries();
-
-protected:
- virtual void DoDestroy(ASTContext &C);
public:
CXXExprWithTemporaries(EmptyShell Empty)
@@ -1991,10 +1974,7 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
/// FIXME: could also be a template-id
- DeclarationName Member;
-
- /// \brief The location of the member name.
- SourceLocation MemberLoc;
+ DeclarationNameInfo MemberNameInfo;
CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, QualType BaseType, bool IsArrow,
@@ -2002,8 +1982,7 @@ class CXXDependentScopeMemberExpr : public Expr {
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
public:
@@ -2014,14 +1993,13 @@ public:
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc)
+ DeclarationNameInfo MemberNameInfo)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- Member(Member), MemberLoc(MemberLoc) { }
+ MemberNameInfo(MemberNameInfo) { }
static CXXDependentScopeMemberExpr *
Create(ASTContext &C,
@@ -2030,8 +2008,7 @@ public:
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
@@ -2092,13 +2069,20 @@ public:
/// \brief Retrieve the name of the member that this expression
/// refers to.
- DeclarationName getMember() const { return Member; }
- void setMember(DeclarationName N) { Member = N; }
+ const DeclarationNameInfo &getMemberNameInfo() const {
+ return MemberNameInfo;
+ }
+ void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; }
+
+ /// \brief Retrieve the name of the member that this expression
+ /// refers to.
+ DeclarationName getMember() const { return MemberNameInfo.getName(); }
+ void setMember(DeclarationName N) { MemberNameInfo.setName(N); }
// \brief Retrieve the location of the name of the member that this
// expression refers to.
- SourceLocation getMemberLoc() const { return MemberLoc; }
- void setMemberLoc(SourceLocation L) { MemberLoc = L; }
+ SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }
+ void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); }
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
@@ -2108,57 +2092,59 @@ public:
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
- ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() {
+ ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgs);
- return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
+ return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
- const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const {
+ const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
return const_cast<CXXDependentScopeMemberExpr *>(this)
- ->getExplicitTemplateArgumentList();
+ ->getExplicitTemplateArgs();
+ }
+
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
}
/// \brief Copies the template arguments (if present) into the given
/// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
- assert(HasExplicitTemplateArgs);
- getExplicitTemplateArgumentList()->copyInto(List);
+ getExplicitTemplateArgs().copyInto(List);
}
/// \brief Initializes the template arguments using the given structure.
void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) {
- assert(HasExplicitTemplateArgs);
- getExplicitTemplateArgumentList()->initializeFrom(List);
+ getExplicitTemplateArgs().initializeFrom(List);
}
/// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any.
SourceLocation getLAngleLoc() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->LAngleLoc;
+ return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->getTemplateArgs();
+ return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as part of this
/// template-id.
unsigned getNumTemplateArgs() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->NumTemplateArgs;
+ return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket following the
/// template arguments ('>').
SourceLocation getRAngleLoc() const {
- assert(HasExplicitTemplateArgs);
- return getExplicitTemplateArgumentList()->RAngleLoc;
+ return getExplicitTemplateArgs().RAngleLoc;
}
virtual SourceRange getSourceRange() const {
@@ -2168,12 +2154,12 @@ public:
else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin());
else
- Range.setBegin(MemberLoc);
+ Range.setBegin(MemberNameInfo.getBeginLoc());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
else
- Range.setEnd(MemberLoc);
+ Range.setEnd(MemberNameInfo.getEndLoc());
return Range;
}
@@ -2226,8 +2212,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@@ -2242,8 +2227,7 @@ public:
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@@ -2287,6 +2271,11 @@ public:
/// \brief Retrieves the naming class of this lookup.
CXXRecordDecl *getNamingClass() const;
+ /// \brief Retrieve the full name info for the member that this expression
+ /// refers to.
+ const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }
+ void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); }
+
/// \brief Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMemberName() const { return getName(); }
@@ -2311,6 +2300,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
}
+ /// \brief Retrieves the optional explicit template arguments.
+ /// This points to the same data as getExplicitTemplateArgs(), but
+ /// returns null if there are no explicit template arguments.
+ const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
+ if (!hasExplicitTemplateArgs()) return 0;
+ return &getExplicitTemplateArgs();
+ }
+
/// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs().copyInto(List);
@@ -2341,18 +2338,14 @@ public:
}
virtual SourceRange getSourceRange() const {
- SourceRange Range;
+ SourceRange Range = getMemberNameInfo().getSourceRange();
if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin());
else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin());
- else
- Range.setBegin(getMemberLoc());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
- else
- Range.setEnd(getMemberLoc());
return Range;
}
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index def9ced94c29..a8ef0053a442 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -14,31 +14,25 @@
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
-#include "clang/AST/DeclarationName.h"
-#include "clang/AST/Type.h"
-#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <vector>
+
+namespace llvm {
+template <class T> class SmallVectorImpl;
+}
+
namespace clang {
class ASTConsumer;
class Decl;
class DeclContext;
+class DeclContextLookupResult;
+class DeclarationName;
class ExternalSemaSource; // layering violation required for downcasting
+class NamedDecl;
+class Selector;
class Stmt;
-/// \brief The deserialized representation of a set of declarations
-/// with the same name that are visible in a given context.
-struct VisibleDeclaration {
- /// \brief The name of the declarations.
- DeclarationName Name;
-
- /// \brief The ID numbers of all of the declarations with this name.
- ///
- /// These declarations have not necessarily been de-serialized.
- llvm::SmallVector<unsigned, 4> Declarations;
-};
-
/// \brief Abstract interface for external sources of AST nodes.
///
/// External AST sources provide AST nodes constructed from some
@@ -58,6 +52,20 @@ public:
virtual ~ExternalASTSource();
+ /// \brief RAII class for safely pairing a StartedDeserializing call
+ /// with FinishedDeserializing.
+ class Deserializing {
+ ExternalASTSource *Source;
+ public:
+ explicit Deserializing(ExternalASTSource *source) : Source(source) {
+ assert(Source);
+ Source->StartedDeserializing();
+ }
+ ~Deserializing() {
+ Source->FinishedDeserializing();
+ }
+ };
+
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
///
@@ -89,10 +97,18 @@ public:
/// Generally the final step of this method is either to call
/// SetExternalVisibleDeclsForName or to recursively call lookup on
/// the DeclContext after calling SetExternalVisibleDecls.
- virtual DeclContext::lookup_result
+ virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) = 0;
+ /// \brief Deserialize all the visible declarations from external storage.
+ ///
+ /// Name lookup deserializes visible declarations lazily, thus a DeclContext
+ /// may not have a complete name lookup table. This function deserializes
+ /// the rest of visible declarations from the external storage and completes
+ /// the name lookup table of the DeclContext.
+ virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
+
/// \brief Finds all declarations lexically contained within the given
/// DeclContext.
///
@@ -100,6 +116,19 @@ public:
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Result) = 0;
+ /// \brief Notify ExternalASTSource that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void StartedDeserializing() { }
+
+ /// \brief Notify ExternalASTSource that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ ///
+ /// The default implementation of this method is a no-op.
+ virtual void FinishedDeserializing() { }
+
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
@@ -113,30 +142,18 @@ public:
virtual void PrintStats();
protected:
- /// \brief Initialize the context's lookup map with the given decls.
- /// It is assumed that none of the declarations are redeclarations of
- /// each other.
- static void SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<VisibleDeclaration> &Decls);
-
- /// \brief Initialize the context's lookup map with the given decls.
- /// It is assumed that none of the declarations are redeclarations of
- /// each other.
- static void SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<NamedDecl*> &Decls);
-
- static DeclContext::lookup_result
- SetExternalVisibleDeclsForName(const DeclContext *DC,
- const VisibleDeclaration &VD);
-
- static DeclContext::lookup_result
+ static DeclContextLookupResult
SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls);
- static DeclContext::lookup_result
+ static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name);
+
+ void MaterializeVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls);
};
/// \brief A lazy pointer to an AST node (of base type T) that resides
@@ -145,7 +162,7 @@ protected:
/// The AST node is identified within the external AST source by a
/// 63-bit offset, and can be retrieved via an operation on the
/// external AST source itself.
-template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)>
+template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
struct LazyOffsetPtr {
/// \brief Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found.
@@ -203,9 +220,13 @@ public:
};
/// \brief A lazy pointer to a statement.
-typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt>
+typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr;
+/// \brief A lazy pointer to a declaration.
+typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
+ LazyDeclPtr;
+
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
diff --git a/include/clang/AST/FullExpr.h b/include/clang/AST/FullExpr.h
index bb81bf0fe7c8..6ceefed8a63a 100644
--- a/include/clang/AST/FullExpr.h
+++ b/include/clang/AST/FullExpr.h
@@ -47,7 +47,6 @@ class FullExpr {
public:
static FullExpr Create(ASTContext &Context, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps);
- void Destroy(ASTContext &Context);
Expr *getExpr() {
if (Expr *E = SubExpr.dyn_cast<Expr *>())
diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile
index 00a1e1bf7977..6ba6e897d186 100644
--- a/include/clang/AST/Makefile
+++ b/include/clang/AST/Makefile
@@ -1,6 +1,6 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc
+BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc
TABLEGEN_INC_FILES_COMMON = 1
@@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
+$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute implementations with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen"
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index 1594b090fea5..3b25f3bb403f 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -181,8 +181,6 @@ public:
ID.AddPointer(Specifier);
}
- void Destroy(ASTContext &Context);
-
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
void dump(const LangOptions &LO);
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
new file mode 100644
index 000000000000..804531192971
--- /dev/null
+++ b/include/clang/AST/OperationKinds.h
@@ -0,0 +1,158 @@
+//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file enumerates the different kinds of operations that can be
+// performed by various expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
+#define LLVM_CLANG_AST_OPERATION_KINDS_H
+
+namespace clang {
+
+/// CastKind - the kind of cast this represents.
+enum CastKind {
+ /// CK_Unknown - Unknown cast kind.
+ /// FIXME: The goal is to get rid of this and make all casts have a
+ /// kind so that the AST client doesn't have to try to figure out what's
+ /// going on.
+ CK_Unknown,
+
+ /// CK_BitCast - Used for reinterpret_cast.
+ CK_BitCast,
+
+ /// CK_LValueBitCast - Used for reinterpret_cast of expressions to
+ /// a reference type.
+ CK_LValueBitCast,
+
+ /// 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,
+
+ /// CK_UncheckedDerivedToBase - Derived to base class casts that
+ /// assume that the derived pointer is not null.
+ CK_UncheckedDerivedToBase,
+
+ /// CK_Dynamic - Dynamic cast.
+ CK_Dynamic,
+
+ /// CK_ToUnion - Cast to union (GCC extension).
+ CK_ToUnion,
+
+ /// CK_ArrayToPointerDecay - Array to pointer decay.
+ CK_ArrayToPointerDecay,
+
+ // CK_FunctionToPointerDecay - Function to pointer decay.
+ CK_FunctionToPointerDecay,
+
+ /// CK_NullToMemberPointer - Null pointer to member pointer.
+ CK_NullToMemberPointer,
+
+ /// CK_BaseToDerivedMemberPointer - Member pointer in base class to
+ /// member pointer in derived class.
+ CK_BaseToDerivedMemberPointer,
+
+ /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
+ /// member pointer in base class.
+ CK_DerivedToBaseMemberPointer,
+
+ /// CK_UserDefinedConversion - Conversion using a user defined type
+ /// conversion function.
+ CK_UserDefinedConversion,
+
+ /// CK_ConstructorConversion - Conversion by constructor
+ CK_ConstructorConversion,
+
+ /// CK_IntegralToPointer - Integral to pointer
+ CK_IntegralToPointer,
+
+ /// CK_PointerToIntegral - Pointer to integral
+ CK_PointerToIntegral,
+
+ /// CK_ToVoid - Cast to void.
+ CK_ToVoid,
+
+ /// CK_VectorSplat - Casting from an integer/floating type to an extended
+ /// vector type with the same element type as the src type. Splats the
+ /// src expression into the destination expression.
+ CK_VectorSplat,
+
+ /// CK_IntegralCast - Casting between integral types of different size.
+ CK_IntegralCast,
+
+ /// CK_IntegralToFloating - Integral to floating point.
+ CK_IntegralToFloating,
+
+ /// CK_FloatingToIntegral - Floating point to integral.
+ CK_FloatingToIntegral,
+
+ /// CK_FloatingCast - Casting between floating types of different size.
+ CK_FloatingCast,
+
+ /// CK_MemberPointerToBoolean - Member pointer to boolean
+ CK_MemberPointerToBoolean,
+
+ /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
+ /// pointer
+ CK_AnyPointerToObjCPointerCast,
+
+ /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
+ /// pointer
+ CK_AnyPointerToBlockPointerCast,
+
+ /// \brief Converting between two Objective-C object types, which
+ /// can occur when performing reference binding to an Objective-C
+ /// object.
+ CK_ObjCObjectLValueCast
+};
+
+
+enum BinaryOperatorKind {
+ // Operators listed in order of precedence.
+ // Note that additions to this should also update the StmtVisitor class.
+ BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators.
+ BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators.
+ BO_Add, BO_Sub, // [C99 6.5.6] Additive operators.
+ BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators.
+ BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators.
+ BO_EQ, BO_NE, // [C99 6.5.9] Equality operators.
+ BO_And, // [C99 6.5.10] Bitwise AND operator.
+ BO_Xor, // [C99 6.5.11] Bitwise XOR operator.
+ BO_Or, // [C99 6.5.12] Bitwise OR operator.
+ BO_LAnd, // [C99 6.5.13] Logical AND operator.
+ BO_LOr, // [C99 6.5.14] Logical OR operator.
+ BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators.
+ BO_DivAssign, BO_RemAssign,
+ BO_AddAssign, BO_SubAssign,
+ BO_ShlAssign, BO_ShrAssign,
+ BO_AndAssign, BO_XorAssign,
+ BO_OrAssign,
+ BO_Comma // [C99 6.5.17] Comma operator.
+};
+
+enum UnaryOperatorKind {
+ // Note that additions to this should also update the StmtVisitor class.
+ UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement
+ UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement
+ UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection
+ UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
+ UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
+ UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
+ UO_Extension // __extension__ marker.
+};
+
+}
+
+#endif
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 0853dddbe9e5..232e47b03ae5 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -42,7 +42,7 @@
OPERATOR(Plus) OPERATOR(Minus) \
OPERATOR(Not) OPERATOR(LNot) \
OPERATOR(Real) OPERATOR(Imag) \
- OPERATOR(Extension) OPERATOR(OffsetOf)
+ OPERATOR(Extension)
// All binary operators (excluding compound assign operators).
#define BINOP_LIST() \
@@ -123,12 +123,27 @@ namespace clang {
/// users may override Traverse* and WalkUpFrom* to implement custom
/// traversal strategies. Returning false from one of these overridden
/// functions will abort the entire traversal.
+///
+/// By default, this visitor tries to visit every part of the explicit
+/// source code exactly once. The default policy towards templates
+/// is to descend into the 'pattern' class or function body, not any
+/// explicit or implicit instantiations. Explicit specializations
+/// are still visited, and the patterns of partial specializations
+/// are visited separately. This behavior can be changed by
+/// overriding shouldVisitTemplateInstantiations() in the derived class
+/// to return true, in which case all known implicit and explicit
+/// instantiations will be visited at the same time as the pattern
+/// from which they were produced.
template<typename Derived>
class RecursiveASTVisitor {
public:
/// \brief Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived*>(this); }
+ /// \brief Return whether this visitor should recurse into
+ /// template instantiations.
+ bool shouldVisitTemplateInstantiations() const { return false; }
+
/// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type.
///
@@ -351,8 +366,11 @@ public:
private:
// These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
- bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
+ bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count);
+ bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D);
bool TraverseCXXRecordHelper(CXXRecordDecl *D);
bool TraverseDeclaratorHelper(DeclaratorDecl *D);
@@ -375,14 +393,14 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
- case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
+ case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
#undef BINOP_LIST
#define OPERATOR(NAME) \
- case BinaryOperator::NAME##Assign: \
+ case BO_##NAME##Assign: \
DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST()
@@ -392,7 +410,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
- case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
+ case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST()
#undef OPERATOR
@@ -540,8 +558,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
return true;
case TemplateArgument::Type: {
- TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo();
- return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ // FIXME: how can TSI ever be NULL?
+ if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
+ return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ else
+ return true;
}
case TemplateArgument::Template:
@@ -796,23 +817,31 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
+ // This isn't available for ArrayType, but is for the ArrayTypeLoc.
+ TRY_TO(TraverseStmt(TL.getSizeExpr()));
+ return true;
+}
+
DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(VariableArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
- if (TL.getTypePtr()->getSizeExpr())
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ return TraverseArrayTypeLocHelper(TL);
})
// FIXME: order? why not size expr first?
@@ -1083,19 +1112,124 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
return true;
}
+// A helper method for traversing the implicit instantiations of a
+// class.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
+ ClassTemplateDecl* D, Decl *Pattern) {
+ assert(isa<ClassTemplateDecl>(Pattern) ||
+ isa<ClassTemplatePartialSpecializationDecl>(Pattern));
+
+ ClassTemplateDecl::spec_iterator end = D->spec_end();
+ for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ ClassTemplateSpecializationDecl* SD = *it;
+
+ switch (SD->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_ImplicitInstantiation: {
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> U
+ = SD->getInstantiatedFrom();
+
+ bool ShouldVisit;
+ if (U.is<ClassTemplateDecl*>())
+ ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern);
+ else
+ ShouldVisit
+ = (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern);
+
+ if (ShouldVisit)
+ TRY_TO(TraverseClassTemplateSpecializationDecl(SD));
+ break;
+ }
+
+ // We don't need to do anything on an explicit instantiation
+ // or explicit specialization because there will be an explicit
+ // node for it elsewhere.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+
+ // We don't need to do anything for an uninstantiated
+ // specialization.
+ case TSK_Undeclared:
+ break;
+ }
+ }
+
+ return true;
+}
+
DEF_TRAVERSE_DECL(ClassTemplateDecl, {
- TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ CXXRecordDecl* TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
- // We should not traverse the specializations/partial
- // specializations. Those will show up in other contexts.
- // getInstantiatedFromMemberTemplate() is just a link from a
- // template instantiation back to the template from which it was
- // instantiated, and thus should not be traversed either.
+
+ // By default, we do not traverse the instantiations of
+ // class templates since they do not apprear in the user code. The
+ // following code optionally traverses them.
+ if (getDerived().shouldVisitTemplateInstantiations()) {
+ // If this is the definition of the primary template, visit
+ // instantiations which were formed from this pattern.
+ if (D->isThisDeclarationADefinition())
+ TRY_TO(TraverseClassInstantiations(D, D));
+ }
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
})
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+ FunctionTemplateDecl* D) {
+ FunctionTemplateDecl::spec_iterator end = D->spec_end();
+ for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ FunctionDecl* FD = *it;
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_ImplicitInstantiation:
+ // We don't know what kind of FunctionDecl this is.
+ TRY_TO(TraverseDecl(FD));
+ break;
+
+ // No need to visit explicit instantiations, we'll find the node
+ // eventually.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_Undeclared: // Declaration of the template definition.
+ case TSK_ExplicitSpecialization:
+ break;
+ default:
+ assert(false && "Unknown specialization kind.");
+ }
+ }
+
+ return true;
+}
+
DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // function templates since they do not apprear in the user code. The
+ // following code optionally traverses them.
+ if (getDerived().shouldVisitTemplateInstantiations()) {
+ // Explicit function specializations will be traversed from the
+ // context of their declaration. There is therefore no need to
+ // traverse them for here.
+ //
+ // In addition, we only traverse the function instantiations when
+ // the function template is a function template definition.
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseFunctionInstantiations(D));
+ }
+ }
})
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
@@ -1110,10 +1244,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
- if (D->hasDefaultArgument())
- TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+ if (D->hasDefaultArgument())
+ TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
})
DEF_TRAVERSE_DECL(TypedefDecl, {
@@ -1166,7 +1300,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
E = D->bases_end();
I != E; ++I) {
- TRY_TO(TraverseType(I->getType()));
+ TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc()));
}
// We don't traverse the friends or the conversions, as they are
// already in decls_begin()/decls_end().
@@ -1191,10 +1325,16 @@ DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
// ("template set<int>;"), we do need a callback, since this
// is the only callback that's made for this instantiation.
// We use getTypeAsWritten() to distinguish.
- // FIXME: see how we want to handle template specializations.
if (TypeSourceInfo *TSI = D->getTypeAsWritten())
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
- return true;
+
+ if (!getDerived().shouldVisitTemplateInstantiations() &&
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ // Returning from here skips traversing the
+ // declaration context of the ClassTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro)
+ // which contains the instantiated members of the class.
+ return true;
})
template <typename Derived>
@@ -1222,6 +1362,12 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
// though that's our parent class -- we already visit all the
// template args here.
TRY_TO(TraverseCXXRecordHelper(D));
+
+ // If we're visiting instantiations, visit the instantiations of
+ // this template now.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D->isThisDeclarationADefinition())
+ TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D));
})
DEF_TRAVERSE_DECL(EnumConstantDecl, {
@@ -1304,7 +1450,45 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
}
TRY_TO(TraverseType(D->getResultType()));
- TRY_TO(TraverseDeclContextHelper(D)); // Parameters.
+
+ // If we're an explicit template specialization, iterate over the
+ // template args that were explicitly specified.
+ if (const FunctionTemplateSpecializationInfo *FTSI =
+ D->getTemplateSpecializationInfo()) {
+ if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
+ FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+ // A specialization might not have explicit template arguments if it has
+ // a templated return type and concrete arguments.
+ if (const TemplateArgumentListInfo *TALI =
+ FTSI->TemplateArgumentsAsWritten) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(),
+ TALI->size()));
+ }
+ }
+ }
+
+ for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+
+ if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
+ if (D->isThisDeclarationADefinition()) {
+ // This would be visited if we called TraverseType(D->getType())
+ // above, but we don't (at least, not in the
+ // declaration-is-a-definition case), in order to avoid duplicate
+ // visiting for parameters. (We need to check parameters here,
+ // rather than letting D->getType() do it, so we visit default
+ // parameter values). So we need to re-do some of the work the
+ // type would do.
+ for (FunctionProtoType::exception_iterator
+ E = FuncProto->exception_begin(),
+ EEnd = FuncProto->exception_end();
+ E != EEnd; ++E) {
+ TRY_TO(TraverseType(*E));
+ }
+ }
+ }
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers.
@@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, {
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
TRY_TO(TraverseDeclaratorHelper(D));
- // FIXME: This often double-counts -- for instance, for all local
- // vars, though not for global vars -- because the initializer is
- // also captured when the var-decl is in a DeclStmt.
TRY_TO(TraverseStmt(D->getInit()));
return true;
}
@@ -1373,11 +1554,13 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ...
- TRY_TO(TraverseStmt(D->getDefaultArgument()));
TRY_TO(TraverseVarHelper(D));
+ TRY_TO(TraverseStmt(D->getDefaultArgument()));
})
DEF_TRAVERSE_DECL(ParmVarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+
if (D->hasDefaultArg() &&
D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg())
@@ -1387,8 +1570,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
!D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg())
TRY_TO(TraverseStmt(D->getDefaultArg()));
-
- TRY_TO(TraverseVarHelper(D));
})
#undef DEF_TRAVERSE_DECL
@@ -1431,35 +1612,36 @@ DEF_TRAVERSE_STMT(AsmStmt, {
})
DEF_TRAVERSE_STMT(CXXCatchStmt, {
- // We don't traverse S->getCaughtType(), as we are already
- // traversing the exception object, which has this type.
+ TRY_TO(TraverseDecl(S->getExceptionDecl()));
// child_begin()/end() iterates over the handler block.
})
-DEF_TRAVERSE_STMT(ForStmt, {
- TRY_TO(TraverseDecl(S->getConditionVariable()));
- // child_begin()/end() iterates over init, cond, inc, and body stmts.
- })
-
-DEF_TRAVERSE_STMT(IfStmt, {
- TRY_TO(TraverseDecl(S->getConditionVariable()));
- // child_begin()/end() iterates over cond, then, and else stmts.
+DEF_TRAVERSE_STMT(DeclStmt, {
+ for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ // Suppress the default iteration over child_begin/end by
+ // returning. Here's why: A DeclStmt looks like 'type var [=
+ // initializer]'. The decls above already traverse over the
+ // initializers, so we don't have to do it again (which
+ // child_begin/end would do).
+ return true;
})
-DEF_TRAVERSE_STMT(WhileStmt, {
- TRY_TO(TraverseDecl(S->getConditionVariable()));
- // child_begin()/end() iterates over cond, then, and else stmts.
- })
// These non-expr stmts (most of them), do not need any action except
// iterating over the children.
DEF_TRAVERSE_STMT(BreakStmt, { })
+DEF_TRAVERSE_STMT(CXXTryStmt, { })
+DEF_TRAVERSE_STMT(CaseStmt, { })
DEF_TRAVERSE_STMT(CompoundStmt, { })
DEF_TRAVERSE_STMT(ContinueStmt, { })
-DEF_TRAVERSE_STMT(CXXTryStmt, { })
-DEF_TRAVERSE_STMT(DeclStmt, { })
+DEF_TRAVERSE_STMT(DefaultStmt, { })
DEF_TRAVERSE_STMT(DoStmt, { })
+DEF_TRAVERSE_STMT(ForStmt, { })
DEF_TRAVERSE_STMT(GotoStmt, { })
+DEF_TRAVERSE_STMT(IfStmt, { })
DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
DEF_TRAVERSE_STMT(LabelStmt, { })
DEF_TRAVERSE_STMT(NullStmt, { })
@@ -1470,10 +1652,10 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ReturnStmt, { })
-DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(SwitchCase, { })
-DEF_TRAVERSE_STMT(CaseStmt, { })
-DEF_TRAVERSE_STMT(DefaultStmt, { })
+DEF_TRAVERSE_STMT(SwitchStmt, { })
+DEF_TRAVERSE_STMT(WhileStmt, { })
+
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
if (S->hasExplicitTemplateArgs()) {
@@ -1565,6 +1747,37 @@ DEF_TRAVERSE_STMT(CXXNewExpr, {
TRY_TO(TraverseType(S->getAllocatedType()));
})
+DEF_TRAVERSE_STMT(OffsetOfExpr, {
+ // The child-iterator will pick up the expression representing
+ // the field.
+ // FIMXE: for code like offsetof(Foo, a.b.c), should we get
+ // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isArgumentType())
+ TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXTypeidExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(TypesCompatibleExpr, {
+ TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
+ TRY_TO(TraverseType(S->getQueriedType()));
+ })
+
// These exprs (most of them), do not need any action except iterating
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@@ -1573,7 +1786,6 @@ DEF_TRAVERSE_STMT(BlockDeclRefExpr, { })
DEF_TRAVERSE_STMT(BlockExpr, { })
DEF_TRAVERSE_STMT(ChooseExpr, { })
DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
-DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { })
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
@@ -1583,7 +1795,6 @@ DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { })
-DEF_TRAVERSE_STMT(CXXTypeidExpr, { })
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
@@ -1598,18 +1809,17 @@ DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
DEF_TRAVERSE_STMT(ObjCSuperExpr, { })
-DEF_TRAVERSE_STMT(OffsetOfExpr, { })
DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
-DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
-DEF_TRAVERSE_STMT(TypesCompatibleExpr, { })
-DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { })
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { })
-DEF_TRAVERSE_STMT(VAArgExpr, { })
+DEF_TRAVERSE_STMT(VAArgExpr, {
+ // The child-iterator will pick up the expression argument.
+ TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
+ })
DEF_TRAVERSE_STMT(CXXConstructExpr, { })
DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h
index 55e1f8477992..ba778293ba2d 100644
--- a/include/clang/AST/Redeclarable.h
+++ b/include/clang/AST/Redeclarable.h
@@ -177,6 +177,9 @@ public:
static_cast<const decl_type*>(this)));
}
redecl_iterator redecls_end() const { return redecl_iterator(); }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
};
}
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index a0c95b1fce8c..62a6b6463df5 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -151,22 +151,11 @@ public:
struct EmptyShell { };
protected:
- /// DestroyChildren - Invoked by destructors of subclasses of Stmt to
- /// recursively release child AST nodes.
- void DestroyChildren(ASTContext& Ctx);
-
/// \brief Construct an empty statement.
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
}
- /// \brief Virtual method that performs the actual destruction of
- /// this statement.
- ///
- /// Subclasses should override this method (not Destroy()) to
- /// provide class-specific destruction.
- virtual void DoDestroy(ASTContext &Ctx);
-
public:
Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
@@ -181,13 +170,6 @@ public:
}
#endif
- /// \brief Destroy the current statement and its children.
- void Destroy(ASTContext &Ctx) {
- assert(RefCount >= 1);
- if (--RefCount == 0)
- DoDestroy(Ctx);
- }
-
/// \brief Increases the reference count for this statement.
///
/// Invoke the Retain() operation when this statement or expression
@@ -221,6 +203,7 @@ public:
/// This is useful in a debugger.
void dump() const;
void dump(SourceManager &SM) const;
+ void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void dumpAll() const;
@@ -295,9 +278,6 @@ class DeclStmt : public Stmt {
DeclGroupRef DG;
SourceLocation StartLoc, EndLoc;
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
-
public:
DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
@@ -671,9 +651,6 @@ public:
// over the initialization expression referenced by the condition variable.
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
};
/// SwitchStmt - This represents a 'switch' stmt.
@@ -685,9 +662,6 @@ class SwitchStmt : public Stmt {
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
-
public:
SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
@@ -794,9 +768,6 @@ public:
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
};
/// DoStmt - This represents a 'do/while' stmt.
@@ -910,9 +881,6 @@ public:
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
};
/// GotoStmt - This represents a direct goto.
@@ -1113,9 +1081,6 @@ class AsmStmt : public Stmt {
StringLiteral **Constraints;
Stmt **Exprs;
StringLiteral **Clobbers;
-
-protected:
- virtual void DoDestroy(ASTContext &Ctx);
public:
AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile,
diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h
index 4e87c2701c26..0508f35e48e8 100644
--- a/include/clang/AST/StmtCXX.h
+++ b/include/clang/AST/StmtCXX.h
@@ -29,14 +29,14 @@ class CXXCatchStmt : public Stmt {
/// The handler block.
Stmt *HandlerBlock;
-protected:
- virtual void DoDestroy(ASTContext& Ctx);
-
public:
CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
: Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
HandlerBlock(handlerBlock) {}
+ CXXCatchStmt(EmptyShell Empty)
+ : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
+
virtual SourceRange getSourceRange() const {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
}
@@ -53,6 +53,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
+
+ friend class ASTStmtReader;
};
/// CXXTryStmt - A C++ try block, including all handlers.
@@ -64,38 +66,46 @@ class CXXTryStmt : public Stmt {
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers,
unsigned numHandlers);
+ CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
+ : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
+
+ Stmt const * const *getStmts() const {
+ return reinterpret_cast<Stmt const * const*>(this + 1);
+ }
+ Stmt **getStmts() {
+ return reinterpret_cast<Stmt **>(this + 1);
+ }
+
public:
static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, Stmt **handlers,
unsigned numHandlers);
+ static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers);
+
virtual SourceRange getSourceRange() const {
return SourceRange(getTryLoc(), getEndLoc());
}
SourceLocation getTryLoc() const { return TryLoc; }
SourceLocation getEndLoc() const {
- Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
- return Stmts[NumHandlers]->getLocEnd();
+ return getStmts()[NumHandlers]->getLocEnd();
}
CompoundStmt *getTryBlock() {
- Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
- return llvm::cast<CompoundStmt>(Stmts[0]);
+ return llvm::cast<CompoundStmt>(getStmts()[0]);
}
const CompoundStmt *getTryBlock() const {
- Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
- return llvm::cast<CompoundStmt>(Stmts[0]);
+ return llvm::cast<CompoundStmt>(getStmts()[0]);
}
unsigned getNumHandlers() const { return NumHandlers; }
CXXCatchStmt *getHandler(unsigned i) {
- Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
- return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+ return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
}
const CXXCatchStmt *getHandler(unsigned i) const {
- Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
- return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+ return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
}
static bool classof(const Stmt *T) {
@@ -105,6 +115,8 @@ public:
virtual child_iterator child_begin();
virtual child_iterator child_end();
+
+ friend class ASTStmtReader;
};
diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h
index 8078451fa31f..b8c141d7ef8e 100644
--- a/include/clang/AST/StmtVisitor.h
+++ b/include/clang/AST/StmtVisitor.h
@@ -37,68 +37,57 @@ public:
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
default: assert(0 && "Unknown binary operator!");
- case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
- case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
- case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator);
- case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator);
- case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator);
- case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator);
- case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator);
- case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator);
- case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator);
-
- case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator);
- case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator);
- case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator);
- case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator);
- case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator);
- case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator);
-
- case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator);
- case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator);
- case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator);
- case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator);
- case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator);
- case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator);
- case BinaryOperator::MulAssign:
- DISPATCH(BinMulAssign, CompoundAssignOperator);
- case BinaryOperator::DivAssign:
- DISPATCH(BinDivAssign, CompoundAssignOperator);
- case BinaryOperator::RemAssign:
- DISPATCH(BinRemAssign, CompoundAssignOperator);
- case BinaryOperator::AddAssign:
- DISPATCH(BinAddAssign, CompoundAssignOperator);
- case BinaryOperator::SubAssign:
- DISPATCH(BinSubAssign, CompoundAssignOperator);
- case BinaryOperator::ShlAssign:
- DISPATCH(BinShlAssign, CompoundAssignOperator);
- case BinaryOperator::ShrAssign:
- DISPATCH(BinShrAssign, CompoundAssignOperator);
- case BinaryOperator::AndAssign:
- DISPATCH(BinAndAssign, CompoundAssignOperator);
- case BinaryOperator::OrAssign:
- DISPATCH(BinOrAssign, CompoundAssignOperator);
- case BinaryOperator::XorAssign:
- DISPATCH(BinXorAssign, CompoundAssignOperator);
- case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator);
+ case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
+ case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
+ case BO_Mul: DISPATCH(BinMul, BinaryOperator);
+ case BO_Div: DISPATCH(BinDiv, BinaryOperator);
+ case BO_Rem: DISPATCH(BinRem, BinaryOperator);
+ case BO_Add: DISPATCH(BinAdd, BinaryOperator);
+ case BO_Sub: DISPATCH(BinSub, BinaryOperator);
+ case BO_Shl: DISPATCH(BinShl, BinaryOperator);
+ case BO_Shr: DISPATCH(BinShr, BinaryOperator);
+
+ case BO_LT: DISPATCH(BinLT, BinaryOperator);
+ case BO_GT: DISPATCH(BinGT, BinaryOperator);
+ case BO_LE: DISPATCH(BinLE, BinaryOperator);
+ case BO_GE: DISPATCH(BinGE, BinaryOperator);
+ case BO_EQ: DISPATCH(BinEQ, BinaryOperator);
+ case BO_NE: DISPATCH(BinNE, BinaryOperator);
+
+ case BO_And: DISPATCH(BinAnd, BinaryOperator);
+ case BO_Xor: DISPATCH(BinXor, BinaryOperator);
+ case BO_Or : DISPATCH(BinOr, BinaryOperator);
+ case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator);
+ case BO_LOr : DISPATCH(BinLOr, BinaryOperator);
+ case BO_Assign: DISPATCH(BinAssign, BinaryOperator);
+ case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator);
+ case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator);
+ case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator);
+ case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator);
+ case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator);
+ case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator);
+ case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator);
+ case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator);
+ case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator);
+ case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator);
+ case BO_Comma: DISPATCH(BinComma, BinaryOperator);
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
default: assert(0 && "Unknown unary operator!");
- case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
- case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
- case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
- case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
- case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
- case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator);
- case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator);
- case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator);
- case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator);
- case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator);
- case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator);
- case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator);
- case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator);
- case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator);
+ case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
+ case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
+ case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
+ case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
+ case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
+ case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator);
+ case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator);
+ case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator);
+ case UO_Not: DISPATCH(UnaryNot, UnaryOperator);
+ case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator);
+ case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
+ case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
+ case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
}
}
@@ -163,7 +152,7 @@ public:
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
- UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
+ UNARYOP_FALLBACK(Extension)
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 4c148e8fa221..92e62a58d42c 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -289,7 +289,18 @@ public:
L += R;
return L;
}
+
+ Qualifiers &operator-=(Qualifiers R) {
+ Mask = Mask & ~(R.Mask);
+ return *this;
+ }
+ /// \brief Compute the difference between two qualifier sets.
+ friend Qualifiers operator-(Qualifiers L, Qualifiers R) {
+ L -= R;
+ return L;
+ }
+
std::string getAsString() const;
std::string getAsString(const PrintingPolicy &Policy) const {
std::string Buffer;
@@ -399,7 +410,8 @@ enum CallingConv {
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
- CC_X86ThisCall // __attribute__((thiscall))
+ CC_X86ThisCall, // __attribute__((thiscall))
+ CC_X86Pascal // __attribute__((pascal))
};
@@ -787,12 +799,12 @@ private:
/// \brief Linkage of this type.
mutable unsigned CachedLinkage : 2;
- /// \brief FromPCH - Whether this type comes from a PCH file.
- mutable bool FromPCH : 1;
+ /// \brief FromAST - Whether this type comes from an AST file.
+ mutable bool FromAST : 1;
- /// \brief Set whether this type comes from a PCH file.
- void setFromPCH(bool V = true) const {
- FromPCH = V;
+ /// \brief Set whether this type comes from an AST file.
+ void setFromAST(bool V = true) const {
+ FromAST = V;
}
protected:
@@ -806,16 +818,15 @@ protected:
Type(TypeClass tc, QualType Canonical, bool dependent)
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
TC(tc), Dependent(dependent), LinkageKnown(false),
- CachedLinkage(NoLinkage), FromPCH(false) {}
- virtual ~Type() {}
- virtual void Destroy(ASTContext& C);
+ CachedLinkage(NoLinkage), FromAST(false) {}
+ virtual ~Type();
friend class ASTContext;
public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
- /// \brief Whether this type comes from a PCH file.
- bool isFromPCH() const { return FromPCH; }
+ /// \brief Whether this type comes from an AST file.
+ bool isFromAST() const { return FromAST; }
bool isCanonicalUnqualified() const {
return CanonicalType.getTypePtr() == this;
@@ -824,14 +835,6 @@ public:
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types.
- /// \brief Determines whether the type describes an object in memory.
- ///
- /// Note that this definition of object type corresponds to the C++
- /// definition of object type, which includes incomplete types, as
- /// opposed to the C definition (which does not include incomplete
- /// types).
- bool isObjectType() const;
-
/// isIncompleteType - Return true if this is an incomplete type.
/// A type that can describe objects, but which lacks information needed to
/// determine its size (e.g. void, or a fwd declared struct). Clients of this
@@ -906,6 +909,7 @@ public:
bool isFunctionPointerType() const;
bool isMemberPointerType() const;
bool isMemberFunctionPointerType() const;
+ bool isMemberDataPointerType() const;
bool isArrayType() const;
bool isConstantArrayType() const;
bool isIncompleteArrayType() const;
@@ -926,6 +930,7 @@ public:
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
bool isObjCQualifiedClassType() const; // Class<foo>
+ bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class
bool isObjCSelType() const; // Class
@@ -952,10 +957,22 @@ public:
/// an objective pointer type for the purpose of GC'ability
bool hasObjCPointerRepresentation() const;
+ /// \brief Determine whether this type has an integer representation
+ /// of some sort, e.g., it is an integer type or a vector.
+ bool hasIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an signed integer representation
+ /// of some sort, e.g., it is an signed integer type or a vector.
+ bool hasSignedIntegerRepresentation() const;
+
+ /// \brief Determine whether this type has an unsigned integer representation
+ /// of some sort, e.g., it is an unsigned integer type or a vector.
+ bool hasUnsignedIntegerRepresentation() const;
+
/// \brief Determine whether this type has a floating-point representation
/// of some sort, e.g., it is a floating-point type or a vector thereof.
bool hasFloatingRepresentation() const;
-
+
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs and qualifiers, and return a pointer to
// the best type we can.
@@ -975,7 +992,8 @@ public:
/// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const;
- // Member-template getAs<specific type>'. This scheme will eventually
+ // Member-template getAs<specific type>'. Look through sugar for
+ // an instance of <specific type>. This scheme will eventually
// replace the specific getAsXXXX methods above.
//
// There are some specializations of this member template listed
@@ -1035,8 +1053,8 @@ public:
void dump() const;
static bool classof(const Type *) { return true; }
- friend class PCHReader;
- friend class PCHWriter;
+ friend class ASTReader;
+ friend class ASTWriter;
};
template <> inline const TypedefType *Type::getAs() const {
@@ -1353,9 +1371,20 @@ protected:
virtual Linkage getLinkageImpl() const;
public:
-
QualType getPointeeType() const { return PointeeType; }
+ /// Returns true if the member type (i.e. the pointee type) is a
+ /// function type rather than a data-member type.
+ bool isMemberFunctionPointer() const {
+ return PointeeType->isFunctionProtoType();
+ }
+
+ /// Returns true if the member type (i.e. the pointee type) is a
+ /// data type rather than a function type.
+ bool isMemberDataPointer() const {
+ return !PointeeType->isFunctionProtoType();
+ }
+
const Type *getClass() const { return Class; }
bool isSugared() const { return false; }
@@ -1454,6 +1483,17 @@ public:
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
+
+ /// \brief Determine the number of bits required to address a member of
+ // an array with the given element type and number of elements.
+ static unsigned getNumAddressingBits(ASTContext &Context,
+ QualType ElementType,
+ const llvm::APInt &NumElements);
+
+ /// \brief Determine the maximum number of active bits that an array's size
+ /// can require, which limits the maximum size of the array.
+ static unsigned getMaxSizeBits(ASTContext &Context);
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSize(),
getSizeModifier(), getIndexTypeCVRQualifiers());
@@ -1533,7 +1573,6 @@ class VariableArrayType : public ArrayType {
: ArrayType(VariableArray, et, can, sm, tq),
SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
- virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const {
@@ -1592,7 +1631,6 @@ class DependentSizedArrayType : public ArrayType {
: ArrayType(DependentSizedArray, et, can, sm, tq),
Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
- virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const {
@@ -1646,7 +1684,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
loc(loc) {}
friend class ASTContext;
- virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const { return SizeExpr; }
@@ -1844,13 +1881,13 @@ class FunctionType : public Type {
// * FunctionNoProtoType::Profile
// * FunctionProtoType::Profile
// * TypePrinter::PrintFunctionProto
- // * PCH read and write
+ // * AST read and write
// * Codegen
class ExtInfo {
public:
// Constructor with no defaults. Use this when you know that you
- // have all the elements (when reading a PCH file for example).
+ // have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
NoReturn(noReturn), RegParm(regParm), CC(cc) {}
@@ -1892,7 +1929,7 @@ class FunctionType : public Type {
// The value passed to __attribute__((regparm(x)))
unsigned RegParm;
// The calling convention as specified via
- // __attribute__((cdecl|stdcall|fastcall|thiscall))
+ // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
CallingConv CC;
};
@@ -2259,14 +2296,9 @@ public:
};
class TagType : public Type {
- /// Stores the TagDecl associated with this type. The decl will
- /// point to the TagDecl that actually defines the entity (or is a
- /// definition in progress), if there is such a definition. The
- /// single-bit value will be non-zero when this tag is in the
- /// process of being defined.
- mutable llvm::PointerIntPair<TagDecl *, 1> decl;
- friend class ASTContext;
- friend class TagDecl;
+ /// Stores the TagDecl associated with this type. The decl may point to any
+ /// TagDecl that declares the entity.
+ TagDecl * decl;
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
@@ -2274,12 +2306,11 @@ protected:
virtual Linkage getLinkageImpl() const;
public:
- TagDecl *getDecl() const { return decl.getPointer(); }
+ TagDecl *getDecl() const;
/// @brief Determines whether this type is in the process of being
/// defined.
- bool isBeingDefined() const { return decl.getInt(); }
- void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
+ bool isBeingDefined() const;
static bool classof(const Type *T) {
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
@@ -2468,8 +2499,6 @@ class TemplateSpecializationType
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon);
- virtual void Destroy(ASTContext& C);
-
friend class ASTContext; // ASTContext creates these
public:
@@ -2574,9 +2603,8 @@ class InjectedClassNameType : public Type {
QualType InjectedType;
friend class ASTContext; // ASTContext creates these.
- friend class TagDecl; // TagDecl mutilates the Decl
- friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not
- // currently suitable for PCH reading, too much
+ friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
+ // currently suitable for AST reading, too much
// interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
: Type(InjectedClassName, QualType(), true),
@@ -2592,7 +2620,7 @@ public:
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
}
- CXXRecordDecl *getDecl() const { return Decl; }
+ CXXRecordDecl *getDecl() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@@ -2836,8 +2864,6 @@ class DependentTemplateSpecializationType :
const TemplateArgument *Args,
QualType Canon);
- virtual void Destroy(ASTContext& C);
-
friend class ASTContext; // ASTContext creates these
public:
@@ -3014,8 +3040,6 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
: ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
public:
- void Destroy(ASTContext& C); // key function
-
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base,
@@ -3049,8 +3073,6 @@ class ObjCInterfaceType : public ObjCObjectType {
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
public:
- void Destroy(ASTContext& C); // key function
-
/// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
@@ -3103,8 +3125,6 @@ protected:
virtual Linkage getLinkageImpl() const;
public:
- void Destroy(ASTContext& C);
-
/// getPointeeType - Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; }
@@ -3486,7 +3506,13 @@ inline bool Type::isMemberPointerType() const {
}
inline bool Type::isMemberFunctionPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>())
- return T->getPointeeType()->isFunctionType();
+ return T->isMemberFunctionPointer();
+ else
+ return false;
+}
+inline bool Type::isMemberDataPointerType() const {
+ if (const MemberPointerType* T = getAs<MemberPointerType>())
+ return T->isMemberDataPointer();
else
return false;
}
@@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const {
inline bool Type::isObjCObjectType() const {
return isa<ObjCObjectType>(CanonicalType);
}
+inline bool Type::isObjCObjectOrInterfaceType() const {
+ return isa<ObjCInterfaceType>(CanonicalType) ||
+ isa<ObjCObjectType>(CanonicalType);
+}
+
inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedIdType();
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 842c06878453..f1c64bd95977 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -341,6 +341,10 @@ private:
template <class Base, class Derived, class TypeClass>
class InheritingConcreteTypeLoc : public Base {
public:
+ static bool classofType(const Type *Ty) {
+ return TypeClass::classof(Ty);
+ }
+
static bool classof(const TypeLoc *TL) {
return Derived::classofType(TL->getTypePtr());
}
diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
index 1a050d29c860..7cf0d5e999b6 100644
--- a/include/clang/AST/TypeOrdering.h
+++ b/include/clang/AST/TypeOrdering.h
@@ -17,6 +17,7 @@
#define LLVM_CLANG_TYPE_ORDERING_H
#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include <functional>
namespace clang {
@@ -51,6 +52,26 @@ namespace llvm {
return LHS == RHS;
}
};
+
+ template<> struct DenseMapInfo<clang::CanQualType> {
+ static inline clang::CanQualType getEmptyKey() {
+ return clang::CanQualType();
+ }
+
+ static inline clang::CanQualType getTombstoneKey() {
+ using clang::CanQualType;
+ return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
+ }
+
+ static unsigned getHashValue(clang::CanQualType Val) {
+ return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+ ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+ }
+
+ static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
+ return LHS == RHS;
+ }
+ };
}
#endif
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
new file mode 100644
index 000000000000..280b1260ac26
--- /dev/null
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -0,0 +1,595 @@
+//= FormatString.h - Analysis of printf/fprintf format strings --*- 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 APIs for analyzing the format strings of printf, fscanf,
+// and friends.
+//
+// The structure of format strings for fprintf are described in C99 7.19.6.1.
+//
+// The structure of format strings for fscanf are described in C99 7.19.6.2.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FORMAT_H
+#define LLVM_CLANG_FORMAT_H
+
+#include "clang/AST/CanonicalType.h"
+
+namespace clang {
+
+//===----------------------------------------------------------------------===//
+/// Common components of both fprintf and fscanf format strings.
+namespace analyze_format_string {
+
+/// Class representing optional flags with location and representation
+/// information.
+class OptionalFlag {
+public:
+ OptionalFlag(const char *Representation)
+ : representation(Representation), flag(false) {}
+ bool isSet() { return flag; }
+ void set() { flag = true; }
+ void clear() { flag = false; }
+ void setPosition(const char *position) {
+ assert(position);
+ this->position = position;
+ }
+ const char *getPosition() const {
+ assert(position);
+ return position;
+ }
+ const char *toString() const { return representation; }
+
+ // Overloaded operators for bool like qualities
+ operator bool() const { return flag; }
+ OptionalFlag& operator=(const bool &rhs) {
+ flag = rhs;
+ return *this; // Return a reference to myself.
+ }
+private:
+ const char *representation;
+ const char *position;
+ bool flag;
+};
+
+/// Represents the length modifier in a format string in scanf/printf.
+class LengthModifier {
+public:
+ enum Kind {
+ None,
+ AsChar, // 'hh'
+ AsShort, // 'h'
+ AsLong, // 'l'
+ AsLongLong, // 'll', 'q' (BSD, deprecated)
+ AsIntMax, // 'j'
+ AsSizeT, // 'z'
+ AsPtrDiff, // 't'
+ AsLongDouble, // 'L'
+ AsWideChar = AsLong // for '%ls', only makes sense for printf
+ };
+
+ LengthModifier()
+ : Position(0), kind(None) {}
+ LengthModifier(const char *pos, Kind k)
+ : Position(pos), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ unsigned getLength() const {
+ switch (kind) {
+ default:
+ return 1;
+ case AsLongLong:
+ case AsChar:
+ return 2;
+ case None:
+ return 0;
+ }
+ }
+
+ Kind getKind() const { return kind; }
+ void setKind(Kind k) { kind = k; }
+
+ const char *toString() const;
+
+private:
+ const char *Position;
+ Kind kind;
+};
+
+class ConversionSpecifier {
+public:
+ enum Kind {
+ InvalidSpecifier = 0,
+ // C99 conversion specifiers.
+ cArg,
+ dArg,
+ iArg,
+ IntArgBeg = cArg, IntArgEnd = iArg,
+
+ oArg,
+ uArg,
+ xArg,
+ XArg,
+ UIntArgBeg = oArg, UIntArgEnd = XArg,
+
+ fArg,
+ FArg,
+ eArg,
+ EArg,
+ gArg,
+ GArg,
+ aArg,
+ AArg,
+ DoubleArgBeg = fArg, DoubleArgEnd = AArg,
+
+ sArg,
+ pArg,
+ nArg,
+ PercentArg,
+ CArg,
+ SArg,
+
+ // ** Printf-specific **
+
+ // Objective-C specific specifiers.
+ ObjCObjArg, // '@'
+ ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
+
+ // GlibC specific specifiers.
+ PrintErrno, // 'm'
+
+ PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
+
+ // ** Scanf-specific **
+ ScanListArg, // '['
+ ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
+ };
+
+ ConversionSpecifier(bool isPrintf)
+ : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
+
+ ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
+ : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
+
+ const char *getStart() const {
+ return Position;
+ }
+
+ llvm::StringRef getCharacters() const {
+ return llvm::StringRef(getStart(), getLength());
+ }
+
+ bool consumesDataArgument() const {
+ switch (kind) {
+ case PrintErrno:
+ assert(IsPrintf);
+ case PercentArg:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ Kind getKind() const { return kind; }
+ void setKind(Kind k) { kind = k; }
+ unsigned getLength() const {
+ return EndScanList ? EndScanList - Position : 1;
+ }
+
+ const char *toString() const;
+
+ bool isPrintfKind() const { return IsPrintf; }
+
+protected:
+ bool IsPrintf;
+ const char *Position;
+ const char *EndScanList;
+ Kind kind;
+};
+
+class ArgTypeResult {
+public:
+ enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
+ CStrTy, WCStrTy, WIntTy };
+private:
+ const Kind K;
+ QualType T;
+ ArgTypeResult(bool) : K(InvalidTy) {}
+public:
+ ArgTypeResult(Kind k = UnknownTy) : K(k) {}
+ ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
+ ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
+
+ static ArgTypeResult Invalid() { return ArgTypeResult(true); }
+
+ bool isValid() const { return K != InvalidTy; }
+
+ const QualType *getSpecificType() const {
+ return K == SpecificTy ? &T : 0;
+ }
+
+ bool matchesType(ASTContext &C, QualType argTy) const;
+
+ bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
+
+ QualType getRepresentativeType(ASTContext &C) const;
+};
+
+class OptionalAmount {
+public:
+ enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
+
+ OptionalAmount(HowSpecified howSpecified,
+ unsigned amount,
+ const char *amountStart,
+ unsigned amountLength,
+ bool usesPositionalArg)
+ : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
+ UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
+
+ OptionalAmount(bool valid = true)
+ : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
+ UsesPositionalArg(0), UsesDotPrefix(0) {}
+
+ bool isInvalid() const {
+ return hs == Invalid;
+ }
+
+ HowSpecified getHowSpecified() const { return hs; }
+ void setHowSpecified(HowSpecified h) { hs = h; }
+
+ bool hasDataArgument() const { return hs == Arg; }
+
+ unsigned getArgIndex() const {
+ assert(hasDataArgument());
+ return amt;
+ }
+
+ unsigned getConstantAmount() const {
+ assert(hs == Constant);
+ return amt;
+ }
+
+ const char *getStart() const {
+ // We include the . character if it is given.
+ return start - UsesDotPrefix;
+ }
+
+ unsigned getConstantLength() const {
+ assert(hs == Constant);
+ return length + UsesDotPrefix;
+ }
+
+ ArgTypeResult getArgType(ASTContext &Ctx) const;
+
+ void toString(llvm::raw_ostream &os) const;
+
+ bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
+ unsigned getPositionalArgIndex() const {
+ assert(hasDataArgument());
+ return amt + 1;
+ }
+
+ bool usesDotPrefix() const { return UsesDotPrefix; }
+ void setUsesDotPrefix() { UsesDotPrefix = true; }
+
+private:
+ const char *start;
+ unsigned length;
+ HowSpecified hs;
+ unsigned amt;
+ bool UsesPositionalArg : 1;
+ bool UsesDotPrefix;
+};
+
+
+class FormatSpecifier {
+protected:
+ LengthModifier LM;
+ OptionalAmount FieldWidth;
+ ConversionSpecifier CS;
+ /// Positional arguments, an IEEE extension:
+ /// IEEE Std 1003.1, 2004 Edition
+ /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
+ bool UsesPositionalArg;
+ unsigned argIndex;
+public:
+ FormatSpecifier(bool isPrintf)
+ : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
+
+ void setLengthModifier(LengthModifier lm) {
+ LM = lm;
+ }
+
+ void setUsesPositionalArg() { UsesPositionalArg = true; }
+
+ void setArgIndex(unsigned i) {
+ argIndex = i;
+ }
+
+ unsigned getArgIndex() const {
+ return argIndex;
+ }
+
+ unsigned getPositionalArgIndex() const {
+ return argIndex + 1;
+ }
+
+ const LengthModifier &getLengthModifier() const {
+ return LM;
+ }
+
+ const OptionalAmount &getFieldWidth() const {
+ return FieldWidth;
+ }
+
+ void setFieldWidth(const OptionalAmount &Amt) {
+ FieldWidth = Amt;
+ }
+
+ bool usesPositionalArg() const { return UsesPositionalArg; }
+
+ bool hasValidLengthModifier() const;
+};
+
+} // end analyze_format_string namespace
+
+//===----------------------------------------------------------------------===//
+/// Pieces specific to fprintf format strings.
+
+namespace analyze_printf {
+
+class PrintfConversionSpecifier :
+ public analyze_format_string::ConversionSpecifier {
+public:
+ PrintfConversionSpecifier()
+ : ConversionSpecifier(true, 0, InvalidSpecifier) {}
+
+ PrintfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(true, pos, k) {}
+
+ bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
+ bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
+ bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
+ bool isDoubleArg() const { return kind >= DoubleArgBeg &&
+ kind <= DoubleArgBeg; }
+ unsigned getLength() const {
+ // Conversion specifiers currently only are represented by
+ // single characters, but we be flexible.
+ return 1;
+ }
+
+ static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+ return CS->isPrintfKind();
+ }
+};
+
+using analyze_format_string::ArgTypeResult;
+using analyze_format_string::LengthModifier;
+using analyze_format_string::OptionalAmount;
+using analyze_format_string::OptionalFlag;
+
+class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag IsLeftJustified; // '-'
+ OptionalFlag HasPlusPrefix; // '+'
+ OptionalFlag HasSpacePrefix; // ' '
+ OptionalFlag HasAlternativeForm; // '#'
+ OptionalFlag HasLeadingZeroes; // '0'
+ OptionalAmount Precision;
+public:
+ PrintfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ true),
+ IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
+ HasAlternativeForm("#"), HasLeadingZeroes("0") {}
+
+ static PrintfSpecifier Parse(const char *beg, const char *end);
+
+ // Methods for incrementally constructing the PrintfSpecifier.
+ void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
+ CS = cs;
+ }
+ void setIsLeftJustified(const char *position) {
+ IsLeftJustified = true;
+ IsLeftJustified.setPosition(position);
+ }
+ void setHasPlusPrefix(const char *position) {
+ HasPlusPrefix = true;
+ HasPlusPrefix.setPosition(position);
+ }
+ void setHasSpacePrefix(const char *position) {
+ HasSpacePrefix = true;
+ HasSpacePrefix.setPosition(position);
+ }
+ void setHasAlternativeForm(const char *position) {
+ HasAlternativeForm = true;
+ HasAlternativeForm.setPosition(position);
+ }
+ void setHasLeadingZeros(const char *position) {
+ HasLeadingZeroes = true;
+ HasLeadingZeroes.setPosition(position);
+ }
+ void setUsesPositionalArg() { UsesPositionalArg = true; }
+
+ // Methods for querying the format specifier.
+
+ const PrintfConversionSpecifier &getConversionSpecifier() const {
+ return cast<PrintfConversionSpecifier>(CS);
+ }
+
+ void setPrecision(const OptionalAmount &Amt) {
+ Precision = Amt;
+ Precision.setUsesDotPrefix();
+ }
+
+ const OptionalAmount &getPrecision() const {
+ return Precision;
+ }
+
+ bool consumesDataArgument() const {
+ return getConversionSpecifier().consumesDataArgument();
+ }
+
+ /// \brief Returns the builtin type that a data argument
+ /// paired with this format specifier should have. This method
+ /// will return null if the format specifier does not have
+ /// a matching data argument or the matching argument matches
+ /// more than one type.
+ ArgTypeResult getArgType(ASTContext &Ctx) const;
+
+ const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
+ const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
+ const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
+ const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
+ const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
+ bool usesPositionalArg() const { return UsesPositionalArg; }
+
+ /// Changes the specifier and length according to a QualType, retaining any
+ /// flags or options. Returns true on success, or false when a conversion
+ /// was not successful.
+ bool fixType(QualType QT);
+
+ void toString(llvm::raw_ostream &os) const;
+
+ // Validation methods - to check if any element results in undefined behavior
+ bool hasValidPlusPrefix() const;
+ bool hasValidAlternativeForm() const;
+ bool hasValidLeadingZeros() const;
+ bool hasValidSpacePrefix() const;
+ bool hasValidLeftJustified() const;
+
+ bool hasValidPrecision() const;
+ bool hasValidFieldWidth() const;
+};
+} // end analyze_printf namespace
+
+//===----------------------------------------------------------------------===//
+/// Pieces specific to fscanf format strings.
+
+namespace analyze_scanf {
+
+class ScanfConversionSpecifier :
+ public analyze_format_string::ConversionSpecifier {
+public:
+ ScanfConversionSpecifier()
+ : ConversionSpecifier(false, 0, InvalidSpecifier) {}
+
+ ScanfConversionSpecifier(const char *pos, Kind k)
+ : ConversionSpecifier(false, pos, k) {}
+
+ void setEndScanList(const char *pos) { EndScanList = pos; }
+
+ static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
+ return !CS->isPrintfKind();
+ }
+};
+
+using analyze_format_string::LengthModifier;
+using analyze_format_string::OptionalAmount;
+using analyze_format_string::OptionalFlag;
+
+class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
+ OptionalFlag SuppressAssignment; // '*'
+public:
+ ScanfSpecifier() :
+ FormatSpecifier(/* isPrintf = */ false),
+ SuppressAssignment("*") {}
+
+ void setSuppressAssignment(const char *position) {
+ SuppressAssignment = true;
+ SuppressAssignment.setPosition(position);
+ }
+
+ const OptionalFlag &getSuppressAssignment() const {
+ return SuppressAssignment;
+ }
+
+ void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
+ CS = cs;
+ }
+
+ const ScanfConversionSpecifier &getConversionSpecifier() const {
+ return cast<ScanfConversionSpecifier>(CS);
+ }
+
+ bool consumesDataArgument() const {
+ return CS.consumesDataArgument() && !SuppressAssignment;
+ }
+
+ static ScanfSpecifier Parse(const char *beg, const char *end);
+};
+
+} // end analyze_scanf namespace
+
+//===----------------------------------------------------------------------===//
+// Parsing and processing of format strings (both fprintf and fscanf).
+
+namespace analyze_format_string {
+
+enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
+
+class FormatStringHandler {
+public:
+ FormatStringHandler() {}
+ virtual ~FormatStringHandler();
+
+ virtual void HandleNullChar(const char *nullCharacter) {}
+
+ virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
+ PositionContext p) {}
+
+ virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
+
+ virtual void HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen) {}
+
+ // Printf-specific handlers.
+
+ virtual bool HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ // Scanf-specific handlers.
+
+ virtual bool HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ return true;
+ }
+
+ virtual void HandleIncompleteScanList(const char *start, const char *end) {}
+};
+
+bool ParsePrintfString(FormatStringHandler &H,
+ const char *beg, const char *end);
+
+bool ParseScanfString(FormatStringHandler &H,
+ const char *beg, const char *end);
+
+} // end analyze_format_string namespace
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 44ab080acbf3..237fe14aed4f 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -41,8 +41,9 @@ struct LiveVariables_ValueTypes {
ObserverTy* Observer;
ValTy AlwaysLive;
AnalysisContext *AC;
+ bool killAtAssign;
- AnalysisDataTy() : Observer(NULL), AC(NULL) {}
+ AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {}
};
//===-----------------------------------------------------===//
@@ -68,7 +69,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
public:
typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
- LiveVariables(AnalysisContext &AC);
+ LiveVariables(AnalysisContext &AC, bool killAtAssign = true);
/// IsLive - Return true if a variable is live at the end of a
/// specified block.
diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h
deleted file mode 100644
index d907637d39c5..000000000000
--- a/include/clang/Analysis/Analyses/PrintfFormatString.h
+++ /dev/null
@@ -1,445 +0,0 @@
-//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Handling of format string in printf and friends. The structure of format
-// strings for fprintf() are described in C99 7.19.6.1.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_FPRINTF_FORMAT_H
-#define LLVM_CLANG_FPRINTF_FORMAT_H
-
-#include "clang/AST/CanonicalType.h"
-
-namespace clang {
-
-class ASTContext;
-
-namespace analyze_printf {
-
-class ArgTypeResult {
-public:
- enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
- CStrTy, WCStrTy };
-private:
- const Kind K;
- QualType T;
- ArgTypeResult(bool) : K(InvalidTy) {}
-public:
- ArgTypeResult(Kind k = UnknownTy) : K(k) {}
- ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
- ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
-
- static ArgTypeResult Invalid() { return ArgTypeResult(true); }
-
- bool isValid() const { return K != InvalidTy; }
-
- const QualType *getSpecificType() const {
- return K == SpecificTy ? &T : 0;
- }
-
- bool matchesType(ASTContext &C, QualType argTy) const;
-
- bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
-
- QualType getRepresentativeType(ASTContext &C) const;
-};
-
-class ConversionSpecifier {
-public:
- enum Kind {
- InvalidSpecifier = 0,
- // C99 conversion specifiers.
- dArg, // 'd'
- IntAsCharArg, // 'c'
- iArg, // 'i',
- oArg, // 'o',
- uArg, // 'u',
- xArg, // 'x',
- XArg, // 'X',
- fArg, // 'f',
- FArg, // 'F',
- eArg, // 'e',
- EArg, // 'E',
- gArg, // 'g',
- GArg, // 'G',
- aArg, // 'a',
- AArg, // 'A',
- CStrArg, // 's'
- VoidPtrArg, // 'p'
- OutIntPtrArg, // 'n'
- PercentArg, // '%'
- // MacOS X unicode extensions.
- CArg, // 'C'
- UnicodeStrArg, // 'S'
- // Objective-C specific specifiers.
- ObjCObjArg, // '@'
- // GlibC specific specifiers.
- PrintErrno, // 'm'
- // Specifier ranges.
- IntArgBeg = dArg,
- IntArgEnd = iArg,
- UIntArgBeg = oArg,
- UIntArgEnd = XArg,
- DoubleArgBeg = fArg,
- DoubleArgEnd = AArg,
- C99Beg = IntArgBeg,
- C99End = DoubleArgEnd,
- ObjCBeg = ObjCObjArg,
- ObjCEnd = ObjCObjArg
- };
-
- ConversionSpecifier()
- : Position(0), kind(InvalidSpecifier) {}
-
- ConversionSpecifier(const char *pos, Kind k)
- : Position(pos), kind(k) {}
-
- const char *getStart() const {
- return Position;
- }
-
- llvm::StringRef getCharacters() const {
- return llvm::StringRef(getStart(), getLength());
- }
-
- bool consumesDataArgument() const {
- switch (kind) {
- case PercentArg:
- case PrintErrno:
- return false;
- default:
- return true;
- }
- }
-
- bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
- bool isIntArg() const { return kind >= dArg && kind <= iArg; }
- bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
- bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
- Kind getKind() const { return kind; }
- void setKind(Kind k) { kind = k; }
- unsigned getLength() const {
- // Conversion specifiers currently only are represented by
- // single characters, but we be flexible.
- return 1;
- }
- const char *toString() const;
-
-private:
- const char *Position;
- Kind kind;
-};
-
-class LengthModifier {
-public:
- enum Kind {
- None,
- AsChar, // 'hh'
- AsShort, // 'h'
- AsLong, // 'l'
- AsLongLong, // 'll', 'q' (BSD, deprecated)
- AsIntMax, // 'j'
- AsSizeT, // 'z'
- AsPtrDiff, // 't'
- AsLongDouble, // 'L'
- AsWideChar = AsLong // for '%ls'
- };
-
- LengthModifier()
- : Position(0), kind(None) {}
- LengthModifier(const char *pos, Kind k)
- : Position(pos), kind(k) {}
-
- const char *getStart() const {
- return Position;
- }
-
- unsigned getLength() const {
- switch (kind) {
- default:
- return 1;
- case AsLongLong:
- case AsChar:
- return 2;
- case None:
- return 0;
- }
- }
-
- Kind getKind() const { return kind; }
- void setKind(Kind k) { kind = k; }
-
- const char *toString() const;
-
-private:
- const char *Position;
- Kind kind;
-};
-
-class OptionalAmount {
-public:
- enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
-
- OptionalAmount(HowSpecified howSpecified,
- unsigned amount,
- const char *amountStart,
- unsigned amountLength,
- bool usesPositionalArg)
- : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
- UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
-
- OptionalAmount(bool valid = true)
- : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
- UsesPositionalArg(0), UsesDotPrefix(0) {}
-
- bool isInvalid() const {
- return hs == Invalid;
- }
-
- HowSpecified getHowSpecified() const { return hs; }
- void setHowSpecified(HowSpecified h) { hs = h; }
-
- bool hasDataArgument() const { return hs == Arg; }
-
- unsigned getArgIndex() const {
- assert(hasDataArgument());
- return amt;
- }
-
- unsigned getConstantAmount() const {
- assert(hs == Constant);
- return amt;
- }
-
- const char *getStart() const {
- // We include the . character if it is given.
- return start - UsesDotPrefix;
- }
-
- unsigned getConstantLength() const {
- assert(hs == Constant);
- return length + UsesDotPrefix;
- }
-
- ArgTypeResult getArgType(ASTContext &Ctx) const;
-
- void toString(llvm::raw_ostream &os) const;
-
- bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
- unsigned getPositionalArgIndex() const {
- assert(hasDataArgument());
- return amt + 1;
- }
-
- bool usesDotPrefix() const { return UsesDotPrefix; }
- void setUsesDotPrefix() { UsesDotPrefix = true; }
-
-private:
- const char *start;
- unsigned length;
- HowSpecified hs;
- unsigned amt;
- bool UsesPositionalArg : 1;
- bool UsesDotPrefix;
-};
-
-// Class representing optional flags with location and representation
-// information.
-class OptionalFlag {
-public:
- OptionalFlag(const char *Representation)
- : representation(Representation), flag(false) {}
- bool isSet() { return flag; }
- void set() { flag = true; }
- void clear() { flag = false; }
- void setPosition(const char *position) {
- assert(position);
- this->position = position;
- }
- const char *getPosition() const {
- assert(position);
- return position;
- }
- const char *toString() const { return representation; }
-
- // Overloaded operators for bool like qualities
- operator bool() const { return flag; }
- OptionalFlag& operator=(const bool &rhs) {
- flag = rhs;
- return *this; // Return a reference to myself.
- }
-private:
- const char *representation;
- const char *position;
- bool flag;
-};
-
-class FormatSpecifier {
- LengthModifier LM;
- OptionalFlag IsLeftJustified; // '-'
- OptionalFlag HasPlusPrefix; // '+'
- OptionalFlag HasSpacePrefix; // ' '
- OptionalFlag HasAlternativeForm; // '#'
- OptionalFlag HasLeadingZeroes; // '0'
- /// Positional arguments, an IEEE extension:
- /// IEEE Std 1003.1, 2004 Edition
- /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
- bool UsesPositionalArg;
- unsigned argIndex;
- ConversionSpecifier CS;
- OptionalAmount FieldWidth;
- OptionalAmount Precision;
-public:
- FormatSpecifier() :
- IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
- HasAlternativeForm("#"), HasLeadingZeroes("0"), UsesPositionalArg(false),
- argIndex(0) {}
-
- static FormatSpecifier Parse(const char *beg, const char *end);
-
- // Methods for incrementally constructing the FormatSpecifier.
- void setConversionSpecifier(const ConversionSpecifier &cs) {
- CS = cs;
- }
- void setLengthModifier(LengthModifier lm) {
- LM = lm;
- }
- void setIsLeftJustified(const char *position) {
- IsLeftJustified = true;
- IsLeftJustified.setPosition(position);
- }
- void setHasPlusPrefix(const char *position) {
- HasPlusPrefix = true;
- HasPlusPrefix.setPosition(position);
- }
- void setHasSpacePrefix(const char *position) {
- HasSpacePrefix = true;
- HasSpacePrefix.setPosition(position);
- }
- void setHasAlternativeForm(const char *position) {
- HasAlternativeForm = true;
- HasAlternativeForm.setPosition(position);
- }
- void setHasLeadingZeros(const char *position) {
- HasLeadingZeroes = true;
- HasLeadingZeroes.setPosition(position);
- }
- void setUsesPositionalArg() { UsesPositionalArg = true; }
-
- void setArgIndex(unsigned i) {
- assert(CS.consumesDataArgument());
- argIndex = i;
- }
-
- unsigned getArgIndex() const {
- assert(CS.consumesDataArgument());
- return argIndex;
- }
-
- unsigned getPositionalArgIndex() const {
- assert(CS.consumesDataArgument());
- return argIndex + 1;
- }
-
- // Methods for querying the format specifier.
-
- const ConversionSpecifier &getConversionSpecifier() const {
- return CS;
- }
-
- const LengthModifier &getLengthModifier() const {
- return LM;
- }
-
- const OptionalAmount &getFieldWidth() const {
- return FieldWidth;
- }
-
- void setFieldWidth(const OptionalAmount &Amt) {
- FieldWidth = Amt;
- }
-
- void setPrecision(const OptionalAmount &Amt) {
- Precision = Amt;
- Precision.setUsesDotPrefix();
- }
-
- const OptionalAmount &getPrecision() const {
- return Precision;
- }
-
- /// \brief Returns the builtin type that a data argument
- /// paired with this format specifier should have. This method
- /// will return null if the format specifier does not have
- /// a matching data argument or the matching argument matches
- /// more than one type.
- ArgTypeResult getArgType(ASTContext &Ctx) const;
-
- const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
- const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
- const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
- const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
- const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
- bool usesPositionalArg() const { return UsesPositionalArg; }
-
- /// Changes the specifier and length according to a QualType, retaining any
- /// flags or options. Returns true on success, or false when a conversion
- /// was not successful.
- bool fixType(QualType QT);
-
- void toString(llvm::raw_ostream &os) const;
-
- // Validation methods - to check if any element results in undefined behavior
- bool hasValidPlusPrefix() const;
- bool hasValidAlternativeForm() const;
- bool hasValidLeadingZeros() const;
- bool hasValidSpacePrefix() const;
- bool hasValidLeftJustified() const;
-
- bool hasValidLengthModifier() const;
- bool hasValidPrecision() const;
- bool hasValidFieldWidth() const;
-};
-
-enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
-
-class FormatStringHandler {
-public:
- FormatStringHandler() {}
- virtual ~FormatStringHandler();
-
- virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier,
- unsigned specifierLen) {}
-
- virtual void HandleNullChar(const char *nullCharacter) {}
-
- virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
- PositionContext p) {}
-
- virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
-
- virtual bool
- HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen) { return true; }
-
- virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen) {
- return true;
- }
-};
-
-bool ParseFormatString(FormatStringHandler &H,
- const char *beg, const char *end);
-
-} // end printf namespace
-} // end clang namespace
-#endif
diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
new file mode 100644
index 000000000000..cb73850b08c7
--- /dev/null
+++ b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
@@ -0,0 +1,45 @@
+//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tracks the usage of variables in a Decl body to see if they are
+// never written to, implying that they constant. This is useful in static
+// analysis to see if a developer might have intended a variable to be const.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+class PseudoConstantAnalysis {
+public:
+ PseudoConstantAnalysis(const Stmt *DeclBody);
+ ~PseudoConstantAnalysis();
+
+ bool isPseudoConstant(const VarDecl *VD);
+ bool wasReferenced(const VarDecl *VD);
+
+private:
+ void RunAnalysis();
+ inline static const Decl *getDecl(const Expr *E);
+
+ // for storing the result of analyzed ValueDecls
+ void *NonConstantsImpl;
+ void *UsedVarsImpl;
+
+ const Stmt *DeclBody;
+ bool Analyzed;
+};
+
+}
+
+#endif
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 9ebd93b75b38..7d4d25f8b0d8 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -30,41 +30,67 @@ class CFG;
class CFGBlock;
class LiveVariables;
class ParentMap;
+class PseudoConstantAnalysis;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
+namespace idx { class TranslationUnit; }
+
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
const Decl *D;
+ // TranslationUnit is NULL if we don't have multiple translation units.
+ idx::TranslationUnit *TU;
+
// AnalysisContext owns the following data.
- CFG *cfg;
- bool builtCFG;
+ CFG *cfg, *completeCFG;
+ bool builtCFG, builtCompleteCFG;
LiveVariables *liveness;
+ LiveVariables *relaxedLiveness;
ParentMap *PM;
+ PseudoConstantAnalysis *PCA;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
+ bool UseUnoptimizedCFG;
bool AddEHEdges;
public:
- AnalysisContext(const Decl *d, bool addehedges = false)
- : D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
- ReferencedBlockVars(0), AddEHEdges(addehedges) {}
+ AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
+ bool useUnoptimizedCFG = false,
+ bool addehedges = false)
+ : D(d), TU(tu), cfg(0), completeCFG(0),
+ builtCFG(false), builtCompleteCFG(false),
+ liveness(0), relaxedLiveness(0), PM(0), PCA(0),
+ ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
+ AddEHEdges(addehedges) {}
~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); }
- const Decl *getDecl() { return D; }
+ const Decl *getDecl() const { return D; }
+
+ idx::TranslationUnit *getTranslationUnit() const { return TU; }
+
/// getAddEHEdges - Return true iff we are adding exceptional edges from
/// callExprs. If this is false, then try/catch statements and blocks
/// reachable from them can appear to be dead in the CFG, analysis passes must
/// cope with that.
bool getAddEHEdges() const { return AddEHEdges; }
+
+ bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
+
Stmt *getBody();
CFG *getCFG();
+
+ /// Return a version of the CFG without any edges pruned.
+ CFG *getUnoptimizedCFG();
+
ParentMap &getParentMap();
+ PseudoConstantAnalysis *getPseudoConstantAnalysis();
LiveVariables *getLiveVariables();
+ LiveVariables *getRelaxedLiveVariables();
typedef const VarDecl * const * referenced_decls_iterator;
@@ -79,10 +105,16 @@ public:
class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
+ bool UseUnoptimizedCFG;
public:
+ AnalysisContextManager(bool useUnoptimizedCFG = false)
+ : UseUnoptimizedCFG(useUnoptimizedCFG) {}
+
~AnalysisContextManager();
- AnalysisContext *getContext(const Decl *D);
+ AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
+
+ bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
// Discard all previously created AnalysisContexts.
void clear();
@@ -94,7 +126,10 @@ public:
private:
ContextKind Kind;
+
+ // AnalysisContext can't be const since some methods may modify its member.
AnalysisContext *Ctx;
+
const LocationContext *Parent;
protected:
@@ -109,6 +144,10 @@ public:
AnalysisContext *getAnalysisContext() const { return Ctx; }
+ idx::TranslationUnit *getTranslationUnit() const {
+ return Ctx->getTranslationUnit();
+ }
+
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index b7256c9dc3db..b7a8e1159693 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -35,22 +35,6 @@ namespace clang {
class LangOptions;
class ASTContext;
-namespace {
-// An element of the CFG for implicit descructor calls implied by the language
-// rules.
-class Dtor {
- // Statement that introduces the variable.
- Stmt *S;
- // A token which ends the scope, return, goto, throw, }.
- SourceLocation Loc;
-public:
- Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) {
- }
- SourceLocation getLoc() { return Loc; }
- Stmt *getStmt() { return S; }
-};
-}
-
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
llvm::PointerIntPair<Stmt *, 2> Data;
@@ -59,7 +43,6 @@ public:
explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
- // CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {}
Stmt *getStmt() const { return Data.getPointer(); }
bool asLValue() const { return Data.getInt() == 1; }
bool asStartScope() const { return Data.getInt() == 2; }
@@ -67,7 +50,6 @@ public:
bool asDtor() const { return Data.getInt() == 4; }
operator Stmt*() const { return getStmt(); }
operator bool() const { return getStmt() != 0; }
- operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@@ -285,6 +267,7 @@ public:
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
+ bool pruneTriviallyFalseEdges = true,
bool AddEHEdges = false,
bool AddScopes = false /* NOT FULLY IMPLEMENTED.
NOT READY FOR GENERAL USE. */);
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
new file mode 100644
index 000000000000..6e8e140afb23
--- /dev/null
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -0,0 +1,52 @@
+//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- 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 CFGStmtMap class, which defines a mapping from
+// Stmt* to CFGBlock*
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CFGSTMTMAP_H
+#define LLVM_CLANG_CFGSTMTMAP_H
+
+#include "clang/Analysis/CFG.h"
+
+namespace clang {
+
+class CFG;
+class CFGBlock;
+class ParentMap;
+class Stmt;
+
+class CFGStmtMap {
+ ParentMap *PM;
+ void *M;
+
+ CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
+
+public:
+ ~CFGStmtMap();
+
+ /// Returns a new CFGMap for the given CFG. It is the caller's
+ /// responsibility to 'delete' this object when done using it.
+ static CFGStmtMap *Build(CFG* C, ParentMap *PM);
+
+ /// Returns the CFGBlock the specified Stmt* appears in. For Stmt* that
+ /// are terminators, the CFGBlock is the block they appear as a terminator,
+ /// and not the block they appear as a block-level expression (e.g, '&&').
+ /// CaseStmts and LabelStmts map to the CFGBlock they label.
+ CFGBlock *getBlock(Stmt * S);
+
+ const CFGBlock *getBlock(const Stmt * S) const {
+ return const_cast<CFGStmtMap*>(this)->getBlock(const_cast<Stmt*>(S));
+ }
+};
+
+} // end clang namespace
+#endif
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
index 3c762011a657..9375db06be72 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h
@@ -231,7 +231,7 @@ private:
EdgeDataMapTy& M = D.getEdgeDataMap();
bool firstMerge = true;
-
+ bool noEdges = true;
for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
CFGBlock *PrevBlk = *I;
@@ -243,6 +243,7 @@ private:
M.find(ItrTraits::PrevEdge(B, PrevBlk));
if (EI != M.end()) {
+ noEdges = false;
if (firstMerge) {
firstMerge = false;
V.copyValues(EI->second);
@@ -252,8 +253,20 @@ private:
}
}
+ bool isInitialized = true;
+ typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B);
+ if(BI == D.getBlockDataMap().end()) {
+ isInitialized = false;
+ BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first;
+ }
+ // If no edges have been found, it means this is the first time the solver
+ // has been called on block B, we copy the initialization values (if any)
+ // as current value for V (which will be used as edge data)
+ if(noEdges && isInitialized)
+ Merge(V, BI->second);
+
// Set the data for the block.
- D.getBlockDataMap()[B].copyValues(V);
+ BI->second.copyValues(V);
}
/// ProcessBlock - Process the transfer functions for a given block.
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 075838d45e5c..ba303de7a8da 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
@@ -26,6 +27,7 @@
namespace clang {
class LocationContext;
+class AnalysisContext;
class FunctionDecl;
class ProgramPoint {
@@ -45,7 +47,7 @@ public:
CallEnterKind,
CallExitKind,
MinPostStmtKind = PostStmtKind,
- MaxPostStmtKind = PostLValueKind };
+ MaxPostStmtKind = CallExitKind };
private:
std::pair<const void *, const void *> Data;
@@ -107,16 +109,16 @@ public:
const void *tag = 0)
: ProgramPoint(B, BlockEntranceKind, L, tag) {}
- CFGBlock* getBlock() const {
- return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
+ const CFGBlock* getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
}
- CFGElement getFirstElement() const {
+ const CFGElement getFirstElement() const {
const CFGBlock* B = getBlock();
return B->empty() ? CFGElement() : B->front();
}
- Stmt *getFirstStmt() const {
+ const Stmt *getFirstStmt() const {
return getFirstElement().getStmt();
}
@@ -130,16 +132,16 @@ public:
BlockExit(const CFGBlock* B, const LocationContext *L)
: ProgramPoint(B, BlockExitKind, L) {}
- CFGBlock* getBlock() const {
- return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
+ const CFGBlock* getBlock() const {
+ return reinterpret_cast<const CFGBlock*>(getData1());
}
- Stmt* getLastStmt() const {
+ const Stmt* getLastStmt() const {
const CFGBlock* B = getBlock();
return B->empty() ? CFGElement() : B->back();
}
- Stmt* getTerminator() const {
+ const Stmt* getTerminator() const {
return getBlock()->getTerminator();
}
@@ -298,12 +300,12 @@ public:
BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {}
- CFGBlock* getSrc() const {
- return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1()));
+ const CFGBlock* getSrc() const {
+ return static_cast<const CFGBlock*>(getData1());
}
- CFGBlock* getDst() const {
- return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2()));
+ const CFGBlock* getDst() const {
+ return static_cast<const CFGBlock*>(getData2());
}
static bool classof(const ProgramPoint* Location) {
@@ -313,16 +315,17 @@ public:
class CallEnter : public StmtPoint {
public:
- // CallEnter uses the caller's location context.
- CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L)
- : StmtPoint(S, fd, CallEnterKind, L, 0) {}
+ // L is caller's location context. AC is callee's AnalysisContext.
+ CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L)
+ : StmtPoint(S, AC, CallEnterKind, L, 0) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
}
- const FunctionDecl *getCallee() const {
- return static_cast<const FunctionDecl *>(getData2());
+ AnalysisContext *getCalleeContext() const {
+ return const_cast<AnalysisContext *>(
+ static_cast<const AnalysisContext *>(getData2()));
}
static bool classof(const ProgramPoint *Location) {
diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
index 8a85ec15cdce..6421f185ff7f 100644
--- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h
+++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h
@@ -86,7 +86,7 @@ public:
BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp())
return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
- else if (B->getOpcode() == BinaryOperator::Comma)
+ else if (B->getOpcode() == BO_Comma)
return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
// Fall through.
}
@@ -149,7 +149,7 @@ public:
case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(S);
- if (B->getOpcode() != BinaryOperator::Comma) break;
+ if (B->getOpcode() != BO_Comma) break;
static_cast<ImplClass*>(this)->Visit(B->getRHS());
return;
}
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 98871d26204f..2f2267f7f79f 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
// a possible subject.
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
[{S->getStorageClass() != VarDecl::Register &&
- S->getKind() != Decl::ImplicitParam
- S->getKind() != Decl::ParmVar
+ S->getKind() != Decl::ImplicitParam &&
+ S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>;
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
[{S->isVirtual()}]>;
@@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
class StringArgument<string name> : Argument<name>;
class ExprArgument<string name> : Argument<name>;
class FunctionArgument<string name> : Argument<name>;
-class ObjCInterfaceArgument<string name> : Argument<name>;
-class UnsignedIntArgument<string name> : Argument<name>;
-class UnsignedIntOrTypeArgument<string name> : Argument<name>;
+class TypeArgument<string name> : Argument<name>;
+class UnsignedArgument<string name> : Argument<name>;
+class VariadicUnsignedArgument<string name> : Argument<name>;
+
+// This one's a doozy, so it gets its own special type
+// It can be an unsigned integer, or a type. Either can
+// be dependent.
+class AlignedArgument<string name> : Argument<name>;
// An integer argument with a default value
class DefaultIntArgument<string name, int default> : IntArgument<name> {
int Default = default;
}
-// Zero or more arguments of a type
-class VariadicArgument<Argument arg> : Argument<arg.Name> {
- Argument VariadicArg = arg;
+// This argument is more complex, it includes the enumerator type name,
+// a list of strings to accept, and a list of enumerators to map them to.
+class EnumArgument<string name, string type, list<string> values,
+ list<string> enums> : Argument<name> {
+ string Type = type;
+ list<string> Values = values;
+ list<string> Enums = enums;
}
class Attr {
@@ -76,9 +85,8 @@ class Attr {
// The attribute will not be permitted in C++0x attribute-specifiers if
// this is empty; the empty string can be used as a namespace.
list<string> Namespaces = [];
- // A temporary development bit to tell TableGen not to emit certain
- // information about the attribute.
- bit DoNotEmit = 1;
+ // Any additional text that should be included verbatim in the class.
+ code AdditionalMembers = [{}];
}
//
@@ -87,13 +95,13 @@ class Attr {
def Alias : Attr {
let Spellings = ["alias"];
- let Args = [StringArgument<"AliasName">];
+ let Args = [StringArgument<"Aliasee">];
}
def Aligned : Attr {
let Spellings = ["align", "aligned"];
let Subjects = [NonBitField, NormalVar, Tag];
- let Args = [UnsignedIntOrTypeArgument<"Alignment">];
+ let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"];
}
@@ -123,19 +131,17 @@ def BaseCheck : Attr {
let Spellings = ["base_check"];
let Subjects = [CXXRecord];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def Blocks : Attr {
let Spellings = ["blocks"];
- let Args = [IdentifierArgument<"Type">];
+ let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
}
def CarriesDependency : Attr {
let Spellings = ["carries_dependency"];
let Subjects = [ParmVar, Function];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def CDecl : Attr {
@@ -189,7 +195,6 @@ def Final : Attr {
let Spellings = ["final"];
let Subjects = [CXXRecord, CXXVirtualMethod];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def Format : Attr {
@@ -211,7 +216,6 @@ def Hiding : Attr {
let Spellings = ["hiding"];
let Subjects = [Field, CXXMethod];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def IBAction : Attr {
@@ -224,7 +228,7 @@ def IBOutlet : Attr {
def IBOutletCollection : Attr {
let Spellings = ["iboutletcollection"];
- let Args = [ObjCInterfaceArgument<"Class">];
+ let Args = [TypeArgument<"Interface">];
}
def Malloc : Attr {
@@ -233,12 +237,12 @@ def Malloc : Attr {
def MaxFieldAlignment : Attr {
let Spellings = [];
- let Args = [UnsignedIntArgument<"Alignment">];
+ let Args = [UnsignedArgument<"Alignment">];
}
def MSP430Interrupt : Attr {
let Spellings = [];
- let Args = [UnsignedIntArgument<"Number">];
+ let Args = [UnsignedArgument<"Number">];
}
def NoDebug : Attr {
@@ -251,7 +255,15 @@ def NoInline : Attr {
def NonNull : Attr {
let Spellings = ["nonnull"];
- let Args = [VariadicArgument<UnsignedIntArgument<"Args">>];
+ let Args = [VariadicUnsignedArgument<"Args">];
+ let AdditionalMembers =
+[{bool isNonNull(unsigned idx) const {
+ for (args_iterator i = args_begin(), e = args_end();
+ i != e; ++i)
+ if (*i == idx)
+ return true;
+ return false;
+ } }];
}
def NoReturn : Attr {
@@ -290,13 +302,20 @@ def Override : Attr {
let Spellings = ["override"];
let Subjects = [CXXVirtualMethod];
let Namespaces = ["", "std"];
- let DoNotEmit = 0;
}
def Overloadable : Attr {
let Spellings = ["overloadable"];
}
+def Ownership : Attr {
+ let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
+ let Args = [EnumArgument<"OwnKind", "OwnershipKind",
+ ["ownership_holds", "ownership_returns", "ownership_takes"],
+ ["Holds", "Returns", "Takes"]>,
+ StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
+}
+
def Packed : Attr {
let Spellings = ["packed"];
}
@@ -307,18 +326,18 @@ def Pure : Attr {
def Regparm : Attr {
let Spellings = ["regparm"];
- let Args = [UnsignedIntArgument<"NumParams">];
+ let Args = [UnsignedArgument<"NumParams">];
}
def ReqdWorkGroupSize : Attr {
let Spellings = ["reqd_work_group_size"];
- let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">,
- UnsignedIntArgument<"ZDim">];
+ let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
+ UnsignedArgument<"ZDim">];
}
def InitPriority : Attr {
let Spellings = ["init_priority"];
- let Args = [UnsignedIntArgument<"Priority">];
+ let Args = [UnsignedArgument<"Priority">];
}
def Section : Attr {
@@ -328,8 +347,8 @@ def Section : Attr {
def Sentinel : Attr {
let Spellings = ["sentinel"];
- let Args = [DefaultIntArgument<"NulPos", 0>,
- DefaultIntArgument<"Sentinel", 0>];
+ let Args = [DefaultIntArgument<"Sentinel", 0>,
+ DefaultIntArgument<"NullPos", 0>];
}
def StdCall : Attr {
@@ -340,6 +359,10 @@ def ThisCall : Attr {
let Spellings = ["thiscall", "__thiscall"];
}
+def Pascal : Attr {
+ let Spellings = ["pascal", "__pascal"];
+}
+
def TransparentUnion : Attr {
let Spellings = ["transparent_union"];
}
@@ -358,7 +381,14 @@ def Used : Attr {
def Visibility : Attr {
let Spellings = ["visibility"];
- let Args = [StringArgument<"Visibility">];
+ let Args = [EnumArgument<"Visibility", "VisibilityType",
+ ["default", "hidden", "internal", "protected"],
+ ["Default", "Hidden", "Hidden", "Protected"]>];
+}
+
+def VecReturn : Attr {
+ let Spellings = ["vecreturn"];
+ let Subjects = [CXXRecord];
}
def WarnUnusedResult : Attr {
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def
index eff4f5e6727b..0da893899b0b 100644
--- a/include/clang/Basic/Builtins.def
+++ b/include/clang/Basic/Builtins.def
@@ -66,6 +66,11 @@
// P:N: -> similar to the p:N: attribute, but the function is like vprintf
// in that it accepts its arguments as a va_list rather than
// through an ellipsis
+// s:N: -> this is a scanf-like function whose Nth argument is the format
+// string.
+// S:N: -> similar to the s:N: attribute, but the function is like vscanf
+// in that it accepts its arguments as a va_list rather than
+// through an ellipsis
// e -> const, but only when -fmath-errno=0
// FIXME: gcc has nonnull
@@ -193,9 +198,9 @@ BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc")
BUILTIN(__builtin_cimag, "dXd", "Fnc")
BUILTIN(__builtin_cimagf, "fXf", "Fnc")
BUILTIN(__builtin_cimagl, "LdXLd", "Fnc")
-BUILTIN(__builtin_conj, "dXd", "Fnc")
-BUILTIN(__builtin_conjf, "fXf", "Fnc")
-BUILTIN(__builtin_conjl, "LdXLd", "Fnc")
+BUILTIN(__builtin_conj, "XdXd", "Fnc")
+BUILTIN(__builtin_conjf, "XfXf", "Fnc")
+BUILTIN(__builtin_conjl, "XLdXLd", "Fnc")
BUILTIN(__builtin_clog, "XdXd", "Fnc")
BUILTIN(__builtin_clogf, "XfXf", "Fnc")
BUILTIN(__builtin_clogl, "XLdXLd", "Fnc")
@@ -281,12 +286,14 @@ BUILTIN(__builtin_stdarg_start, "vA.", "n")
BUILTIN(__builtin_bcmp, "iv*v*z", "n")
BUILTIN(__builtin_bcopy, "vv*v*z", "n")
BUILTIN(__builtin_bzero, "vv*z", "nF")
+BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memset, "v*v*iz", "nF")
+BUILTIN(__builtin_printf, "icC*.", "Fp:0:")
BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF")
BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF")
BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF")
@@ -319,7 +326,7 @@ BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:")
BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
// GCC exception builtins
-BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t!
+BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t!
BUILTIN(__builtin_frob_return_addr, "v*v*", "n")
BUILTIN(__builtin_dwarf_cfa, "v*", "n")
BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
@@ -363,75 +370,75 @@ BUILTIN(__builtin_alloca, "v*z" , "n")
// long long -> i64.
BUILTIN(__sync_fetch_and_add, "v.", "")
-BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_sub, "v.", "")
-BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_or, "v.", "")
-BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_and, "v.", "")
-BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_xor, "v.", "")
-BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n")
-BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n")
-BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n")
-BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "n")
+BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "n")
+BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "n")
+BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_add_and_fetch, "v.", "")
-BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_sub_and_fetch, "v.", "")
-BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_or_and_fetch, "v.", "")
-BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_and_and_fetch, "v.", "")
-BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_xor_and_fetch, "v.", "")
-BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n")
-BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n")
-BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n")
-BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "n")
+BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "n")
+BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "n")
+BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_bool_compare_and_swap, "v.", "")
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")
@@ -448,18 +455,18 @@ BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n")
BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n")
BUILTIN(__sync_lock_test_and_set, "v.", "")
-BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n")
-BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n")
-BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n")
-BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n")
-BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n")
+BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "n")
+BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "n")
+BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "n")
+BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "n")
+BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_lock_release, "v.", "")
-BUILTIN(__sync_lock_release_1, "vc*.", "n")
-BUILTIN(__sync_lock_release_2, "vs*.", "n")
-BUILTIN(__sync_lock_release_4, "vi*.", "n")
-BUILTIN(__sync_lock_release_8, "vLLi*.", "n")
-BUILTIN(__sync_lock_release_16, "vLLLi*.", "n")
+BUILTIN(__sync_lock_release_1, "vcD*.", "n")
+BUILTIN(__sync_lock_release_2, "vsD*.", "n")
+BUILTIN(__sync_lock_release_4, "viD*.", "n")
+BUILTIN(__sync_lock_release_8, "vLLiD*.", "n")
+BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n")
@@ -468,10 +475,10 @@ BUILTIN(__sync_synchronize, "v.", "n")
// LLVM instruction builtin [Clang extension].
BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
// GCC does not support these, they are a Clang extension.
-BUILTIN(__sync_fetch_and_min, "ii*i", "n")
-BUILTIN(__sync_fetch_and_max, "ii*i", "n")
-BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n")
-BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n")
+BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
+BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
+BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n")
+BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n")
// Random libc builtins.
BUILTIN(__builtin_abort, "v", "Fnr")
@@ -516,6 +523,7 @@ LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h")
LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h")
LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
+LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h")
// C99
LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h")
@@ -560,5 +568,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h")
LIBBUILTIN(cosl, "LdLd", "fe", "math.h")
LIBBUILTIN(cosf, "ff", "fe", "math.h")
+// Blocks runtime Builtin math library functions
+LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h")
+LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h")
+// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
+
#undef BUILTIN
#undef LIBBUILTIN
diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h
index 07f091a58a4e..94d5e6955a24 100644
--- a/include/clang/Basic/Builtins.h
+++ b/include/clang/Basic/Builtins.h
@@ -119,6 +119,11 @@ public:
/// argument and whether this function as a va_list argument.
bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+ /// \brief Determine whether this builtin is like scanf in its
+ /// formatting rules and, if so, set the index to the format string
+ /// argument and whether this function as a va_list argument.
+ bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
+
/// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
/// as an operand or return type.
bool hasVAListUse(unsigned ID) const {
diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def
index 54e4c2b2083a..080d17fa1e32 100644
--- a/include/clang/Basic/BuiltinsARM.def
+++ b/include/clang/Basic/BuiltinsARM.def
@@ -15,9 +15,21 @@
// The format of this database matches clang/Basic/Builtins.def.
// In libgcc
-BUILTIN(__clear_cache, "vc*c*", "")
+BUILTIN(__clear_cache, "v.", "")
BUILTIN(__builtin_thread_pointer, "v*", "")
+// Saturating arithmetic
+BUILTIN(__builtin_arm_qadd, "iii", "nc")
+BUILTIN(__builtin_arm_qsub, "iii", "nc")
+BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
+BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
+
+// VFP
+BUILTIN(__builtin_arm_get_fpscr, "Ui", "nc")
+BUILTIN(__builtin_arm_set_fpscr, "vUi", "nc")
+BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc")
+BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc")
+
// NEON
#define GET_NEON_BUILTINS
#include "clang/Basic/arm_neon.inc"
diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def
index a878dd1bd1a3..5ad64b9b49d1 100644
--- a/include/clang/Basic/BuiltinsX86.def
+++ b/include/clang/Basic/BuiltinsX86.def
@@ -22,10 +22,81 @@
// definition anyway, since code generation will lower to the
// intrinsic if one exists.
-BUILTIN(__builtin_ia32_emms , "v", "")
-
// FIXME: Are these nothrow/const?
+// MMX
+BUILTIN(__builtin_ia32_emms, "v", "")
+BUILTIN(__builtin_ia32_femms, "v", "")
+BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
+BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
+BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
+BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
+BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
+BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
+BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
+BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
+BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
+BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
+BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
+BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
+BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
+BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
+BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
+BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
+BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") // FIXME: Correct type?
+BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
+BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
+BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
+BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
+
// SSE intrinsics.
BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
@@ -57,29 +128,6 @@ BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
-BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
-BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
-BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
-BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
@@ -147,18 +195,6 @@ BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
-BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
-BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
-BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
-BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
-BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
-BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
-BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
@@ -166,17 +202,13 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
-BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
-BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
-BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_sfence, "v", "")
-BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
@@ -212,15 +244,6 @@ BUILTIN(__builtin_ia32_lfence, "v", "")
BUILTIN(__builtin_ia32_mfence, "v", "")
BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
-BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
-BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
-BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
-BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
-BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
@@ -244,8 +267,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
-BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "")
-BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "")
+BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") // FIXME: Correct type?
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
@@ -324,5 +346,98 @@ BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
-BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "")
+BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLic", "")
+
+// AVX
+BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "")
+BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "")
+BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
+BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
+BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
+BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
+BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4di", "")
+BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fi", "")
+BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
+BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
+BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fi", "")
+BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "")
+BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dc", "")
+BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fc", "")
+BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8ic", "")
+BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "")
+BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "")
+BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "")
+BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "")
+BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "")
+BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "")
+BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "")
+BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
+BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dc", "")
+BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fc", "")
+BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8ic", "")
+BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dc", "")
+BUILTIN(__builtin_ia32_vpermilps, "V4fV4fc", "")
+BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dc", "")
+BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fc", "")
+BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dc", "")
+BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fc", "")
+BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4ic", "")
+BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "")
+BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "")
+BUILTIN(__builtin_ia32_roundpd256, "V4dV4di", "")
+BUILTIN(__builtin_ia32_roundps256, "V8fV8fi", "")
+BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "")
+BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "")
+BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "")
+BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "")
+BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "")
+BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "")
+BUILTIN(__builtin_ia32_movmskps256, "iV8f", "")
+BUILTIN(__builtin_ia32_vzeroall, "v", "")
+BUILTIN(__builtin_ia32_vzeroupper, "v", "")
+BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "")
+BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "")
+BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "")
+BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "")
+BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "")
+BUILTIN(__builtin_ia32_loadupd256, "V4ddC*", "")
+BUILTIN(__builtin_ia32_loadups256, "V8ffC*", "")
+BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "")
+BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "")
+BUILTIN(__builtin_ia32_loaddqu256, "V32ccC*", "")
+BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "")
+BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "")
+BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "")
+BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "")
+BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "")
+BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2d", "")
+BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4f", "")
+BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4d", "")
+BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8f", "")
+BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2dV2d", "")
+BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "")
+BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "")
+BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "")
+
#undef BUILTIN
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index 203fb451e38b..e2f93e02c525 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -43,8 +43,9 @@ def Named : Decl<1>;
def ParmVar : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Var>;
def Template : DDecl<Named, 1>;
- def FunctionTemplate : DDecl<Template>;
- def ClassTemplate : DDecl<Template>;
+ def RedeclarableTemplate : DDecl<Template, 1>;
+ def FunctionTemplate : DDecl<RedeclarableTemplate>;
+ def ClassTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>;
def Using : DDecl<Named>;
def UsingShadow : DDecl<Named>;
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 1fe0d8154cd4..37d26947c335 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h"
#include <string>
@@ -95,23 +96,20 @@ namespace clang {
/// compilation.
class FixItHint {
public:
- /// \brief Code that should be removed to correct the error.
+ /// \brief Code that should be replaced to correct the error. Empty for an
+ /// insertion hint.
CharSourceRange RemoveRange;
- /// \brief The location at which we should insert code to correct
- /// the error.
- SourceLocation InsertionLoc;
-
/// \brief The actual code to insert at the insertion location, as a
/// string.
std::string CodeToInsert;
/// \brief Empty code modification hint, indicating that no code
/// modification is known.
- FixItHint() : RemoveRange(), InsertionLoc() { }
+ FixItHint() : RemoveRange() { }
bool isNull() const {
- return !RemoveRange.isValid() && !InsertionLoc.isValid();
+ return !RemoveRange.isValid();
}
/// \brief Create a code modification hint that inserts the given
@@ -119,7 +117,8 @@ public:
static FixItHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) {
FixItHint Hint;
- Hint.InsertionLoc = InsertionLoc;
+ Hint.RemoveRange =
+ CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
Hint.CodeToInsert = Code;
return Hint;
}
@@ -141,7 +140,6 @@ public:
llvm::StringRef Code) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
- Hint.InsertionLoc = RemoveRange.getBegin();
Hint.CodeToInsert = Code;
return Hint;
}
@@ -205,16 +203,32 @@ private:
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
- DiagnosticClient *Client;
-
+ llvm::OwningPtr<DiagnosticClient> Client;
+
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into four bits per diagnostic. The low three bits are the mapping
/// (an instance of diag::Mapping), or zero if unset. The high bit is set
/// when the mapping was established as a user mapping. If the high bit is
/// clear, then the low bits are set to the default value, and should be
/// mapped with -pedantic, -Werror, etc.
+ class DiagMappings {
+ unsigned char Values[diag::DIAG_UPPER_LIMIT/2];
+
+ public:
+ DiagMappings() {
+ memset(Values, 0, diag::DIAG_UPPER_LIMIT/2);
+ }
+
+ void setMapping(diag::kind Diag, unsigned Map) {
+ size_t Shift = (Diag & 1)*4;
+ Values[Diag/2] = (Values[Diag/2] & ~(15 << Shift)) | (Map << Shift);
+ }
+
+ diag::Mapping getMapping(diag::kind Diag) const {
+ return (diag::Mapping)((Values[Diag/2] >> (Diag & 1)*4) & 15);
+ }
+ };
- typedef std::vector<unsigned char> DiagMappings;
mutable std::vector<DiagMappings> DiagMappingsStack;
/// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
@@ -272,8 +286,12 @@ public:
// Diagnostic characterization methods, used by a client to customize how
//
- DiagnosticClient *getClient() { return Client; }
- const DiagnosticClient *getClient() const { return Client; }
+ DiagnosticClient *getClient() { return Client.get(); }
+ const DiagnosticClient *getClient() const { return Client.get(); }
+
+ /// \brief Return the current diagnostic client along with ownership of that
+ /// client.
+ DiagnosticClient *takeClient() { return Client.take(); }
/// pushMappings - Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
@@ -285,7 +303,10 @@ public:
/// stack.
bool popMappings();
- void setClient(DiagnosticClient* client) { Client = client; }
+ /// \brief Set the diagnostic client associated with this diagnostic object.
+ ///
+ /// The diagnostic object takes ownership of \c client.
+ void setClient(DiagnosticClient* client) { Client.reset(client); }
/// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit.
@@ -382,6 +403,10 @@ public:
unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; }
unsigned getNumWarnings() const { return NumWarnings; }
+ void setNumWarnings(unsigned NumWarnings) {
+ this->NumWarnings = NumWarnings;
+ }
+
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
@@ -404,6 +429,10 @@ public:
ArgToStringCookie = Cookie;
}
+ /// \brief Reset the state of the diagnostic object to its initial
+ /// configuration.
+ void Reset();
+
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
@@ -535,17 +564,13 @@ private:
/// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized.
diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const {
- const DiagMappings &currentMappings = DiagMappingsStack.back();
- return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
+ return DiagMappingsStack.back().getMapping(Diag);
}
void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
bool isUser) const {
if (isUser) Map |= 8; // Set the high bit for user mappings.
- unsigned char &Slot = DiagMappingsStack.back()[DiagId/2];
- unsigned Shift = (DiagId & 1)*4;
- Slot &= ~(15 << Shift);
- Slot |= Map << Shift;
+ DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map);
}
/// getDiagnosticLevel - This is an internal implementation helper used when
@@ -927,7 +952,9 @@ public:
Diagnostic::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
-
+
+ void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
+
typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_iterator range_begin() const { return Ranges.begin(); }
range_iterator range_end() const { return Ranges.end(); }
diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td
index 4b0bf57bef63..98ea9d4bd6d9 100644
--- a/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/include/clang/Basic/DiagnosticCommonKinds.td
@@ -41,7 +41,8 @@ def err_expected_colon_after_setter_name : Error<
"must end with ':'">;
// Parse && Sema
-def ext_no_declarators : ExtWarn<"declaration does not declare anything">;
+def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
+ InGroup<MissingDeclarations>;
def err_param_redefinition : Error<"redefinition of parameter %0">;
def err_invalid_storage_class_in_func_decl : Error<
"invalid storage class specifier in function declarator">;
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index f4a31cc5766c..34cd6004edee 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -68,6 +68,8 @@ def err_drv_invalid_gcc_output_type : Error<
"invalid output type '%0' for use with gcc tool">;
def err_drv_cc_print_options_failure : Error<
"unable to open CC_PRINT_OPTIONS file: %0">;
+def err_drv_preamble_format : Error<
+ "incorrect format for -preamble-bytes=N,END">;
def warn_drv_input_file_unused : Warning<
"%0: '%1' input unused when '%2' is present">;
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index 989ec38d2950..7c74bf458e58 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -99,7 +99,7 @@ def warn_fixit_no_changes : Note<
def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal;
// PCH reader
-def err_relocatable_without_without_isysroot : Error<
+def err_relocatable_without_isysroot : Error<
"must specify system root with -isysroot when building a relocatable "
"PCH file">;
def warn_pch_target_triple : Error<
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 49077513c137..d4b7f1f55743 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -25,15 +25,19 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def : DiagGroup<"attributes">;
def : DiagGroup<"bad-function-cast">;
def BoolConversions : DiagGroup<"bool-conversions">;
-def : DiagGroup<"c++-compat">;
-def : DiagGroup<"cast-align">;
+def CXXCompat: DiagGroup<"c++-compat">;
+def CastAlign : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
def : DiagGroup<"ctor-dtor-privacy">;
def : DiagGroup<"declaration-after-statement">;
def GNUDesignator : DiagGroup<"gnu-designator">;
-def Deprecated : DiagGroup<"deprecated">;
+
+def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
+ DiagCategory<"Deprecations">;
+
def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">;
@@ -46,7 +50,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXXHexFloats : DiagGroup<"c++-hex-floats">;
def : DiagGroup<"c++0x-compat", [CXXHexFloats]>;
+def : DiagGroup<"effc++">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def GlobalConstructors : DiagGroup<"global-constructors">;
def : DiagGroup<"idiomatic-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
@@ -55,9 +61,10 @@ def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
def : DiagGroup<"invalid-pch">;
def LiteralRange : DiagGroup<"literal-range">;
+def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
def : DiagGroup<"main">;
def MissingBraces : DiagGroup<"missing-braces">;
-def : DiagGroup<"missing-declarations">;
+def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
def : DiagGroup<"missing-include-dirs">;
def : DiagGroup<"missing-noreturn">;
@@ -71,8 +78,11 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
def : DiagGroup<"non-virtual-dtor">;
+def : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
+def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">;
+def OverlengthStrings : DiagGroup<"overlength-strings">;
def : DiagGroup<"overloaded-virtual">;
def : DiagGroup<"packed">;
def PointerArith : DiagGroup<"pointer-arith">;
@@ -88,6 +98,8 @@ def Shadow : DiagGroup<"shadow">;
def : DiagGroup<"shorten-64-to-32">;
def : DiagGroup<"sign-promo">;
def SignCompare : DiagGroup<"sign-compare">;
+def : DiagGroup<"stack-protector">;
+def : DiagGroup<"switch-default">;
def : DiagGroup<"synth">;
// Preprocessor warnings.
@@ -110,7 +122,7 @@ def : DiagGroup<"strict-overflow">;
def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
def : DiagGroup<"strict-prototypes">;
-def : DiagGroup<"strict-selector-match">;
+def StrictSelector : DiagGroup<"strict-selector-match">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch", [SwitchEnum]>;
def Trigraphs : DiagGroup<"trigraphs">;
@@ -119,9 +131,11 @@ def : DiagGroup<"type-limits">;
def Uninitialized : DiagGroup<"uninitialized">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnusedFunction : DiagGroup<"unused-function">;
+def UnusedMemberFunction : DiagGroup<"unused-member-function">;
def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
@@ -129,6 +143,8 @@ def UnusedVariable : DiagGroup<"unused-variable">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
+def Selector : DiagGroup<"selector">;
+def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def : DiagGroup<"variadic-macros">;
@@ -154,6 +170,7 @@ def Conversion : DiagGroup<"conversion",
def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel,
// UnusedParameter, (matches GCC's behavior)
+ // UnusedMemberFunction, (clean-up llvm before enabling)
UnusedValue, UnusedVariable]>,
DiagCategory<"Unused Entity Issue">;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 21c93e7e8fa2..dcb05c8fcd45 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -51,6 +51,7 @@ def err_empty_character : Error<"empty character constant">;
def err_unterminated_block_comment : Error<"unterminated /* comment">;
def err_invalid_character_to_charify : Error<
"invalid argument to convert to character">;
+def err_unterminated___pragma : Error<"missing terminating ')' character">;
def err_conflict_marker : Error<"version control conflict marker in file">;
@@ -94,7 +95,10 @@ def ext_binary_literal : Extension<
def err_pascal_string_too_long : Error<"Pascal string is too long">;
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">;
-
+def ext_string_too_long : Extension<"string literal of length %0 exceeds "
+ "maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
+ "support">, InGroup<OverlengthStrings>;
+
//===----------------------------------------------------------------------===//
// PTH Diagnostics
//===----------------------------------------------------------------------===//
@@ -227,6 +231,10 @@ def err_pragma_comment_malformed : Error<
"pragma comment requires parenthesized identifier and optional string">;
def err_pragma_message_malformed : Error<
"pragma message requires parenthesized string">;
+def err_pragma_push_pop_macro_malformed : Error<
+ "pragma %0 requires a parenthesized string">;
+def warn_pragma_pop_macro_no_push : Warning<
+ "pragma pop_macro could not pop '%0', no matching push_macro">;
def warn_pragma_message : Warning<"%0">;
def warn_pragma_ignored : Warning<"unknown pragma ignored">,
InGroup<UnknownPragmas>, DefaultIgnore;
@@ -241,15 +249,11 @@ def ext_stdc_pragma_syntax_eom :
def warn_stdc_fenv_access_not_supported :
Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_gcc_invalid :
- ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or"
- " 'fatal'">,
- InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_clang_invalid :
- ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'"
+def warn_pragma_diagnostic_invalid :
+ ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
" 'push', or 'pop'">,
InGroup<UnknownPragmas>;
-def warn_pragma_diagnostic_clang_cannot_ppp :
+def warn_pragma_diagnostic_cannot_pop :
ExtWarn<"pragma diagnostic pop could not pop, no matching push">,
InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_invalid_option :
@@ -261,6 +265,9 @@ def warn_pragma_diagnostic_invalid_token :
def warn_pragma_diagnostic_unknown_warning :
ExtWarn<"unknown warning group '%0', ignored">,
InGroup<UnknownPragmas>;
+// - #pragma __debug
+def warn_pragma_debug_unexpected_command : Warning<
+ "unexpected debug command '%0'">;
def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
@@ -277,6 +284,9 @@ def err_too_few_args_in_macro_invoc : Error<
"too few arguments provided to function-like macro invocation">;
def err_pp_bad_paste : Error<
"pasting formed '%0', an invalid preprocessing token">;
+def err_pp_bad_paste_ms : Warning<
+ "pasting formed '%0', an invalid preprocessing token">, DefaultError,
+ InGroup<DiagGroup<"invalid-token-paste">>;
def err_pp_operator_used_as_macro_name : Error<
"C++ operator '%0' cannot be used as a macro name">;
def err_pp_illegal_floating_literal : Error<
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index ca761f9bf5e9..646fd0d1bfb6 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -35,8 +35,9 @@ def ext_integer_complex : Extension<
"complex integer types are an extension">;
def ext_thread_before : Extension<"'__thread' before 'static'">;
-def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">;
-
+def ext_empty_struct_union : Extension<"empty %select{struct|union}0 "
+ "(accepted as an extension) has size 0 in C, size 1 in C++">,
+ InGroup<CXXCompat>;
def error_empty_enum : Error<"use of empty enum">;
def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
def err_invalid_short_spec : Error<"'short %0' is invalid">;
@@ -102,6 +103,8 @@ def err_expected_member_name_or_semi : Error<
"expected member name or ';' after declaration specifiers">;
def err_function_declared_typedef : Error<
"function definition declared 'typedef'">;
+def err_iboutletcollection_builtintype : Error<
+ "type argument of iboutletcollection attribute cannot be a builtin type">;
def err_expected_fn_body : Error<
"expected function body after function declarator">;
def err_expected_method_body : Error<"expected method body">;
@@ -125,6 +128,7 @@ def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">;
def err_unexpected_namespace_attributes_alias : Error<
"attributes can not be specified on namespace alias">;
+def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
def err_namespace_nonnamespace_scope : Error<
"namespaces can only be defined in global or namespace scope">;
def err_expected_semi_after_attribute_list : Error<
@@ -150,6 +154,8 @@ def err_illegal_decl_reference_to_reference : Error<
"%0 declared as a reference to a reference">;
def err_rvalue_reference : Error<
"rvalue references are only allowed in C++0x">;
+def ext_inline_namespace : Extension<
+ "inline namespaces are a C++0x feature">;
def err_argument_required_after_attribute : Error<
"argument required after attribute">;
def err_missing_param : Error<"expected parameter declarator">;
@@ -270,6 +276,8 @@ def err_destructor_tilde_identifier : Error<
"expected a class name after '~' to name a destructor">;
def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
+def err_default_arg_unparsed : Error<
+ "unexpected end of default argument expression">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@@ -373,10 +381,10 @@ def warn_pragma_extra_tokens_at_eol : Warning<
// - #pragma options
def warn_pragma_options_expected_align : Warning<
"expected 'align' following '#pragma options' - ignored">;
-def warn_pragma_options_expected_equal : Warning<
- "expected '=' following '#pragma options align' - ignored">;
-def warn_pragma_options_invalid_option : Warning<
- "invalid alignment option in '#pragma options align' - ignored">;
+def warn_pragma_align_expected_equal : Warning<
+ "expected '=' following '#pragma %select{align|options align}0' - ignored">;
+def warn_pragma_align_invalid_option : Warning<
+ "invalid alignment option in '#pragma %select{align|options align}0' - ignored">;
// - #pragma pack
def warn_pragma_pack_invalid_action : Warning<
"unknown action for '#pragma pack' - ignored">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 01a37fb6f2c6..a25b2a341fc5 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -104,6 +104,8 @@ def warn_decl_in_param_list : Warning<
"declaration of %0 will not be visible outside of this function">;
def warn_unused_function : Warning<"unused function %0">,
InGroup<UnusedFunction>, DefaultIgnore;
+def warn_unused_member_function : Warning<"unused member function %0">,
+ InGroup<UnusedMemberFunction>, DefaultIgnore;
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
@@ -168,6 +170,13 @@ def warn_access_decl_deprecated : Warning<
"access declarations are deprecated; use using declarations instead">,
InGroup<Deprecated>;
+def warn_global_constructor : Warning<
+ "declaration requires a global constructor">,
+ InGroup<GlobalConstructors>, DefaultIgnore;
+def warn_global_destructor : Warning<
+ "declaration requires a global destructor">,
+ InGroup<GlobalConstructors>, DefaultIgnore;
+
def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">;
def err_thread_non_global : Error<
@@ -227,7 +236,8 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"platform-specific data}0) must be of type %1">;
/// parser diagnostics
-def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">;
+def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">,
+ InGroup<MissingDeclarations>;
def err_typedef_not_identifier : Error<"typedef name must be an identifier">;
def err_statically_allocated_object : Error<
"interface type cannot be statically allocated">;
@@ -322,6 +332,8 @@ def warn_implements_nscopying : Warning<
"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
+def warn_strict_multiple_method_decl : Warning<
+ "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">;
def note_declared_at : Note<"declared here">;
@@ -399,6 +411,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
+def warn_unimplemented_selector: Warning<
+ "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"method in protocol not implemented">, InGroup<Protocol>;
@@ -407,6 +421,10 @@ def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">;
def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
+def err_inline_namespace_mismatch : Error<
+ "%select{|non-}0inline namespace "
+ "cannot be reopened as %select{non-|}0inline">;
+
def err_unexpected_friend : Error<
"friends can only be classes or functions">;
def ext_enum_friend : ExtWarn<
@@ -549,6 +567,8 @@ def note_access_natural : Note<
def note_access_constrained_by_path : Note<
"constrained by %select{|implicitly }1%select{private|protected}0"
" inheritance here">;
+def note_access_protected_restricted : Note<
+ "object type %select{|%1 }0must derive from context type %2">;
// C++ name lookup
def err_incomplete_nested_name_spec : Error<
@@ -621,9 +641,9 @@ 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">;
+def err_illegal_union_or_anon_struct_member : Error<
+ "%select{anonymous struct|union}0 member %1 has a non-trivial "
+ "%select{constructor|copy constructor|copy assignment operator|destructor}2">;
def note_nontrivial_has_virtual : Note<
"because type %0 has a virtual %select{member function|base class}1">;
def note_nontrivial_has_nontrivial : Note<
@@ -814,6 +834,11 @@ def err_attributes_are_not_compatible : Error<
"%0 and %1 attributes are not compatible">;
def err_attribute_wrong_number_arguments : Error<
"attribute requires %0 argument(s)">;
+def err_iboutletcollection_type : Error<
+ "invalid type %0 as argument of iboutletcollection attribute">;
+def err_iboutletcollection_object_type : Error<
+ "%select{ivar|property}1 with iboutletcollection attribute must "
+ "have object type (invalid %0)">;
def err_attribute_missing_parameter_name : Error<
"attribute requires unquoted parameter">;
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
@@ -833,8 +858,10 @@ def err_attribute_argument_out_of_bounds : Error<
"'%0' attribute parameter %1 is out of bounds">;
def err_attribute_requires_objc_interface : Error<
"attribute may only be applied to an Objective-C interface">;
-def err_nonnull_pointers_only : Error<
+def warn_nonnull_pointers_only : Warning<
"nonnull attribute only applies to pointer arguments">;
+def err_ownership_type : Error<
+ "%0 attribute only applies to %1 arguments">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_requires_variadic : Error<
@@ -957,6 +984,10 @@ def warn_impcast_integer_64_32 : Warning<
"implicit conversion loses integer precision: %0 to %1">,
InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
+def warn_cast_align : Warning<
+ "cast from %0 to %1 increases required alignment from %2 to %3">,
+ InGroup<CastAlign>, 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<
@@ -976,7 +1007,7 @@ def warn_transparent_union_attribute_zero_fields : Warning<
"transparent_union attribute ignored">;
def warn_attribute_type_not_supported : Warning<
"'%0' attribute argument not supported: %1">;
-def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">;
+def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">;
def err_unknown_machine_mode : Error<"unknown machine mode %0">;
def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
def err_mode_not_primitive : Error<
@@ -1139,6 +1170,9 @@ def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
def note_ovl_candidate_instantiation_depth : Note<
"candidate template ignored: substitution exceeded maximum template "
"instantiation depth">;
+def note_ovl_candidate_underqualified : Note<
+ "candidate template ignored: can't deduce a type for %0 which would "
+ "make %2 equal %1">;
def note_ovl_candidate_substitution_failure : Note<
"candidate template ignored: substitution failure %0">;
@@ -1195,7 +1229,7 @@ def note_ovl_candidate_bad_cvr_this : Note<"candidate "
"%select{|function|||function||||"
"function (the implicit copy assignment operator)}0 not viable: "
"'this' argument has type %2, but method is not marked "
- "%select{const|volatile|const or volatile|restrict|const or restrict|"
+ "%select{const|restrict|const or restrict|volatile|const or volatile|"
"volatile or restrict|const, volatile, or restrict}3">;
def note_ovl_candidate_bad_cvr : Note<"candidate "
"%select{function|function|constructor|"
@@ -1204,7 +1238,7 @@ def note_ovl_candidate_bad_cvr : Note<"candidate "
"constructor (the implicit copy constructor)|"
"function (the implicit copy assignment operator)}0%1 not viable: "
"%ordinal4 argument (%2) would lose "
- "%select{const|volatile|const and volatile|restrict|const and restrict|"
+ "%select{const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}3 qualifier"
"%select{||s||s|s|s}3">;
def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
@@ -1258,6 +1292,8 @@ def err_addr_ovl_ambiguous : Error<
"address of overloaded function %0 is ambiguous">;
def err_addr_ovl_not_func_ptrref : Error<
"address of overloaded function %0 cannot be converted to type %1">;
+def err_addr_ovl_no_qualifier : Error<
+ "can't form member pointer of type %0 without '&' and class name">;
// C++ Template Declarations
def err_template_param_shadow : Error<
@@ -1335,9 +1371,10 @@ def err_template_arg_nontype_ambig : Error<
"template argument for non-type template parameter is treated as type %0">;
def err_template_arg_must_be_template : Error<
"template argument for template template parameter must be a class template">;
-def err_template_arg_local_type : Error<"template argument uses local type %0">;
-def err_template_arg_unnamed_type : Error<
- "template argument uses unnamed type">;
+def ext_template_arg_local_type : ExtWarn<
+ "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
+def ext_template_arg_unnamed_type : ExtWarn<
+ "template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>;
def note_template_unnamed_type_here : Note<
"unnamed type used in template argument was declared here">;
def err_template_arg_overload_type : Error<
@@ -1683,9 +1720,8 @@ def note_dependent_var_use : Note<"must qualify identifier to find this "
"declaration in dependent base class">;
def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">,
- InGroup<DiagGroup<"deprecated-declarations">>;
-def warn_unavailable : Warning<"%0 is unavailable">,
- InGroup<DiagGroup<"unavailable-declarations">>;
+ InGroup<DeprecatedDeclarations>;
+def err_unavailable : Error<"%0 is unavailable">;
def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning<
@@ -1706,6 +1742,8 @@ def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
+def err_inline_declaration_block_scope : Error<
+ "inline declaration of %0 not allowed in block scope">;
def err_static_non_static : Error<
"static declaration of %0 follows non-static declaration">;
def err_non_static_static : Error<
@@ -1768,6 +1806,8 @@ def err_typecheck_field_variable_size : Error<
"extension will never be supported">;
def err_vm_func_decl : Error<
"function declaration cannot have variably modified type">;
+def err_array_too_large : Error<
+ "array is too large (%0 elements)">;
def err_typecheck_negative_array_size : Error<"array size is negative">;
def warn_typecheck_function_qualifiers : Warning<
@@ -1809,7 +1849,7 @@ def warn_missing_field_initializers : Warning<
InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">;
-def err_many_braces_around_scalar_init : Error<
+def warn_many_braces_around_scalar_init : ExtWarn<
"too many braces around scalar initializer">;
def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
def err_illegal_initializer : Error<
@@ -1844,9 +1884,9 @@ def warn_missing_braces : Warning<
def err_redefinition_of_label : Error<"redefinition of label '%0'">;
def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
-def err_goto_into_protected_scope : Error<"illegal goto into protected scope">;
+def err_goto_into_protected_scope : Error<"goto into protected scope">;
def err_switch_into_protected_scope : Error<
- "illegal switch case into protected scope">;
+ "switch case is in protected scope">;
def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">;
def warn_indirect_goto_in_protected_scope : Warning<
@@ -1990,7 +2030,7 @@ def note_precedence_bitwise_silence : Note<
def warn_logical_instead_of_bitwise : Warning<
"use of logical %0 with constant operand; switch to bitwise %1 or "
- "remove constant">, InGroup<DiagGroup<"logical-bitwise-confusion">>;
+ "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in "
@@ -2048,8 +2088,9 @@ def err_qualified_typedef_declarator : Error<
"typedef declarator cannot be qualified">;
def err_qualified_param_declarator : Error<
"parameter declarator cannot be qualified">;
-def err_out_of_line_declaration : Error<
- "out-of-line declaration of a member must be a definition">;
+def ext_out_of_line_declaration : ExtWarn<
+ "out-of-line declaration of a member must be a definition">,
+ InGroup<OutOfLineDeclaration>, DefaultError;
def note_member_def_close_match : Note<"member declaration nearly matches">;
def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">;
@@ -2093,7 +2134,11 @@ def err_typecheck_address_of : Error<"address of %0 requested">;
def ext_typecheck_addrof_void : Extension<
"ISO C forbids taking the address of an expression of type 'void'">;
def err_unqualified_pointer_member_function : Error<
- "must explicitly qualify member function %0 when taking its address">;
+ "must explicitly qualify name of member function when taking its address">;
+def err_invalid_form_pointer_member_function : Error<
+ "cannot create a non-constant pointer to member function">;
+def err_parens_pointer_member_function : Error<
+ "cannot parenthesize the name of a method when forming a member pointer">;
def err_typecheck_invalid_lvalue_addrof : Error<
"address expression must be an lvalue or a function designator">;
def ext_typecheck_addrof_class_temporary : ExtWarn<
@@ -2110,8 +2155,8 @@ def warn_indirection_through_null : Warning<
def note_indirection_through_null : Note<
"consider using __builtin_trap() or qualifying pointer with 'volatile'">;
-def err_indirection_requires_nonfragile_object : Error<
- "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">;
+def err_assignment_requires_nonfragile_object : Error<
+ "cannot assign to class object in non-fragile ABI (%0 invalid)">;
def err_direct_interface_unsupported : Error<
"indirection to an interface is not supported (%0 invalid)">;
def err_typecheck_invalid_operands : Error<
@@ -2183,10 +2228,10 @@ def err_builtin_direct_init_more_than_one_arg : Error<
"initializer of a builtin type can only take one argument">;
def err_value_init_for_array_type : Error<
"array types cannot be value-initialized">;
-def warn_printf_nonliteral_noargs : Warning<
+def warn_format_nonliteral_noargs : Warning<
"format string is not a string literal (potentially insecure)">,
InGroup<FormatSecurity>;
-def warn_printf_nonliteral : Warning<
+def warn_format_nonliteral : Warning<
"format string is not a string literal">,
InGroup<FormatNonLiteral>, DefaultIgnore;
@@ -2215,7 +2260,7 @@ def ext_integer_complement_complex : Extension<
def error_nosetter_property_assignment : Error<
"setter method is needed to assign to object using property" " assignment syntax">;
def error_no_subobject_property_setting : Error<
- "expression is not assignable using property assignment syntax">;
+ "expression is not assignable">;
def ext_freestanding_complex : Extension<
"complex numbers are an extension in a freestanding C99 implementation">;
@@ -2263,7 +2308,13 @@ def warn_register_objc_catch_parm : Warning<
"'register' storage specifier on @catch parameter will be ignored">;
def err_qualified_objc_catch_parm : Error<
"@catch parameter declarator cannot be qualified">;
-
+def err_objc_pointer_cxx_catch_gnu : Error<
+ "can't catch Objective C exceptions in C++ in the GNU runtime">;
+def err_objc_pointer_cxx_catch_fragile : Error<
+ "can't catch Objective C exceptions in C++ in the non-unified "
+ "exception model">;
+def err_objc_object_catch : Error<
+ "can't catch an Objective C object by value">;
def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - "
@@ -2313,6 +2364,9 @@ def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error<
"cannot cast from type %1 to member pointer type %2">;
+def err_bad_cxx_cast_member_pointer_size : Error<
+ "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer "
+ "type %1 to member pointer type %2 of different size">;
def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
// These messages don't adhere to the pattern.
@@ -2378,8 +2432,12 @@ 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_delete_incomplete_class_type : Warning<
+ "deleting incomplete class type %0; no conversions to pointer type">;
def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">;
+def err_ambiguous_suitable_delete_member_function_found : Error<
+ "multiple suitable %0 functions in %1">;
def note_member_declared_here : Note<
"member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">;
@@ -2486,8 +2544,11 @@ def note_condition_assign_to_comparison : Note<
def note_condition_assign_silence : Note<
"place parentheses around the assignment to silence this warning">;
-def warn_value_always_zero : Warning<
- "%0 is always %select{zero|false|NULL}1 in this context">;
+def warn_ivar_variable_conflict : Warning<
+ "when default property synthesis is on, "
+ "%0 lookup will access property ivar instead of global variable">,
+ InGroup<NonfragileAbi2>;
+def note_global_declared_at : Note<"global variable declared here">;
// assignment related diagnostics (also for argument passing, returning, etc).
// In most of these diagnostics the %2 is a value from the
@@ -2648,6 +2709,8 @@ def err_typecheck_cond_expect_scalar : Error<
"used type %0 where arithmetic or pointer type is required">;
def ext_typecheck_cond_one_void : Extension<
"C99 forbids conditional expressions with only one void side">;
+def err_typecheck_cast_to_incomplete : Error<
+ "cast to incomplete type %0">;
def ext_typecheck_cast_nonscalar : Extension<
"C99 forbids casting nonscalar type %0 to the same type">;
def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">;
@@ -2885,7 +2948,7 @@ def err_operator_new_default_arg: Error<
def err_operator_delete_dependent_param_type : Error<
"%0 cannot take a dependent type as first parameter; use %1 instead">;
def err_operator_delete_param_type : Error<
- "%0 takes type %1 as first parameter">;
+ "first parameter of %0 must have type %1">;
// C++ literal operators
def err_literal_operator_outside_namespace : Error<
@@ -2932,33 +2995,36 @@ def warn_printf_insufficient_data_args : Warning<
"more '%%' conversions than data arguments">, InGroup<Format>;
def warn_printf_data_arg_not_used : Warning<
"data argument not used by format string">, InGroup<FormatExtraArgs>;
-def warn_printf_invalid_conversion : Warning<
+def warn_format_invalid_conversion : Warning<
"invalid conversion specifier '%0'">, InGroup<Format>;
def warn_printf_incomplete_specifier : Warning<
"incomplete format specifier">, InGroup<Format>;
-def warn_printf_missing_format_string : Warning<
+def warn_missing_format_string : Warning<
"format string missing">, InGroup<Format>;
+def warn_scanf_nonzero_width : Warning<
+ "zero field width in scanf format string is unused">,
+ InGroup<Format>;
def warn_printf_conversion_argument_type_mismatch : Warning<
"conversion specifies type %0 but the argument has type %1">,
InGroup<Format>;
def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">,
InGroup<Format>;
-def warn_printf_zero_positional_specifier : Warning<
+def warn_format_zero_positional_specifier : Warning<
"position arguments in format strings start counting at 1 (not 0)">,
InGroup<Format>;
-def warn_printf_invalid_positional_specifier : Warning<
+def warn_format_invalid_positional_specifier : Warning<
"invalid position specified for %select{field width|field precision}0">,
InGroup<Format>;
-def warn_printf_mix_positional_nonpositional_args : Warning<
+def warn_format_mix_positional_nonpositional_args : Warning<
"cannot mix positional and non-positional arguments in format string">,
InGroup<Format>;
def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">,
InGroup<NonNull>;
-def warn_printf_empty_format_string : Warning<
+def warn_empty_format_string : Warning<
"format string is empty">, InGroup<FormatZeroLength>;
-def warn_printf_format_string_is_wide_literal : Warning<
+def warn_format_string_is_wide_literal : Warning<
"format string should not be a wide string">, InGroup<Format>;
def warn_printf_format_string_contains_null_char : Warning<
"format string contains '\\0' within the string body">, InGroup<Format>;
@@ -2973,12 +3039,15 @@ def warn_printf_nonsensical_optional_amount: Warning<
def warn_printf_nonsensical_flag: Warning<
"flag '%0' results in undefined behavior with '%1' conversion specifier">,
InGroup<Format>;
-def warn_printf_nonsensical_length: Warning<
+def warn_format_nonsensical_length: Warning<
"length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">,
InGroup<Format>;
def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>;
+def warn_scanf_scanlist_incomplete : Warning<
+ "no closing ']' for '%%[' in scanf format string">,
+ InGroup<Format>;
// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr : Warning<
@@ -2995,7 +3064,8 @@ def err_ret_local_block : Error<
// should result in a warning, since these always evaluate to a constant.
// Array comparisons have similar warnings
def warn_comparison_always : Warning<
- "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">;
+ "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
+ InGroup<DiagGroup<"tautological-compare">>;
def warn_stringcompare : Warning<
"result of comparison against %select{a string literal|@encode}0 is "
@@ -3127,6 +3197,8 @@ def err_selector_element_type : Error<
"selector element type %0 is not a valid object">;
def err_collection_expr_type : Error<
"collection expression type %0 is not a valid object">;
+def warn_collection_expr_type : Warning<
+ "collection expression type %0 may not respond to %1">;
def err_invalid_conversion_between_ext_vectors : Error<
"invalid conversion between ext-vector type %0 and %1">;
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index 6b8bcdc52f6f..24fe086a79e9 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -59,7 +59,11 @@ class IdentifierInfo {
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
- // 9 bits left in 32-bit word.
+ bool IsFromAST : 1; // True if identfier first appeared in an AST
+ // file and wasn't modified since.
+ bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
+ // called.
+ // 7 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry;
@@ -125,13 +129,28 @@ public:
NeedsHandleIdentifier = 1;
else
RecomputeNeedsHandleIdentifier();
+ IsFromAST = false;
}
- /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
+ /// getTokenID - If this is a source-language token (e.g. 'for'), this API
/// can be used to cause the lexer to map identifiers to source-language
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
- void setTokenID(tok::TokenKind ID) { TokenID = ID; }
+
+ /// \brief True if RevertTokenIDToIdentifier() was called.
+ bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
+
+ /// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
+ /// compatibility.
+ ///
+ /// TokenID is normally read-only but there are 2 instances where we revert it
+ /// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
+ /// using this method so we can inform serialization about it.
+ void RevertTokenIDToIdentifier() {
+ assert(TokenID != tok::identifier && "Already at tok::identifier");
+ TokenID = tok::identifier;
+ RevertedTokenID = true;
+ }
/// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
/// For example, "define" will return tok::pp_define.
@@ -186,6 +205,7 @@ public:
NeedsHandleIdentifier = 1;
else
RecomputeNeedsHandleIdentifier();
+ IsFromAST = false;
}
/// isPoisoned - Return true if this token has been poisoned.
@@ -213,6 +233,12 @@ public:
/// know that HandleIdentifier will not affect the token.
bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
+ /// isFromAST - Return true if the identifier in its current state was loaded
+ /// from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
private:
/// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
/// several special (but rare) things to identifiers of various sorts. For
@@ -313,6 +339,12 @@ public:
return *II;
}
+ IdentifierInfo &get(llvm::StringRef Name, tok::TokenKind TokenCode) {
+ IdentifierInfo &II = get(Name);
+ II.TokenID = TokenCode;
+ return II;
+ }
+
IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
return get(llvm::StringRef(NameStart, NameEnd-NameStart));
}
@@ -321,35 +353,33 @@ public:
return get(llvm::StringRef(Name, NameLen));
}
- /// \brief Creates a new IdentifierInfo from the given string.
+ /// \brief Gets an IdentifierInfo for the given name without consulting
+ /// external sources.
///
- /// This is a lower-level version of get() that requires that this
- /// identifier not be known previously and that does not consult an
- /// external source for identifiers. In particular, external
- /// identifier sources can use this routine to build IdentifierInfo
- /// nodes and then introduce additional information about those
- /// identifiers.
- IdentifierInfo &CreateIdentifierInfo(const char *NameStart,
- const char *NameEnd) {
+ /// This is a version of get() meant for external sources that want to
+ /// introduce or modify an identifier. If they called get(), they would
+ /// likely end up in a recursion.
+ IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) {
llvm::StringMapEntry<IdentifierInfo*> &Entry =
HashTable.GetOrCreateValue(NameStart, NameEnd);
IdentifierInfo *II = Entry.getValue();
- assert(!II && "IdentifierInfo already exists");
+ if (!II) {
- // Lookups failed, make a new IdentifierInfo.
- void *Mem = getAllocator().Allocate<IdentifierInfo>();
- II = new (Mem) IdentifierInfo();
- Entry.setValue(II);
+ // Lookups failed, make a new IdentifierInfo.
+ void *Mem = getAllocator().Allocate<IdentifierInfo>();
+ II = new (Mem) IdentifierInfo();
+ Entry.setValue(II);
- // Make sure getName() knows how to find the IdentifierInfo
- // contents.
- II->Entry = &Entry;
+ // Make sure getName() knows how to find the IdentifierInfo
+ // contents.
+ II->Entry = &Entry;
+ }
return *II;
}
- IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) {
- return CreateIdentifierInfo(Name.begin(), Name.end());
+ IdentifierInfo &getOwn(llvm::StringRef Name) {
+ return getOwn(Name.begin(), Name.end());
}
typedef HashTableTy::const_iterator iterator;
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index bbcceb70ac91..5bd0d04a4eea 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -34,6 +34,7 @@ public:
unsigned HexFloats : 1; // C99 Hexadecimal float constants.
unsigned C99 : 1; // C99 Support
unsigned Microsoft : 1; // Microsoft extensions.
+ unsigned Borland : 1; // Borland extensions.
unsigned CPlusPlus : 1; // C++ Support
unsigned CPlusPlus0x : 1; // C++0x Support
unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords.
@@ -140,7 +141,7 @@ public:
HexFloats = 0;
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
- C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0;
+ C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
NeXTRuntime = 1;
diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h
index de0de348d351..01b6c790428a 100644
--- a/include/clang/Basic/Linkage.h
+++ b/include/clang/Basic/Linkage.h
@@ -41,6 +41,17 @@ enum Linkage {
ExternalLinkage
};
+/// \brief A more specific kind of linkage. This is relevant to CodeGen and
+/// AST file reading.
+enum GVALinkage {
+ GVA_Internal,
+ GVA_C99Inline,
+ GVA_CXXInline,
+ GVA_StrongExternal,
+ GVA_TemplateInstantiation,
+ GVA_ExplicitTemplateInstantiation
+};
+
/// \brief Determine whether the given linkage is semantically
/// external.
inline bool isExternalLinkage(Linkage L) {
diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile
index 7db3e2982af4..bc64f6aab555 100644
--- a/include/clang/Basic/Makefile
+++ b/include/clang/Basic/Makefile
@@ -16,6 +16,7 @@ INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td)
# Compute the Clang version from the LLVM version, unless specified explicitly.
ifndef CLANG_VERSION
CLANG_VERSION := $(subst svn,,$(LLVMVersion))
+CLANG_VERSION := $(subst rc,,$(CLANG_VERSION))
endif
CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION))
diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h
index 2019e27ce5de..8909e47146a7 100644
--- a/include/clang/Basic/OnDiskHashTable.h
+++ b/include/clang/Basic/OnDiskHashTable.h
@@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {
Item *next;
const uint32_t hash;
- Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
- : key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
+ Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
+ Info &InfoObj)
+ : key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
};
class Bucket {
@@ -168,10 +169,17 @@ public:
void insert(typename Info::key_type_ref key,
typename Info::data_type_ref data) {
+ Info InfoObj;
+ insert(key, data, InfoObj);
+ }
+
+ void insert(typename Info::key_type_ref key,
+ typename Info::data_type_ref data, Info &InfoObj) {
++NumEntries;
if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
- insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data));
+ insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data,
+ InfoObj));
}
io::Offset Emit(llvm::raw_ostream &out) {
@@ -278,8 +286,8 @@ public:
InfoPtr = &InfoObj;
using namespace io;
- const internal_key_type& iKey = Info::GetInternalKey(eKey);
- unsigned key_hash = Info::ComputeHash(iKey);
+ const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
+ unsigned key_hash = InfoObj.ComputeHash(iKey);
// Each bucket is just a 32-bit offset into the hash table file.
unsigned idx = key_hash & (NumBuckets - 1);
@@ -326,6 +334,71 @@ public:
iterator end() const { return iterator(); }
+ /// \brief Iterates over all the entries in the table, returning
+ /// a key/data pair.
+ class item_iterator {
+ const unsigned char* Ptr;
+ unsigned NumItemsInBucketLeft;
+ unsigned NumEntriesLeft;
+ Info *InfoObj;
+ public:
+ typedef std::pair<external_key_type, data_type> value_type;
+
+ item_iterator(const unsigned char* const Ptr, unsigned NumEntries,
+ Info *InfoObj)
+ : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
+ InfoObj(InfoObj) { }
+ item_iterator()
+ : Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
+
+ bool operator==(const item_iterator& X) const {
+ return X.NumEntriesLeft == NumEntriesLeft;
+ }
+ bool operator!=(const item_iterator& X) const {
+ return X.NumEntriesLeft != NumEntriesLeft;
+ }
+
+ item_iterator& operator++() { // Preincrement
+ if (!NumItemsInBucketLeft) {
+ // 'Items' starts with a 16-bit unsigned integer representing the
+ // number of items in this bucket.
+ NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
+ }
+ Ptr += 4; // Skip the hash.
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
+ Ptr += L.first + L.second;
+ assert(NumItemsInBucketLeft);
+ --NumItemsInBucketLeft;
+ assert(NumEntriesLeft);
+ --NumEntriesLeft;
+ return *this;
+ }
+ item_iterator operator++(int) { // Postincrement
+ item_iterator tmp = *this; ++*this; return tmp;
+ }
+
+ value_type operator*() const {
+ const unsigned char* LocalPtr = Ptr;
+ if (!NumItemsInBucketLeft)
+ LocalPtr += 2; // number of items in bucket
+ LocalPtr += 4; // Skip the hash.
+
+ // Determine the length of the key and the data.
+ const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(LocalPtr);
+
+ // Read the key.
+ const internal_key_type& Key =
+ InfoObj->ReadKey(LocalPtr, L.first);
+ return std::make_pair(InfoObj->GetExternalKey(Key),
+ InfoObj->ReadData(Key, LocalPtr + L.first, L.second));
+ }
+ };
+
+ item_iterator item_begin() {
+ return item_iterator(Base + 4, getNumEntries(), &InfoObj);
+ }
+ item_iterator item_end() { return item_iterator(); }
static OnDiskChainedHashTable* Create(const unsigned char* buckets,
const unsigned char* const base,
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 6a4be4609433..7a66117f2076 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -50,13 +50,20 @@ namespace SrcMgr {
C_User, C_System, C_ExternCSystem
};
- /// ContentCache - Once instance of this struct is kept for every file
+ /// ContentCache - One instance of this struct is kept for every file
/// loaded or used. This object owns the MemoryBuffer object.
class ContentCache {
+ enum CCFlags {
+ /// \brief Whether the buffer is invalid.
+ InvalidFlag = 0x01,
+ /// \brief Whether the buffer should not be freed on destruction.
+ DoNotFreeFlag = 0x02
+ };
+
/// Buffer - The actual buffer containing the characters from the input
/// file. This is owned by the ContentCache object.
- /// The bit indicates whether the buffer is invalid.
- mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 1, bool> Buffer;
+ /// The bits indicate indicates whether the buffer is invalid.
+ mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
public:
/// Reference to the file entry. This reference does not own
@@ -103,11 +110,27 @@ namespace SrcMgr {
Buffer.setPointer(B);
Buffer.setInt(false);
}
+
+ /// \brief Get the underlying buffer, returning NULL if the buffer is not
+ /// yet available.
+ const llvm::MemoryBuffer *getRawBuffer() const {
+ return Buffer.getPointer();
+ }
/// \brief Replace the existing buffer (which will be deleted)
/// with the given buffer.
- void replaceBuffer(const llvm::MemoryBuffer *B);
+ void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
+ /// \brief Determine whether the buffer itself is invalid.
+ bool isBufferInvalid() const {
+ return Buffer.getInt() & InvalidFlag;
+ }
+
+ /// \brief Determine whether the buffer should be freed.
+ bool shouldFreeBuffer() const {
+ return (Buffer.getInt() & DoNotFreeFlag) == 0;
+ }
+
ContentCache(const FileEntry *Ent = 0)
: Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {}
@@ -421,10 +444,9 @@ public:
FileID getMainFileID() const { return MainFileID; }
/// createMainFileID - Create the FileID for the main source file.
- FileID createMainFileID(const FileEntry *SourceFile,
- SourceLocation IncludePos) {
+ FileID createMainFileID(const FileEntry *SourceFile) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
- MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User);
+ MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
return MainFileID;
}
@@ -435,7 +457,7 @@ public:
/// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This returns 0 on
/// error and translates NULL into standard input.
- /// PreallocateID should be non-zero to specify which a pre-allocated,
+ /// PreallocateID should be non-zero to specify which pre-allocated,
/// lazily computed source location is being filled in by this operation.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
@@ -485,14 +507,18 @@ public:
/// \brief Override the contents of the given source file by providing an
/// already-allocated buffer.
///
- /// \param SourceFile the source file whose contents will be override.
+ /// \param SourceFile the source file whose contents will be overriden.
///
/// \param Buffer the memory buffer whose contents will be used as the
/// data in the given source file.
///
+ /// \param DoNotFree If true, then the buffer will not be freed when the
+ /// source manager is destroyed.
+ ///
/// \returns true if an error occurred, false otherwise.
bool overrideFileContents(const FileEntry *SourceFile,
- const llvm::MemoryBuffer *Buffer);
+ const llvm::MemoryBuffer *Buffer,
+ bool DoNotFree = false);
//===--------------------------------------------------------------------===//
// FileID manipulation methods.
@@ -768,7 +794,7 @@ public:
unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
// FIXME: Exposing this is a little gross; what we want is a good way
- // to iterate the entries that were not defined in a PCH file (or
+ // to iterate the entries that were not defined in an AST file (or
// any other external source).
unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }
diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h
index 9e54762add7d..e757a2f4a185 100644
--- a/include/clang/Basic/Specifiers.h
+++ b/include/clang/Basic/Specifiers.h
@@ -78,6 +78,68 @@ namespace clang {
AS_none
};
+ /// ExprValueKind - The categorization of expression values,
+ /// currently following the C++0x scheme.
+ enum ExprValueKind {
+ /// An r-value expression (a gr-value in the C++0x taxonomy)
+ /// produces a temporary value.
+ VK_RValue,
+
+ /// An l-value expression is a reference to an object with
+ /// independent storage.
+ VK_LValue,
+
+ /// An x-value expression is a reference to an object with
+ /// independent storage but which can be "moved", i.e.
+ /// efficiently cannibalized for its resources.
+ VK_XValue
+ };
+
+ // \brief Describes the kind of template specialization that a
+ // particular template specialization declaration represents.
+ enum TemplateSpecializationKind {
+ /// This template specialization was formed from a template-id but
+ /// has not yet been declared, defined, or instantiated.
+ TSK_Undeclared = 0,
+ /// This template specialization was implicitly instantiated from a
+ /// template. (C++ [temp.inst]).
+ TSK_ImplicitInstantiation,
+ /// This template specialization was declared or defined by an
+ /// explicit specialization (C++ [temp.expl.spec]) or partial
+ /// specialization (C++ [temp.class.spec]).
+ TSK_ExplicitSpecialization,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation declaration request
+ /// (C++0x [temp.explicit]).
+ TSK_ExplicitInstantiationDeclaration,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation definition request
+ /// (C++ [temp.explicit]).
+ TSK_ExplicitInstantiationDefinition
+ };
+
+ /// \brief Storage classes.
+ enum StorageClass {
+ // These are legal on both functions and variables.
+ SC_None,
+ SC_Extern,
+ SC_Static,
+ SC_PrivateExtern,
+
+ // These are only legal on variables.
+ SC_Auto,
+ SC_Register
+ };
+
+ /// Checks whether the given storage class is legal for functions.
+ inline bool isLegalForFunction(StorageClass SC) {
+ return SC <= SC_PrivateExtern;
+ }
+
+ /// Checks whether the given storage class is legal for variables.
+ inline bool isLegalForVariable(StorageClass SC) {
+ return true;
+ }
} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index a2f69730a010..4aa055e695e9 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -103,7 +103,6 @@ def UnaryTypeTraitExpr : DStmt<Expr>;
def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
-def CXXBindReferenceExpr : DStmt<Expr>;
def CXXExprWithTemporaries : DStmt<Expr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>;
diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h
index 9f7debf9c500..40df9ba11da4 100644
--- a/include/clang/Basic/TargetInfo.h
+++ b/include/clang/Basic/TargetInfo.h
@@ -16,6 +16,7 @@
// FIXME: Daniel isn't smart enough to use a prototype for this.
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/System/DataTypes.h"
#include <cassert>
@@ -37,6 +38,22 @@ class TargetOptions;
namespace Builtin { struct Info; }
+/// TargetCXXABI - The types of C++ ABIs for which we can generate code.
+enum TargetCXXABI {
+ /// The generic ("Itanium") C++ ABI, documented at:
+ /// http://www.codesourcery.com/public/cxx-abi/
+ CXXABI_Itanium,
+
+ /// The ARM C++ ABI, based largely on the Itanium ABI but with
+ /// significant differences.
+ /// http://infocenter.arm.com
+ /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+ CXXABI_ARM,
+
+ /// The Visual Studio ABI. Only scattered official documentation exists.
+ CXXABI_Microsoft
+};
+
/// TargetInfo - This class exposes information about the current target.
///
class TargetInfo {
@@ -58,7 +75,7 @@ protected:
const char *UserLabelPrefix;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
unsigned char RegParmMax, SSERegParmMax;
- std::string CXXABI;
+ TargetCXXABI CXXABI;
unsigned HasAlignMac68kSupport : 1;
unsigned RealTypeUsesObjCFPRet : 3;
@@ -412,7 +429,7 @@ public:
}
/// getCXXABI - Get the C++ ABI in use.
- virtual llvm::StringRef getCXXABI() const {
+ virtual TargetCXXABI getCXXABI() const {
return CXXABI;
}
@@ -434,11 +451,23 @@ public:
/// setCXXABI - Use this specific C++ ABI.
///
- /// \return - False on error (invalid ABI name).
- virtual bool setCXXABI(const std::string &Name) {
- if (Name != "itanium" && Name != "microsoft")
- return false;
- CXXABI = Name;
+ /// \return - False on error (invalid C++ ABI name).
+ bool setCXXABI(const std::string &Name) {
+ static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1);
+ TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name)
+ .Case("arm", CXXABI_ARM)
+ .Case("itanium", CXXABI_Itanium)
+ .Case("microsoft", CXXABI_Microsoft)
+ .Default(Unknown);
+ if (ABI == Unknown) return false;
+ return setCXXABI(ABI);
+ }
+
+ /// setCXXABI - Set the C++ ABI to be used by this implementation.
+ ///
+ /// \return - False on error (ABI not valid on this target)
+ virtual bool setCXXABI(TargetCXXABI ABI) {
+ CXXABI = ABI;
return true;
}
diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h
index 19b0cbbf5820..f3c206f2cc96 100644
--- a/include/clang/Basic/TargetOptions.h
+++ b/include/clang/Basic/TargetOptions.h
@@ -18,11 +18,6 @@ namespace clang {
/// TargetOptions - Options for controlling the target.
class TargetOptions {
public:
-
- TargetOptions() {
- CXXABI = "itanium";
- }
-
/// 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;
@@ -37,6 +32,9 @@ public:
/// to "itanium".
std::string CXXABI;
+ /// If given, the version string of the linker in use.
+ std::string LinkerVersion;
+
/// 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;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index b16b82854b1c..dc360adf8f19 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -96,6 +96,7 @@ TOK(unknown) // Not a token.
TOK(eof) // End of file.
TOK(eom) // End of macro (end of line inside a macro).
TOK(code_completion) // Code completion marker
+TOK(cxx_defaultarg_end) // C++ default argument end marker
// C99 6.4.9: Comments.
TOK(comment) // Comment (only in -E -C[C] mode)
@@ -185,6 +186,7 @@ PUNCTUATOR(at, "@")
// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
// KEYGNU - This is a keyword if GNU extensions are enabled
// KEYMS - This is a keyword if Microsoft extensions are enabled
+// KEYBORLAND - This is a keyword if Borland extensions are enabled
//
KEYWORD(auto , KEYALL)
KEYWORD(break , KEYALL)
@@ -272,16 +274,11 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
// C++0x keywords
KEYWORD(alignof , KEYCXX0X)
-KEYWORD(axiom , KEYCXX0X)
KEYWORD(char16_t , KEYCXX0X)
KEYWORD(char32_t , KEYCXX0X)
-KEYWORD(concept , KEYCXX0X)
-KEYWORD(concept_map , KEYCXX0X)
KEYWORD(constexpr , KEYCXX0X)
KEYWORD(decltype , KEYCXX0X)
-KEYWORD(late_check , KEYCXX0X)
KEYWORD(nullptr , KEYCXX0X)
-KEYWORD(requires , KEYCXX0X)
KEYWORD(static_assert , KEYCXX0X)
KEYWORD(thread_local , KEYCXX0X)
@@ -339,6 +336,9 @@ KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL)
+// Borland Extension.
+KEYWORD(__pascal , KEYALL)
+
// Altivec Extension.
KEYWORD(__vector , KEYALTIVEC)
KEYWORD(__pixel , KEYALTIVEC)
@@ -375,6 +375,9 @@ ALIAS("_fastcall" , __fastcall , KEYMS)
ALIAS("_stdcall" , __stdcall , KEYMS)
ALIAS("_thiscall" , __thiscall , KEYMS)
+// Borland Extensions which should be disabled in strict conformance mode.
+ALIAS("_pascal" , __pascal , KEYBORLAND)
+
//===----------------------------------------------------------------------===//
// Objective-C @-preceeded keywords.
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index b42755ca72ae..fa6ebb756ca3 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -64,6 +64,7 @@ class WInst<string p, string t> : Inst<p, t, OP_NONE> {}
// u: unsigned integer (int/float args)
// f: float (int args)
// d: default
+// g: default, ignore 'Q' size modifier.
// w: double width elements, same num elts
// n: double width elements, half num elts
// h: half width elements, double num elts
@@ -239,6 +240,7 @@ def VCREATE: Inst<"dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
// E.3.19 Set all lanes to same value
def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
+def VDUP_LANE : WInst<"dgi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
////////////////////////////////////////////////////////////////////////////////
// E.3.20 Combining vectors
diff --git a/include/clang/CMakeLists.txt b/include/clang/CMakeLists.txt
index c2880481a2e9..e82cf429eecc 100644
--- a/include/clang/CMakeLists.txt
+++ b/include/clang/CMakeLists.txt
@@ -1,3 +1,4 @@
add_subdirectory(AST)
add_subdirectory(Basic)
add_subdirectory(Driver)
+add_subdirectory(Serialization)
diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h
index 3749b43d7e23..370d96552c45 100644
--- a/include/clang/Checker/BugReporter/BugReporter.h
+++ b/include/clang/Checker/BugReporter/BugReporter.h
@@ -471,6 +471,9 @@ void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
void registerNilReceiverVisitor(BugReporterContext &BRC);
+void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
+ const ExplodedNode *N);
+
} // end namespace clang::bugreporter
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Checker/PathSensitive/AnalysisManager.h b/include/clang/Checker/PathSensitive/AnalysisManager.h
index 3c7cb68c0943..38550798b812 100644
--- a/include/clang/Checker/PathSensitive/AnalysisManager.h
+++ b/include/clang/Checker/PathSensitive/AnalysisManager.h
@@ -21,6 +21,11 @@
namespace clang {
+namespace idx {
+ class Indexer;
+ class TranslationUnit;
+}
+
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
@@ -35,6 +40,11 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
+ /// \brief Provide function definitions in other translation units. This is
+ /// NULL if we don't have multiple translation units. AnalysisManager does
+ /// not own the Indexer.
+ idx::Indexer *Idxer;
+
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
// The maximum number of exploded nodes the analyzer will generate.
@@ -62,13 +72,15 @@ public:
AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr, unsigned maxnodes,
- unsigned maxloop,
+ ConstraintManagerCreator constraintmgr,
+ idx::Indexer *idxer,
+ unsigned maxnodes, unsigned maxloop,
bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
- bool inlinecall)
+ bool inlinecall, bool useUnoptimizedCFG)
- : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
- CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
+ : AnaCtxMgr(useUnoptimizedCFG), Ctx(ctx), Diags(diags), LangInfo(lang),
+ PD(pd),
+ CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
@@ -79,6 +91,10 @@ public:
LocCtxMgr.clear();
AnaCtxMgr.clear();
}
+
+ AnalysisContextManager& getAnalysisContextManager() {
+ return AnaCtxMgr;
+ }
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
@@ -88,6 +104,8 @@ public:
return CreateConstraintMgr;
}
+ idx::Indexer *getIndexer() const { return Idxer; }
+
virtual ASTContext &getASTContext() {
return Ctx;
}
@@ -133,6 +151,10 @@ public:
bool shouldInlineCall() const { return InlineCall; }
+ bool hasIndexer() const { return Idxer != 0; }
+
+ const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
+
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
}
@@ -145,9 +167,25 @@ public:
return AnaCtxMgr.getContext(D)->getParentMap();
}
+ AnalysisContext *getAnalysisContext(const Decl *D) {
+ return AnaCtxMgr.getContext(D);
+ }
+
+ AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) {
+ return AnaCtxMgr.getContext(D, TU);
+ }
+
+ const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
+ LocationContext const *Parent,
+ Stmt const *S, const CFGBlock *Blk,
+ unsigned Idx) {
+ return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
+ }
+
// Get the top level stack frame.
- const StackFrameContext *getStackFrame(Decl const *D) {
- return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0);
+ const StackFrameContext *getStackFrame(Decl const *D,
+ idx::TranslationUnit *TU) {
+ return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
}
// Get a stack frame with parent.
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h
index 49dc3fa7dc44..136a29da5f2a 100644
--- a/include/clang/Checker/PathSensitive/Checker.h
+++ b/include/clang/Checker/PathSensitive/Checker.h
@@ -36,7 +36,6 @@ class CheckerContext {
const GRState *ST;
const Stmt *statement;
const unsigned size;
- bool DoneEvaluating; // FIXME: This is not a permanent API change.
public:
bool *respondsToCallback;
public:
@@ -166,6 +165,10 @@ public:
Eng.getBugReporter().EmitReport(R);
}
+ AnalysisContext *getCurrentAnalysisContext() const {
+ return Pred->getLocationContext()->getAnalysisContext();
+ }
+
private:
ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
bool markAsSink) {
@@ -223,7 +226,6 @@ private:
// 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) {
@@ -231,7 +233,7 @@ private:
isPrevisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind, 0, StoreE);
assert(isPrevisit && "Only previsit supported for now.");
- PreVisitBind(C, AssignE, StoreE, location, val);
+ PreVisitBind(C, StoreE, location, val);
}
// FIXME: Remove the 'tag' option.
@@ -261,15 +263,17 @@ public:
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 PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val) {}
virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {}
+ virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
+
virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
GRExprEngine &Eng,
- Stmt *Condition, void *tag) {}
+ const Stmt *Condition, void *tag) {}
virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
return false;
@@ -280,12 +284,23 @@ public:
}
virtual const GRState *EvalAssume(const GRState *state, SVal Cond,
- bool Assumption) {
+ bool Assumption, bool *respondsToCallback) {
+ *respondsToCallback = false;
+ return state;
+ }
+
+ virtual bool WantsRegionChangeUpdate(const GRState *state) { return false; }
+
+ virtual const GRState *EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool *respondsToCallback) {
+ *respondsToCallback = false;
return state;
}
virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
- bool hasWorkRemaining) {}
+ GRExprEngine &Eng) {}
};
} // end clang namespace
diff --git a/include/clang/Checker/PathSensitive/CheckerHelpers.h b/include/clang/Checker/PathSensitive/CheckerHelpers.h
new file mode 100644
index 000000000000..ea3c842ffc1f
--- /dev/null
+++ b/include/clang/Checker/PathSensitive/CheckerHelpers.h
@@ -0,0 +1,40 @@
+//== CheckerHelpers.h - Helper functions for checkers ------------*- 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 CheckerVisitor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
+#define LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
+
+#include "clang/AST/Stmt.h"
+
+namespace clang {
+
+bool containsMacro(const Stmt *S);
+bool containsEnum(const Stmt *S);
+bool containsStaticLocal(const Stmt *S);
+bool containsBuiltinOffsetOf(const Stmt *S);
+template <class T> bool containsStmt(const Stmt *S) {
+ if (isa<T>(S))
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsStmt<T>(child))
+ return true;
+
+ return false;
+}
+
+}
+
+#endif
diff --git a/include/clang/Checker/PathSensitive/ConstraintManager.h b/include/clang/Checker/PathSensitive/ConstraintManager.h
index ce7d1b381714..97535f55bfb9 100644
--- a/include/clang/Checker/PathSensitive/ConstraintManager.h
+++ b/include/clang/Checker/PathSensitive/ConstraintManager.h
@@ -34,9 +34,6 @@ public:
virtual const GRState *Assume(const GRState *state, DefinedSVal Cond,
bool Assumption) = 0;
- virtual const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx,
- DefinedSVal UpperBound, bool Assumption) = 0;
-
std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state,
DefinedSVal Cond) {
return std::make_pair(Assume(state, Cond, true),
diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h
index 2981731f863c..611f5079452a 100644
--- a/include/clang/Checker/PathSensitive/Environment.h
+++ b/include/clang/Checker/PathSensitive/Environment.h
@@ -83,8 +83,14 @@ public:
return Environment(F.GetEmptyMap());
}
- Environment BindExpr(Environment Env, const Stmt *S, SVal V,
+ /// Bind the value 'V' to the statement 'S'.
+ Environment bindExpr(Environment Env, const Stmt *S, SVal V,
bool Invalidate);
+
+ /// Bind the location 'location' and value 'V' to the statement 'S'. This
+ /// is used when simulating loads/stores.
+ Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
+ SVal V);
Environment RemoveDeadBindings(Environment Env,
SymbolReaper &SymReaper, const GRState *ST,
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
index 7f101dca97e5..216ecac73653 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h
@@ -43,6 +43,11 @@ class GRCoreEngine {
friend class GRCallEnterNodeBuilder;
friend class GRCallExitNodeBuilder;
+public:
+ typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
+ BlocksAborted;
+private:
+
GRSubEngine& SubEngine;
/// G - The simulation graph. Each node is a (location,state) pair.
@@ -57,21 +62,21 @@ class GRCoreEngine {
/// These are used to record for key nodes in the ExplodedGraph the
/// number of times different CFGBlocks have been visited along a path.
GRBlockCounter::Factory BCounterFactory;
-
- /// A flag that indicates whether paths were halted because
- /// ProcessBlockEntrace returned false.
- bool BlockAborted;
+
+ /// The locations where we stopped doing work because we visited a location
+ /// too many times.
+ BlocksAborted blocksAborted;
void GenerateNode(const ProgramPoint& Loc, const GRState* State,
ExplodedNode* Pred);
void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
- void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred);
- void HandlePostStmt(const PostStmt& S, CFGBlock* B,
+ void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
+ void HandlePostStmt(const PostStmt& S, const CFGBlock* B,
unsigned StmtIdx, ExplodedNode *Pred);
- void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
+ void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
ExplodedNode* Pred);
void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred);
@@ -82,25 +87,42 @@ class GRCoreEngine {
return SubEngine.getInitialState(InitLoc);
}
- void ProcessEndPath(GREndPathNodeBuilder& Builder);
+ void ProcessEndPath(GREndPathNodeBuilder& Builder) {
+ SubEngine.ProcessEndPath(Builder);
+ }
- void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder);
+ void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) {
+ SubEngine.ProcessStmt(E, Builder);
+ }
- bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
- GRBlockCounter BC);
+ bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred,
+ GRBlockCounter BC) {
+ return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
+ }
- void ProcessBranch(Stmt* Condition, Stmt* Terminator,
- GRBranchNodeBuilder& Builder);
+ void ProcessBranch(const Stmt* Condition, const Stmt* Terminator,
+ GRBranchNodeBuilder& Builder) {
+ SubEngine.ProcessBranch(Condition, Terminator, Builder);
+ }
- void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder);
+ void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
+ SubEngine.ProcessIndirectGoto(Builder);
+ }
- void ProcessSwitch(GRSwitchNodeBuilder& Builder);
+ void ProcessSwitch(GRSwitchNodeBuilder& Builder) {
+ SubEngine.ProcessSwitch(Builder);
+ }
- void ProcessCallEnter(GRCallEnterNodeBuilder &Builder);
- void ProcessCallExit(GRCallExitNodeBuilder &Builder);
+ void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
+ SubEngine.ProcessCallEnter(Builder);
+ }
+
+ void ProcessCallExit(GRCallExitNodeBuilder &Builder) {
+ SubEngine.ProcessCallExit(Builder);
+ }
private:
GRCoreEngine(const GRCoreEngine&); // Do not implement.
@@ -112,16 +134,14 @@ public:
GRCoreEngine(GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()),
WList(GRWorkList::MakeBFS()),
- BCounterFactory(G->getAllocator()),
- BlockAborted(false) {}
+ BCounterFactory(G->getAllocator()) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'.
GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()), WList(wlist),
- BCounterFactory(G->getAllocator()),
- BlockAborted(false) {}
+ BCounterFactory(G->getAllocator()) {}
~GRCoreEngine() {
delete WList;
@@ -136,12 +156,29 @@ public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
- bool ExecuteWorkList(const LocationContext *L, unsigned Steps);
+ bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
+ const GRState *InitState);
+ void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst);
+
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return !blocksAborted.empty(); }
+ bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
+
+ GRWorkList *getWorkList() const { return WList; }
+
+ BlocksAborted::const_iterator blocks_aborted_begin() const {
+ return blocksAborted.begin();
+ }
+ BlocksAborted::const_iterator blocks_aborted_end() const {
+ return blocksAborted.end();
+ }
};
class GRStmtNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock& B;
+ const CFGBlock& B;
const unsigned Idx;
ExplodedNode* Pred;
GRStateManager& Mgr;
@@ -163,7 +200,7 @@ public:
void GenerateAutoTransition(ExplodedNode* N);
public:
- GRStmtNodeBuilder(CFGBlock* b, unsigned idx, ExplodedNode* N,
+ GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
GRCoreEngine* e, GRStateManager &mgr);
~GRStmtNodeBuilder();
@@ -222,11 +259,11 @@ public:
/// getStmt - Return the current block-level expression associated with
/// this builder.
- Stmt* getStmt() const { return B[Idx]; }
+ const Stmt* getStmt() const { return B[Idx]; }
/// getBlock - Return the CFGBlock associated with the block-level expression
/// of this builder.
- CFGBlock* getBlock() const { return &B; }
+ const CFGBlock* getBlock() const { return &B; }
unsigned getIndex() const { return Idx; }
@@ -239,15 +276,15 @@ public:
return Pred->getState();
}
- ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
- const GRState* St) {
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St) {
return MakeNode(Dst, S, Pred, St, PointKind);
}
- ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred,
const GRState* St, ProgramPoint::Kind K);
- ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, Stmt* S,
+ ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S,
ExplodedNode* Pred, const GRState* St) {
bool Tmp = BuildSinks;
BuildSinks = true;
@@ -259,9 +296,9 @@ public:
class GRBranchNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock* Src;
- CFGBlock* DstT;
- CFGBlock* DstF;
+ const CFGBlock* Src;
+ const CFGBlock* DstT;
+ const CFGBlock* DstF;
ExplodedNode* Pred;
typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy;
@@ -273,8 +310,8 @@ class GRBranchNodeBuilder {
bool InFeasibleFalse;
public:
- GRBranchNodeBuilder(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
- ExplodedNode* pred, GRCoreEngine* e)
+ GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
+ const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e)
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
GeneratedTrue(false), GeneratedFalse(false),
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
@@ -289,7 +326,7 @@ public:
ExplodedNode* generateNode(const GRState* State, bool branch);
- CFGBlock* getTargetBlock(bool branch) const {
+ const CFGBlock* getTargetBlock(bool branch) const {
return branch ? DstT : DstF;
}
@@ -311,31 +348,31 @@ public:
class GRIndirectGotoNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock* Src;
- CFGBlock& DispatchBlock;
- Expr* E;
+ const CFGBlock* Src;
+ const CFGBlock& DispatchBlock;
+ const Expr* E;
ExplodedNode* Pred;
public:
- GRIndirectGotoNodeBuilder(ExplodedNode* pred, CFGBlock* src, Expr* e,
- CFGBlock* dispatch, GRCoreEngine* eng)
- : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+ GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng)
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
class iterator {
- CFGBlock::succ_iterator I;
+ CFGBlock::const_succ_iterator I;
friend class GRIndirectGotoNodeBuilder;
- iterator(CFGBlock::succ_iterator i) : I(i) {}
+ iterator(CFGBlock::const_succ_iterator i) : I(i) {}
public:
iterator& operator++() { ++I; return *this; }
bool operator!=(const iterator& X) const { return I != X.I; }
- LabelStmt* getLabel() const {
+ const LabelStmt* getLabel() const {
return llvm::cast<LabelStmt>((*I)->getLabel());
}
- CFGBlock* getBlock() const {
+ const CFGBlock* getBlock() const {
return *I;
}
};
@@ -346,37 +383,38 @@ public:
ExplodedNode* generateNode(const iterator& I, const GRState* State,
bool isSink = false);
- Expr* getTarget() const { return E; }
+ const Expr* getTarget() const { return E; }
const GRState* getState() const { return Pred->State; }
};
class GRSwitchNodeBuilder {
GRCoreEngine& Eng;
- CFGBlock* Src;
- Expr* Condition;
+ const CFGBlock* Src;
+ const Expr* Condition;
ExplodedNode* Pred;
public:
- GRSwitchNodeBuilder(ExplodedNode* pred, CFGBlock* src,
- Expr* condition, GRCoreEngine* eng)
+ GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
+ const Expr* condition, GRCoreEngine* eng)
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
class iterator {
- CFGBlock::succ_reverse_iterator I;
+ CFGBlock::const_succ_reverse_iterator I;
friend class GRSwitchNodeBuilder;
- iterator(CFGBlock::succ_reverse_iterator i) : I(i) {}
+ iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
public:
iterator& operator++() { ++I; return *this; }
- bool operator!=(const iterator& X) const { return I != X.I; }
+ bool operator!=(const iterator &X) const { return I != X.I; }
+ bool operator==(const iterator &X) const { return I == X.I; }
- CaseStmt* getCase() const {
+ const CaseStmt* getCase() const {
return llvm::cast<CaseStmt>((*I)->getLabel());
}
- CFGBlock* getBlock() const {
+ const CFGBlock* getBlock() const {
return *I;
}
};
@@ -389,21 +427,21 @@ public:
ExplodedNode* generateDefaultCaseNode(const GRState* State,
bool isSink = false);
- Expr* getCondition() const { return Condition; }
+ const Expr* getCondition() const { return Condition; }
const GRState* getState() const { return Pred->State; }
};
class GREndPathNodeBuilder {
GRCoreEngine &Eng;
- CFGBlock& B;
+ const CFGBlock& B;
ExplodedNode* Pred;
public:
bool HasGeneratedNode;
public:
- GREndPathNodeBuilder(CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
+ GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
: Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
~GREndPathNodeBuilder();
@@ -427,7 +465,7 @@ public:
void GenerateCallExitNode(const GRState *state);
- CFGBlock* getBlock() const { return &B; }
+ const CFGBlock* getBlock() const { return &B; }
const GRState* getState() const {
return getPredecessor()->getState();
@@ -442,8 +480,8 @@ class GRCallEnterNodeBuilder {
// The call site.
const Stmt *CE;
- // The definition of callee.
- const FunctionDecl *FD;
+ // The AnalysisContext of the callee.
+ AnalysisContext *CalleeCtx;
// The parent block of the CallExpr.
const CFGBlock *Block;
@@ -453,9 +491,9 @@ class GRCallEnterNodeBuilder {
public:
GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
- const Stmt *s, const FunctionDecl *fd,
+ const Stmt *s, AnalysisContext *callee,
const CFGBlock *blk, unsigned idx)
- : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {}
+ : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
const GRState *getState() const { return Pred->getState(); }
@@ -465,7 +503,7 @@ public:
const Stmt *getCallExpr() const { return CE; }
- const FunctionDecl *getCallee() const { return FD; }
+ AnalysisContext *getCalleeContext() const { return CalleeCtx; }
const CFGBlock *getBlock() const { return Block; }
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
index 8eaf3f4a97d7..5ba0b36b315d 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -64,7 +64,7 @@ class GRExprEngine : public GRSubEngine {
const GRState* CleanedState;
/// CurrentStmt - The current block-level statement.
- Stmt* CurrentStmt;
+ const Stmt* CurrentStmt;
// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
@@ -75,10 +75,26 @@ class GRExprEngine : public GRSubEngine {
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
+ enum CallbackKind {
+ PreVisitStmtCallback,
+ PostVisitStmtCallback,
+ ProcessAssumeCallback,
+ EvalRegionChangesCallback
+ };
+
+ typedef uint32_t CallbackTag;
+
+ /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub'
+ /// argument can be used to differentiate callbacks that depend on another
+ /// value from a small set of possibilities, such as statement classes.
+ static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) {
+ assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits");
+ return K | (Sub << 8);
+ }
+
typedef llvm::DenseMap<void *, unsigned> CheckerMap;
typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered;
- typedef llvm::DenseMap<std::pair<unsigned, unsigned>, CheckersOrdered *>
- CheckersOrderedCache;
+ typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache;
/// A registration map from checker tag to the index into the
/// ordered checkers vector.
@@ -89,7 +105,7 @@ class GRExprEngine : public GRSubEngine {
CheckersOrdered Checkers;
/// A map used for caching the checkers that respond to the callback for
- /// a particular statement and visitation order.
+ /// a particular callback tag.
CheckersOrderedCache COCache;
/// The BugReporter associated with this engine. It is important that
@@ -101,10 +117,10 @@ class GRExprEngine : public GRSubEngine {
class CallExprWLItem {
public:
- CallExpr::arg_iterator I;
+ CallExpr::const_arg_iterator I;
ExplodedNode *N;
- CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n)
+ CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
: I(i), N(n) {}
};
@@ -114,13 +130,22 @@ public:
~GRExprEngine();
void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
- CoreEngine.ExecuteWorkList(L, Steps);
+ CoreEngine.ExecuteWorkList(L, Steps, 0);
+ }
+
+ /// Execute the work list with an initial state. Nodes that reaches the exit
+ /// of the function are added into the Dst set, which represent the exit
+ /// state of the function call.
+ void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst) {
+ CoreEngine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
}
/// getContext - Return the ASTContext associated with this analysis.
ASTContext& getContext() const { return AMgr.getASTContext(); }
- AnalysisManager &getAnalysisManager() const { return AMgr; }
+ virtual AnalysisManager &getAnalysisManager() { return AMgr; }
SValuator &getSValuator() { return SVator; }
@@ -166,17 +191,18 @@ public:
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
- void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder);
+ void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder);
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
- bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
+ bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder);
+ void ProcessBranch(const Stmt* Condition, const Stmt* Term,
+ GRBranchNodeBuilder& builder);
/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
@@ -201,10 +227,19 @@ public:
/// EvalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values.
- const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption);
+ const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
+
+ /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a ProcessRegionChanges update.
+ bool WantsRegionChangeUpdate(const GRState* state);
- GRStateManager& getStateManager() { return StateMgr; }
- const GRStateManager& getStateManager() const { return StateMgr; }
+ /// ProcessRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ const GRState* ProcessRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End);
+
+ virtual GRStateManager& getStateManager() { return StateMgr; }
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
@@ -227,21 +262,29 @@ public:
SymbolManager& getSymbolManager() { return SymMgr; }
const SymbolManager& getSymbolManager() const { return SymMgr; }
+ // Functions for external checking of whether we have unfinished work
+ bool wasBlockAborted() const { return CoreEngine.wasBlockAborted(); }
+ bool hasWorkRemaining() const {
+ return wasBlockAborted() || CoreEngine.getWorkList()->hasWork();
+ }
+
+ const GRCoreEngine &getCoreEngine() const { return CoreEngine; }
+
protected:
const GRState* GetState(ExplodedNode* N) {
return N == EntryNode ? CleanedState : N->getState();
}
public:
- ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
- const GRState* St,
+ ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
+ ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
- void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- bool isPrevisit);
+ void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
+ CallbackKind Kind);
bool CheckerEvalCall(const CallExpr *CE,
ExplodedNodeSet &Dst,
@@ -252,125 +295,130 @@ public:
const GRState *state,
ExplodedNode *Pred);
- void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
- ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- SVal location, SVal val, bool isPrevisit);
-
+ void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, SVal location, SVal val,
+ bool isPrevisit);
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
- void Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
/// storage location. Note that not all kinds of expressions has lvalue.
- void VisitLValue(Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses.
- void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, ExplodedNode* Pred,
+ void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitAsmStmt - Transfer function logic for inline asm.
- void VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
- void VisitAsmStmtHelperOutputs(AsmStmt* A,
- AsmStmt::outputs_iterator I,
- AsmStmt::outputs_iterator E,
+ void VisitAsmStmtHelperOutputs(const AsmStmt* A,
+ AsmStmt::const_outputs_iterator I,
+ AsmStmt::const_outputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
- void VisitAsmStmtHelperInputs(AsmStmt* A,
- AsmStmt::inputs_iterator I,
- AsmStmt::inputs_iterator E,
+ void VisitAsmStmtHelperInputs(const AsmStmt* A,
+ AsmStmt::const_inputs_iterator I,
+ AsmStmt::const_inputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitBlockExpr - Transfer function logic for BlockExprs.
- void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst);
+ void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
- void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
+ void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCall - Transfer function for function calls.
- void VisitCall(CallExpr* CE, ExplodedNode* Pred,
- CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
+ void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
+ CallExpr::const_arg_iterator AI,
+ CallExpr::const_arg_iterator AE,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
- void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
+ void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
- void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
- void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
+ void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
- void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred,
+ void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
- void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue);
+ void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst,
+ bool asLValue);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
- void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
- void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
- ExplodedNodeSet& Dst);
+ void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitCondInit - Transfer function for handling the initialization
/// of a condition variable in an IfStmt, SwitchStmt, etc.
- void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred,
+ void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet& Dst);
- void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
+ void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
- void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
+ void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions.
- void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,
- bool asLValue);
+ void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred,
+ void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
- void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred,
- ExplodedNodeSet& Dst);
+ void VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst);
- void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
+ void VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
ExplodedNode* Pred,
ExplodedNodeSet& Dst, SVal ElementV);
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
- void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
+ void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitReturnStmt - Transfer function logic for return statements.
- void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst);
+ void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst);
/// VisitOffsetOfExpr - Transfer function for offsetof.
- void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred,
+ void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
- void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
+ void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
- void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred,
+ void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
- void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
+ void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
@@ -380,17 +428,17 @@ public:
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
- void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
+ void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
- void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
+ void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue.
- void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+ void CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion.
@@ -398,14 +446,15 @@ public:
const StackFrameContext *SFC);
/// Evaluate arguments with a work list algorithm.
- void EvalArguments(ExprIterator AI, ExprIterator AE,
+ void EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
const FunctionProtoType *FnType,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// 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.
- void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, Expr *Ex);
+ void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
+ const Expr *Ex);
SVal EvalMinus(SVal X) {
return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X;
@@ -433,42 +482,41 @@ public:
}
protected:
- void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME,
+ void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
ExplodedNode* Pred, const GRState *state) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
}
- const GRState* MarkBranch(const GRState* St, Stmt* Terminator,
+ const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
bool branchTaken);
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others.
- void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
- Stmt* StoreE, ExplodedNode* Pred,
+ void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
const GRState* St, SVal location, SVal Val,
bool atDeclInit = false);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+ void EvalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag = 0,
QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE,
+ void EvalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
private:
- void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
+ void EvalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag,
QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
- void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
+ void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
const void *tag, bool isLoad);
diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h
index 67a2caf06a13..d72d63ab3c98 100644
--- a/include/clang/Checker/PathSensitive/GRState.h
+++ b/include/clang/Checker/PathSensitive/GRState.h
@@ -77,6 +77,10 @@ private:
Store St;
GenericDataMap GDM;
+ /// makeWithStore - Return a GRState with the same values as the current
+ /// state with the exception of using the specified Store.
+ const GRState *makeWithStore(Store store) const;
+
public:
/// This ctor is used when creating the first GRState object.
@@ -134,10 +138,6 @@ public:
return Env.LookupExpr(E);
}
- /// makeWithStore - Return a GRState with the same values as the current
- /// state with the exception of using the specified Store.
- const GRState *makeWithStore(Store store) const;
-
BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const;
@@ -201,8 +201,15 @@ public:
const LocationContext *LC,
SVal V) const;
+ /// Create a new state by binding the value 'V' to the statement 'S' in the
+ /// state's environment.
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
+ /// Create a new state by binding the value 'V' and location 'locaton' to the
+ /// statement 'S' in the state's environment.
+ const GRState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
+ const;
+
const GRState *bindDecl(const VarRegion *VR, SVal V) const;
const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
@@ -215,6 +222,28 @@ public:
const GRState *unbindLoc(Loc LV) const;
+ /// InvalidateRegion - Returns the state with bindings for the given region
+ /// cleared from the store. See InvalidateRegions.
+ const GRState *InvalidateRegion(const MemRegion *R,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols *IS = NULL)
+ const {
+ return InvalidateRegions(&R, &R+1, E, BlockCount, IS, false);
+ }
+
+ /// InvalidateRegions - Returns the state with bindings for the given regions
+ /// cleared from the store. The regions are provided as a continuous array
+ /// from Begin to End. Optionally invalidates global regions as well.
+ const GRState *InvalidateRegions(const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned BlockCount,
+ StoreManager::InvalidatedSymbols *IS,
+ bool invalidateGlobals) const;
+
+ /// EnterStackFrame - Returns the state for entry to the given stack frame,
+ /// preserving the current state.
+ const GRState *EnterStackFrame(const StackFrameContext *frame) const;
+
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@@ -235,11 +264,18 @@ public:
const llvm::APSInt *getSymVal(SymbolRef sym) const;
- SVal getSVal(const Stmt* Ex) const;
-
+ /// Returns the SVal bound to the statement 'S' in the state's environment.
+ SVal getSVal(const Stmt* S) const;
+
SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
SVal getSVal(Loc LV, QualType T = QualType()) const;
+
+ /// Returns a "simplified" SVal bound to the location 'LV' in the state's
+ /// store. A simplified SVal will include optimizations such as
+ /// if the SVal is a symbol whose value is perfectly constrained then that
+ /// constant value is returned instead.
+ SVal getSimplifiedSVal(Loc LV, QualType T= QualType()) const;
SVal getSVal(const MemRegion* R) const;
@@ -375,6 +411,9 @@ class GRStateManager {
friend class GRState;
friend class GRExprEngine; // FIXME: Remove.
private:
+ /// Eng - The GRSubEngine that owns this state manager.
+ GRSubEngine &Eng;
+
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr;
llvm::OwningPtr<ConstraintManager> ConstraintMgr;
@@ -404,7 +443,8 @@ public:
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc,
GRSubEngine &subeng)
- : EnvMgr(alloc),
+ : Eng(subeng),
+ EnvMgr(alloc),
GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this),
Alloc(alloc) {
@@ -447,11 +487,16 @@ public:
StoreManager& getStoreManager() { return *StoreMgr; }
ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
+ GRSubEngine& getOwningEngine() { return Eng; }
const GRState* RemoveDeadBindings(const GRState* St,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper);
+ /// Marshal a new state for the callee in another translation unit.
+ /// 'state' is owned by the caller's engine.
+ const GRState *MarshalState(const GRState *state, const StackFrameContext *L);
+
public:
SVal ArrayToPointer(Loc Array) {
@@ -581,50 +626,10 @@ GRState::Assume(DefinedOrUnknownSVal Cond) const {
cast<DefinedSVal>(Cond));
}
-inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
- DefinedOrUnknownSVal UpperBound,
- bool Assumption) const {
- if (Idx.isUnknown() || UpperBound.isUnknown())
- return this;
-
- ConstraintManager &CM = *getStateManager().ConstraintMgr;
- return CM.AssumeInBound(this, cast<DefinedSVal>(Idx),
- cast<DefinedSVal>(UpperBound), Assumption);
-}
-
-inline const GRState *
-GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
- const LocationContext *LC, SVal V) const {
- Store new_store =
- getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V);
- return makeWithStore(new_store);
-}
-
-inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
- Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal);
- return makeWithStore(new_store);
-}
-
-inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
- Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR);
- return makeWithStore(new_store);
-}
-
-inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
- Store new_store = getStateManager().StoreMgr->Bind(St, LV, V);
- return makeWithStore(new_store);
-}
-
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
}
-inline const GRState *GRState::bindDefault(SVal loc, SVal V) const {
- const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
- Store new_store = getStateManager().StoreMgr->BindDefault(St, R, V);
- return makeWithStore(new_store);
-}
-
inline Loc GRState::getLValue(const VarDecl* VD,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueVar(VD, LC);
diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h
index 90a41d7c093f..1904835fbc34 100644
--- a/include/clang/Checker/PathSensitive/GRSubEngine.h
+++ b/include/clang/Checker/PathSensitive/GRSubEngine.h
@@ -17,7 +17,7 @@
namespace clang {
-class Stmt;
+class AnalysisManager;
class CFGBlock;
class CFGElement;
class ExplodedNode;
@@ -32,6 +32,8 @@ class GREndPathNodeBuilder;
class GRCallEnterNodeBuilder;
class GRCallExitNodeBuilder;
class LocationContext;
+class MemRegion;
+class Stmt;
class GRSubEngine {
public:
@@ -39,21 +41,23 @@ public:
virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
- virtual GRStateManager& getStateManager() = 0;
+ virtual AnalysisManager &getAnalysisManager() = 0;
+
+ virtual GRStateManager &getStateManager() = 0;
/// Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
- virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0;
+ virtual void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder) = 0;
/// Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
- virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
+ virtual bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC) = 0;
/// Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
- virtual void ProcessBranch(Stmt* Condition, Stmt* Term,
+ virtual void ProcessBranch(const Stmt* Condition, const Stmt* Term,
GRBranchNodeBuilder& builder) = 0;
/// Called by GRCoreEngine. Used to generate successor
@@ -73,12 +77,27 @@ public:
// Generate the first post callsite node.
virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
-
+
/// Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
virtual const GRState* ProcessAssume(const GRState *state,
SVal cond, bool assumption) = 0;
-
+
+ /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
+ /// region change should trigger a ProcessRegionChanges update.
+ virtual bool WantsRegionChangeUpdate(const GRState* state) = 0;
+
+ /// ProcessRegionChanges - Called by GRStateManager whenever a change is made
+ /// to the store. Used to update checkers that track region values.
+ virtual const GRState* ProcessRegionChanges(const GRState* state,
+ const MemRegion* const *Begin,
+ const MemRegion* const *End) = 0;
+
+ inline const GRState* ProcessRegionChange(const GRState* state,
+ const MemRegion* MR) {
+ return ProcessRegionChanges(state, &MR, &MR+1);
+ }
+
/// Called by GRCoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached.
virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0;
diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
index 374f99820bd0..320b7f7b8abd 100644
--- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h
@@ -42,13 +42,13 @@ public:
virtual void EvalCall(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- CallExpr* CE, SVal L,
+ const CallExpr* CE, SVal L,
ExplodedNode* Pred) {}
virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- ObjCMessageExpr* ME,
+ const ObjCMessageExpr* ME,
ExplodedNode* Pred,
const GRState *state) {}
@@ -73,7 +73,7 @@ public:
virtual void EvalReturn(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- ReturnStmt* S,
+ const ReturnStmt* S,
ExplodedNode* Pred) {}
// Assumptions.
diff --git a/include/clang/Checker/PathSensitive/GRWorkList.h b/include/clang/Checker/PathSensitive/GRWorkList.h
index b8f90fa1eea1..315b614043d4 100644
--- a/include/clang/Checker/PathSensitive/GRWorkList.h
+++ b/include/clang/Checker/PathSensitive/GRWorkList.h
@@ -27,12 +27,12 @@ class ExplodedNodeImpl;
class GRWorkListUnit {
ExplodedNode* Node;
GRBlockCounter Counter;
- CFGBlock* Block;
+ const CFGBlock* Block;
unsigned BlockIdx; // This is the index of the next statement.
public:
GRWorkListUnit(ExplodedNode* N, GRBlockCounter C,
- CFGBlock* B, unsigned idx)
+ const CFGBlock* B, unsigned idx)
: Node(N),
Counter(C),
Block(B),
@@ -46,7 +46,7 @@ public:
ExplodedNode* getNode() const { return Node; }
GRBlockCounter getBlockCounter() const { return Counter; }
- CFGBlock* getBlock() const { return Block; }
+ const CFGBlock* getBlock() const { return Block; }
unsigned getIndex() const { return BlockIdx; }
};
@@ -58,8 +58,8 @@ public:
virtual void Enqueue(const GRWorkListUnit& U) = 0;
- void Enqueue(ExplodedNode* N, CFGBlock& B, unsigned idx) {
- Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx));
+ void Enqueue(ExplodedNode* N, const CFGBlock* B, unsigned idx) {
+ Enqueue(GRWorkListUnit(N, CurrentCounter, B, idx));
}
void Enqueue(ExplodedNode* N) {
diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h
index feb4b7218a7e..96f906af28e1 100644
--- a/include/clang/Checker/PathSensitive/MemRegion.h
+++ b/include/clang/Checker/PathSensitive/MemRegion.h
@@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/FoldingSet.h"
#include <string>
@@ -38,6 +39,22 @@ class ValueManager;
class VarRegion;
class CodeTextRegion;
+/// Represent a region's offset within the top level base region.
+class RegionOffset {
+ /// The base region.
+ const MemRegion *R;
+
+ /// The bit offset within the base region. It shouldn't be negative.
+ int64_t Offset;
+
+public:
+ RegionOffset(const MemRegion *r) : R(r), Offset(0) {}
+ RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
+
+ const MemRegion *getRegion() const { return R; }
+ int64_t getOffset() const { return Offset; }
+};
+
//===----------------------------------------------------------------------===//
// Base region classes.
//===----------------------------------------------------------------------===//
@@ -111,6 +128,9 @@ public:
bool hasStackParametersStorage() const;
+ /// Compute the offset within the top level memory object.
+ RegionOffset getAsOffset() const;
+
virtual void dumpToStream(llvm::raw_ostream& os) const;
void dump() const;
@@ -261,6 +281,7 @@ public:
}
};
+
/// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion.
class SubRegion : public MemRegion {
@@ -287,31 +308,6 @@ public:
};
//===----------------------------------------------------------------------===//
-// Auxillary data classes for use with MemRegions.
-//===----------------------------------------------------------------------===//
-
-class ElementRegion;
-
-class RegionRawOffset {
-private:
- friend class ElementRegion;
-
- const MemRegion *Region;
- int64_t Offset;
-
- RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
- : Region(reg), Offset(offset) {}
-
-public:
- // FIXME: Eventually support symbolic offsets.
- int64_t getByteOffset() const { return Offset; }
- const MemRegion *getRegion() const { return Region; }
-
- void dumpToStream(llvm::raw_ostream& os) const;
- void dump() const;
-};
-
-//===----------------------------------------------------------------------===//
// MemRegion subclasses.
//===----------------------------------------------------------------------===//
@@ -353,25 +349,23 @@ protected:
TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
public:
- virtual QualType getValueType(ASTContext &C) const = 0;
+ virtual QualType getValueType() const = 0;
- virtual QualType getLocationType(ASTContext& C) const {
+ virtual QualType getLocationType() const {
// FIXME: We can possibly optimize this later to cache this value.
- return C.getPointerType(getValueType(C));
+ return getContext().getPointerType(getValueType());
}
- QualType getDesugaredValueType(ASTContext& C) const {
- QualType T = getValueType(C);
+ QualType getDesugaredValueType() const {
+ QualType T = getValueType();
return T.getTypePtr() ? T.getDesugaredType() : T;
}
- QualType getDesugaredLocationType(ASTContext& C) const {
- return getLocationType(C).getDesugaredType();
+ QualType getDesugaredLocationType() const {
+ return getLocationType().getDesugaredType();
}
- bool isBoundable() const {
- return !getValueType(getContext()).isNull();
- }
+ bool isBoundable() const { return true; }
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
@@ -384,9 +378,8 @@ class CodeTextRegion : public TypedRegion {
protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public:
- QualType getValueType(ASTContext &C) const {
- // Do not get the object type of a CodeTextRegion.
- assert(0);
+ QualType getValueType() const {
+ assert(0 && "Do not get the object type of a CodeTextRegion.");
return QualType();
}
@@ -405,8 +398,8 @@ public:
FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
- QualType getLocationType(ASTContext &C) const {
- return C.getPointerType(FD->getType());
+ QualType getLocationType() const {
+ return getContext().getPointerType(FD->getType());
}
const FunctionDecl *getDecl() const {
@@ -444,7 +437,7 @@ class BlockTextRegion : public CodeTextRegion {
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public:
- QualType getLocationType(ASTContext &C) const {
+ QualType getLocationType() const {
return locTy;
}
@@ -581,7 +574,7 @@ public:
const StringLiteral* getStringLiteral() const { return Str; }
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
return Str->getType();
}
@@ -615,8 +608,8 @@ private:
const CompoundLiteralExpr* CL,
const MemRegion* superRegion);
public:
- QualType getValueType(ASTContext& C) const {
- return C.getCanonicalType(CL->getType());
+ QualType getValueType() const {
+ return CL->getType();
}
bool isBoundable() const { return !CL->isFileScope(); }
@@ -673,9 +666,9 @@ public:
const StackFrameContext *getStackFrame() const;
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
// FIXME: We can cache this if needed.
- return C.getCanonicalType(getDecl()->getType());
+ return getDecl()->getType();
}
void dumpToStream(llvm::raw_ostream& os) const;
@@ -701,10 +694,10 @@ class CXXThisRegion : public TypedRegion {
void Profile(llvm::FoldingSetNodeID &ID) const;
public:
- QualType getValueType(ASTContext &C) const {
+ QualType getValueType() const {
return QualType(ThisPointerTy, 0);
}
-
+
void dumpToStream(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
@@ -727,9 +720,9 @@ public:
const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
// FIXME: We can cache this if needed.
- return C.getCanonicalType(getDecl()->getType());
+ return getDecl()->getType();
}
DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
@@ -758,7 +751,7 @@ class ObjCIvarRegion : public DeclRegion {
public:
const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
- QualType getValueType(ASTContext&) const { return getDecl()->getType(); }
+ QualType getValueType() const { return getDecl()->getType(); }
void dumpToStream(llvm::raw_ostream& os) const;
@@ -766,6 +759,30 @@ public:
return R->getKind() == ObjCIvarRegionKind;
}
};
+//===----------------------------------------------------------------------===//
+// Auxillary data classes for use with MemRegions.
+//===----------------------------------------------------------------------===//
+
+class ElementRegion;
+
+class RegionRawOffset {
+private:
+ friend class ElementRegion;
+
+ const MemRegion *Region;
+ int64_t Offset;
+
+ RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
+ : Region(reg), Offset(offset) {}
+
+public:
+ // FIXME: Eventually support symbolic offsets.
+ int64_t getByteOffset() const { return Offset; }
+ const MemRegion *getRegion() const { return Region; }
+
+ void dumpToStream(llvm::raw_ostream& os) const;
+ void dump() const;
+};
class ElementRegion : public TypedRegion {
friend class MemRegionManager;
@@ -788,15 +805,15 @@ public:
SVal getIndex() const { return Index; }
- QualType getValueType(ASTContext&) const {
+ QualType getValueType() const {
return ElementType;
}
QualType getElementType() const {
return ElementType;
}
-
- RegionRawOffset getAsRawOffset() const;
+ /// Compute the offset within the array. The array might also be a subobject.
+ RegionRawOffset getAsArrayOffset() const;
void dumpToStream(llvm::raw_ostream& os) const;
@@ -820,7 +837,7 @@ class CXXObjectRegion : public TypedRegion {
Expr const *E, const MemRegion *sReg);
public:
- QualType getValueType(ASTContext& C) const {
+ QualType getValueType() const {
return Ex->getType();
}
diff --git a/include/clang/Checker/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h
index 55fd3ea5c929..cdb338a3f2cc 100644
--- a/include/clang/Checker/PathSensitive/SVals.h
+++ b/include/clang/Checker/PathSensitive/SVals.h
@@ -45,15 +45,14 @@ public:
enum { BaseBits = 2, BaseMask = 0x3 };
protected:
- void* Data;
+ const void* Data;
unsigned Kind;
protected:
SVal(const void* d, bool isLoc, unsigned ValKind)
- : Data(const_cast<void*>(d)),
- Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
+ : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
- explicit SVal(BaseKind k, void* D = NULL)
+ explicit SVal(BaseKind k, const void* D = NULL)
: Data(D), Kind(k) {}
public:
@@ -69,7 +68,7 @@ public:
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind());
- ID.AddPointer(reinterpret_cast<void*>(Data));
+ ID.AddPointer(Data);
}
inline bool operator==(const SVal& R) const {
@@ -163,13 +162,13 @@ public:
class UndefinedVal : public SVal {
public:
UndefinedVal() : SVal(UndefinedKind) {}
- UndefinedVal(void* D) : SVal(UndefinedKind, D) {}
+ UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
static inline bool classof(const SVal* V) {
return V->getBaseKind() == UndefinedKind;
}
- void* getData() const { return Data; }
+ const void* getData() const { return Data; }
};
class DefinedOrUnknownSVal : public SVal {
@@ -287,7 +286,7 @@ public:
: NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
const SymExpr *getSymbolicExpression() const {
- return reinterpret_cast<SymExpr*>(Data);
+ return reinterpret_cast<const SymExpr*>(Data);
}
static inline bool classof(const SVal* V) {
@@ -305,7 +304,7 @@ public:
ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
+ return *static_cast<const llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
@@ -368,7 +367,7 @@ class CompoundVal : public NonLoc {
public:
const CompoundValData* getValue() const {
- return static_cast<CompoundValData*>(Data);
+ return static_cast<const CompoundValData*>(Data);
}
typedef llvm::ImmutableList<SVal>::iterator iterator;
@@ -419,8 +418,8 @@ class GotoLabel : public Loc {
public:
GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
- LabelStmt* getLabel() const {
- return static_cast<LabelStmt*>(Data);
+ const LabelStmt* getLabel() const {
+ return static_cast<const LabelStmt*>(Data);
}
static inline bool classof(const SVal* V) {
@@ -439,7 +438,7 @@ public:
MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
const MemRegion* getRegion() const {
- return static_cast<MemRegion*>(Data);
+ return static_cast<const MemRegion*>(Data);
}
const MemRegion* StripCasts() const;
@@ -473,7 +472,7 @@ public:
ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
- return *static_cast<llvm::APSInt*>(Data);
+ return *static_cast<const llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h
index 7a60ebb0838e..a1a41847a206 100644
--- a/include/clang/Checker/PathSensitive/Store.h
+++ b/include/clang/Checker/PathSensitive/Store.h
@@ -149,9 +149,8 @@ public:
return UnknownVal();
}
- virtual const GRState *RemoveDeadBindings(GRState &state,
- const StackFrameContext *LCtx,
- SymbolReaper& SymReaper,
+ virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
@@ -159,25 +158,39 @@ public:
virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
-
- virtual Store InvalidateRegion(Store store,
- const MemRegion *R,
- const Expr *E, unsigned Count,
- InvalidatedSymbols *IS) = 0;
-
+ typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions;
+
+ /// InvalidateRegions - Clears out the specified regions from the store,
+ /// marking their values as unknown. Depending on the store, this may also
+ /// invalidate additional regions that may have changed based on accessing
+ /// the given regions. Optionally, invalidates non-static globals as well.
+ /// \param[in] store The initial store
+ /// \param[in] Begin A pointer to the first region to invalidate.
+ /// \param[in] End A pointer just past the last region to invalidate.
+ /// \param[in] E The current statement being evaluated. Used to conjure
+ /// symbols to mark the values of invalidated regions.
+ /// \param[in] Count The current block count. Used to conjure
+ /// symbols to mark the values of invalidated regions.
+ /// \param[in,out] IS A set to fill with any symbols that are no longer
+ /// accessible. Pass \c NULL if this information will not be used.
+ /// \param[in] invalidateGlobals If \c true, any non-static global regions
+ /// are invalidated as well.
+ /// \param[in,out] Regions A vector to fill with any regions being
+ /// invalidated. This should include any regions explicitly invalidated
+ /// even if they do not currently have bindings. Pass \c NULL if this
+ /// information will not be used.
virtual Store InvalidateRegions(Store store,
const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned Count,
InvalidatedSymbols *IS,
- bool invalidateGlobals) = 0;
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) = 0;
/// EnterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
- virtual const GRState *EnterStackFrame(const GRState *state,
- const StackFrameContext *frame) {
- return state;
- }
+ virtual Store EnterStackFrame(const GRState *state,
+ const StackFrameContext *frame);
virtual void print(Store store, llvm::raw_ostream& Out,
const char* nl, const char *sep) = 0;
diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h
index ffbd2892499e..26ed0c1bc06f 100644
--- a/include/clang/Checker/PathSensitive/SymbolManager.h
+++ b/include/clang/Checker/PathSensitive/SymbolManager.h
@@ -40,6 +40,7 @@ class SymExpr : public llvm::FoldingSetNode {
public:
enum Kind { BEGIN_SYMBOLS,
RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
+ MetadataKind,
END_SYMBOLS,
SymIntKind, SymSymKind };
private:
@@ -190,6 +191,9 @@ public:
}
};
+/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
+/// Clients should not ask the SymbolManager for a region's extent. Always use
+/// SubRegion::getExtent instead -- the value returned may not be a symbol.
class SymbolExtent : public SymbolData {
const SubRegion *R;
@@ -218,6 +222,51 @@ public:
}
};
+/// SymbolMetadata - Represents path-dependent metadata about a specific region.
+/// Metadata symbols remain live as long as they are marked as in use before
+/// dead-symbol sweeping AND their associated regions are still alive.
+/// Intended for use by checkers.
+class SymbolMetadata : public SymbolData {
+ const MemRegion* R;
+ const Stmt* S;
+ QualType T;
+ unsigned Count;
+ const void* Tag;
+public:
+ SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t,
+ unsigned count, const void* tag)
+ : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
+
+ const MemRegion *getRegion() const { return R; }
+ const Stmt* getStmt() const { return S; }
+ unsigned getCount() const { return Count; }
+ const void* getTag() const { return Tag; }
+
+ QualType getType(ASTContext&) const;
+
+ void dumpToStream(llvm::raw_ostream &os) const;
+
+ static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
+ const Stmt *S, QualType T, unsigned Count,
+ const void *Tag) {
+ profile.AddInteger((unsigned) MetadataKind);
+ profile.AddPointer(R);
+ profile.AddPointer(S);
+ profile.Add(T);
+ profile.AddInteger(Count);
+ profile.AddPointer(Tag);
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID& profile) {
+ Profile(profile, R, S, T, Count, Tag);
+ }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymExpr* SE) {
+ return SE->getKind() == MetadataKind;
+ }
+};
+
// SymIntExpr - Represents symbolic expression like 'x' + 3.
class SymIntExpr : public SymExpr {
const SymExpr *LHS;
@@ -336,6 +385,10 @@ public:
const SymbolExtent *getExtentSymbol(const SubRegion *R);
+ const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
+ QualType T, unsigned VisitCount,
+ const void* SymbolTag = 0);
+
const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t);
@@ -359,6 +412,7 @@ class SymbolReaper {
typedef llvm::DenseSet<SymbolRef> SetTy;
SetTy TheLiving;
+ SetTy MetadataInUse;
SetTy TheDead;
const LocationContext *LCtx;
const Stmt *Loc;
@@ -374,12 +428,24 @@ public:
const Stmt *getCurrentStatement() const { return Loc; }
bool isLive(SymbolRef sym);
-
bool isLive(const Stmt *ExprVal) const;
-
bool isLive(const VarRegion *VR) const;
-
+
+ // markLive - Unconditionally marks a symbol as live. This should never be
+ // used by checkers, only by the state infrastructure such as the store and
+ // environment. Checkers should instead use metadata symbols and markInUse.
void markLive(SymbolRef sym);
+
+ // markInUse - Marks a symbol as important to a checker. For metadata symbols,
+ // this will keep the symbol alive as long as its associated region is also
+ // live. For other symbols, this has no effect; checkers are not permitted
+ // to influence the life of other symbols. This should be used before any
+ // symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
+ void markInUse(SymbolRef sym);
+
+ // maybeDead - If a symbol is known to be live, marks the symbol as live.
+ // Otherwise, if the symbol cannot be proven live, it is marked as dead.
+ // Returns true if the symbol is dead, false if live.
bool maybeDead(SymbolRef sym);
typedef SetTy::const_iterator dead_iterator;
@@ -389,6 +455,13 @@ public:
bool hasDeadSymbols() const {
return !TheDead.empty();
}
+
+ /// isDead - Returns whether or not a symbol has been confirmed dead. This
+ /// should only be called once all marking of dead symbols has completed.
+ /// (For checkers, this means only in the EvalDeadSymbols callback.)
+ bool isDead(SymbolRef sym) const {
+ return TheDead.count(sym);
+ }
};
class SymbolVisitor {
diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h
index 5a9d54d337b0..b81e9c150234 100644
--- a/include/clang/Checker/PathSensitive/ValueManager.h
+++ b/include/clang/Checker/PathSensitive/ValueManager.h
@@ -106,6 +106,9 @@ public:
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
const TypedRegion *R);
+ DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR,
+ const Expr *E, QualType T, unsigned Count);
+
DefinedSVal getFunctionPointer(const FunctionDecl *FD);
DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 7076f30995d0..fd40aa0c5f4b 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -26,6 +26,8 @@ def target_cpu : Separate<"-target-cpu">,
HelpText<"Target a specific cpu type">;
def target_feature : Separate<"-target-feature">,
HelpText<"Target specific attributes">;
+def target_linker_version : Separate<"-target-linker-version">,
+ HelpText<"Target linker version">;
def triple : Separate<"-triple">,
HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
def triple_EQ : Joined<"-triple=">, Alias<triple>;
@@ -38,6 +40,8 @@ def analysis_CFGDump : Flag<"-cfg-dump">,
HelpText<"Display Control-Flow Graphs">;
def analysis_CFGView : Flag<"-cfg-view">,
HelpText<"View Control-Flow Graphs using GraphViz">;
+def analysis_UnoptimizedCFG : Flag<"-unoptimized-cfg">,
+ HelpText<"Generate unoptimized CFGs for all analyses">;
def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">,
HelpText<"Print results of live variable analysis">;
def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">,
@@ -58,6 +62,8 @@ def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">,
HelpText<"Run the [Core] Foundation reference count checker">;
def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
+def analysis_WarnIdempotentOps : Flag<"-analyzer-check-idempotent-operations">,
+ HelpText<"Warn about idempotent operations">;
def analyzer_store : Separate<"-analyzer-store">,
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
@@ -81,8 +87,6 @@ def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
HelpText<"Use experimental path-sensitive checks">;
-def analyzer_idempotent_operation : Flag<"-analyzer-idempotent-operation">,
- HelpText<"Use experimental path-sensitive idempotent operation checker">;
def analyzer_experimental_internal_checks :
Flag<"-analyzer-experimental-internal-checks">,
HelpText<"Use new default path-sensitive checks currently in testing">;
@@ -137,6 +141,8 @@ def ffunction_sections : Flag<"-ffunction-sections">,
HelpText<"Place each function in its own section (ELF Only)">;
def fdata_sections : Flag<"-fdata-sections">,
HelpText<"Place each data in its own section (ELF Only)">;
+def funroll_loops : Flag<"-funroll-loops">,
+ HelpText<"Turn on loop unroller">;
def masm_verbose : Flag<"-masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<"-mcode-model">,
@@ -209,6 +215,8 @@ def W : Joined<"-W">;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
HelpText<"Print source range spans in numeric form">;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">,
+ HelpText<"Print fix-its in machine parseable form">;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
HelpText<"Print diagnostic name with mappable diagnostics">;
def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
@@ -229,7 +237,7 @@ def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
HelpText<"Silence ObjC rewriting warnings">;
def Wwrite_strings : Flag<"-Wwrite-strings">,
- HelpText<"Add const qualifier to string literals">;
+ HelpText<"Remove const qualifier from string literals">;
def verify : Flag<"-verify">,
HelpText<"Verify emitted diagnostics and warnings">;
@@ -258,6 +266,8 @@ def code_completion_macros : Flag<"-code-completion-macros">,
HelpText<"Include macros in code-completion results">;
def code_completion_patterns : Flag<"-code-completion-patterns">,
HelpText<"Include code patterns in code-completion results">;
+def no_code_completion_globals : Flag<"-no-code-completion-globals">,
+ HelpText<"Do not include global declarations in code-completion results.">;
def disable_free : Flag<"-disable-free">,
HelpText<"Disable freeing of memory on exit">;
def help : Flag<"-help">,
@@ -296,16 +306,15 @@ def dump_tokens : Flag<"-dump-tokens">,
HelpText<"Run preprocessor, dump internal rep of tokens">;
def init_only : Flag<"-init-only">,
HelpText<"Only execute frontend initialization">;
-def parse_noop : Flag<"-parse-noop">,
- HelpText<"Run parser with noop callbacks (for timings)">;
def fsyntax_only : Flag<"-fsyntax-only">,
HelpText<"Run parser and perform semantic analysis">;
def fixit : Flag<"-fixit">,
HelpText<"Apply fix-it advice to the input source">;
def fixit_EQ : Joined<"-fixit=">,
HelpText<"Apply fix-it advice creating a file with the given suffix">;
-def parse_print_callbacks : Flag<"-parse-print-callbacks">,
- HelpText<"Run parser and print each callback invoked">;
+def print_preamble : Flag<"-print-preamble">,
+ HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit"
+ " precompiled headers.">;
def emit_html : Flag<"-emit-html">,
HelpText<"Output input source as HTML">;
def ast_print : Flag<"-ast-print">,
@@ -343,8 +352,13 @@ def rewrite_objc : Flag<"-rewrite-objc">,
def rewrite_macros : Flag<"-rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
+def create_module : Flag<"-create-module">,
+ HelpText<"Create a module definition file">;
}
+def import_module : Separate<"-import-module">,
+ HelpText<"Import a module definition file">;
+
def relocatable_pch : Flag<"-relocatable-pch">,
HelpText<"Whether to build a relocatable precompiled header">;
def chained_pch : Flag<"-chained-pch">,
@@ -353,9 +367,10 @@ def print_stats : Flag<"-print-stats">,
HelpText<"Print performance metrics and statistics">;
def ftime_report : Flag<"-ftime-report">,
HelpText<"Print the amount of time each phase of compilation takes">;
-
def fdump_record_layouts : Flag<"-fdump-record-layouts">,
HelpText<"Dump record layout information">;
+def fix_what_you_can : Flag<"-fix-what-you-can">,
+ HelpText<"Apply fix-it advice even in the presence of unfixable errors">;
// Generic forwarding to LLVM options. This should only be used for debugging
// and experimental features.
@@ -395,12 +410,16 @@ def ffreestanding : Flag<"-ffreestanding">,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fgnu_runtime : Flag<"-fgnu-runtime">,
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
+def fhidden_weak_vtables : Flag<"-fhidden-weak-vtables">,
+ HelpText<"Generate weak vtables and RTTI with hidden visibility">;
def std_EQ : Joined<"-std=">,
HelpText<"Language standard to compile for">;
def fmath_errno : Flag<"-fmath-errno">,
HelpText<"Require math functions to indicate errors by setting errno">;
def fms_extensions : Flag<"-fms-extensions">,
HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
+def fborland_extensions : Flag<"-fborland-extensions">,
+ HelpText<"Accept non-standard constructs supported by the Borland compiler">;
def main_file_name : Separate<"-main-file-name">,
HelpText<"Main file name to use for debug info">;
def fno_elide_constructors : Flag<"-fno-elide-constructors">,
@@ -444,6 +463,8 @@ def fpascal_strings : Flag<"-fpascal-strings">,
HelpText<"Recognize and construct Pascal-style string literals">;
def fno_rtti : Flag<"-fno-rtti">,
HelpText<"Disable generation of rtti information">;
+def fno_validate_pch : Flag<"-fno-validate-pch">,
+ HelpText<"Disable validation of precompiled headers">;
def fshort_wchar : Flag<"-fshort-wchar">,
HelpText<"Force wchar_t to be a short unsigned int">;
def static_define : Flag<"-static-define">,
@@ -483,6 +504,9 @@ def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
HelpText<"Add directory to QUOTE include search path">;
def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to SYSTEM include search path">;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">,MetaVarName<"<directory>">,
+ HelpText<"Add directory to SYSTEM include search path, "
+ "absolute paths are relative to -isysroot">;
def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,
@@ -508,6 +532,9 @@ def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">,
HelpText<"Include precompiled header file">;
def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">,
HelpText<"Include file before parsing">;
+def preamble_bytes_EQ : Joined<"-preamble-bytes=">,
+ HelpText<"Assume that the precompiled header is a precompiled preamble "
+ "covering the first N bytes of the main file">;
def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">,
HelpText<"Use specified token cache file">;
def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
@@ -531,3 +558,5 @@ def dM : Flag<"-dM">,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dD : Flag<"-dD">,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def H : Flag<"-H">,
+ HelpText<"Show header includes and nesting depth">;
diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h
index 5f062a121c6d..22d6b4ec6c8f 100644
--- a/include/clang/Driver/Compilation.h
+++ b/include/clang/Driver/Compilation.h
@@ -80,6 +80,8 @@ public:
JobList &getJobs() { return Jobs; }
const JobList &getJobs() const { return Jobs; }
+ void addCommand(Command *C) { Jobs.addJob(C); }
+
const ArgStringList &getTempFiles() const { return TempFiles; }
const ArgStringList &getResultFiles() const { return ResultFiles; }
diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h
index bb578b516ce3..28eff4f1d71d 100644
--- a/include/clang/Driver/Driver.h
+++ b/include/clang/Driver/Driver.h
@@ -37,7 +37,6 @@ namespace driver {
class InputInfo;
class JobAction;
class OptTable;
- class PipedJob;
class ToolChain;
/// Driver - Encapsulate logic for constructing compilation processes
@@ -65,6 +64,9 @@ public:
/// The original path to the clang executable.
std::string ClangExecutable;
+ /// The path to the installed clang directory, if any.
+ std::string InstalledDir;
+
/// The path to the compiler resource directory.
std::string ResourceDir;
@@ -145,7 +147,7 @@ private:
DerivedArgList *TranslateInputArgs(const InputArgList &Args) const;
public:
- Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
+ Driver(llvm::StringRef _ClangExecutable,
llvm::StringRef _DefaultHostTriple,
llvm::StringRef _DefaultImageName,
bool IsProduction, bool CXXIsProduction,
@@ -167,8 +169,18 @@ public:
void setTitle(std::string Value) { DriverTitle = Value; }
/// \brief Get the path to the main clang executable.
- std::string getClangProgramPath() const {
- return ClangExecutable;
+ const char *getClangProgramPath() const {
+ return ClangExecutable.c_str();
+ }
+
+ /// \brief Get the path to where the clang executable was installed.
+ const char *getInstalledDir() const {
+ if (!InstalledDir.empty())
+ return InstalledDir.c_str();
+ return Dir.c_str();
+ }
+ void setInstalledDir(llvm::StringRef Value) {
+ InstalledDir = Value;
}
/// @}
@@ -194,16 +206,20 @@ public:
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
///
+ /// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildActions(const ArgList &Args, ActionList &Actions) const;
+ void BuildActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const;
/// BuildUniversalActions - Construct the list of actions to perform
/// for the given arguments, which may require a universal build.
///
+ /// \param TC - The default host tool chain.
/// \param Args - The input arguments.
/// \param Actions - The list to store the resulting actions onto.
- void BuildUniversalActions(const ArgList &Args, ActionList &Actions) const;
+ void BuildUniversalActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const;
/// BuildJobs - Bind actions to concrete tools and translate
/// arguments to form the list of jobs to run.
@@ -278,7 +294,6 @@ public:
const Action *A,
const ToolChain *TC,
const char *BoundArch,
- bool CanAcceptPipe,
bool AtTopLevel,
const char *LinkingOutput,
InputInfo &Result) const;
diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h
index 1b99a4459d16..04e72992d684 100644
--- a/include/clang/Driver/HostInfo.h
+++ b/include/clang/Driver/HostInfo.h
@@ -10,7 +10,6 @@
#ifndef CLANG_DRIVER_HOSTINFO_H_
#define CLANG_DRIVER_HOSTINFO_H_
-#include "clang/Driver/Types.h"
#include "llvm/ADT/Triple.h"
#include <string>
@@ -48,10 +47,6 @@ public:
/// this host and support -arch, -Xarch, etc.
virtual bool useDriverDriver() const = 0;
- /// lookupTypeForExtension - Return the default language type to use for the
- /// given extension.
- virtual types::ID lookupTypeForExtension(const char *Ext) const = 0;
-
/// CreateToolChain - Construct the toolchain to use for this host (which the
/// host retains ownership of).
///
@@ -84,6 +79,10 @@ const HostInfo *createLinuxHostInfo(const Driver &D,
const llvm::Triple& Triple);
const HostInfo *createTCEHostInfo(const Driver &D,
const llvm::Triple& Triple);
+const HostInfo *createWindowsHostInfo(const Driver &D,
+ const llvm::Triple &Triple);
+const HostInfo *createMinGWHostInfo(const Driver &D,
+ const llvm::Triple &Triple);
const HostInfo *createUnknownHostInfo(const Driver &D,
const llvm::Triple& Triple);
diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h
index 5a789fbb8f41..d2767d1b877b 100644
--- a/include/clang/Driver/Job.h
+++ b/include/clang/Driver/Job.h
@@ -29,7 +29,6 @@ class Job {
public:
enum JobClass {
CommandClass,
- PipedJobClass,
JobListClass
};
@@ -86,39 +85,6 @@ public:
static bool classof(const Command *) { return true; }
};
- /// PipedJob - A list of Commands which should be executed together
- /// with their standard inputs and outputs connected.
-class PipedJob : public Job {
-public:
- typedef llvm::SmallVector<Command*, 4> list_type;
- typedef list_type::size_type size_type;
- typedef list_type::iterator iterator;
- typedef list_type::const_iterator const_iterator;
-
-private:
- list_type Commands;
-
-public:
- PipedJob();
- virtual ~PipedJob();
-
- /// Add a command to the piped job (taking ownership).
- void addCommand(Command *C) { Commands.push_back(C); }
-
- const list_type &getCommands() const { return Commands; }
-
- size_type size() const { return Commands.size(); }
- iterator begin() { return Commands.begin(); }
- const_iterator begin() const { return Commands.begin(); }
- iterator end() { return Commands.end(); }
- const_iterator end() const { return Commands.end(); }
-
- static bool classof(const Job *J) {
- return J->getKind() == PipedJobClass;
- }
- static bool classof(const PipedJob *) { return true; }
-};
-
/// JobList - A sequence of jobs to perform.
class JobList : public Job {
public:
diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td
index a9f4289fc86e..04efd00fb1d8 100644
--- a/include/clang/Driver/OptParser.td
+++ b/include/clang/Driver/OptParser.td
@@ -82,6 +82,9 @@ def Unsupported : OptionFlag;
// arguments to implement hidden help groups.
def HelpHidden : OptionFlag;
+// NoForward - The option should not be implicitly forwarded to other tools.
+def NoForward : OptionFlag;
+
// Define the option group class.
class OptionGroup<string name> {
diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h
index e4a2eba578b8..08b483c90017 100644
--- a/include/clang/Driver/OptTable.h
+++ b/include/clang/Driver/OptTable.h
@@ -25,10 +25,11 @@ namespace options {
HelpHidden = (1 << 1),
LinkerInput = (1 << 2),
NoArgumentUnused = (1 << 3),
- RenderAsInput = (1 << 4),
- RenderJoined = (1 << 5),
- RenderSeparate = (1 << 6),
- Unsupported = (1 << 7)
+ NoForward = (1 << 4),
+ RenderAsInput = (1 << 5),
+ RenderJoined = (1 << 6),
+ RenderSeparate = (1 << 7),
+ Unsupported = (1 << 8)
};
}
@@ -52,7 +53,7 @@ namespace options {
const char *HelpText;
const char *MetaVar;
unsigned char Kind;
- unsigned char Flags;
+ unsigned short Flags;
unsigned char Param;
unsigned short GroupID;
unsigned short AliasID;
diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h
index 0864382cb3a6..9625465f48f4 100644
--- a/include/clang/Driver/Option.h
+++ b/include/clang/Driver/Option.h
@@ -92,6 +92,9 @@ namespace driver {
/// This option should not report argument unused errors.
bool NoArgumentUnused : 1;
+ /// This option should not be implicitly forwarded.
+ bool NoForward : 1;
+
protected:
Option(OptionClass Kind, OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias);
@@ -124,7 +127,12 @@ namespace driver {
bool hasNoArgumentUnused() const { return NoArgumentUnused; }
void setNoArgumentUnused(bool Value) { NoArgumentUnused = Value; }
- bool hasForwardToGCC() const { return !DriverOption && !LinkerInput; }
+ bool hasNoForward() const { return NoForward; }
+ void setNoForward(bool Value) { NoForward = Value; }
+
+ bool hasForwardToGCC() const {
+ return !NoForward && !DriverOption && !LinkerInput;
+ }
/// getUnaliasedOption - Return the final option this option
/// aliases (itself, if the option has no alias).
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 73c8e6bda2e4..c51d12a48769 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -180,7 +180,8 @@ def Xarch__ : JoinedAndSeparate<"-Xarch_">, Flags<[DriverOption]>;
def Xassembler : Separate<"-Xassembler">,
HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">;
def Xclang : Separate<"-Xclang">,
- HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">;
+ HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">,
+ Flags<[NoForward]>;
def Xlinker : Separate<"-Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">;
def Xpreprocessor : Separate<"-Xpreprocessor">,
@@ -242,6 +243,7 @@ def fast : Flag<"-fast">, Group<f_Group>;
def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>;
def fblocks : Flag<"-fblocks">, Group<f_Group>;
def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
+def fborland_extensions : Flag<"-fborland-extensions">, Group<f_Group>;
def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;
def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>;
def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>;
@@ -260,6 +262,7 @@ def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>;
def fdiagnostics_binary : Flag<"-fdiagnostics-binary">, Group<f_Group>, Flags<[HelpHidden]>;
def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>;
def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>;
+def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>;
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>;
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;
@@ -300,6 +303,7 @@ def fno_asm : Flag<"-fno-asm">, Group<f_Group>;
def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>;
def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>;
def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>;
+def fno_borland_extensions : Flag<"-fno-borland-extensions">, Group<f_Group>;
def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>;
def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>;
def fno_builtin : Flag<"-fno-builtin">, Group<f_Group>;
@@ -361,6 +365,7 @@ def fno_pie : Flag<"-fno-pie">, Group<f_Group>;
def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>;
def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>;
def framework : Separate<"-framework">, Flags<[LinkerInput]>;
+def frandom_seed_EQ : Joined<"-frandom-seed=">, Group<clang_ignored_f_Group>;
def frtti : Flag<"-frtti">, Group<f_Group>;
def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>;
def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>;
@@ -385,6 +390,7 @@ def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>;
def ftime_report : Flag<"-ftime-report">, Group<f_Group>;
def ftrapv : Flag<"-ftrapv">, Group<f_Group>;
def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>;
+def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>;
def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<"-funsigned-char">, Group<f_Group>;
def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>;
@@ -420,7 +426,7 @@ def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>;
def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>;
def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>;
def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>;
-def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<i_Group>;
+def iwithsysroot : JoinedOrSeparate<"-iwithsysroot">, Group<clang_i_Group>;
def i : Joined<"-i">, Group<i_Group>;
def keep__private__externs : Flag<"-keep_private_externs">;
def l : JoinedOrSeparate<"-l">, Flags<[LinkerInput, RenderJoined]>;
@@ -441,6 +447,7 @@ def mhard_float : Flag<"-mhard-float">, Group<m_Group>;
def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>;
def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_min_EQ>;
def mkernel : Flag<"-mkernel">, Group<m_Group>;
+def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>;
def mllvm : Separate<"-mllvm">;
def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>;
def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>;
@@ -461,6 +468,7 @@ def mno_sse4_2 : Flag<"-mno-sse4.2">, Group<m_x86_Features_Group>;
def mno_sse : Flag<"-mno-sse">, Group<m_x86_Features_Group>;
def mno_ssse3 : Flag<"-mno-ssse3">, Group<m_x86_Features_Group>;
def mno_aes : Flag<"-mno-aes">, Group<m_x86_Features_Group>;
+def mno_avx : Flag<"-mno-avx">, Group<m_x86_Features_Group>;
def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>;
def marm : Flag<"-marm">, Alias<mno_thumb>;
@@ -481,6 +489,7 @@ def msse4_2 : Flag<"-msse4.2">, Group<m_x86_Features_Group>;
def msse : Flag<"-msse">, Group<m_x86_Features_Group>;
def mssse3 : Flag<"-mssse3">, Group<m_x86_Features_Group>;
def maes : Flag<"-maes">, Group<m_x86_Features_Group>;
+def mavx : Flag<"-mavx">, Group<m_x86_Features_Group>;
def mthumb : Flag<"-mthumb">, Group<m_Group>;
def mtune_EQ : Joined<"-mtune=">, Group<m_Group>;
def multi__module : Flag<"-multi_module">;
diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h
index 4368a81e3a41..c30fa4c6e731 100644
--- a/include/clang/Driver/Tool.h
+++ b/include/clang/Driver/Tool.h
@@ -49,8 +49,6 @@ public:
const ToolChain &getToolChain() const { return TheToolChain; }
- virtual bool acceptsPipedInput() const = 0;
- virtual bool canPipeOutput() const = 0;
virtual bool hasIntegratedAssembler() const { return false; }
virtual bool hasIntegratedCPP() const = 0;
@@ -61,13 +59,11 @@ public:
/// ConstructJob - Construct jobs to perform the action \arg JA,
/// writing to \arg Output and with \arg Inputs.
///
- /// \param Dest - Where to put the resulting commands.
/// \param TCArgs - The argument list for this toolchain, with any
/// tool chain specific translations applied.
/// \param LinkingOutput - If this output will eventually feed the
/// linker, then this is the final output name of the linked image.
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index 11a153c48ca3..55be4eee3d19 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -10,6 +10,7 @@
#ifndef CLANG_DRIVER_TOOLCHAIN_H_
#define CLANG_DRIVER_TOOLCHAIN_H_
+#include "clang/Driver/Types.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/System/Path.h"
@@ -17,6 +18,7 @@
namespace clang {
namespace driver {
+ class ArgList;
class Compilation;
class DerivedArgList;
class Driver;
@@ -53,6 +55,7 @@ public:
const Driver &getDriver() const;
const llvm::Triple &getTriple() const { return Triple; }
+ llvm::Triple::ArchType getArch() const { return Triple.getArch(); }
llvm::StringRef getArchName() const { return Triple.getArchName(); }
llvm::StringRef getPlatform() const { return Triple.getVendorName(); }
llvm::StringRef getOS() const { return Triple.getOSName(); }
@@ -89,6 +92,10 @@ public:
// Platform defaults information
+ /// LookupTypeForExtension - Return the default language type to use for the
+ /// given extension.
+ virtual types::ID LookupTypeForExtension(const char *Ext) const;
+
/// IsBlocksDefault - Does this tool chain enable -fblocks by default.
virtual bool IsBlocksDefault() const { return false; }
@@ -135,6 +142,17 @@ public:
/// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
virtual bool UseSjLjExceptions() const { return false; }
+
+ /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
+ /// command line arguments into account.
+ virtual std::string ComputeLLVMTriple(const ArgList &Args) const;
+
+ /// ComputeEffectiveClangTriple - Return the Clang triple to use for this
+ /// target, which may take into account the command line arguments. For
+ /// example, on Darwin the -mmacosx-version-min= command line argument (which
+ /// sets the deployment target) determines the version in the triple passed to
+ /// Clang.
+ virtual std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
};
} // end namespace driver
diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h
index 2d1df44cc968..cca243d6cd71 100644
--- a/include/clang/Frontend/ASTConsumers.h
+++ b/include/clang/Frontend/ASTConsumers.h
@@ -29,7 +29,6 @@ class CodeGenOptions;
class Diagnostic;
class FileManager;
class LangOptions;
-class PCHReader;
class Preprocessor;
class TargetOptions;
@@ -58,14 +57,6 @@ ASTConsumer *CreateASTViewer();
// to stderr; this is intended for debugging.
ASTConsumer *CreateDeclContextPrinter();
-// PCH generator: generates a precompiled header file; this file can be used
-// later with the PCHReader (clang -cc1 option -include-pch) to speed up compile
-// times.
-ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
- llvm::raw_ostream *OS,
- PCHReader *Chain,
- const char *isysroot = 0);
-
// Inheritance viewer: for C++ code, creates a graph of the inheritance
// tree for the given class and displays it with "dotty".
ASTConsumer *CreateInheritanceViewer(const std::string& clsname);
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 9252358f42a6..e3fd4b37edac 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -14,19 +14,26 @@
#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
#define LLVM_CLANG_FRONTEND_ASTUNIT_H
+#include "clang/Index/ASTLocation.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang-c/Index.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Index/ASTLocation.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/System/Path.h"
+#include "llvm/Support/Timer.h"
#include <map>
#include <string>
#include <vector>
#include <cassert>
#include <utility>
+#include <sys/types.h>
namespace llvm {
class MemoryBuffer;
@@ -34,6 +41,7 @@ namespace llvm {
namespace clang {
class ASTContext;
+class CodeCompleteConsumer;
class CompilerInvocation;
class Decl;
class Diagnostic;
@@ -45,13 +53,14 @@ class SourceManager;
class TargetInfo;
using namespace idx;
-
-/// \brief Utility class for loading a ASTContext from a PCH file.
+
+/// \brief Utility class for loading a ASTContext from an AST file.
///
class ASTUnit {
public:
typedef std::map<FileID, std::vector<PreprocessedEntity *> >
PreprocessedEntitiesByFileMap;
+
private:
llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
llvm::OwningPtr<FileManager> FileMgr;
@@ -61,18 +70,32 @@ private:
llvm::OwningPtr<Preprocessor> PP;
llvm::OwningPtr<ASTContext> Ctx;
+ /// \brief The AST consumer that received information about the translation
+ /// unit as it was parsed or loaded.
+ llvm::OwningPtr<ASTConsumer> Consumer;
+
+ /// \brief The semantic analysis object used to type-check the translation
+ /// unit.
+ llvm::OwningPtr<Sema> TheSema;
+
/// Optional owned invocation, just used to make the invocation used in
/// LoadFromCommandLine available.
llvm::OwningPtr<CompilerInvocation> Invocation;
-
+
// OnlyLocalDecls - when true, walking this AST should only visit declarations
// that come from the AST itself, not from included precompiled headers.
// FIXME: This is temporary; eventually, CIndex will always do this.
bool OnlyLocalDecls;
- /// Track whether the main file was loaded from an AST or not.
+ /// \brief Whether to capture any diagnostics produced.
+ bool CaptureDiagnostics;
+
+ /// \brief Track whether the main file was loaded from an AST or not.
bool MainFileIsAST;
+ /// \brief Whether this AST represents a complete translation unit.
+ bool CompleteTranslationUnit;
+
/// Track the top-level decls which appeared in an ASTUnit which was loaded
/// from a source file.
//
@@ -114,12 +137,189 @@ private:
unsigned int ConcurrencyCheckValue;
static const unsigned int CheckLocked = 28573289;
static const unsigned int CheckUnlocked = 9803453;
+
+ /// \brief Counter that determines when we want to try building a
+ /// precompiled preamble.
+ ///
+ /// If zero, we will never build a precompiled preamble. Otherwise,
+ /// it's treated as a counter that decrements each time we reparse
+ /// without the benefit of a precompiled preamble. When it hits 1,
+ /// we'll attempt to rebuild the precompiled header. This way, if
+ /// building the precompiled preamble fails, we won't try again for
+ /// some number of calls.
+ unsigned PreambleRebuildCounter;
+
+ /// \brief The file in which the precompiled preamble is stored.
+ std::string PreambleFile;
+
+ /// \brief The contents of the preamble that has been precompiled to
+ /// \c PreambleFile.
+ std::vector<char> Preamble;
+
+ /// \brief Whether the preamble ends at the start of a new line.
+ ///
+ /// Used to inform the lexer as to whether it's starting at the beginning of
+ /// a line after skipping the preamble.
+ bool PreambleEndsAtStartOfLine;
+
+ /// \brief The size of the source buffer that we've reserved for the main
+ /// file within the precompiled preamble.
+ unsigned PreambleReservedSize;
+
+ /// \brief Keeps track of the files that were used when computing the
+ /// preamble, with both their buffer size and their modification time.
+ ///
+ /// If any of the files have changed from one compile to the next,
+ /// the preamble must be thrown away.
+ llvm::StringMap<std::pair<off_t, time_t> > FilesInPreamble;
+
+ /// \brief When non-NULL, this is the buffer used to store the contents of
+ /// the main file when it has been padded for use with the precompiled
+ /// preamble.
+ llvm::MemoryBuffer *SavedMainFileBuffer;
+
+ /// \brief When non-NULL, this is the buffer used to store the
+ /// contents of the preamble when it has been padded to build the
+ /// precompiled preamble.
+ llvm::MemoryBuffer *PreambleBuffer;
+
+ /// \brief The number of warnings that occurred while parsing the preamble.
+ ///
+ /// This value will be used to restore the state of the \c Diagnostic object
+ /// when re-using the precompiled preamble. Note that only the
+ /// number of warnings matters, since we will not save the preamble
+ /// when any errors are present.
+ unsigned NumWarningsInPreamble;
+
+ /// \brief The number of diagnostics that were stored when parsing
+ /// the precompiled preamble.
+ ///
+ /// This value is used to determine how many of the stored
+ /// diagnostics should be retained when reparsing in the presence of
+ /// a precompiled preamble.
+ unsigned NumStoredDiagnosticsInPreamble;
+
+ /// \brief The group of timers associated with this translation unit.
+ llvm::OwningPtr<llvm::TimerGroup> TimerGroup;
+
+ /// \brief A list of the serialization ID numbers for each of the top-level
+ /// declarations parsed within the precompiled preamble.
+ std::vector<serialization::DeclID> TopLevelDeclsInPreamble;
+
+ ///
+ /// \defgroup CodeCompleteCaching Code-completion caching
+ ///
+ /// \{
+ ///
+
+ /// \brief Whether we should be caching code-completion results.
+ bool ShouldCacheCodeCompletionResults;
+
+public:
+ /// \brief A cached code-completion result, which may be introduced in one of
+ /// many different contexts.
+ struct CachedCodeCompletionResult {
+ /// \brief The code-completion string corresponding to this completion
+ /// result.
+ CodeCompletionString *Completion;
+
+ /// \brief A bitmask that indicates which code-completion contexts should
+ /// contain this completion result.
+ ///
+ /// The bits in the bitmask correspond to the values of
+ /// CodeCompleteContext::Kind. To map from a completion context kind to a
+ /// bit, subtract one from the completion context kind and shift 1 by that
+ /// number of bits. Many completions can occur in several different
+ /// contexts.
+ unsigned ShowInContexts;
+
+ /// \brief The priority given to this code-completion result.
+ unsigned Priority;
+
+ /// \brief The libclang cursor kind corresponding to this code-completion
+ /// result.
+ CXCursorKind Kind;
+
+ /// \brief The availability of this code-completion result.
+ CXAvailabilityKind Availability;
+
+ /// \brief The simplified type class for a non-macro completion result.
+ SimplifiedTypeClass TypeClass;
+
+ /// \brief The type of a non-macro completion result, stored as a unique
+ /// integer used by the string map of cached completion types.
+ ///
+ /// This value will be zero if the type is not known, or a unique value
+ /// determined by the formatted type string. Se \c CachedCompletionTypes
+ /// for more information.
+ unsigned Type;
+ };
+
+ /// \brief Retrieve the mapping from formatted type names to unique type
+ /// identifiers.
+ llvm::StringMap<unsigned> &getCachedCompletionTypes() {
+ return CachedCompletionTypes;
+ }
+
+private:
+ /// \brief The set of cached code-completion results.
+ std::vector<CachedCodeCompletionResult> CachedCompletionResults;
+
+ /// \brief A mapping from the formatted type name to a unique number for that
+ /// type, which is used for type equality comparisons.
+ llvm::StringMap<unsigned> CachedCompletionTypes;
+
+ /// \brief The number of top-level declarations present the last time we
+ /// cached code-completion results.
+ ///
+ /// The value is used to help detect when we should repopulate the global
+ /// completion cache.
+ unsigned NumTopLevelDeclsAtLastCompletionCache;
+
+ /// \brief The number of reparses left until we'll consider updating the
+ /// code-completion cache.
+ ///
+ /// This is meant to avoid thrashing during reparsing, by not allowing the
+ /// code-completion cache to be updated on every reparse.
+ unsigned CacheCodeCompletionCoolDown;
+
+ /// \brief Bit used by CIndex to mark when a translation unit may be in an
+ /// inconsistent state, and is not safe to free.
+ unsigned UnsafeToFree : 1;
+
+ /// \brief Cache any "global" code-completion results, so that we can avoid
+ /// recomputing them with each completion.
+ void CacheCodeCompletionResults();
+
+ /// \brief Clear out and deallocate
+ void ClearCachedCompletionResults();
+
+ ///
+ /// \}
+ ///
+
+ /// \brief The timers we've created from the various parses, reparses, etc.
+ /// involved in this translation unit.
+ std::vector<llvm::Timer *> Timers;
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
explicit ASTUnit(bool MainFileIsAST);
+ void CleanTemporaryFiles();
+ bool Parse(llvm::MemoryBuffer *OverrideMainBuffer);
+
+ std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
+ ComputePreamble(CompilerInvocation &Invocation,
+ unsigned MaxLines, bool &CreatedBuffer);
+
+ llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
+ bool AllowRebuild = true,
+ unsigned MaxLines = 0);
+ void RealizeTopLevelDeclsFromPreamble();
+
public:
class ConcurrencyCheck {
volatile ASTUnit &Self;
@@ -143,6 +343,9 @@ public:
bool isMainFileAST() const { return MainFileIsAST; }
+ bool isUnsafeToFree() const { return UnsafeToFree; }
+ void setUnsafeToFree(bool Value) { UnsafeToFree = Value; }
+
const Diagnostic &getDiagnostics() const { return *Diagnostics; }
Diagnostic &getDiagnostics() { return *Diagnostics; }
@@ -155,11 +358,17 @@ public:
const ASTContext &getASTContext() const { return *Ctx.get(); }
ASTContext &getASTContext() { return *Ctx.get(); }
+ bool hasSema() const { return TheSema; }
+ Sema &getSema() const {
+ assert(TheSema && "ASTUnit does not have a Sema object!");
+ return *TheSema;
+ }
+
const FileManager &getFileManager() const { return *FileMgr; }
FileManager &getFileManager() { return *FileMgr; }
const std::string &getOriginalSourceFileName();
- const std::string &getPCHFileName();
+ const std::string &getASTFileName();
/// \brief Add a temporary file that the ASTUnit depends on.
///
@@ -170,16 +379,48 @@ public:
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ /// \brief Retrieve the maximum PCH level of declarations that a
+ /// traversal of the translation unit should consider.
+ unsigned getMaxPCHLevel() const;
+
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
ASTLocation getLastASTLocation() const { return LastLoc; }
- std::vector<Decl*> &getTopLevelDecls() {
+ typedef std::vector<Decl *>::iterator top_level_iterator;
+
+ top_level_iterator top_level_begin() {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.begin();
+ }
+
+ top_level_iterator top_level_end() {
+ assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
+ if (!TopLevelDeclsInPreamble.empty())
+ RealizeTopLevelDeclsFromPreamble();
+ return TopLevelDecls.end();
+ }
+
+ std::size_t top_level_size() const {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
- return TopLevelDecls;
+ return TopLevelDeclsInPreamble.size() + TopLevelDecls.size();
}
- const std::vector<Decl*> &getTopLevelDecls() const {
+
+ bool top_level_empty() const {
assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!");
- return TopLevelDecls;
+ return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty();
+ }
+
+ /// \brief Add a new top-level declaration.
+ void addTopLevelDecl(Decl *D) {
+ TopLevelDecls.push_back(D);
+ }
+
+ /// \brief Add a new top-level declaration, identified by its ID in
+ /// the precompiled preamble.
+ void addTopLevelDeclFromPreamble(serialization::DeclID D) {
+ TopLevelDeclsInPreamble.push_back(D);
}
/// \brief Retrieve the mapping from File IDs to the preprocessed entities
@@ -202,19 +443,40 @@ public:
return StoredDiagnostics;
}
+ typedef std::vector<CachedCodeCompletionResult>::iterator
+ cached_completion_iterator;
+
+ cached_completion_iterator cached_completion_begin() {
+ return CachedCompletionResults.begin();
+ }
+
+ cached_completion_iterator cached_completion_end() {
+ return CachedCompletionResults.end();
+ }
+
+ unsigned cached_completion_size() const {
+ return CachedCompletionResults.size();
+ }
+
+ /// \brief Whether this AST represents a complete translation unit.
+ ///
+ /// If false, this AST is only a partial translation unit, e.g., one
+ /// that might still be used as a precompiled header or preamble.
+ bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; }
+
/// \brief A mapping from a file name to the memory buffer that stores the
/// remapped contents of that file.
typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile;
- /// \brief Create a ASTUnit from a PCH file.
+ /// \brief Create a ASTUnit from an AST file.
///
- /// \param Filename - The PCH file to load.
+ /// \param Filename - The AST file to load.
///
/// \param Diags - The diagnostics engine to use for reporting errors; its
/// lifetime is expected to extend past that of the returned ASTUnit.
///
- /// \returns - The initialized ASTUnit or null if the PCH failed to load.
- static ASTUnit *LoadFromPCHFile(const std::string &Filename,
+ /// \returns - The initialized ASTUnit or null if the AST failed to load.
+ static ASTUnit *LoadFromASTFile(const std::string &Filename,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls = false,
RemappedFile *RemappedFiles = 0,
@@ -235,7 +497,10 @@ public:
static ASTUnit *LoadFromCompilerInvocation(CompilerInvocation *CI,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls = false,
- bool CaptureDiagnostics = false);
+ bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false,
+ bool CompleteTranslationUnit = true,
+ bool CacheCodeCompletionResults = false);
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
/// arguments, which must specify exactly one source file.
@@ -258,7 +523,49 @@ public:
bool OnlyLocalDecls = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0,
- bool CaptureDiagnostics = false);
+ bool CaptureDiagnostics = false,
+ bool PrecompilePreamble = false,
+ bool CompleteTranslationUnit = true,
+ bool CacheCodeCompletionResults = false);
+
+ /// \brief Reparse the source files using the same command-line options that
+ /// were originally used to produce this translation unit.
+ ///
+ /// \returns True if a failure occurred that causes the ASTUnit not to
+ /// contain any translation-unit information, false otherwise.
+ bool Reparse(RemappedFile *RemappedFiles = 0,
+ unsigned NumRemappedFiles = 0);
+
+ /// \brief Perform code completion at the given file, line, and
+ /// column within this translation unit.
+ ///
+ /// \param File The file in which code completion will occur.
+ ///
+ /// \param Line The line at which code completion will occur.
+ ///
+ /// \param Column The column at which code completion will occur.
+ ///
+ /// \param IncludeMacros Whether to include macros in the code-completion
+ /// results.
+ ///
+ /// \param IncludeCodePatterns Whether to include code patterns (such as a
+ /// for loop) in the code-completion results.
+ ///
+ /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and
+ /// OwnedBuffers parameters are all disgusting hacks. They will go away.
+ void CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
+ RemappedFile *RemappedFiles, unsigned NumRemappedFiles,
+ bool IncludeMacros, bool IncludeCodePatterns,
+ CodeCompleteConsumer &Consumer,
+ Diagnostic &Diag, LangOptions &LangOpts,
+ SourceManager &SourceMgr, FileManager &FileMgr,
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
+
+ /// \brief Save this translation unit to a file with the given name.
+ ///
+ /// \returns True if an error occurred, false otherwise.
+ bool Save(llvm::StringRef File);
};
} // namespace clang
diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h
index ab4aed96d864..9ed15ba2f996 100644
--- a/include/clang/Frontend/AnalyzerOptions.h
+++ b/include/clang/Frontend/AnalyzerOptions.h
@@ -66,6 +66,7 @@ public:
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
unsigned EagerlyAssume : 1;
+ unsigned IdempotentOps : 1;
unsigned PurgeDead : 1;
unsigned TrimGraph : 1;
unsigned VisualizeEGDot : 1;
@@ -74,6 +75,7 @@ public:
unsigned EnableExperimentalInternalChecks : 1;
unsigned EnableIdempotentOperationChecker : 1;
unsigned InlineCall : 1;
+ unsigned UnoptimizedCFG : 1;
public:
AnalyzerOptions() {
@@ -90,6 +92,7 @@ public:
VisualizeEGUbi = 0;
EnableExperimentalChecks = 0;
EnableExperimentalInternalChecks = 0;
+ UnoptimizedCFG = 0;
}
};
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index 2918f4e9d3cb..b3f57094b4af 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -46,7 +46,14 @@ public:
/// internal state before optimizations are
/// done.
unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled.
+ unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl*
+ /// various IR entities came from. Only useful
+ /// when running CodeGen as a subroutine.
unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled
+ unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for
+ /// template classes with hidden visibility
+ unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with
+ /// hidden visibility
unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is enabled
unsigned MergeAllConstants : 1; /// Merge identical constants.
unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled.
@@ -67,9 +74,6 @@ public:
unsigned UnwindTables : 1; /// Emit unwind tables.
unsigned VerifyModule : 1; /// Control whether the module should be run
/// through the LLVM Verifier.
- unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl*
- /// various IR entities came from. Only useful
- /// when running CodeGen as a subroutine.
/// The code model to use (-mcmodel).
std::string CodeModel;
@@ -108,7 +112,11 @@ public:
DisableFPElim = 0;
DisableLLVMOpts = 0;
DisableRedZone = 0;
+ EmitDeclMetadata = 0;
FunctionSections = 0;
+ HiddenWeakTemplateVTables = 0;
+ HiddenWeakVTables = 0;
+ InstrumentFunctions = 0;
MergeAllConstants = 1;
NoCommon = 0;
NoImplicitFloat = 0;
@@ -125,7 +133,6 @@ public:
UnrollLoops = 0;
UnwindTables = 0;
VerifyModule = 1;
- EmitDeclMetadata = 0;
Inlining = NoInlining;
RelocationModel = "pic";
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index 54ce8bfe3ba0..1b3c336fc0eb 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -34,8 +34,9 @@ class DiagnosticClient;
class ExternalASTSource;
class FileManager;
class FrontendAction;
-class PCHReader;
+class ASTReader;
class Preprocessor;
+class Sema;
class SourceManager;
class TargetInfo;
@@ -67,9 +68,6 @@ class CompilerInstance {
/// The diagnostics engine instance.
llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics;
- /// The diagnostics client instance.
- llvm::OwningPtr<DiagnosticClient> DiagClient;
-
/// The target being compiled for.
llvm::OwningPtr<TargetInfo> Target;
@@ -91,15 +89,15 @@ class CompilerInstance {
/// The code completion consumer.
llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer;
+ /// \brief The semantic analysis object.
+ llvm::OwningPtr<Sema> TheSema;
+
/// The frontend timer
llvm::OwningPtr<llvm::Timer> FrontendTimer;
/// The list of active output files.
std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles;
- /// The PCH reader. Not owned; the ASTContext owns this.
- PCHReader *Reader;
-
void operator=(const CompilerInstance &); // DO NOT IMPLEMENT
CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT
public:
@@ -265,18 +263,11 @@ public:
void setDiagnostics(Diagnostic *Value);
DiagnosticClient &getDiagnosticClient() const {
- assert(DiagClient && "Compiler instance has no diagnostic client!");
- return *DiagClient;
+ assert(Diagnostics && Diagnostics->getClient() &&
+ "Compiler instance has no diagnostic client!");
+ return *Diagnostics->getClient();
}
- /// 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
/// {
@@ -372,6 +363,10 @@ public:
/// takes ownership of \arg Value.
void setASTContext(ASTContext *Value);
+ /// \brief Replace the current Sema; the compiler instance takes ownership
+ /// of S.
+ void setSema(Sema *S);
+
/// }
/// @name ASTConsumer
/// {
@@ -392,6 +387,18 @@ public:
void setASTConsumer(ASTConsumer *Value);
/// }
+ /// @name Semantic analysis
+ /// {
+ bool hasSema() const { return TheSema != 0; }
+
+ Sema &getSema() const {
+ assert(TheSema && "Compiler instance has no Sema object!");
+ return *TheSema;
+ }
+
+ Sema *takeSema() { return TheSema.take(); }
+
+ /// }
/// @name Code Completion
/// {
@@ -502,17 +509,18 @@ public:
/// Create an external AST source to read a PCH file and attach it to the AST
/// context.
- void createPCHExternalASTSource(llvm::StringRef Path);
+ void createPCHExternalASTSource(llvm::StringRef Path,
+ bool DisablePCHValidation,
+ void *DeserializationListener);
/// 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);
-
- /// Get the PCH reader, if any.
- PCHReader *getPCHReader() { return Reader; }
+ bool DisablePCHValidation,
+ Preprocessor &PP, ASTContext &Context,
+ void *DeserializationListener);
/// Create a code completion consumer using the invocation; note that this
/// will cause the source manager to truncate the input source file at the
@@ -526,8 +534,13 @@ public:
createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename,
unsigned Line, unsigned Column,
bool UseDebugPrinter, bool ShowMacros,
- bool ShowCodePatterns, llvm::raw_ostream &OS);
+ bool ShowCodePatterns, bool ShowGlobals,
+ llvm::raw_ostream &OS);
+ /// \brief Create the Sema object to be used for parsing.
+ void createSema(bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CompletionConsumer);
+
/// Create the frontend timer and replace any existing one with it.
void createFrontendTimer();
diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def
index 16551ee03e1f..18451189bc06 100644
--- a/include/clang/Frontend/DeclXML.def
+++ b/include/clang/Frontend/DeclXML.def
@@ -95,10 +95,10 @@ NODE_XML(FunctionDecl, "Function")
TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType())
ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type")
ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
- ENUM_XML(FunctionDecl::None, "")
- ENUM_XML(FunctionDecl::Extern, "extern")
- ENUM_XML(FunctionDecl::Static, "static")
- ENUM_XML(FunctionDecl::PrivateExtern, "__private_extern__")
+ ENUM_XML(SC_None, "")
+ ENUM_XML(SC_Extern, "extern")
+ ENUM_XML(SC_Static, "static")
+ ENUM_XML(SC_PrivateExtern, "__private_extern__")
END_ENUM_XML
ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline")
//ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference
@@ -289,12 +289,12 @@ NODE_XML(VarDecl, "Var")
ATTRIBUTE_XML(getNameAsString(), "name")
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class")
- ENUM_XML(VarDecl::None, "")
- ENUM_XML(VarDecl::Auto, "auto")
- ENUM_XML(VarDecl::Register, "register")
- ENUM_XML(VarDecl::Extern, "extern")
- ENUM_XML(VarDecl::Static, "static")
- ENUM_XML(VarDecl::PrivateExtern, "__private_extern__")
+ ENUM_XML(SC_None, "")
+ ENUM_XML(SC_Auto, "auto")
+ ENUM_XML(SC_Register, "register")
+ ENUM_XML(SC_Extern, "extern")
+ ENUM_XML(SC_Static, "static")
+ ENUM_XML(SC_PrivateExtern, "__private_extern__")
END_ENUM_XML
SUB_NODE_OPT_XML(Expr) // init expr
END_NODE_XML
diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h
index 516dc67b425d..c80bc037212b 100644
--- a/include/clang/Frontend/DiagnosticOptions.h
+++ b/include/clang/Frontend/DiagnosticOptions.h
@@ -30,6 +30,7 @@ public:
unsigned ShowCarets : 1; /// Show carets in diagnostics.
unsigned ShowFixits : 1; /// Show fixit information.
unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form.
+ unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its.
unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable
/// diagnostics.
unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number,
@@ -83,6 +84,7 @@ public:
ShowOptionNames = 0;
ShowCategories = 0;
ShowSourceRanges = 0;
+ ShowParseableFixits = 0;
VerifyDiagnostics = 0;
BinaryOutput = 0;
ErrorLimit = 0;
diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h
index 73d892105f21..602d84655828 100644
--- a/include/clang/Frontend/DocumentXML.h
+++ b/include/clang/Frontend/DocumentXML.h
@@ -150,7 +150,6 @@ inline void DocumentXML::addAttribute(const char* pName, const T& value) {
{
llvm::raw_string_ostream buf(repr);
buf << value;
- buf.flush();
}
Out << ' ' << pName << "=\""
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index f6a68bf69e89..773543ac06a5 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -145,8 +145,8 @@ public:
/// @{
/// 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.
+ /// no AST context will be created and this action will be invalid with AST
+ /// file inputs.
virtual bool usesPreprocessorOnly() const = 0;
/// usesCompleteTranslationUnit - For AST based actions, should the
@@ -225,8 +225,14 @@ protected:
llvm::StringRef InFile) = 0;
public:
- virtual bool ParseArgs(const std::vector<std::string>& arg) = 0;
- virtual void PrintHelp(llvm::raw_ostream&) = 0;
+ /// ParseArgs - Parse the given plugin command line arguments.
+ ///
+ /// \param CI - The compiler instance, for use in reporting diagnostics.
+ /// \return True if the parsing succeeded; otherwise the plugin will be
+ /// destroyed and no action run. The plugin is responsible for using the
+ /// CompilerInstance's Diagnostic object to report errors.
+ virtual bool ParseArgs(const CompilerInstance &CI,
+ const std::vector<std::string> &arg) = 0;
};
/// PreprocessorFrontendAction - Abstract base class to use for preprocessor
diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h
index 26262cfa9522..7b8063ce549c 100644
--- a/include/clang/Frontend/FrontendActions.h
+++ b/include/clang/Frontend/FrontendActions.h
@@ -74,6 +74,17 @@ protected:
virtual bool usesCompleteTranslationUnit() { return false; }
virtual bool hasASTFileSupport() const { return false; }
+
+public:
+ /// \brief Compute the AST consumer arguments that will be used to
+ /// create the PCHGenerator instance returned by CreateASTConsumer.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ static bool ComputeASTConsumerArguments(CompilerInstance &CI,
+ llvm::StringRef InFile,
+ std::string &Sysroot,
+ llvm::raw_ostream *&OS,
+ bool &Chaining);
};
class InheritanceViewAction : public ASTFrontendAction {
@@ -134,6 +145,16 @@ public:
virtual bool hasCodeCompletionSupport() const;
};
+class PrintPreambleAction : public FrontendAction {
+protected:
+ void ExecuteAction();
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &, llvm::StringRef) {
+ return 0;
+ }
+
+ virtual bool usesPreprocessorOnly() const { return true; }
+};
+
//===----------------------------------------------------------------------===//
// Preprocessor Actions
//===----------------------------------------------------------------------===//
@@ -153,28 +174,18 @@ 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; }
};
-
+
} // end namespace clang
#endif
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index 4010ea6dd7dc..4c16d084fc0d 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -25,6 +25,7 @@ namespace frontend {
ASTPrintXML, ///< Parse ASTs and print them in XML.
ASTView, ///< Parse ASTs and view them in Graphviz.
BoostCon, ///< BoostCon mode.
+ CreateModule, ///< Create module definition
DumpRawTokens, ///< Dump out raw tokens.
DumpTokens, ///< Dump out preprocessed tokens.
EmitAssembly, ///< Emit a .s file.
@@ -39,11 +40,10 @@ namespace frontend {
GeneratePTH, ///< Generate pre-tokenized header.
InheritanceView, ///< View C++ inheritance for a specified class.
InitOnly, ///< Only execute frontend initialization.
- 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.
+ PrintPreamble, ///< Print the "preamble" of the input file
PrintPreprocessedInput, ///< -E mode.
RewriteMacros, ///< Expand macros but not #includes.
RewriteObjC, ///< ObjC->C Rewriter.
@@ -60,21 +60,25 @@ public:
/// completion results.
unsigned DisableFree : 1; ///< Disable memory freeing on exit.
unsigned RelocatablePCH : 1; ///< When generating PCH files,
- /// instruct the PCH writer to create
+ /// instruct the AST writer to create
/// relocatable PCH files.
unsigned ChainedPCH : 1; ///< When generating PCH files,
- /// instruct the PCH writer to create
+ /// instruct the AST writer to create
/// chained PCH files.
unsigned ShowHelp : 1; ///< Show the -help text.
unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion
/// results.
unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code
/// completion results.
+ unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in
+ /// code completion results.
unsigned ShowStats : 1; ///< Show frontend performance
/// metrics and statistics.
unsigned ShowTimers : 1; ///< Show timers for individual
/// actions.
unsigned ShowVersion : 1; ///< Show the -version text.
+ unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are
+ /// unfixable errors.
/// The input files and their types.
std::vector<std::pair<InputKind, std::string> > Inputs;
@@ -106,6 +110,9 @@ public:
/// \brief The list of AST files to merge.
std::vector<std::string> ASTMergeFiles;
+ /// \brief The list of modules to import.
+ std::vector<std::string> Modules;
+
/// \brief A list of arguments to forward to LLVM's option processing; this
/// should only be used for debugging and experimental features.
std::vector<std::string> LLVMArgs;
@@ -121,6 +128,7 @@ public:
ShowHelp = 0;
ShowMacrosInCodeCompletion = 0;
ShowCodePatternsInCodeCompletion = 0;
+ ShowGlobalSymbolsInCodeCompletion = 1;
ShowStats = 0;
ShowTimers = 0;
ShowVersion = 0;
diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h
index c6682451835a..588d32bf736e 100644
--- a/include/clang/Frontend/HeaderSearchOptions.h
+++ b/include/clang/Frontend/HeaderSearchOptions.h
@@ -35,11 +35,16 @@ public:
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) {}
+
+ /// IsSysRootRelative - This is true if an absolute path should be treated
+ /// relative to the sysroot, or false if it should always be the absolute
+ /// path.
+ unsigned IsSysRootRelative : 1;
+
+ Entry(llvm::StringRef path, frontend::IncludeDirGroup group,
+ bool isUserSupplied, bool isFramework, bool isSysRootRelative)
+ : Path(path), Group(group), IsUserSupplied(isUserSupplied),
+ IsFramework(isFramework), IsSysRootRelative(isSysRootRelative) {}
};
/// If non-empty, the directory to use as a "virtual system root" for include
@@ -85,8 +90,9 @@ public:
/// 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));
+ bool IsUserSupplied, bool IsFramework, bool IsSysRootRelative) {
+ UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework,
+ IsSysRootRelative));
}
};
diff --git a/include/clang/Frontend/PCHDeserializationListener.h b/include/clang/Frontend/PCHDeserializationListener.h
deleted file mode 100644
index c9b90e22c8cd..000000000000
--- a/include/clang/Frontend/PCHDeserializationListener.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- PCHDeserializationListener.h - Decl/Type PCH Read Events -*- 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 PCHDeserializationListener class, which is notified
-// by the PCHReader whenever a type or declaration is deserialized.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_FRONTEND_PCH_DESERIALIZATION_LISTENER_H
-#define LLVM_CLANG_FRONTEND_PCH_DESERIALIZATION_LISTENER_H
-
-#include "clang/Frontend/PCHBitCodes.h"
-
-namespace clang {
-
-class Decl;
-class QualType;
-
-class PCHDeserializationListener {
-protected:
- ~PCHDeserializationListener() {}
-
-public:
- virtual void TypeRead(pch::TypeID ID, QualType T) = 0;
- virtual void DeclRead(pch::DeclID ID, const Decl *D) = 0;
-};
-
-}
-
-#endif
diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h
index 891359b74784..851c1f0108af 100644
--- a/include/clang/Frontend/PreprocessorOptions.h
+++ b/include/clang/Frontend/PreprocessorOptions.h
@@ -43,6 +43,17 @@ public:
/// The implicit PCH included at the start of the translation unit, or empty.
std::string ImplicitPCHInclude;
+ /// \brief When true, disables most of the normal validation performed on
+ /// precompiled headers.
+ bool DisablePCHValidation;
+
+ /// \brief If non-zero, the implicit PCH include is actually a precompiled
+ /// preamble that covers this number of bytes in the main source file.
+ ///
+ /// The boolean indicates whether the preamble ends at the start of a new
+ /// line.
+ std::pair<unsigned, bool> PrecompiledPreambleBytes;
+
/// The implicit PTH input included at the start of the translation unit, or
/// empty.
std::string ImplicitPTHInclude;
@@ -62,26 +73,53 @@ public:
std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >
RemappedFileBuffers;
- typedef std::vector<std::pair<std::string, std::string> >::const_iterator
+ /// \brief Whether the compiler instance should retain (i.e., not free)
+ /// the buffers associated with remapped files.
+ ///
+ /// This flag defaults to false; it can be set true only through direct
+ /// manipulation of the compiler invocation object, in cases where the
+ /// compiler invocation and its buffers will be reused.
+ bool RetainRemappedFileBuffers;
+
+ typedef std::vector<std::pair<std::string, std::string> >::iterator
remapped_file_iterator;
- remapped_file_iterator remapped_file_begin() const {
+ typedef std::vector<std::pair<std::string, std::string> >::const_iterator
+ const_remapped_file_iterator;
+ remapped_file_iterator remapped_file_begin() {
return RemappedFiles.begin();
}
- remapped_file_iterator remapped_file_end() const {
+ const_remapped_file_iterator remapped_file_begin() const {
+ return RemappedFiles.begin();
+ }
+ remapped_file_iterator remapped_file_end() {
+ return RemappedFiles.end();
+ }
+ const_remapped_file_iterator remapped_file_end() const {
return RemappedFiles.end();
}
typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
- const_iterator remapped_file_buffer_iterator;
- remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+ iterator remapped_file_buffer_iterator;
+ typedef std::vector<std::pair<std::string, const llvm::MemoryBuffer *> >::
+ const_iterator const_remapped_file_buffer_iterator;
+ remapped_file_buffer_iterator remapped_file_buffer_begin() {
return RemappedFileBuffers.begin();
}
- remapped_file_buffer_iterator remapped_file_buffer_end() const {
+ const_remapped_file_buffer_iterator remapped_file_buffer_begin() const {
+ return RemappedFileBuffers.begin();
+ }
+ remapped_file_buffer_iterator remapped_file_buffer_end() {
+ return RemappedFileBuffers.end();
+ }
+ const_remapped_file_buffer_iterator remapped_file_buffer_end() const {
return RemappedFileBuffers.end();
}
public:
- PreprocessorOptions() : UsePredefines(true), DetailedRecord(false) {}
+ PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
+ DisablePCHValidation(false),
+ PrecompiledPreambleBytes(0, true),
+ RetainRemappedFileBuffers(false) { }
void addMacroDef(llvm::StringRef Name) {
Macros.push_back(std::make_pair(Name, false));
@@ -92,9 +130,24 @@ public:
void addRemappedFile(llvm::StringRef From, llvm::StringRef To) {
RemappedFiles.push_back(std::make_pair(From, To));
}
+
+ remapped_file_iterator eraseRemappedFile(remapped_file_iterator Remapped) {
+ return RemappedFiles.erase(Remapped);
+ }
+
void addRemappedFile(llvm::StringRef From, const llvm::MemoryBuffer * To) {
RemappedFileBuffers.push_back(std::make_pair(From, To));
}
+
+ remapped_file_buffer_iterator
+ eraseRemappedFile(remapped_file_buffer_iterator Remapped) {
+ return RemappedFileBuffers.erase(Remapped);
+ }
+
+ void clearRemappedFiles() {
+ RemappedFiles.clear();
+ RemappedFileBuffers.clear();
+ }
};
} // end namespace clang
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
index a712a3d1bb05..82517c51d1c1 100644
--- a/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -16,19 +16,21 @@ namespace clang {
/// 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.
+ unsigned ShowCPP : 1; ///< Print normal preprocessed output.
+ unsigned ShowComments : 1; ///< Show comments.
+ unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
+ unsigned ShowLineMarkers : 1; ///< Show #line markers.
+ unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+ unsigned ShowMacros : 1; ///< Print macro definitions.
public:
PreprocessorOutputOptions() {
ShowCPP = 1;
- ShowMacros = 0;
- ShowLineMarkers = 1;
ShowComments = 0;
+ ShowHeaderIncludes = 0;
+ ShowLineMarkers = 1;
ShowMacroComments = 0;
+ ShowMacros = 0;
}
};
diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def
index f63761a908af..c03a5a883569 100644
--- a/include/clang/Frontend/StmtXML.def
+++ b/include/clang/Frontend/StmtXML.def
@@ -241,20 +241,19 @@ NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
- ENUM_XML(UnaryOperator::PostInc, "postinc")
- ENUM_XML(UnaryOperator::PostDec, "postdec")
- ENUM_XML(UnaryOperator::PreInc, "preinc")
- ENUM_XML(UnaryOperator::PreDec, "predec")
- ENUM_XML(UnaryOperator::AddrOf, "addrof")
- ENUM_XML(UnaryOperator::Deref, "deref")
- ENUM_XML(UnaryOperator::Plus, "plus")
- ENUM_XML(UnaryOperator::Minus, "minus")
- ENUM_XML(UnaryOperator::Not, "not") // bitwise not
- ENUM_XML(UnaryOperator::LNot, "lnot") // boolean not
- ENUM_XML(UnaryOperator::Real, "__real")
- ENUM_XML(UnaryOperator::Imag, "__imag")
- ENUM_XML(UnaryOperator::Extension, "__extension__")
- ENUM_XML(UnaryOperator::OffsetOf, "__builtin_offsetof")
+ ENUM_XML(UO_PostInc, "postinc")
+ ENUM_XML(UO_PostDec, "postdec")
+ ENUM_XML(UO_PreInc, "preinc")
+ ENUM_XML(UO_PreDec, "predec")
+ ENUM_XML(UO_AddrOf, "addrof")
+ ENUM_XML(UO_Deref, "deref")
+ ENUM_XML(UO_Plus, "plus")
+ ENUM_XML(UO_Minus, "minus")
+ ENUM_XML(UO_Not, "not") // bitwise not
+ ENUM_XML(UO_LNot, "lnot") // boolean not
+ ENUM_XML(UO_Real, "__real")
+ ENUM_XML(UO_Imag, "__imag")
+ ENUM_XML(UO_Extension, "__extension__")
END_ENUM_XML
SUB_NODE_XML(Expr) // expr
END_NODE_XML
@@ -263,38 +262,38 @@ NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
ATTRIBUTE_ENUM_XML(getOpcode(), "kind")
- ENUM_XML(BinaryOperator::PtrMemD , "ptrmemd")
- ENUM_XML(BinaryOperator::PtrMemI , "ptrmemi")
- ENUM_XML(BinaryOperator::Mul , "mul")
- ENUM_XML(BinaryOperator::Div , "div")
- ENUM_XML(BinaryOperator::Rem , "rem")
- ENUM_XML(BinaryOperator::Add , "add")
- ENUM_XML(BinaryOperator::Sub , "sub")
- ENUM_XML(BinaryOperator::Shl , "shl")
- ENUM_XML(BinaryOperator::Shr , "shr")
- ENUM_XML(BinaryOperator::LT , "lt")
- ENUM_XML(BinaryOperator::GT , "gt")
- ENUM_XML(BinaryOperator::LE , "le")
- ENUM_XML(BinaryOperator::GE , "ge")
- ENUM_XML(BinaryOperator::EQ , "eq")
- ENUM_XML(BinaryOperator::NE , "ne")
- ENUM_XML(BinaryOperator::And , "and") // bitwise and
- ENUM_XML(BinaryOperator::Xor , "xor")
- ENUM_XML(BinaryOperator::Or , "or") // bitwise or
- ENUM_XML(BinaryOperator::LAnd , "land") // boolean and
- ENUM_XML(BinaryOperator::LOr , "lor") // boolean or
- ENUM_XML(BinaryOperator::Assign , "assign")
- ENUM_XML(BinaryOperator::MulAssign, "mulassign")
- ENUM_XML(BinaryOperator::DivAssign, "divassign")
- ENUM_XML(BinaryOperator::RemAssign, "remassign")
- ENUM_XML(BinaryOperator::AddAssign, "addassign")
- ENUM_XML(BinaryOperator::SubAssign, "subassign")
- ENUM_XML(BinaryOperator::ShlAssign, "shlassign")
- ENUM_XML(BinaryOperator::ShrAssign, "shrassign")
- ENUM_XML(BinaryOperator::AndAssign, "andassign")
- ENUM_XML(BinaryOperator::XorAssign, "xorassign")
- ENUM_XML(BinaryOperator::OrAssign , "orassign")
- ENUM_XML(BinaryOperator::Comma , "comma")
+ ENUM_XML(BO_PtrMemD , "ptrmemd")
+ ENUM_XML(BO_PtrMemI , "ptrmemi")
+ ENUM_XML(BO_Mul , "mul")
+ ENUM_XML(BO_Div , "div")
+ ENUM_XML(BO_Rem , "rem")
+ ENUM_XML(BO_Add , "add")
+ ENUM_XML(BO_Sub , "sub")
+ ENUM_XML(BO_Shl , "shl")
+ ENUM_XML(BO_Shr , "shr")
+ ENUM_XML(BO_LT , "lt")
+ ENUM_XML(BO_GT , "gt")
+ ENUM_XML(BO_LE , "le")
+ ENUM_XML(BO_GE , "ge")
+ ENUM_XML(BO_EQ , "eq")
+ ENUM_XML(BO_NE , "ne")
+ ENUM_XML(BO_And , "and") // bitwise and
+ ENUM_XML(BO_Xor , "xor")
+ ENUM_XML(BO_Or , "or") // bitwise or
+ ENUM_XML(BO_LAnd , "land") // boolean and
+ ENUM_XML(BO_LOr , "lor") // boolean or
+ ENUM_XML(BO_Assign , "assign")
+ ENUM_XML(BO_MulAssign, "mulassign")
+ ENUM_XML(BO_DivAssign, "divassign")
+ ENUM_XML(BO_RemAssign, "remassign")
+ ENUM_XML(BO_AddAssign, "addassign")
+ ENUM_XML(BO_SubAssign, "subassign")
+ ENUM_XML(BO_ShlAssign, "shlassign")
+ ENUM_XML(BO_ShrAssign, "shrassign")
+ ENUM_XML(BO_AndAssign, "andassign")
+ ENUM_XML(BO_XorAssign, "xorassign")
+ ENUM_XML(BO_OrAssign , "orassign")
+ ENUM_XML(BO_Comma , "comma")
END_ENUM_XML
SUB_NODE_XML(Expr) // expr1
SUB_NODE_XML(Expr) // expr2
@@ -445,6 +444,14 @@ NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ..
SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
END_NODE_XML
+NODE_XML(CXXConstructExpr, "CXXConstructExpr") // ctor(arg1, arg2, ...)
+ ATTRIBUTE_FILE_LOCATION_XML
+ TYPE_ATTRIBUTE_XML(getType())
+ ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned
+ SUB_NODE_XML(Expr) // fnexpr
+ SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN
+END_NODE_XML
+
NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr)
ATTRIBUTE_FILE_LOCATION_XML
TYPE_ATTRIBUTE_XML(getType())
diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def
index e8cb4a6de055..1536c924a82f 100644
--- a/include/clang/Frontend/TypeXML.def
+++ b/include/clang/Frontend/TypeXML.def
@@ -278,18 +278,10 @@ NODE_XML(UnresolvedUsingType, "UnresolvedUsing")
ID_ATTRIBUTE_XML
END_NODE_XML
-NODE_XML(DependentTypeOfExprType, "DependentTypeOfExpr")
- ID_ATTRIBUTE_XML
-END_NODE_XML
-
NODE_XML(DecltypeType, "Decltype")
ID_ATTRIBUTE_XML
END_NODE_XML
-NODE_XML(DependentDecltypeType, "DependentDecltype")
- ID_ATTRIBUTE_XML
-END_NODE_XML
-
//===----------------------------------------------------------------------===//
#undef NODE_XML
#undef ID_ATTRIBUTE_XML
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index f37cc01a2753..fe722db381d0 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -23,6 +23,7 @@ class Triple;
namespace clang {
class ASTConsumer;
+class CompilerInstance;
class Decl;
class DependencyOutputOptions;
class Diagnostic;
@@ -31,7 +32,6 @@ class HeaderSearch;
class HeaderSearchOptions;
class IdentifierTable;
class LangOptions;
-class MinimalAction;
class Preprocessor;
class PreprocessorOptions;
class PreprocessorOutputOptions;
@@ -65,11 +65,6 @@ void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts);
void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
const PreprocessorOutputOptions &Opts);
-/// CreatePrintParserActionsAction - Return the actions implementation that
-/// implements the -parse-print-callbacks option.
-MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP,
- llvm::raw_ostream* OS);
-
/// CheckDiagnostics - Gather the expected diagnostics and check them.
bool CheckDiagnostics(Preprocessor &PP);
diff --git a/include/clang/FrontendTool/Utils.h b/include/clang/FrontendTool/Utils.h
new file mode 100644
index 000000000000..031ee7df70ae
--- /dev/null
+++ b/include/clang/FrontendTool/Utils.h
@@ -0,0 +1,30 @@
+//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains miscellaneous utilities for various front-end actions
+// which were split from Frontend to minimise Frontend's dependencies.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H
+#define LLVM_CLANG_FRONTENDTOOL_UTILS_H
+
+namespace clang {
+
+class CompilerInstance;
+
+/// ExecuteCompilerInvocation - Execute the given actions described by the
+/// compiler invocation object in the given compiler instance.
+///
+/// \return - True on success.
+bool ExecuteCompilerInvocation(CompilerInstance *Clang);
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Index/TranslationUnit.h b/include/clang/Index/TranslationUnit.h
index b86ba3ee8a58..0099d630f164 100644
--- a/include/clang/Index/TranslationUnit.h
+++ b/include/clang/Index/TranslationUnit.h
@@ -16,6 +16,7 @@
namespace clang {
class ASTContext;
+ class Diagnostic;
class Preprocessor;
namespace idx {
@@ -28,6 +29,7 @@ public:
virtual ~TranslationUnit();
virtual ASTContext &getASTContext() = 0;
virtual Preprocessor &getPreprocessor() = 0;
+ virtual Diagnostic &getDiagnostic() = 0;
virtual DeclReferenceMap &getDeclReferenceMap() = 0;
virtual SelectorMap &getSelectorMap() = 0;
};
diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h
deleted file mode 100644
index f8e01f728648..000000000000
--- a/include/clang/Index/Utils.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===--- Utils.h - Misc utilities for indexing-----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This header contains miscellaneous utilities for indexing related
-// functionality.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_INDEX_UTILS_H
-#define LLVM_CLANG_INDEX_UTILS_H
-
-namespace clang {
- class ASTContext;
- class SourceLocation;
-
-namespace idx {
- class ASTLocation;
-
-/// \brief Returns the ASTLocation that a source location points to.
-///
-/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
-/// location could not be resolved.
-ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- ASTLocation *LastLoc = 0);
-
-} // end namespace idx
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h
new file mode 100644
index 000000000000..d28a3aa7d630
--- /dev/null
+++ b/include/clang/Lex/CodeCompletionHandler.h
@@ -0,0 +1,67 @@
+//===--- CodeCompletionHandler.h - Preprocessor code completion -*- 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 CodeCompletionHandler interface, which provides
+// code-completion callbacks for the preprocessor.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+
+namespace clang {
+
+class IdentifierInfo;
+class MacroInfo;
+
+/// \brief Callback handler that receives notifications when performing code
+/// completion within the preprocessor.
+class CodeCompletionHandler {
+public:
+ virtual ~CodeCompletionHandler();
+
+ /// \brief Callback invoked when performing code completion for a preprocessor
+ /// directive.
+ ///
+ /// This callback will be invoked when the preprocessor processes a '#' at the
+ /// start of a line, followed by the code-completion token.
+ ///
+ /// \param InConditional Whether we're inside a preprocessor conditional
+ /// already.
+ virtual void CodeCompleteDirective(bool InConditional) { }
+
+ /// \brief Callback invoked when performing code completion within a block of
+ /// code that was excluded due to preprocessor conditionals.
+ virtual void CodeCompleteInConditionalExclusion() { }
+
+ /// \brief Callback invoked when performing code completion in a context
+ /// where the name of a macro is expected.
+ ///
+ /// \param IsDefinition Whether this is the definition of a macro, e.g.,
+ /// in a #define.
+ virtual void CodeCompleteMacroName(bool IsDefinition) { }
+
+ /// \brief Callback invoked when performing code completion in a preprocessor
+ /// expression, such as the condition of an #if or #elif directive.
+ virtual void CodeCompletePreprocessorExpression() { }
+
+ /// \brief Callback invoked when performing code completion inside a
+ /// function-like macro argument.
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) { }
+
+ /// \brief Callback invoked when performing code completion in a part of the
+ /// file where we expect natural language, e.g., a comment, string, or
+ /// #error directive.
+ virtual void CodeCompleteNaturalLanguage() { }
+};
+
+}
+
+#endif // LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h
index af5c3898161e..791d3fe304ec 100644
--- a/include/clang/Lex/ExternalPreprocessorSource.h
+++ b/include/clang/Lex/ExternalPreprocessorSource.h
@@ -19,7 +19,7 @@ namespace clang {
/// \brief Abstract interface for external sources of preprocessor
/// information.
///
-/// This abstract class allows an external sources (such as the \c PCHReader)
+/// This abstract class allows an external sources (such as the \c ASTReader)
/// to provide additional macro definitions.
class ExternalPreprocessorSource {
public:
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 978585caf0e4..80b38dee06af 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -219,7 +219,7 @@ public:
header_file_iterator header_file_end() const { return FileInfo.end(); }
unsigned header_file_size() const { return FileInfo.size(); }
- // Used by PCHReader.
+ // Used by ASTReader.
void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID);
void PrintStats();
diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h
index 6a6e319463f0..9e0fb7ee70ea 100644
--- a/include/clang/Lex/Lexer.h
+++ b/include/clang/Lex/Lexer.h
@@ -219,6 +219,33 @@ public:
const SourceManager &SM,
const LangOptions &LangOpts);
+ /// \brief Given a location any where in a source buffer, find the location
+ /// that corresponds to the beginning of the token in which the original
+ /// source location lands.
+ ///
+ /// \param Loc
+ static SourceLocation GetBeginningOfToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// \brief Compute the preamble of the given file.
+ ///
+ /// The preamble of a file contains the initial comments, include directives,
+ /// and other preprocessor directives that occur before the code in this
+ /// particular file actually begins. The preamble of the main source file is
+ /// a potential prefix header.
+ ///
+ /// \param Buffer The memory buffer containing the file's contents.
+ ///
+ /// \param MaxLines If non-zero, restrict the length of the preamble
+ /// to fewer than this number of lines.
+ ///
+ /// \returns The offset into the file where the preamble ends and the rest
+ /// of the file begins along with a boolean value indicating whether
+ /// the preamble ends at the beginning of a new line.
+ static std::pair<unsigned, bool>
+ ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines = 0);
+
//===--------------------------------------------------------------------===//
// Internal implementation interfaces.
private:
@@ -361,6 +388,8 @@ private:
//===--------------------------------------------------------------------===//
// Other lexer functions.
+ void SkipBytes(unsigned Bytes, bool StartOfLine);
+
// Helper functions to lex the remainder of a token of the specific type.
void LexIdentifier (Token &Result, const char *CurPtr);
void LexNumericConstant (Token &Result, const char *CurPtr);
diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h
index 5887041c46b9..90f95b7acee3 100644
--- a/include/clang/Lex/MacroInfo.h
+++ b/include/clang/Lex/MacroInfo.h
@@ -62,6 +62,9 @@ class MacroInfo {
/// it has not yet been redefined or undefined.
bool IsBuiltinMacro : 1;
+ /// IsFromAST - True if this macro was loaded from an AST file.
+ bool IsFromAST : 1;
+
private:
//===--------------------------------------------------------------------===//
// State that changes as the macro is used.
@@ -76,24 +79,28 @@ private:
/// emit -Wunused-macros diagnostics.
bool IsUsed : 1;
- ~MacroInfo() {
+ /// AllowRedefinitionsWithoutWarning - True if this macro can be redefined
+ /// without emitting a warning.
+ bool IsAllowRedefinitionsWithoutWarning : 1;
+
+ ~MacroInfo() {
assert(ArgumentList == 0 && "Didn't call destroy before dtor!");
}
public:
MacroInfo(SourceLocation DefLoc);
-
+ MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator);
+
/// FreeArgumentList - Free the argument list of the macro, restoring it to a
/// state where it can be reused for other devious purposes.
- void FreeArgumentList(llvm::BumpPtrAllocator &PPAllocator) {
- PPAllocator.Deallocate(ArgumentList);
+ void FreeArgumentList() {
ArgumentList = 0;
NumArguments = 0;
}
/// Destroy - destroy this MacroInfo object.
- void Destroy(llvm::BumpPtrAllocator &PPAllocator) {
- FreeArgumentList(PPAllocator);
+ void Destroy() {
+ FreeArgumentList();
this->~MacroInfo();
}
@@ -125,6 +132,12 @@ public:
IsUsed = Val;
}
+ /// setIsAllowRedefinitionsWithoutWarning - Set the value of the
+ /// IsAllowRedefinitionsWithoutWarning flag.
+ void setIsAllowRedefinitionsWithoutWarning(bool Val) {
+ IsAllowRedefinitionsWithoutWarning = Val;
+ }
+
/// setArgumentList - Set the specified list of identifiers as the argument
/// list for this macro.
void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
@@ -172,10 +185,22 @@ public:
/// __LINE__, which requires processing before expansion.
bool isBuiltinMacro() const { return IsBuiltinMacro; }
+ /// isFromAST - Return true if this macro was loaded from an AST file.
+ bool isFromAST() const { return IsFromAST; }
+
+ /// setIsFromAST - Set whether this macro was loaded from an AST file.
+ void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
+
/// isUsed - Return false if this macro is defined in the main file and has
/// not yet been used.
bool isUsed() const { return IsUsed; }
+ /// isAllowRedefinitionsWithoutWarning - Return true if this macro can be
+ /// redefined without warning.
+ bool isAllowRedefinitionsWithoutWarning() const {
+ return IsAllowRedefinitionsWithoutWarning;
+ }
+
/// getNumTokens - Return the number of tokens that this macro expands to.
///
unsigned getNumTokens() const {
diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h
index 99fe29b22dc2..782f2d57a5c6 100644
--- a/include/clang/Lex/PPCallbacks.h
+++ b/include/clang/Lex/PPCallbacks.h
@@ -89,7 +89,8 @@ public:
/// MacroUndefined - This hook is called whenever a macro #undef is seen.
/// MI is released immediately following this callback.
- virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) {
+ virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI) {
}
};
@@ -149,9 +150,10 @@ public:
Second->MacroDefined(II, MI);
}
- virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI) {
- First->MacroUndefined(II, MI);
- Second->MacroUndefined(II, MI);
+ virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI) {
+ First->MacroUndefined(Loc, II, MI);
+ Second->MacroUndefined(Loc, II, MI);
}
};
diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h
index e96a8c514e6e..0b5a76ccfd6e 100644
--- a/include/clang/Lex/PTHLexer.h
+++ b/include/clang/Lex/PTHLexer.h
@@ -50,6 +50,8 @@ class PTHLexer : public PreprocessorLexer {
/// ReadToken - Used by PTHLexer to read tokens TokBuf.
void ReadToken(Token& T);
+
+ bool LexEndOfFile(Token &Result);
/// PTHMgr - The PTHManager object that created this PTHLexer.
PTHManager& PTHMgr;
diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h
index ef28af9b7fe0..730f04f2fa09 100644
--- a/include/clang/Lex/PreprocessingRecord.h
+++ b/include/clang/Lex/PreprocessingRecord.h
@@ -257,7 +257,8 @@ namespace clang {
virtual void MacroExpands(const Token &Id, const MacroInfo* MI);
virtual void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
- virtual void MacroUndefined(const IdentifierInfo *II, const MacroInfo *MI);
+ virtual void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI);
};
} // end namespace clang
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 1ee4bb635179..6b9b89ea5eb9 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -42,6 +42,7 @@ class CommentHandler;
class ScratchBuffer;
class TargetInfo;
class PPCallbacks;
+class CodeCompletionHandler;
class DirectoryLookup;
class PreprocessingRecord;
@@ -77,7 +78,8 @@ class Preprocessor {
IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
IdentifierInfo *Ident__COUNTER__; // __COUNTER__
- IdentifierInfo *Ident_Pragma, *Ident__VA_ARGS__; // _Pragma, __VA_ARGS__
+ IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
+ IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
IdentifierInfo *Ident__has_feature; // __has_feature
IdentifierInfo *Ident__has_builtin; // __has_builtin
IdentifierInfo *Ident__has_include; // __has_include
@@ -117,7 +119,7 @@ class Preprocessor {
/// conceptually similar the IdentifierTable. In addition, the current control
/// flow (in clang::ParseAST()), make it convenient to put here.
/// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
- /// the lifetime fo the preprocessor.
+ /// the lifetime of the preprocessor.
SelectorTable Selectors;
/// BuiltinInfo - Information about builtins.
@@ -131,9 +133,18 @@ class Preprocessor {
/// with this preprocessor.
std::vector<CommentHandler *> CommentHandlers;
+ /// \brief The code-completion handler.
+ CodeCompletionHandler *CodeComplete;
+
/// \brief The file that we're performing code-completion for, if any.
const FileEntry *CodeCompletionFile;
+ /// \brief The number of bytes that we will initially skip when entering the
+ /// main file, which is used when loading a precompiled preamble, along
+ /// with a flag that indicates whether skipping this number of bytes will
+ /// place the lexer at the start of a line.
+ std::pair<unsigned, bool> SkipMainFilePreamble;
+
/// CurLexer - This is the current top of the stack that we're lexing from if
/// not expanding a macro and we are lexing directly from source code.
/// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null.
@@ -192,6 +203,11 @@ class Preprocessor {
/// reused for quick allocation.
MacroArgs *MacroArgCache;
friend class MacroArgs;
+
+ /// PragmaPushMacroInfo - For each IdentifierInfo used in a #pragma
+ /// push_macro directive, we keep a MacroInfo stack used to restore
+ /// previous macro value.
+ llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo;
// Various statistics we track for performance analysis.
unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
@@ -362,6 +378,25 @@ public:
/// It is an error to remove a handler that has not been registered.
void RemoveCommentHandler(CommentHandler *Handler);
+ /// \brief Set the code completion handler to the given object.
+ void setCodeCompletionHandler(CodeCompletionHandler &Handler) {
+ CodeComplete = &Handler;
+ }
+
+ /// \brief Retrieve the current code-completion handler.
+ CodeCompletionHandler *getCodeCompletionHandler() const {
+ return CodeComplete;
+ }
+
+ /// \brief Clear out the code completion handler.
+ void clearCodeCompletionHandler() {
+ CodeComplete = 0;
+ }
+
+ /// \brief Hook used by the lexer to invoke the "natural language" code
+ /// completion point.
+ void CodeCompleteNaturalLanguage();
+
/// \brief Retrieve the preprocessing record, or NULL if there is no
/// preprocessing record.
PreprocessingRecord *getPreprocessingRecord() const { return Record; }
@@ -556,6 +591,18 @@ public:
/// for which we are performing code completion.
bool isCodeCompletionFile(SourceLocation FileLoc) const;
+ /// \brief Instruct the preprocessor to skip part of the main
+ /// the main source file.
+ ///
+ /// \brief Bytes The number of bytes in the preamble to skip.
+ ///
+ /// \brief StartOfLine Whether skipping these bytes puts the lexer at the
+ /// start of a line.
+ void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) {
+ SkipMainFilePreamble.first = Bytes;
+ SkipMainFilePreamble.second = StartOfLine;
+ }
+
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at
/// the specified Token's location, translating the token's start
/// position in the current buffer into a SourcePosition object for rendering.
@@ -726,7 +773,10 @@ public:
/// AllocateMacroInfo - Allocate a new MacroInfo object with the provide
/// SourceLocation.
- MacroInfo* AllocateMacroInfo(SourceLocation L);
+ MacroInfo *AllocateMacroInfo(SourceLocation L);
+
+ /// CloneMacroInfo - Allocate a new MacroInfo object which is clone of MI.
+ MacroInfo *CloneMacroInfo(const MacroInfo &MI);
/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully
/// checked and spelled filename, e.g. as an operand of #include. This returns
@@ -784,6 +834,9 @@ private:
IncludeMacroStack.pop_back();
}
+ /// AllocateMacroInfo - Allocate a new MacroInfo object.
+ MacroInfo *AllocateMacroInfo();
+
/// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
/// be reused for allocating new MacroInfo objects.
void ReleaseMacroInfo(MacroInfo* MI);
@@ -852,6 +905,13 @@ private:
/// been read into 'Tok'.
void Handle_Pragma(Token &Tok);
+ /// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
+ /// is not enclosed within a string literal.
+ void HandleMicrosoft__pragma(Token &Tok);
+
+ void Handle_Pragma(const std::string &StrVal, SourceLocation PragmaLoc,
+ SourceLocation RParenLoc);
+
/// EnterSourceFileWithLexer - Add a lexer to the top of the include stack and
/// start lexing tokens from it instead of the current buffer.
void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
@@ -880,7 +940,8 @@ private:
bool InCachingLexMode() const {
// If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
// that we are past EOF, not that we are in CachingLex mode.
- return CurPPLexer == 0 && CurTokenLexer == 0 && !IncludeMacroStack.empty();
+ return CurPPLexer == 0 && CurTokenLexer == 0 && CurPTHLexer == 0 &&
+ !IncludeMacroStack.empty();
}
void EnterCachingLexMode();
void ExitCachingLexMode() {
@@ -929,6 +990,10 @@ public:
void HandlePragmaDependency(Token &DependencyTok);
void HandlePragmaComment(Token &CommentTok);
void HandlePragmaMessage(Token &MessageTok);
+ void HandlePragmaPushMacro(Token &Tok);
+ void HandlePragmaPopMacro(Token &Tok);
+ IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
+
// Return true and store the first token only if any CommentHandler
// has inserted some tokens and getCommentRetentionState() is false.
bool HandleComment(Token &Token, SourceRange Comment);
diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h
index bd9b46869a35..954b36ec6d11 100644
--- a/include/clang/Lex/Token.h
+++ b/include/clang/Lex/Token.h
@@ -231,6 +231,7 @@ public:
/// newlines in it.
///
bool needsCleaning() const { return (Flags & NeedsCleaning) ? true : false; }
+
};
/// PPConditionalInfo - Information about the conditional stack (#if directives)
diff --git a/include/clang/Makefile b/include/clang/Makefile
index e366e4ec4458..030b0720fd81 100644
--- a/include/clang/Makefile
+++ b/include/clang/Makefile
@@ -1,5 +1,5 @@
CLANG_LEVEL := ../..
-DIRS := AST Basic Driver
+DIRS := AST Basic Driver Serialization
include $(CLANG_LEVEL)/Makefile
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
deleted file mode 100644
index 9cb47aa8da25..000000000000
--- a/include/clang/Parse/Action.h
+++ /dev/null
@@ -1,3309 +0,0 @@
-//===--- Action.h - Parser Action Interface ---------------------*- 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 Action and EmptyAction interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_ACTION_H
-#define LLVM_CLANG_PARSE_ACTION_H
-
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/Basic/TemplateKinds.h"
-#include "clang/Basic/TypeTraits.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Ownership.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/ADT/PointerUnion.h"
-
-namespace clang {
- // Semantic.
- class DeclSpec;
- class ObjCDeclSpec;
- class CXXScopeSpec;
- class Declarator;
- class AttributeList;
- struct FieldDeclarator;
- // Parse.
- class Scope;
- class Action;
- class Selector;
- class Designation;
- class InitListDesignations;
- // Lex.
- class Preprocessor;
- class Token;
-
- // We can re-use the low bit of expression, statement, base, and
- // member-initializer pointers for the "invalid" flag of
- // ActionResult.
- template<> struct IsResultPtrLowBitFree<0> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<1> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<3> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<4> { static const bool value = true;};
- template<> struct IsResultPtrLowBitFree<5> { static const bool value = true;};
-
-/// Action - As the parser reads the input file and recognizes the productions
-/// of the grammar, it invokes methods on this class to turn the parsed input
-/// into something useful: e.g. a parse tree.
-///
-/// The callback methods that this class provides are phrased as actions that
-/// the parser has just done or is about to do when the method is called. They
-/// are not requests that the actions module do the specified action.
-///
-/// All of the methods here are optional except getTypeName() and
-/// isCurrentClassName(), which must be specified in order for the
-/// parse to complete accurately. The MinimalAction class does this
-/// bare-minimum of tracking to implement this functionality.
-class Action : public ActionBase {
- /// \brief The parser's current scope.
- ///
- /// The parser maintains this state here so that is accessible to \c Action
- /// subclasses via \c getCurScope().
- Scope *CurScope;
-
-protected:
- friend class Parser;
-
- /// \brief Retrieve the parser's current scope.
- Scope *getCurScope() const { return CurScope; }
-
-public:
- Action() : CurScope(0) { }
-
- /// Out-of-line virtual destructor to provide home for this class.
- virtual ~Action();
-
- // Types - Though these don't actually enforce strong typing, they document
- // what types are required to be identical for the actions.
- typedef ActionBase::ExprTy ExprTy;
- typedef ActionBase::StmtTy StmtTy;
-
- /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
- /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
- /// allowing for failure.
- typedef ActionResult<0> ExprResult;
- typedef ActionResult<1> StmtResult;
- typedef ActionResult<2> TypeResult;
- typedef ActionResult<3> BaseResult;
- typedef ActionResult<4> MemInitResult;
- typedef ActionResult<5, DeclPtrTy> DeclResult;
-
- /// Same, but with ownership.
- typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
- typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
- // Note that these will replace ExprResult and StmtResult when the transition
- // is complete.
-
- /// Single expressions or statements as arguments.
-#if !defined(DISABLE_SMART_POINTERS)
- typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg;
- typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg;
-#else
- typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
- typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
-#endif
-
- /// Multiple expressions or statements as arguments.
- typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
- typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
- typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
-
- class FullExprArg {
- public:
- FullExprArg(ActionBase &actions) : Expr(actions) { }
-
- // FIXME: The const_cast here is ugly. RValue references would make this
- // much nicer (or we could duplicate a bunch of the move semantics
- // emulation code from Ownership.h).
- FullExprArg(const FullExprArg& Other)
- : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {}
-
- FullExprArg &operator=(const FullExprArg& Other) {
- Expr.operator=(move(const_cast<FullExprArg&>(Other).Expr));
- return *this;
- }
-
- OwningExprResult release() {
- return move(Expr);
- }
-
- ExprArg* operator->() {
- return &Expr;
- }
-
- private:
- // FIXME: No need to make the entire Action class a friend when it's just
- // Action::FullExpr that needs access to the constructor below.
- friend class Action;
-
- explicit FullExprArg(ExprArg expr)
- : Expr(move(expr)) {}
-
- ExprArg Expr;
- };
-
- template<typename T>
- FullExprArg MakeFullExpr(T &Arg) {
- return FullExprArg(ActOnFinishFullExpr(move(Arg)));
- }
-
- // Utilities for Action implementations to return smart results.
-
- OwningExprResult ExprError() { return OwningExprResult(*this, true); }
- OwningStmtResult StmtError() { return OwningStmtResult(*this, true); }
-
- OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
- OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
-
- OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); }
- OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); }
-
- /// Statistics.
- virtual void PrintStats() const {}
-
- /// getDeclName - Return a pretty name for the specified decl if possible, or
- /// an empty string if not. This is used for pretty crash reporting.
- virtual std::string getDeclName(DeclPtrTy D) { return ""; }
-
- //===--------------------------------------------------------------------===//
- // Declaration Tracking Callbacks.
- //===--------------------------------------------------------------------===//
-
- typedef uintptr_t ParsingDeclStackState;
-
- /// PushParsingDeclaration - Notes that the parser has begun
- /// processing a declaration of some sort. Guaranteed to be matched
- /// by a call to PopParsingDeclaration with the value returned by
- /// this method.
- virtual ParsingDeclStackState PushParsingDeclaration() {
- return ParsingDeclStackState();
- }
-
- /// PopParsingDeclaration - Notes that the parser has completed
- /// processing a declaration of some sort. The decl will be empty
- /// if the declaration didn't correspond to a full declaration (or
- /// if the actions module returned an empty decl for it).
- virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) {
- }
-
- /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
- /// needs a decl group, it calls this to convert between the two
- /// representations.
- virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
- return DeclGroupPtrTy();
- }
-
- /// getTypeName - Return non-null if the specified identifier is a type name
- /// in the current scope.
- ///
- /// \param II the identifier for which we are performing name lookup
- ///
- /// \param NameLoc the location of the identifier
- ///
- /// \param S the scope in which this name lookup occurs
- ///
- /// \param SS if non-NULL, the C++ scope specifier that precedes the
- /// identifier
- ///
- /// \param isClassName whether this is a C++ class-name production, in
- /// which we can end up referring to a member of an unknown specialization
- /// that we know (from the grammar) is supposed to be a type. For example,
- /// this occurs when deriving from "std::vector<T>::allocator_type", where T
- /// is a template parameter.
- ///
- /// \param ObjectType if we're checking whether an identifier is a type
- /// within a C++ member access expression, this will be the type of the
- ///
- /// \returns the type referred to by this identifier, or NULL if the type
- /// does not name an identifier.
- virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec *SS = 0,
- bool isClassName = false,
- TypeTy *ObjectType = 0) = 0;
-
- /// isTagName() - This method is called *for error recovery purposes only*
- /// to determine if the specified name is a valid tag name ("struct foo"). If
- /// so, this returns the TST for the tag corresponding to it (TST_enum,
- /// TST_union, TST_struct, TST_class). This is used to diagnose cases in C
- /// where the user forgot to specify the tag.
- virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S) {
- return DeclSpec::TST_unspecified;
- }
-
- /// \brief Action called as part of error recovery when the parser has
- /// determined that the given name must refer to a type, but
- /// \c getTypeName() did not return a result.
- ///
- /// This callback permits the action to give a detailed diagnostic when an
- /// unknown type name is encountered and, potentially, to try to recover
- /// by producing a new type in \p SuggestedType.
- ///
- /// \param II the name that should be a type.
- ///
- /// \param IILoc the location of the name in the source.
- ///
- /// \param S the scope in which name lookup was performed.
- ///
- /// \param SS if non-NULL, the C++ scope specifier that preceded the name.
- ///
- /// \param SuggestedType if the action sets this type to a non-NULL type,
- /// the parser will recovery by consuming the type name token and then
- /// pretending that the given type was the type it parsed.
- ///
- /// \returns true if a diagnostic was emitted, false otherwise. When false,
- /// the parser itself will emit a generic "unknown type name" diagnostic.
- virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- CXXScopeSpec *SS,
- TypeTy *&SuggestedType) {
- return false;
- }
-
- /// isCurrentClassName - Return true if the specified name is the
- /// name of the innermost C++ class type currently being defined.
- virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS = 0) = 0;
-
- /// \brief Determine whether the given name refers to a template.
- ///
- /// This callback is used by the parser after it has seen a '<' to determine
- /// whether the given name refers to a template and, if so, what kind of
- /// template.
- ///
- /// \param S the scope in which the name occurs.
- ///
- /// \param SS the C++ nested-name-specifier that precedes the template name,
- /// if any.
- ///
- /// \param Name the name that we are querying to determine whether it is
- /// a template.
- ///
- /// \param ObjectType if we are determining whether the given name is a
- /// template name in the context of a member access expression (e.g.,
- /// \c p->X<int>), this is the type of the object referred to by the
- /// member access (e.g., \c p).
- ///
- /// \param EnteringContext whether we are potentially entering the context
- /// referred to by the nested-name-specifier \p SS, which allows semantic
- /// analysis to look into uninstantiated templates.
- ///
- /// \param Template if the name does refer to a template, the declaration
- /// of the template that the name refers to.
- ///
- /// \param MemberOfUnknownSpecialization Will be set true if the resulting
- /// member would be a member of an unknown specialization, in which case this
- /// lookup cannot possibly pass at this time.
- ///
- /// \returns the kind of template that this name refers to.
- virtual TemplateNameKind isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template,
- bool &MemberOfUnknownSpecialization) = 0;
-
- /// \brief Action called as part of error recovery when the parser has
- /// determined that the given name must refer to a template, but
- /// \c isTemplateName() did not return a result.
- ///
- /// This callback permits the action to give a detailed diagnostic when an
- /// unknown template name is encountered and, potentially, to try to recover
- /// by producing a new template in \p SuggestedTemplate.
- ///
- /// \param II the name that should be a template.
- ///
- /// \param IILoc the location of the name in the source.
- ///
- /// \param S the scope in which name lookup was performed.
- ///
- /// \param SS the C++ scope specifier that preceded the name.
- ///
- /// \param SuggestedTemplate if the action sets this template to a non-NULL,
- /// template, the parser will recover by consuming the template name token
- /// and the template argument list that follows.
- ///
- /// \param SuggestedTemplateKind as input, the kind of template that we
- /// expect (e.g., \c TNK_Type_template or \c TNK_Function_template). If the
- /// action provides a suggested template, this should be set to the kind of
- /// template.
- ///
- /// \returns true if a diagnostic was emitted, false otherwise. When false,
- /// the parser itself will emit a generic "unknown template name" diagnostic.
- virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- const CXXScopeSpec *SS,
- TemplateTy &SuggestedTemplate,
- TemplateNameKind &SuggestedKind) {
- return false;
- }
-
- /// \brief Determine whether the given name refers to a non-type nested name
- /// specifier, e.g., the name of a namespace or namespace alias.
- ///
- /// This actual is used in the parsing of pseudo-destructor names to
- /// distinguish a nested-name-specifier and a "type-name ::" when we
- /// see the token sequence "X :: ~".
- virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
- SourceLocation IdLoc,
- IdentifierInfo &II,
- TypeTy *ObjectType) {
- return false;
- }
-
- /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
- /// global scope ('::').
- virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
- SourceLocation CCLoc) {
- return 0;
- }
-
- /// \brief Parsed an identifier followed by '::' in a C++
- /// nested-name-specifier.
- ///
- /// \param S the scope in which the nested-name-specifier was parsed.
- ///
- /// \param SS the nested-name-specifier that precedes the identifier. For
- /// example, if we are parsing "foo::bar::", \p SS will describe the "foo::"
- /// that has already been parsed.
- ///
- /// \param IdLoc the location of the identifier we have just parsed (e.g.,
- /// the "bar" in "foo::bar::".
- ///
- /// \param CCLoc the location of the '::' at the end of the
- /// nested-name-specifier.
- ///
- /// \param II the identifier that represents the scope that this
- /// nested-name-specifier refers to, e.g., the "bar" in "foo::bar::".
- ///
- /// \param ObjectType if this nested-name-specifier occurs as part of a
- /// C++ member access expression such as "x->Base::f", the type of the base
- /// object (e.g., *x in the example, if "x" were a pointer).
- ///
- /// \param EnteringContext if true, then we intend to immediately enter the
- /// context of this nested-name-specifier, e.g., for an out-of-line
- /// definition of a class member.
- ///
- /// \returns a CXXScopeTy* object representing the C++ scope.
- virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- TypeTy *ObjectType,
- bool EnteringContext) {
- return 0;
- }
-
- /// IsInvalidUnlessNestedName - This method is used for error recovery
- /// purposes to determine whether the specified identifier is only valid as
- /// a nested name specifier, for example a namespace name. It is
- /// conservatively correct to always return false from this method.
- ///
- /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
- virtual bool IsInvalidUnlessNestedName(Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo &II,
- TypeTy *ObjectType,
- bool EnteringContext) {
- return false;
- }
-
- /// ActOnCXXNestedNameSpecifier - Called during parsing of a
- /// nested-name-specifier that involves a template-id, e.g.,
- /// "foo::bar<int, float>::", and now we need to build a scope
- /// specifier. \p SS is empty or the previously parsed nested-name
- /// part ("foo::"), \p Type is the already-parsed class template
- /// specialization (or other template-id that names a type), \p
- /// TypeRange is the source range where the type is located, and \p
- /// CCLoc is the location of the trailing '::'.
- virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- TypeTy *Type,
- SourceRange TypeRange,
- SourceLocation CCLoc) {
- return 0;
- }
-
- /// ShouldEnterDeclaratorScope - Called when a C++ scope specifier
- /// is parsed as part of a declarator-id to determine whether a scope
- /// should be entered.
- ///
- /// \param S the current scope
- /// \param SS the scope being entered
- /// \param isFriendDeclaration whether this is a friend declaration
- virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
- return false;
- }
-
- /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
- /// scope or nested-name-specifier) is parsed as part of a declarator-id.
- /// After this method is called, according to [C++ 3.4.3p3], names should be
- /// looked up in the declarator-id's scope, until the declarator is parsed and
- /// ActOnCXXExitDeclaratorScope is called.
- /// The 'SS' should be a non-empty valid CXXScopeSpec.
- /// \returns true if an error occurred, false otherwise.
- virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) {
- return false;
- }
-
- /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
- /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
- /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
- /// Used to indicate that names should revert to being looked up in the
- /// defining scope.
- virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
- }
-
- /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
- /// initializer for the declaration 'Dcl'.
- /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
- /// static data member of class X, names should be looked up in the scope of
- /// class X.
- virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
- }
-
- /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
- /// initializer for the declaration 'Dcl'.
- virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
- }
-
- /// ActOnDeclarator - This callback is invoked when a declarator is parsed and
- /// 'Init' specifies the initializer if any. This is for things like:
- /// "int X = 4" or "typedef int foo".
- ///
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- /// ActOnParamDeclarator - This callback is invoked when a parameter
- /// declarator is parsed. This callback only occurs for functions
- /// with prototypes. S is the function prototype scope for the
- /// parameters (C++ [basic.scope.proto]).
- virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- /// \brief Parsed an exception object declaration within an Objective-C
- /// @catch statement.
- virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- /// AddInitializerToDecl - This action is called immediately after
- /// ActOnDeclarator (when an initializer is present). The code is factored
- /// this way to make sure we are able to handle the following:
- /// void func() { int xx = xx; }
- /// This allows ActOnDeclarator to register "xx" prior to parsing the
- /// initializer. The declaration above should still result in a warning,
- /// since the reference to "xx" is uninitialized.
- virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) {
- return;
- }
-
- /// SetDeclDeleted - This action is called immediately after ActOnDeclarator
- /// if =delete is parsed. C++0x [dcl.fct.def]p10
- /// Note that this can be called even for variable declarations. It's the
- /// action's job to reject it.
- virtual void SetDeclDeleted(DeclPtrTy Dcl, SourceLocation DelLoc) {
- return;
- }
-
- /// ActOnUninitializedDecl - This action is called immediately after
- /// ActOnDeclarator (when an initializer is *not* present).
- /// If TypeContainsUndeducedAuto is true, then the type of the declarator
- /// has an undeduced 'auto' type somewhere.
- virtual void ActOnUninitializedDecl(DeclPtrTy Dcl,
- bool TypeContainsUndeducedAuto) {
- return;
- }
-
- /// \brief Note that the given declaration had an initializer that could not
- /// be parsed.
- virtual void ActOnInitializerError(DeclPtrTy Dcl) {
- return;
- }
-
- /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
- /// gives the actions implementation a chance to process the group as a whole.
- virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS,
- DeclPtrTy *Group,
- unsigned NumDecls) {
- return DeclGroupPtrTy();
- }
-
-
- /// @brief Indicates that all K&R-style parameter declarations have
- /// been parsed prior to a function definition.
- /// @param S The function prototype scope.
- /// @param D The function declarator.
- virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
- SourceLocation LocAfterDecls) {
- }
-
- /// ActOnStartOfFunctionDef - This is called at the start of a function
- /// definition, instead of calling ActOnDeclarator. The Declarator includes
- /// information about formal arguments that are part of this function.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
- // Default to ActOnDeclarator.
- return ActOnStartOfFunctionDef(FnBodyScope,
- ActOnDeclarator(FnBodyScope, D));
- }
-
- /// ActOnStartOfFunctionDef - This is called at the start of a function
- /// definition, after the FunctionDecl has already been created.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
- return D;
- }
-
- virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
- return;
- }
-
- /// ActOnFinishFunctionBody - This is called when a function body has
- /// completed parsing. Decl is returned by ParseStartOfFunctionDef.
- virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) {
- return Decl;
- }
-
- virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc,
- ExprArg AsmString) {
- return DeclPtrTy();
- }
-
- /// ActOnPopScope - This callback is called immediately before the specified
- /// scope is popped and deleted.
- virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {}
-
- /// ActOnTranslationUnitScope - This callback is called once, immediately
- /// after creating the translation unit scope (in Parser::Initialize).
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {}
-
- /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
- /// no declarator (e.g. "struct foo;") is parsed.
- virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S,
- AccessSpecifier Access,
- DeclSpec &DS) {
- return DeclPtrTy();
- }
-
- /// ActOnStartLinkageSpecification - Parsed the beginning of a C++
- /// linkage specification, including the language and (if present)
- /// the '{'. ExternLoc is the location of the 'extern', LangLoc is
- /// the location of the language string literal, which is provided
- /// by Lang/StrSize. LBraceLoc, if valid, provides the location of
- /// the '{' brace. Otherwise, this linkage specification does not
- /// have any braces.
- virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation LangLoc,
- llvm::StringRef Lang,
- SourceLocation LBraceLoc) {
- return DeclPtrTy();
- }
-
- /// ActOnFinishLinkageSpecification - Completely the definition of
- /// the C++ linkage specification LinkageSpec. If RBraceLoc is
- /// valid, it's the position of the closing '}' brace in a linkage
- /// specification that uses braces.
- virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S,
- DeclPtrTy LinkageSpec,
- SourceLocation RBraceLoc) {
- return LinkageSpec;
- }
-
- /// ActOnEndOfTranslationUnit - This is called at the very end of the
- /// translation unit when EOF is reached and all but the top-level scope is
- /// popped.
- virtual void ActOnEndOfTranslationUnit() {}
-
- //===--------------------------------------------------------------------===//
- // Type Parsing Callbacks.
- //===--------------------------------------------------------------------===//
-
- /// ActOnTypeName - A type-name (type-id in C++) was parsed.
- virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
- return TypeResult();
- }
-
- enum TagUseKind {
- TUK_Reference, // Reference to a tag: 'struct foo *X;'
- TUK_Declaration, // Fwd decl of a tag: 'struct foo;'
- TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;'
- TUK_Friend // Friend declaration: 'friend struct foo;'
- };
-
- /// \brief The parser has encountered a tag (e.g., "class X") that should be
- /// turned into a declaration by the action module.
- ///
- /// \param S the scope in which this tag occurs.
- ///
- /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag
- /// this is (struct/union/enum/class).
- ///
- /// \param TUK how the tag we have encountered is being used, which
- /// can be a reference to a (possibly pre-existing) tag, a
- /// declaration of that tag, or the beginning of a definition of
- /// that tag.
- ///
- /// \param KWLoc the location of the "struct", "class", "union", or "enum"
- /// keyword.
- ///
- /// \param SS C++ scope specifier that precedes the name of the tag, e.g.,
- /// the "std::" in "class std::type_info".
- ///
- /// \param Name the name of the tag, e.g., "X" in "struct X". This parameter
- /// may be NULL, to indicate an anonymous class/struct/union/enum type.
- ///
- /// \param NameLoc the location of the name of the tag.
- ///
- /// \param Attr the set of attributes that appertain to the tag.
- ///
- /// \param AS when this tag occurs within a C++ class, provides the
- /// current access specifier (AS_public, AS_private, AS_protected).
- /// Otherwise, it will be AS_none.
- ///
- /// \param TemplateParameterLists the set of C++ template parameter lists
- /// that apply to this tag, if the tag is a declaration or definition (see
- /// the \p TK parameter). The action module is responsible for determining,
- /// based on the template parameter lists and the scope specifier, whether
- /// the declared tag is a class template or not.
- ///
- /// \param OwnedDecl the callee should set this flag true when the returned
- /// declaration is "owned" by this reference. Ownership is handled entirely
- /// by the action module.
- ///
- /// \returns the declaration to which this tag refers.
- virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
- MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent) {
- return DeclPtrTy();
- }
-
- /// Acts on a reference to a dependent tag name. This arises in
- /// cases like:
- ///
- /// template <class T> class A;
- /// template <class T> class B {
- /// friend class A<T>::M; // here
- /// };
- ///
- /// \param TagSpec an instance of DeclSpec::TST corresponding to the
- /// tag specifier.
- ///
- /// \param TUK the tag use kind (either TUK_Friend or TUK_Reference)
- ///
- /// \param SS the scope specifier (always defined)
- virtual TypeResult ActOnDependentTag(Scope *S,
- unsigned TagSpec,
- TagUseKind TUK,
- const CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation KWLoc,
- SourceLocation NameLoc) {
- return TypeResult();
- }
-
- /// Act on @defs() element found when parsing a structure. ClassName is the
- /// name of the referenced class.
- virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
- IdentifierInfo *ClassName,
- llvm::SmallVectorImpl<DeclPtrTy> &Decls) {}
- virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
- SourceLocation DeclStart,
- Declarator &D, ExprTy *BitfieldWidth) {
- return DeclPtrTy();
- }
-
- virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
- DeclPtrTy IntfDecl,
- Declarator &D, ExprTy *BitfieldWidth,
- tok::ObjCKeywordKind visibility) {
- return DeclPtrTy();
- }
-
- virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl,
- DeclPtrTy *Fields, unsigned NumFields,
- SourceLocation LBrac, SourceLocation RBrac,
- AttributeList *AttrList) {}
-
- /// ActOnTagStartDefinition - Invoked when we have entered the
- /// scope of a tag's definition (e.g., for an enumeration, class,
- /// struct, or union).
- virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { }
-
- /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
- /// C++ record definition's base-specifiers clause and are starting its
- /// member declarations.
- virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl,
- SourceLocation LBraceLoc) { }
-
- /// ActOnTagFinishDefinition - Invoked once we have finished parsing
- /// the definition of a tag (enumeration, class, struct, or union).
- ///
- /// The scope is the scope of the tag definition.
- virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl,
- SourceLocation RBraceLoc) { }
-
- /// ActOnTagDefinitionError - Invoked if there's an unrecoverable
- /// error parsing the definition of a tag.
- ///
- /// The scope is the scope of the tag definition.
- virtual void ActOnTagDefinitionError(Scope *S, DeclPtrTy TagDecl) { }
-
- virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
- DeclPtrTy LastEnumConstant,
- SourceLocation IdLoc, IdentifierInfo *Id,
- SourceLocation EqualLoc, ExprTy *Val) {
- return DeclPtrTy();
- }
- virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
- DeclPtrTy *Elements, unsigned NumElements,
- Scope *S, AttributeList *AttrList) {}
-
- //===--------------------------------------------------------------------===//
- // Statement Parsing Callbacks.
- //===--------------------------------------------------------------------===//
-
- virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
- MultiStmtArg Elts,
- bool isStmtExpr) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- return StmtEmpty();
- }
-
- virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl) {
- }
-
- virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) {
- return OwningStmtResult(*this, Expr->release());
- }
-
- /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
- /// which can specify an RHS value. The sub-statement of the case is
- /// specified in a separate action.
- virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
- SourceLocation DotDotDotLoc,
- ExprArg RHSVal,
- SourceLocation ColonLoc) {
- return StmtEmpty();
- }
-
- /// ActOnCaseStmtBody - This installs a statement as the body of a case.
- virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt) {}
-
- virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
- SourceLocation ColonLoc,
- StmtArg SubStmt, Scope *CurScope){
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation ColonLoc,
- StmtArg SubStmt) {
- return StmtEmpty();
- }
-
- /// \brief Parsed an "if" statement.
- ///
- /// \param IfLoc the location of the "if" keyword.
- ///
- /// \param CondVal if the "if" condition was parsed as an expression,
- /// the expression itself.
- ///
- /// \param CondVar if the "if" condition was parsed as a condition variable,
- /// the condition variable itself.
- ///
- /// \param ThenVal the "then" statement.
- ///
- /// \param ElseLoc the location of the "else" keyword.
- ///
- /// \param ElseVal the "else" statement.
- virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
- FullExprArg CondVal,
- DeclPtrTy CondVar,
- StmtArg ThenVal,
- SourceLocation ElseLoc,
- StmtArg ElseVal) {
- return StmtEmpty();
- }
-
- /// \brief Parsed the start of a "switch" statement.
- ///
- /// \param SwitchLoc The location of the "switch" keyword.
- ///
- /// \param Cond if the "switch" condition was parsed as an expression,
- /// the expression itself.
- ///
- /// \param CondVar if the "switch" condition was parsed as a condition
- /// variable, the condition variable itself.
- virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
- ExprArg Cond,
- DeclPtrTy CondVar) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
- StmtArg Switch, StmtArg Body) {
- return StmtEmpty();
- }
-
- /// \brief Parsed a "while" statement.
- ///
- /// \param Cond if the "while" condition was parsed as an expression,
- /// the expression itself.
- ///
- /// \param CondVar if the "while" condition was parsed as a condition
- /// variable, the condition variable itself.
- ///
- /// \param Body the body of the "while" loop.
- virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
- FullExprArg Cond, DeclPtrTy CondVar,
- StmtArg Body) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
- SourceLocation WhileLoc,
- SourceLocation CondLParen,
- ExprArg Cond,
- SourceLocation CondRParen) {
- return StmtEmpty();
- }
-
- /// \brief Parsed a "for" statement.
- ///
- /// \param ForLoc the location of the "for" keyword.
- ///
- /// \param LParenLoc the location of the left parentheses.
- ///
- /// \param First the statement used to initialize the for loop.
- ///
- /// \param Second the condition to be checked during each iteration, if
- /// that condition was parsed as an expression.
- ///
- /// \param SecondArg the condition variable to be checked during each
- /// iterator, if that condition was parsed as a variable declaration.
- ///
- /// \param Third the expression that will be evaluated to "increment" any
- /// values prior to the next iteration.
- ///
- /// \param RParenLoc the location of the right parentheses.
- ///
- /// \param Body the body of the "body" loop.
- virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc,
- StmtArg First, FullExprArg Second,
- DeclPtrTy SecondVar, FullExprArg Third,
- SourceLocation RParenLoc,
- StmtArg Body) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
- SourceLocation LParenLoc,
- StmtArg First, ExprArg Second,
- SourceLocation RParenLoc, StmtArg Body) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
- SourceLocation LabelLoc,
- IdentifierInfo *LabelII) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
- SourceLocation StarLoc,
- ExprArg DestExp) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
- Scope *CurScope) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
- Scope *CurScope) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
- ExprArg RetValExp) {
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
- bool IsSimple,
- bool IsVolatile,
- unsigned NumOutputs,
- unsigned NumInputs,
- IdentifierInfo **Names,
- MultiExprArg Constraints,
- MultiExprArg Exprs,
- ExprArg AsmString,
- MultiExprArg Clobbers,
- SourceLocation RParenLoc,
- bool MSAsm = false) {
- return StmtEmpty();
- }
-
- // Objective-c statements
-
- /// \brief Parsed an Objective-C @catch statement.
- ///
- /// \param AtLoc The location of the '@' starting the '@catch'.
- ///
- /// \param RParen The location of the right parentheses ')' after the
- /// exception variable.
- ///
- /// \param Parm The variable that will catch the exception. Will be NULL if
- /// this is a @catch(...) block.
- ///
- /// \param Body The body of the @catch block.
- virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
- SourceLocation RParen,
- DeclPtrTy Parm, StmtArg Body) {
- return StmtEmpty();
- }
-
- /// \brief Parsed an Objective-C @finally statement.
- ///
- /// \param AtLoc The location of the '@' starting the '@finally'.
- ///
- /// \param Body The body of the @finally block.
- virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
- StmtArg Body) {
- return StmtEmpty();
- }
-
- /// \brief Parsed an Objective-C @try-@catch-@finally statement.
- ///
- /// \param AtLoc The location of the '@' starting '@try'.
- ///
- /// \param Try The body of the '@try' statement.
- ///
- /// \param CatchStmts The @catch statements.
- ///
- /// \param Finally The @finally statement.
- virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
- StmtArg Try,
- MultiStmtArg CatchStmts,
- StmtArg Finally) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg Throw,
- Scope *CurScope) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
- ExprArg SynchExpr,
- StmtArg SynchBody) {
- return StmtEmpty();
- }
-
- // C++ Statements
- virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) {
- return DeclPtrTy();
- }
-
- virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
- DeclPtrTy ExceptionDecl,
- StmtArg HandlerBlock) {
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
- StmtArg TryBlock,
- MultiStmtArg Handlers) {
- return StmtEmpty();
- }
-
- //===--------------------------------------------------------------------===//
- // Expression Parsing Callbacks.
- //===--------------------------------------------------------------------===//
-
- /// \brief Describes how the expressions currently being parsed are
- /// evaluated at run-time, if at all.
- enum ExpressionEvaluationContext {
- /// \brief The current expression and its subexpressions occur within an
- /// unevaluated operand (C++0x [expr]p8), such as a constant expression
- /// or the subexpression of \c sizeof, where the type or the value of the
- /// expression may be significant but no code will be generated to evaluate
- /// the value of the expression at run time.
- Unevaluated,
-
- /// \brief The current expression is potentially evaluated at run time,
- /// which means that code may be generated to evaluate the value of the
- /// expression at run time.
- PotentiallyEvaluated,
-
- /// \brief The current expression may be potentially evaluated or it may
- /// be unevaluated, but it is impossible to tell from the lexical context.
- /// This evaluation context is used primary for the operand of the C++
- /// \c typeid expression, whose argument is potentially evaluated only when
- /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
- PotentiallyPotentiallyEvaluated
- };
-
- /// \brief The parser is entering a new expression evaluation context.
- ///
- /// \param NewContext is the new expression evaluation context.
- virtual void
- PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { }
-
- /// \brief The parser is exiting an expression evaluation context.
- virtual void
- PopExpressionEvaluationContext() { }
-
- // Primary Expressions.
-
- /// \brief Retrieve the source range that corresponds to the given
- /// expression.
- virtual SourceRange getExprRange(ExprTy *E) const {
- return SourceRange();
- }
-
- /// \brief Parsed an id-expression (C++) or identifier (C) in expression
- /// context, e.g., the expression "x" that refers to a variable named "x".
- ///
- /// \param S the scope in which this id-expression or identifier occurs.
- ///
- /// \param SS the C++ nested-name-specifier that qualifies the name of the
- /// value, e.g., "std::" in "std::sort".
- ///
- /// \param Name the name to which the id-expression refers. In C, this will
- /// always be an identifier. In C++, it may also be an overloaded operator,
- /// destructor name (if there is a nested-name-specifier), or template-id.
- ///
- /// \param HasTrailingLParen whether the next token following the
- /// id-expression or identifier is a left parentheses ('(').
- ///
- /// \param IsAddressOfOperand whether the token that precedes this
- /// id-expression or identifier was an ampersand ('&'), indicating that
- /// we will be taking the address of this expression.
- virtual OwningExprResult ActOnIdExpression(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- bool HasTrailingLParen,
- bool IsAddressOfOperand) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
- tok::TokenKind Kind) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnCharacterConstant(const Token &) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnNumericConstant(const Token &) {
- return ExprEmpty();
- }
-
- /// ActOnStringLiteral - The specified tokens were lexed as pasted string
- /// fragments (e.g. "foo" "bar" L"baz").
- virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
- unsigned NumToks) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
- ExprArg Val) {
- return move(Val); // Default impl returns operand.
- }
-
- virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L,
- SourceLocation R,
- MultiExprArg Val,
- TypeTy *TypeOfCast=0) {
- return ExprEmpty();
- }
-
- // Postfix Expressions.
- virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind,
- ExprArg Input) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
- SourceLocation LLoc,
- ExprArg Idx,
- SourceLocation RLoc) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a member access expresion (C99 6.5.2.3, C++ [expr.ref])
- /// of the form \c x.m or \c p->m.
- ///
- /// \param S the scope in which the member access expression occurs.
- ///
- /// \param Base the class or pointer to class into which this member
- /// access expression refers, e.g., \c x in \c x.m.
- ///
- /// \param OpLoc the location of the "." or "->" operator.
- ///
- /// \param OpKind the kind of member access operator, which will be either
- /// tok::arrow ("->") or tok::period (".").
- ///
- /// \param SS in C++, the nested-name-specifier that precedes the member
- /// name, if any.
- ///
- /// \param Member the name of the member that we are referring to. In C,
- /// this will always store an identifier; in C++, we may also have operator
- /// names, conversion function names, destructors, and template names.
- ///
- /// \param ObjCImpDecl the Objective-C implementation declaration.
- /// FIXME: Do we really need this?
- ///
- /// \param HasTrailingLParen whether this member name is immediately followed
- /// by a left parentheses ('(').
- virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &Member,
- DeclPtrTy ObjCImpDecl,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
- /// This provides the location of the left/right parens and a list of comma
- /// locations. There are guaranteed to be one fewer commas than arguments,
- /// unless there are zero arguments.
- virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- // Unary Operators. 'Tok' is the token for the operator.
- virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg Input) {
- return ExprEmpty();
- }
- virtual OwningExprResult
- ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
- void *TyOrEx, const SourceRange &ArgRange) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen,
- ExprArg Op) {
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
- MultiExprArg InitList,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
- /// @brief Parsed a C99 designated initializer.
- ///
- /// @param Desig Contains the designation with one or more designators.
- ///
- /// @param Loc The location of the '=' or ':' prior to the
- /// initialization expression.
- ///
- /// @param GNUSyntax If true, then this designated initializer used
- /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather
- /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo.
- ///
- /// @param Init The value that the entity (or entities) described by
- /// the designation will be initialized with.
- virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig,
- SourceLocation Loc,
- bool GNUSyntax,
- OwningExprResult Init) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- TypeTy *Ty, SourceLocation RParenLoc,
- ExprArg Op) {
- return ExprEmpty();
- }
-
- virtual bool TypeIsVectorType(TypeTy *Ty) {
- return false;
- }
-
- virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
- tok::TokenKind Kind,
- ExprArg LHS, ExprArg RHS) {
- return ExprEmpty();
- }
-
- /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
- /// in the case of a the GNU conditional expr extension.
- virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
- SourceLocation ColonLoc,
- ExprArg Cond, ExprArg LHS,
- ExprArg RHS) {
- return ExprEmpty();
- }
-
- //===---------------------- GNU Extension Expressions -------------------===//
-
- virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
- IdentifierInfo *LabelII) { // "&&foo"
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt,
- SourceLocation RPLoc) { // "({..})"
- return ExprEmpty();
- }
-
- // __builtin_offsetof(type, identifier(.identifier|[expr])*)
- struct OffsetOfComponent {
- SourceLocation LocStart, LocEnd;
- bool isBrackets; // true if [expr], false if .ident
- union {
- IdentifierInfo *IdentInfo;
- ExprTy *E;
- } U;
- };
-
- virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
- SourceLocation BuiltinLoc,
- SourceLocation TypeLoc,
- TypeTy *Arg1,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- // __builtin_types_compatible_p(type1, type2)
- virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
- TypeTy *arg1, TypeTy *arg2,
- SourceLocation RPLoc) {
- return ExprEmpty();
- }
- // __builtin_choose_expr(constExpr, expr1, expr2)
- virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
- ExprArg cond, ExprArg expr1,
- ExprArg expr2, SourceLocation RPLoc){
- return ExprEmpty();
- }
-
- // __builtin_va_arg(expr, type)
- virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
- ExprArg expr, TypeTy *type,
- SourceLocation RPLoc) {
- return ExprEmpty();
- }
-
- /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token
- /// for which is at position TokenLoc.
- virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) {
- return ExprEmpty();
- }
-
- //===------------------------- "Block" Extension ------------------------===//
-
- /// ActOnBlockStart - This callback is invoked when a block literal is
- /// started. The result pointer is passed into the block finalizers.
- virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {}
-
- /// ActOnBlockArguments - This callback allows processing of block arguments.
- /// If there are no arguments, this is still invoked.
- virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {}
-
- /// ActOnBlockError - If there is an error parsing a block, this callback
- /// is invoked to pop the information about the block from the action impl.
- virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {}
-
- /// ActOnBlockStmtExpr - This is called when the body of a block statement
- /// literal was successfully completed. ^(int x){...}
- virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
- StmtArg Body,
- Scope *CurScope) {
- return ExprEmpty();
- }
-
- //===------------------------- C++ Declarations -------------------------===//
-
- /// ActOnStartNamespaceDef - This is called at the start of a namespace
- /// definition.
- virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
- IdentifierInfo *Ident,
- SourceLocation LBrace,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
-
- /// ActOnFinishNamespaceDef - This callback is called after a namespace is
- /// exited. Decl is returned by ActOnStartNamespaceDef.
- virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) {
- return;
- }
-
- /// ActOnUsingDirective - This is called when using-directive is parsed.
- virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList);
-
- /// ActOnNamespaceAliasDef - This is called when a namespace alias definition
- /// is parsed.
- virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *Ident) {
- return DeclPtrTy();
- }
-
- /// \brief Parsed a C++ using-declaration.
- ///
- /// This callback will be invoked when the parser has parsed a C++
- /// using-declaration, e.g.,
- ///
- /// \code
- /// namespace std {
- /// template<typename T, typename Alloc> class vector;
- /// }
- ///
- /// using std::vector; // using-declaration here
- /// \endcode
- ///
- /// \param CurScope the scope in which this using declaration was parsed.
- ///
- /// \param AS the currently-active access specifier.
- ///
- /// \param HasUsingKeyword true if this was declared with an
- /// explicit 'using' keyword (i.e. if this is technically a using
- /// declaration, not an access declaration)
- ///
- /// \param UsingLoc the location of the 'using' keyword.
- ///
- /// \param SS the nested-name-specifier that precedes the name.
- ///
- /// \param Name the name to which the using declaration refers.
- ///
- /// \param AttrList attributes applied to this using declaration, if any.
- ///
- /// \param IsTypeName whether this using declaration started with the
- /// '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,
- bool HasUsingKeyword,
- SourceLocation UsingLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- bool IsTypeName,
- SourceLocation TypenameLoc);
-
- /// ActOnParamDefaultArgument - Parse default argument for function parameter
- virtual void ActOnParamDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- ExprArg defarg) {
- }
-
- /// ActOnParamUnparsedDefaultArgument - We've seen a default
- /// argument for a function parameter, but we can't parse it yet
- /// because we're inside a class definition. Note that this default
- /// argument will be parsed later.
- virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- SourceLocation ArgLoc) { }
-
- /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
- /// the default argument for the parameter param failed.
- virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { }
-
- /// AddCXXDirectInitializerToDecl - This action is called immediately after
- /// ActOnDeclarator, when a C++ direct initializer is present.
- /// e.g: "int x(1);"
- virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return;
- }
-
- /// \brief Called when we re-enter a template parameter scope.
- ///
- /// This action occurs when we are going to parse an member
- /// function's default arguments or inline definition after the
- /// outermost class definition has been completed, and when one or
- /// more of the class definitions enclosing the member function is a
- /// template. The "entity" in the given scope will be set as it was
- /// when we entered the scope of the template initially, and should
- /// be used to, e.g., reintroduce the names of template parameters
- /// into the current scope so that they can be found by name lookup.
- ///
- /// \param S The (new) template parameter scope.
- ///
- /// \param Template the class template declaration whose template
- /// parameters should be reintroduced into the current scope.
- virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) {
- }
-
- /// ActOnStartDelayedMemberDeclarations - We have completed parsing
- /// a C++ class, and we are about to start parsing any parts of
- /// member declarations that could not be parsed earlier. Enter
- /// the appropriate record scope.
- virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
- DeclPtrTy Record) {
- }
-
- /// ActOnStartDelayedCXXMethodDeclaration - We have completed
- /// parsing a top-level (non-nested) C++ class, and we are now
- /// parsing those parts of the given Method declaration that could
- /// not be parsed earlier (C++ [class.mem]p2), such as default
- /// arguments. This action should enter the scope of the given
- /// Method declaration as if we had just parsed the qualified method
- /// name. However, it should not bring the parameters into scope;
- /// that will be performed by ActOnDelayedCXXMethodParameter.
- virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method) {
- }
-
- /// ActOnDelayedCXXMethodParameter - We've already started a delayed
- /// C++ method declaration. We're (re-)introducing the given
- /// function parameter into scope for use in parsing later parts of
- /// the method declaration. For example, we could see an
- /// ActOnParamDefaultArgument event for this parameter.
- virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) {
- }
-
- /// ActOnFinishDelayedCXXMethodDeclaration - We have finished
- /// processing the delayed method declaration for Method. The method
- /// declaration is now considered finished. There may be a separate
- /// ActOnStartOfFunctionDef action later (not necessarily
- /// immediately!) for this method, if it was also defined inside the
- /// class body.
- virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method) {
- }
-
- /// ActOnFinishDelayedMemberDeclarations - We have finished parsing
- /// a C++ class, and we are about to start parsing any parts of
- /// member declarations that could not be parsed earlier. Enter the
- /// appropriate record scope.
- virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
- DeclPtrTy Record) {
- }
-
- /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
- virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
- ExprArg AssertExpr,
- ExprArg AssertMessageExpr) {
- return DeclPtrTy();
- }
-
- /// ActOnFriendFunctionDecl - Parsed a friend function declarator.
- /// The name is actually a slight misnomer, because the declarator
- /// is not necessarily a function declarator.
- virtual DeclPtrTy ActOnFriendFunctionDecl(Scope *S,
- Declarator &D,
- bool IsDefinition,
- MultiTemplateParamsArg TParams) {
- return DeclPtrTy();
- }
-
- /// ActOnFriendTypeDecl - Parsed a friend type declaration.
- virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
- MultiTemplateParamsArg TParams) {
- return DeclPtrTy();
- }
-
- //===------------------------- C++ Expressions --------------------------===//
-
- /// \brief Parsed a destructor name or pseudo-destructor name.
- ///
- /// \returns the type being destructed.
- virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
- IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec &SS,
- TypeTy *ObjectType,
- bool EnteringContext) {
- return getTypeName(II, NameLoc, S, &SS, false, ObjectType);
- }
-
-
- /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
- virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc,
- TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc,
- ExprArg Op,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXTypeidOfType - Parse typeid( type-id ).
- virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXThis - Parse the C++ 'this' pointer.
- virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXBoolLiteral - Parse {true,false} literals.
- virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
- tok::TokenKind Kind) {
- return ExprEmpty();
- }
-
- /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
- virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) {
- return ExprEmpty();
- }
-
- /// ActOnCXXThrow - Parse throw expressions.
- virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) {
- return ExprEmpty();
- }
-
- /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
- /// Can be interpreted either as function-style casting ("int(x)")
- /// or class type construction ("ClassType(x,y,z)")
- /// or creation of a value-initialized type ("int()").
- virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
- TypeTy *TypeRep,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a condition declaration in a C++ if, switch, or while
- /// statement.
- ///
- /// This callback will be invoked after parsing the declaration of "x" in
- ///
- /// \code
- /// if (int x = f()) {
- /// // ...
- /// }
- /// \endcode
- ///
- /// \param S the scope of the if, switch, or while statement.
- ///
- /// \param D the declarator that that describes the variable being declared.
- virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
- return DeclResult();
- }
-
- /// \brief Parsed an expression that will be handled as the condition in
- /// an if/while/for statement.
- ///
- /// This routine handles the conversion of the expression to 'bool'.
- ///
- /// \param S The scope in which the expression occurs.
- ///
- /// \param Loc The location of the construct that requires the conversion to
- /// a boolean value.
- ///
- /// \param SubExpr The expression that is being converted to bool.
- virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,
- ExprArg SubExpr) {
- return move(SubExpr);
- }
-
- /// \brief Parsed a C++ 'new' expression.
- ///
- /// \param StartLoc The start of the new expression, which is either the
- /// "new" keyword or the "::" preceding it, depending on \p UseGlobal.
- ///
- /// \param UseGlobal True if the "new" was qualified with "::".
- ///
- /// \param PlacementLParen The location of the opening parenthesis ('(') for
- /// the placement arguments, if any.
- ///
- /// \param PlacementArgs The placement arguments, if any.
- ///
- /// \param PlacementRParen The location of the closing parenthesis (')') for
- /// the placement arguments, if any.
- ///
- /// \param TypeIdParens If the type was expressed as a type-id in parentheses,
- /// the source range covering the parenthesized type-id.
- ///
- /// \param D The parsed declarator, which may include an array size (for
- /// array new) as the first declarator.
- ///
- /// \param ConstructorLParen The location of the opening parenthesis ('(') for
- /// the constructor arguments, if any.
- ///
- /// \param ConstructorArgs The constructor arguments, if any.
- ///
- /// \param ConstructorRParen The location of the closing parenthesis (')') for
- /// the constructor arguments, if any.
- virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
- SourceLocation PlacementLParen,
- MultiExprArg PlacementArgs,
- SourceLocation PlacementRParen,
- SourceRange TypeIdParens, Declarator &D,
- SourceLocation ConstructorLParen,
- MultiExprArg ConstructorArgs,
- SourceLocation ConstructorRParen) {
- return ExprEmpty();
- }
-
- /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if
- /// the delete was qualified (::delete). ArrayForm is true if the array form
- /// was used (delete[]).
- virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
- bool UseGlobal, bool ArrayForm,
- ExprArg Operand) {
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
- SourceLocation KWLoc,
- SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen) {
- return ExprEmpty();
- }
-
- /// \brief Invoked when the parser is starting to parse a C++ member access
- /// expression such as x.f or x->f.
- ///
- /// \param S the scope in which the member access expression occurs.
- ///
- /// \param Base the expression in which a member is being accessed, e.g., the
- /// "x" in "x.f".
- ///
- /// \param OpLoc the location of the member access operator ("." or "->")
- ///
- /// \param OpKind the kind of member access operator ("." or "->")
- ///
- /// \param ObjectType originally NULL. The action should fill in this type
- /// with the type into which name lookup should look to find the member in
- /// the member access expression.
- ///
- /// \param MayBePseudoDestructor Originally false. The action should
- /// set this true if the expression may end up being a
- /// pseudo-destructor expression, indicating to the parser that it
- /// shoudl be parsed as a pseudo-destructor rather than as a member
- /// access expression. Note that this should apply both when the
- /// object type is a scalar and when the object type is dependent.
- ///
- /// \returns the (possibly modified) \p Base expression
- virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- TypeTy *&ObjectType,
- bool &MayBePseudoDestructor) {
- return ExprEmpty();
- }
-
- /// \brief Parsed a C++ pseudo-destructor expression or a dependent
- /// member access expression that has the same syntactic form as a
- /// pseudo-destructor expression.
- ///
- /// \param S The scope in which the member access expression occurs.
- ///
- /// \param Base The expression in which a member is being accessed, e.g., the
- /// "x" in "x.f".
- ///
- /// \param OpLoc The location of the member access operator ("." or "->")
- ///
- /// \param OpKind The kind of member access operator ("." or "->")
- ///
- /// \param SS The nested-name-specifier that precedes the type names
- /// in the grammar. Note that this nested-name-specifier will not
- /// cover the last "type-name ::" in the grammar, because it isn't
- /// necessarily a nested-name-specifier.
- ///
- /// \param FirstTypeName The type name that follows the optional
- /// nested-name-specifier but precedes the '::', e.g., the first
- /// type-name in "type-name :: type-name". This type name may be
- /// empty. This will be either an identifier or a template-id.
- ///
- /// \param CCLoc The location of the '::' in "type-name ::
- /// typename". May be invalid, if there is no \p FirstTypeName.
- ///
- /// \param TildeLoc The location of the '~'.
- ///
- /// \param SecondTypeName The type-name following the '~', which is
- /// the name of the type being destroyed. This will be either an
- /// identifier or a template-id.
- ///
- /// \param HasTrailingLParen Whether the next token in the stream is
- /// a left parentheses.
- virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
- return ExprEmpty();
- }
-
- /// ActOnFinishFullExpr - Called whenever a full expression has been parsed.
- /// (C++ [intro.execution]p12).
- virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) {
- return move(Expr);
- }
-
- //===---------------------------- C++ Classes ---------------------------===//
- /// ActOnBaseSpecifier - Parsed a base specifier
- virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl,
- SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
- TypeTy *basetype,
- SourceLocation BaseLoc) {
- return BaseResult();
- }
-
- virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
- unsigned NumBases) {
- }
-
- /// ActOnAccessSpecifier - This is invoked when an access specifier
- /// (and the colon following it) is found during the parsing of a
- /// C++ class member declarator.
- virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier AS,
- SourceLocation ASLoc,
- SourceLocation ColonLoc) {
- return DeclPtrTy();
- }
-
- /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
- /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth'
- /// specifies the bitfield width if there is one and 'Init' specifies the
- /// initializer if any. 'Deleted' is true if there's a =delete
- /// specifier on the function.
- virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
- Declarator &D,
- MultiTemplateParamsArg TemplateParameterLists,
- ExprTy *BitfieldWidth,
- ExprTy *Init,
- bool IsDefinition,
- bool Deleted = false) {
- return DeclPtrTy();
- }
-
- virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- TypeTy *TemplateTypeTy,
- SourceLocation IdLoc,
- SourceLocation LParenLoc,
- ExprTy **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- return true;
- }
-
- /// ActOnMemInitializers - This is invoked when all of the member
- /// initializers of a constructor have been parsed. ConstructorDecl
- /// is the function declaration (which will be a C++ constructor in
- /// a well-formed program), ColonLoc is the location of the ':' that
- /// starts the constructor initializer, and MemInit/NumMemInits
- /// contains the individual member (and base) initializers.
- /// AnyErrors will be true if there were any invalid member initializers
- /// that are not represented in the list.
- virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
- SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits,
- bool AnyErrors){
- }
-
- virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {}
-
- /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators
- /// are parsed but *before* parsing of inline method definitions.
- virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- DeclPtrTy TagDecl,
- SourceLocation LBrac,
- SourceLocation RBrac,
- AttributeList *AttrList) {
- }
-
- //===---------------------------C++ Templates----------------------------===//
-
- /// \brief Called when a C++ template type parameter(e.g., "typename T") has
- /// been parsed.
- ///
- /// Given
- ///
- /// \code
- /// template<typename T, typename U = T> struct pair;
- /// \endcode
- ///
- /// this callback will be invoked twice: once for the type parameter \c T
- /// with \p Depth=0 and \p Position=0, and once for the type parameter \c U
- /// with \p Depth=0 and \p Position=1.
- ///
- /// \param Typename Specifies whether the keyword "typename" was used to
- /// declare the type parameter (otherwise, "class" was used).
- ///
- /// \param Ellipsis Specifies whether this is a C++0x parameter pack.
- ///
- /// \param EllipsisLoc Specifies the start of the ellipsis.
- ///
- /// \param KeyLoc The location of the "class" or "typename" keyword.
- ///
- /// \param ParamName The name of the parameter, where NULL indicates an
- /// unnamed template parameter.
- ///
- /// \param ParamNameLoc The location of the parameter name (if any).
- ///
- /// \param Depth The depth of this template parameter, e.g., the number of
- /// template parameter lists that occurred outside the template parameter
- /// list in which this template type parameter occurs.
- ///
- /// \param Position The zero-based position of this template parameter within
- /// its template parameter list, which is also the number of template
- /// parameters that precede this parameter in the template parameter list.
- ///
- /// \param EqualLoc The location of the '=' sign for the default template
- /// argument, if any.
- ///
- /// \param DefaultArg The default argument, if provided.
- virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
- SourceLocation EllipsisLoc,
- SourceLocation KeyLoc,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position,
- SourceLocation EqualLoc,
- TypeTy *DefaultArg) {
- return DeclPtrTy();
- }
-
- /// \brief Called when a C++ non-type template parameter has been parsed.
- ///
- /// Given
- ///
- /// \code
- /// template<int Size> class Array;
- /// \endcode
- ///
- /// This callback will be invoked for the 'Size' non-type template parameter.
- ///
- /// \param S The current scope.
- ///
- /// \param D The parsed declarator.
- ///
- /// \param Depth The depth of this template parameter, e.g., the number of
- /// template parameter lists that occurred outside the template parameter
- /// list in which this template type parameter occurs.
- ///
- /// \param Position The zero-based position of this template parameter within
- /// its template parameter list, which is also the number of template
- /// parameters that precede this parameter in the template parameter list.
- ///
- /// \param EqualLoc The location of the '=' sign for the default template
- /// argument, if any.
- ///
- /// \param DefaultArg The default argument, if provided.
- virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- ExprArg DefaultArg) {
- return DeclPtrTy();
- }
-
- /// \brief Adds a default argument to the given non-type template
- /// parameter.
- virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam,
- SourceLocation EqualLoc,
- ExprArg Default) {
- }
-
- /// \brief Called when a C++ template template parameter has been parsed.
- ///
- /// Given
- ///
- /// \code
- /// template<template <typename> class T> class X;
- /// \endcode
- ///
- /// this callback will be invoked for the template template parameter \c T.
- ///
- /// \param S The scope in which this template template parameter occurs.
- ///
- /// \param TmpLoc The location of the "template" keyword.
- ///
- /// \param TemplateParams The template parameters required by the template.
- ///
- /// \param ParamName The name of the parameter, or NULL if unnamed.
- ///
- /// \param ParamNameLoc The source location of the parameter name (if given).
- ///
- /// \param Depth The depth of this template parameter, e.g., the number of
- /// template parameter lists that occurred outside the template parameter
- /// list in which this template parameter occurs.
- ///
- /// \param Position The zero-based position of this template parameter within
- /// its template parameter list, which is also the number of template
- /// parameters that precede this parameter in the template parameter list.
- ///
- /// \param EqualLoc The location of the '=' sign for the default template
- /// argument, if any.
- ///
- /// \param DefaultArg The default argument, if provided.
- virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
- SourceLocation TmpLoc,
- TemplateParamsTy *Params,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &DefaultArg) {
- return DeclPtrTy();
- }
-
- /// ActOnTemplateParameterList - Called when a complete template
- /// parameter list has been parsed, e.g.,
- ///
- /// @code
- /// export template<typename T, T Size>
- /// @endcode
- ///
- /// Depth is the number of enclosing template parameter lists. This
- /// value does not include templates from outer scopes. For example:
- ///
- /// @code
- /// template<typename T> // depth = 0
- /// class A {
- /// template<typename U> // depth = 0
- /// class B;
- /// };
- ///
- /// template<typename T> // depth = 0
- /// template<typename U> // depth = 1
- /// class A<T>::B { ... };
- /// @endcode
- ///
- /// ExportLoc, if valid, is the position of the "export"
- /// keyword. Otherwise, "export" was not specified.
- /// TemplateLoc is the position of the template keyword, LAngleLoc
- /// is the position of the left angle bracket, and RAngleLoc is the
- /// position of the corresponding right angle bracket.
- /// Params/NumParams provides the template parameters that were
- /// parsed as part of the template-parameter-list.
- virtual TemplateParamsTy *
- ActOnTemplateParameterList(unsigned Depth,
- SourceLocation ExportLoc,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- DeclPtrTy *Params, unsigned NumParams,
- SourceLocation RAngleLoc) {
- return 0;
- }
-
- /// \brief Form a type from a template and a list of template
- /// arguments.
- ///
- /// This action merely forms the type for the template-id, possibly
- /// checking well-formedness of the template arguments. It does not
- /// imply the declaration of any entity.
- ///
- /// \param Template A template whose specialization results in a
- /// type, e.g., a class template or template template parameter.
- virtual TypeResult ActOnTemplateIdType(TemplateTy Template,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc) {
- return TypeResult();
- }
-
- /// \brief Note that a template ID was used with a tag.
- ///
- /// \param Type The result of ActOnTemplateIdType.
- ///
- /// \param TUK Either TUK_Reference or TUK_Friend. Declarations and
- /// definitions are interpreted as explicit instantiations or
- /// specializations.
- ///
- /// \param TagSpec The tag keyword that was provided as part of the
- /// elaborated-type-specifier; either class, struct, union, or enum.
- ///
- /// \param TagLoc The location of the tag keyword.
- virtual TypeResult ActOnTagTemplateIdType(TypeResult Type,
- TagUseKind TUK,
- DeclSpec::TST TagSpec,
- SourceLocation TagLoc) {
- return TypeResult();
- }
-
- /// \brief Form a dependent template name.
- ///
- /// This action forms a dependent template name given the template
- /// name and its (presumably dependent) scope specifier. For
- /// example, given "MetaFun::template apply", the scope specifier \p
- /// SS will be "MetaFun::", \p TemplateKWLoc contains the location
- /// of the "template" keyword, and "apply" is the \p Name.
- ///
- /// \param S The scope in which the dependent template name was parsed.
- ///
- /// \param TemplateKWLoc the location of the "template" keyword (if any).
- ///
- /// \param SS the nested-name-specifier that precedes the "template" keyword
- /// or the template name. If the dependent template name occurs in
- /// a member access expression, e.g., "x.template f<T>", this
- /// nested-name-specifier will be empty.
- ///
- /// \param Name the name of the template.
- ///
- /// \param ObjectType if this dependent template name occurs in the
- /// context of a member access expression, the type of the object being
- /// accessed.
- ///
- /// \param EnteringContext whether we are entering the context of this
- /// template.
- ///
- /// \param Template Will be set to the dependent template name, on success.
- ///
- /// \returns The kind of template name that was produced. Generally, this will
- /// be \c TNK_Dependent_template_name. However, if the nested-name-specifier
- /// is not dependent, or refers to the current instantiation, then we may
- /// be able to resolve the template kind more specifically.
- virtual TemplateNameKind ActOnDependentTemplateName(Scope *S,
- SourceLocation TemplateKWLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template) {
- return TNK_Non_template;
- }
-
- /// \brief Process the declaration or definition of an explicit
- /// class template specialization or a class template partial
- /// specialization.
- ///
- /// This routine is invoked when an explicit class template
- /// specialization or a class template partial specialization is
- /// declared or defined, to introduce the (partial) specialization
- /// and produce a declaration for it. In the following example,
- /// ActOnClassTemplateSpecialization will be invoked for the
- /// declarations at both A and B:
- ///
- /// \code
- /// template<typename T> class X;
- /// template<> class X<int> { }; // A: explicit specialization
- /// template<typename T> class X<T*> { }; // B: partial specialization
- /// \endcode
- ///
- /// Note that it is the job of semantic analysis to determine which
- /// of the two cases actually occurred in the source code, since
- /// they are parsed through the same path. The formulation of the
- /// template parameter lists describes which case we are in.
- ///
- /// \param S the current scope
- ///
- /// \param TagSpec whether this declares a class, struct, or union
- /// (template)
- ///
- /// \param TUK whether this is a declaration or a definition
- ///
- /// \param KWLoc the location of the 'class', 'struct', or 'union'
- /// keyword.
- ///
- /// \param SS the scope specifier preceding the template-id
- ///
- /// \param Template the declaration of the class template that we
- /// are specializing.
- ///
- /// \param Attr attributes on the specialization
- ///
- /// \param TemplateParameterLists the set of template parameter
- /// lists that apply to this declaration. In a well-formed program,
- /// the number of template parameter lists will be one more than the
- /// number of template-ids in the scope specifier. However, it is
- /// common for users to provide the wrong number of template
- /// parameter lists (such as a missing \c template<> prior to a
- /// specialization); the parser does not check this condition.
- virtual DeclResult
- ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc,
- AttributeList *Attr,
- MultiTemplateParamsArg TemplateParameterLists) {
- return DeclResult();
- }
-
- /// \brief Invoked when a declarator that has one or more template parameter
- /// lists has been parsed.
- ///
- /// This action is similar to ActOnDeclarator(), except that the declaration
- /// being created somehow involves a template, e.g., it is a template
- /// declaration or specialization.
- virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
- return DeclPtrTy();
- }
-
- /// \brief Invoked when the parser is beginning to parse a function template
- /// or function template specialization definition.
- virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
- return DeclPtrTy();
- }
-
- /// \brief Process the explicit instantiation of a class template
- /// specialization.
- ///
- /// This routine is invoked when an explicit instantiation of a
- /// class template specialization is encountered. In the following
- /// example, ActOnExplicitInstantiation will be invoked to force the
- /// instantiation of X<int>:
- ///
- /// \code
- /// template<typename T> class X { /* ... */ };
- /// template class X<int>; // explicit instantiation
- /// \endcode
- ///
- /// \param S the current scope
- ///
- /// \param ExternLoc the location of the 'extern' keyword that specifies that
- /// this is an extern template (if any).
- ///
- /// \param TemplateLoc the location of the 'template' keyword that
- /// specifies that this is an explicit instantiation.
- ///
- /// \param TagSpec whether this declares a class, struct, or union
- /// (template).
- ///
- /// \param KWLoc the location of the 'class', 'struct', or 'union'
- /// keyword.
- ///
- /// \param SS the scope specifier preceding the template-id.
- ///
- /// \param Template the declaration of the class template that we
- /// are instantiation.
- ///
- /// \param LAngleLoc the location of the '<' token in the template-id.
- ///
- /// \param TemplateArgs the template arguments used to form the
- /// template-id.
- ///
- /// \param TemplateArgLocs the locations of the template arguments.
- ///
- /// \param RAngleLoc the location of the '>' token in the template-id.
- ///
- /// \param Attr attributes that apply to this instantiation.
- virtual DeclResult
- ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- const CXXScopeSpec &SS,
- TemplateTy Template,
- SourceLocation TemplateNameLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation RAngleLoc,
- AttributeList *Attr) {
- return DeclResult();
- }
-
- /// \brief Process the explicit instantiation of a member class of a
- /// class template specialization.
- ///
- /// This routine is invoked when an explicit instantiation of a
- /// member class of a class template specialization is
- /// encountered. In the following example,
- /// ActOnExplicitInstantiation will be invoked to force the
- /// instantiation of X<int>::Inner:
- ///
- /// \code
- /// template<typename T> class X { class Inner { /* ... */}; };
- /// template class X<int>::Inner; // explicit instantiation
- /// \endcode
- ///
- /// \param S the current scope
- ///
- /// \param ExternLoc the location of the 'extern' keyword that specifies that
- /// this is an extern template (if any).
- ///
- /// \param TemplateLoc the location of the 'template' keyword that
- /// specifies that this is an explicit instantiation.
- ///
- /// \param TagSpec whether this declares a class, struct, or union
- /// (template).
- ///
- /// \param KWLoc the location of the 'class', 'struct', or 'union'
- /// keyword.
- ///
- /// \param SS the scope specifier preceding the template-id.
- ///
- /// \param Template the declaration of the class template that we
- /// are instantiation.
- ///
- /// \param LAngleLoc the location of the '<' token in the template-id.
- ///
- /// \param TemplateArgs the template arguments used to form the
- /// template-id.
- ///
- /// \param TemplateArgLocs the locations of the template arguments.
- ///
- /// \param RAngleLoc the location of the '>' token in the template-id.
- ///
- /// \param Attr attributes that apply to this instantiation.
- virtual DeclResult
- ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec,
- SourceLocation KWLoc,
- CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- AttributeList *Attr) {
- return DeclResult();
- }
-
- /// \brief Process the explicit instantiation of a function template or a
- /// member of a class template.
- ///
- /// This routine is invoked when an explicit instantiation of a
- /// function template or member function of a class template specialization
- /// is encountered. In the following example,
- /// ActOnExplicitInstantiation will be invoked to force the
- /// instantiation of X<int>:
- ///
- /// \code
- /// template<typename T> void f(T);
- /// template void f(int); // explicit instantiation
- /// \endcode
- ///
- /// \param S the current scope
- ///
- /// \param ExternLoc the location of the 'extern' keyword that specifies that
- /// this is an extern template (if any).
- ///
- /// \param TemplateLoc the location of the 'template' keyword that
- /// specifies that this is an explicit instantiation.
- ///
- /// \param D the declarator describing the declaration to be implicitly
- /// instantiated.
- virtual DeclResult ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- Declarator &D) {
- return DeclResult();
- }
-
-
- /// \brief Called when the parser has parsed a C++ typename
- /// specifier that ends in an identifier, e.g., "typename T::type".
- ///
- /// \param TypenameLoc the location of the 'typename' keyword
- /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
- /// \param II the identifier we're retrieving (e.g., 'type' in the example).
- /// \param IdLoc the location of the identifier.
- virtual TypeResult
- ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
- const CXXScopeSpec &SS, const IdentifierInfo &II,
- SourceLocation IdLoc) {
- return TypeResult();
- }
-
- /// \brief Called when the parser has parsed a C++ typename
- /// specifier that ends in a template-id, e.g.,
- /// "typename MetaFun::template apply<T1, T2>".
- ///
- /// \param TypenameLoc the location of the 'typename' keyword
- /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
- /// \param TemplateLoc the location of the 'template' keyword, if any.
- /// \param Ty the type that the typename specifier refers to.
- virtual TypeResult
- ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
- const CXXScopeSpec &SS, SourceLocation TemplateLoc,
- TypeTy *Ty) {
- return TypeResult();
- }
-
- /// \brief Called when the parser begins parsing a construct which should not
- /// have access control applied to it.
- virtual void ActOnStartSuppressingAccessChecks() {
- }
-
- /// \brief Called when the parser finishes parsing a construct which should
- /// not have access control applied to it.
- virtual void ActOnStopSuppressingAccessChecks() {
- }
-
- //===----------------------- Obj-C Declarations -------------------------===//
-
- // ActOnStartClassInterface - this action is called immediately after parsing
- // the prologue for a class interface (before parsing the instance
- // variables). Instance variables are processed by ActOnFields().
- virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
-
- /// ActOnCompatiblityAlias - this action is called after complete parsing of
- /// @compaatibility_alias declaration. It sets up the alias relationships.
- virtual DeclPtrTy ActOnCompatiblityAlias(
- SourceLocation AtCompatibilityAliasLoc,
- IdentifierInfo *AliasName, SourceLocation AliasLocation,
- IdentifierInfo *ClassName, SourceLocation ClassLocation) {
- return DeclPtrTy();
- }
-
- // ActOnStartProtocolInterface - this action is called immdiately after
- // parsing the prologue for a protocol interface.
- virtual DeclPtrTy ActOnStartProtocolInterface(SourceLocation AtProtoLoc,
- IdentifierInfo *ProtocolName,
- SourceLocation ProtocolLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
- // ActOnStartCategoryInterface - this action is called immdiately after
- // parsing the prologue for a category interface.
- virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *CategoryName,
- SourceLocation CategoryLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc) {
- return DeclPtrTy();
- }
- // ActOnStartClassImplementation - this action is called immdiately after
- // parsing the prologue for a class implementation. Instance variables are
- // processed by ActOnFields().
- virtual DeclPtrTy ActOnStartClassImplementation(
- SourceLocation AtClassImplLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperClassname,
- SourceLocation SuperClassLoc) {
- return DeclPtrTy();
- }
- // ActOnStartCategoryImplementation - this action is called immdiately after
- // parsing the prologue for a category implementation.
- virtual DeclPtrTy ActOnStartCategoryImplementation(
- SourceLocation AtCatImplLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *CatName,
- SourceLocation CatLoc) {
- return DeclPtrTy();
- }
- // ActOnPropertyImplDecl - called for every property implementation
- virtual DeclPtrTy ActOnPropertyImplDecl(
- Scope *S,
- SourceLocation AtLoc, // location of the @synthesize/@dynamic
- SourceLocation PropertyNameLoc, // location for the property name
- bool ImplKind, // true for @synthesize, false for
- // @dynamic
- DeclPtrTy ClassImplDecl, // class or category implementation
- IdentifierInfo *propertyId, // name of property
- IdentifierInfo *propertyIvar) { // name of the ivar
- return DeclPtrTy();
- }
-
- struct ObjCArgInfo {
- IdentifierInfo *Name;
- SourceLocation NameLoc;
- // The Type is null if no type was specified, and the DeclSpec is invalid
- // in this case.
- TypeTy *Type;
- ObjCDeclSpec DeclSpec;
-
- /// ArgAttrs - Attribute list for this argument.
- AttributeList *ArgAttrs;
- };
-
- // ActOnMethodDeclaration - called for all method declarations.
- virtual DeclPtrTy ActOnMethodDeclaration(
- SourceLocation BeginLoc, // location of the + or -.
- SourceLocation EndLoc, // location of the ; or {.
- tok::TokenKind MethodType, // tok::minus for instance, tok::plus for class.
- DeclPtrTy ClassDecl, // class this methods belongs to.
- ObjCDeclSpec &ReturnQT, // for return type's in inout etc.
- TypeTy *ReturnType, // the method return type.
- Selector Sel, // a unique name for the method.
- ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries.
- DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
- AttributeList *MethodAttrList, // optional
- // tok::objc_not_keyword, tok::objc_optional, tok::objc_required
- tok::ObjCKeywordKind impKind,
- bool isVariadic = false) {
- return DeclPtrTy();
- }
- // ActOnAtEnd - called to mark the @end. For declarations (interfaces,
- // protocols, categories), the parser passes all methods/properties.
- // For class implementations, these values default to 0. For implementations,
- // methods are processed incrementally (by ActOnMethodDeclaration above).
- virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd,
- DeclPtrTy classDecl,
- DeclPtrTy *allMethods = 0,
- unsigned allNum = 0,
- DeclPtrTy *allProperties = 0,
- unsigned pNum = 0,
- DeclGroupPtrTy *allTUVars = 0,
- unsigned tuvNum = 0) {
- }
- // ActOnProperty - called to build one property AST
- virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
- FieldDeclarator &FD, ObjCDeclSpec &ODS,
- Selector GetterSel, Selector SetterSel,
- DeclPtrTy ClassCategory,
- bool *OverridingProperty,
- tok::ObjCKeywordKind MethodImplKind) {
- return DeclPtrTy();
- }
-
- virtual OwningExprResult
- ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation receiverNameLoc,
- SourceLocation propertyNameLoc) {
- return ExprEmpty();
- }
-
- /// \brief Describes the kind of message expression indicated by a message
- /// send that starts with an identifier.
- enum ObjCMessageKind {
- /// \brief The message is sent to 'super'.
- ObjCSuperMessage,
- /// \brief The message is an instance message.
- ObjCInstanceMessage,
- /// \brief The message is a class message, and the identifier is a type
- /// name.
- ObjCClassMessage
- };
-
- /// \brief Determine the kind of Objective-C message send that we will be
- /// performing based on the identifier given.
- ///
- /// This action determines how a message send that starts with [
- /// identifier (followed by another identifier) will be parsed,
- /// e.g., as a class message, instance message, super message. The
- /// result depends on the meaning of the given identifier. If the
- /// identifier is unknown, the action should indicate that the
- /// message is an instance message.
- ///
- /// By default, this routine applies syntactic disambiguation and uses
- /// \c getTypeName() to determine whether the identifier refers to a type.
- /// However, \c Action subclasses may override this routine to improve
- /// error recovery.
- ///
- /// \param S The scope in which the message send occurs.
- ///
- /// \param Name The identifier following the '['.
- ///
- /// \param NameLoc The location of the identifier.
- ///
- /// \param IsSuper Whether the name is the pseudo-keyword "super".
- ///
- /// \param HasTrailingDot Whether the name is followed by a period.
- ///
- /// \param ReceiverType If this routine returns \c ObjCClassMessage,
- /// this argument will be set to the receiver type.
- ///
- /// \returns The kind of message send.
- virtual ObjCMessageKind getObjCMessageKind(Scope *S,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- bool IsSuper,
- bool HasTrailingDot,
- TypeTy *&ReceiverType);
-
- /// \brief Parsed a message send to 'super'.
- ///
- /// \param S The scope in which the message send occurs.
- /// \param SuperLoc The location of the 'super' keyword.
- /// \param Sel The selector to which the message is being sent.
- /// \param LBracLoc The location of the opening square bracket ']'.
- /// \param SelectorLoc The location of the first identifier in the selector.
- /// \param RBrac The location of the closing square bracket ']'.
- /// \param Args The message arguments.
- virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- return OwningExprResult(*this);
- }
-
- /// \brief Parsed a message send to a class.
- ///
- /// \param S The scope in which the message send occurs.
- /// \param Receiver The type of the class receiving the message.
- /// \param Sel The selector to which the message is being sent.
- /// \param LBracLoc The location of the opening square bracket ']'.
- /// \param SelectorLoc The location of the first identifier in the selector.
- /// \param RBrac The location of the closing square bracket ']'.
- /// \param Args The message arguments.
- virtual OwningExprResult ActOnClassMessage(Scope *S,
- TypeTy *Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- return OwningExprResult(*this);
- }
-
- /// \brief Parsed a message send to an object instance.
- ///
- /// \param S The scope in which the message send occurs.
- /// \param Receiver The expression that computes the receiver object.
- /// \param Sel The selector to which the message is being sent.
- /// \param LBracLoc The location of the opening square bracket ']'.
- /// \param SelectorLoc The location of the first identifier in the selector.
- /// \param RBrac The location of the closing square bracket ']'.
- /// \param Args The message arguments.
- virtual OwningExprResult ActOnInstanceMessage(Scope *S,
- ExprArg Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- return OwningExprResult(*this);
- }
-
- virtual DeclPtrTy ActOnForwardClassDeclaration(
- SourceLocation AtClassLoc,
- IdentifierInfo **IdentList,
- SourceLocation *IdentLocs,
- unsigned NumElts) {
- return DeclPtrTy();
- }
- virtual DeclPtrTy ActOnForwardProtocolDeclaration(
- SourceLocation AtProtocolLoc,
- const IdentifierLocPair*IdentList,
- unsigned NumElts,
- AttributeList *AttrList) {
- return DeclPtrTy();
- }
-
- /// FindProtocolDeclaration - This routine looks up protocols and
- /// issues error if they are not declared. It returns list of valid
- /// protocols found.
- virtual void FindProtocolDeclaration(bool WarnOnDeclarations,
- const IdentifierLocPair *ProtocolId,
- unsigned NumProtocols,
- llvm::SmallVectorImpl<DeclPtrTy> &ResProtos) {
- }
-
- //===----------------------- Obj-C Expressions --------------------------===//
-
- virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
- ExprTy **Strings,
- unsigned NumStrings) {
- return ExprResult();
- }
-
- virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
- SourceLocation EncLoc,
- SourceLocation LParenLoc,
- TypeTy *Ty,
- SourceLocation RParenLoc) {
- return ExprResult();
- }
-
- virtual ExprResult ParseObjCSelectorExpression(Selector Sel,
- SourceLocation AtLoc,
- SourceLocation SelLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return ExprResult();
- }
-
- virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
- SourceLocation AtLoc,
- SourceLocation ProtoLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return ExprResult();
- }
-
- //===---------------------------- Pragmas -------------------------------===//
-
- enum PragmaOptionsAlignKind {
- POAK_Native, // #pragma options align=native
- POAK_Natural, // #pragma options align=natural
- POAK_Packed, // #pragma options align=packed
- POAK_Power, // #pragma options align=power
- POAK_Mac68k, // #pragma options align=mac68k
- POAK_Reset // #pragma options align=reset
- };
-
- /// ActOnPragmaOptionsAlign - Called on well formed #pragma options
- /// align={...}.
- virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
- SourceLocation PragmaLoc,
- SourceLocation KindLoc) {
- return;
- }
-
- enum PragmaPackKind {
- PPK_Default, // #pragma pack([n])
- PPK_Show, // #pragma pack(show), only supported by MSVC.
- PPK_Push, // #pragma pack(push, [identifier], [n])
- PPK_Pop // #pragma pack(pop, [identifier], [n])
- };
-
- /// ActOnPragmaPack - Called on well formed #pragma pack(...).
- virtual void ActOnPragmaPack(PragmaPackKind Kind,
- IdentifierInfo *Name,
- ExprTy *Alignment,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return;
- }
-
- /// ActOnPragmaUnused - Called on well formed #pragma unused(...).
- virtual void ActOnPragmaUnused(const Token *Identifiers,
- unsigned NumIdentifiers, Scope *CurScope,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
- return;
- }
-
- /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
- virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc) {
- return;
- }
-
- /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
- virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc,
- SourceLocation AliasNameLoc) {
- return;
- }
-
- /// \name Code completion actions
- ///
- /// These actions are used to signal that a code-completion token has been
- /// found at a point in the grammar where the Action implementation is
- /// likely to be able to provide a list of possible completions, e.g.,
- /// after the "." or "->" of a member access expression.
- ///
- /// \todo Code completion for designated field initializers
- /// \todo Code completion for call arguments after a function template-id
- /// \todo Code completion within a call expression, object construction, etc.
- /// \todo Code completion within a template argument list.
- /// \todo Code completion for attributes.
- //@{
-
- /// \brief Describes the context in which code completion occurs.
- enum CodeCompletionContext {
- /// \brief Code completion occurs at top-level or namespace context.
- CCC_Namespace,
- /// \brief Code completion occurs within a class, struct, or union.
- CCC_Class,
- /// \brief Code completion occurs within an Objective-C interface, protocol,
- /// or category.
- CCC_ObjCInterface,
- /// \brief Code completion occurs within an Objective-C implementation or
- /// category implementation
- CCC_ObjCImplementation,
- /// \brief Code completion occurs within the list of instance variables
- /// in an Objective-C interface, protocol, category, or implementation.
- CCC_ObjCInstanceVariableList,
- /// \brief Code completion occurs following one or more template
- /// headers.
- CCC_Template,
- /// \brief Code completion occurs following one or more template
- /// headers within a class.
- CCC_MemberTemplate,
- /// \brief Code completion occurs within an expression.
- CCC_Expression,
- /// \brief Code completion occurs within a statement, which may
- /// also be an expression or a declaration.
- CCC_Statement,
- /// \brief Code completion occurs at the beginning of the
- /// initialization statement (or expression) in a for loop.
- CCC_ForInit,
- /// \brief Code completion occurs within the condition of an if,
- /// while, switch, or for statement.
- CCC_Condition,
- /// \brief Code completion occurs within the body of a function on a
- /// recovery path, where we do not have a specific handle on our position
- /// in the grammar.
- CCC_RecoveryInFunction
- };
-
- /// \brief Code completion for an ordinary name that occurs within the given
- /// scope.
- ///
- /// \param S the scope in which the name occurs.
- ///
- /// \param CompletionContext the context in which code completion
- /// occurs.
- virtual void CodeCompleteOrdinaryName(Scope *S,
- CodeCompletionContext CompletionContext) { }
-
- /// \brief Code completion for a member access expression.
- ///
- /// This code completion action is invoked when the code-completion token
- /// is found after the "." or "->" of a member access expression.
- ///
- /// \param S the scope in which the member access expression occurs.
- ///
- /// \param Base the base expression (e.g., the x in "x.foo") of the member
- /// access.
- ///
- /// \param OpLoc the location of the "." or "->" operator.
- ///
- /// \param IsArrow true when the operator is "->", false when it is ".".
- virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
- SourceLocation OpLoc,
- bool IsArrow) { }
-
- /// \brief Code completion for a reference to a tag.
- ///
- /// This code completion action is invoked when the code-completion
- /// token is found after a tag keyword (struct, union, enum, or class).
- ///
- /// \param S the scope in which the tag reference occurs.
- ///
- /// \param TagSpec an instance of DeclSpec::TST, indicating what kind of tag
- /// this is (struct/union/enum/class).
- virtual void CodeCompleteTag(Scope *S, unsigned TagSpec) { }
-
- /// \brief Code completion for a case statement.
- ///
- /// \brief S the scope in which the case statement occurs.
- virtual void CodeCompleteCase(Scope *S) { }
-
- /// \brief Code completion for a call.
- ///
- /// \brief S the scope in which the call occurs.
- ///
- /// \param Fn the expression describing the function being called.
- ///
- /// \param Args the arguments to the function call (so far).
- ///
- /// \param NumArgs the number of arguments in \p Args.
- virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
- ExprTy **Args, unsigned NumArgs) { }
-
- /// \brief Code completion for the initializer of a variable declaration.
- ///
- /// \param S The scope in which the initializer occurs.
- ///
- /// \param D The declaration being initialized.
- virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D) { }
-
- /// \brief Code completion after the "return" keyword within a function.
- ///
- /// \param S The scope in which the return statement occurs.
- virtual void CodeCompleteReturn(Scope *S) { }
-
- /// \brief Code completion for the right-hand side of an assignment or
- /// compound assignment operator.
- ///
- /// \param S The scope in which the assignment occurs.
- ///
- /// \param LHS The left-hand side of the assignment expression.
- virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { }
-
- /// \brief Code completion for a C++ nested-name-specifier that precedes a
- /// qualified-id of some form.
- ///
- /// This code completion action is invoked when the code-completion token
- /// is found after the "::" of a nested-name-specifier.
- ///
- /// \param S the scope in which the nested-name-specifier occurs.
- ///
- /// \param SS the scope specifier ending with "::".
- ///
- /// \parame EnteringContext whether we're entering the context of this
- /// scope specifier.
- virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
- bool EnteringContext) { }
-
- /// \brief Code completion for a C++ "using" declaration or directive.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the "using" keyword.
- ///
- /// \param S the scope in which the "using" occurs.
- virtual void CodeCompleteUsing(Scope *S) { }
-
- /// \brief Code completion for a C++ using directive.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after "using namespace".
- ///
- /// \param S the scope in which the "using namespace" occurs.
- virtual void CodeCompleteUsingDirective(Scope *S) { }
-
- /// \brief Code completion for a C++ namespace declaration or namespace
- /// alias declaration.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after "namespace".
- ///
- /// \param S the scope in which the "namespace" token occurs.
- virtual void CodeCompleteNamespaceDecl(Scope *S) { }
-
- /// \brief Code completion for a C++ namespace alias declaration.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after "namespace identifier = ".
- ///
- /// \param S the scope in which the namespace alias declaration occurs.
- virtual void CodeCompleteNamespaceAliasDecl(Scope *S) { }
-
- /// \brief Code completion for an operator name.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the keyword "operator".
- ///
- /// \param S the scope in which the operator keyword occurs.
- virtual void CodeCompleteOperatorName(Scope *S) { }
-
- /// \brief Code completion after the '@' at the top level.
- ///
- /// \param S the scope in which the '@' occurs.
- ///
- /// \param ObjCImpDecl the Objective-C implementation or category
- /// implementation.
- ///
- /// \param InInterface whether we are in an Objective-C interface or
- /// protocol.
- virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
- bool InInterface) { }
-
- /// \brief Code completion after the '@' in the list of instance variables.
- virtual void CodeCompleteObjCAtVisibility(Scope *S) { }
-
- /// \brief Code completion after the '@' in a statement.
- virtual void CodeCompleteObjCAtStatement(Scope *S) { }
-
- /// \brief Code completion after the '@' in an expression.
- virtual void CodeCompleteObjCAtExpression(Scope *S) { }
-
- /// \brief Code completion for an ObjC property decl.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the left paren.
- ///
- /// \param S the scope in which the operator keyword occurs.
- virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { }
-
- /// \brief Code completion for the getter of an Objective-C property
- /// declaration.
- ///
- /// This code completion action is invoked when the code-completion
- /// token is found after the "getter = " in a property declaration.
- ///
- /// \param S the scope in which the property is being declared.
- ///
- /// \param ClassDecl the Objective-C class or category in which the property
- /// is being defined.
- ///
- /// \param Methods the set of methods declared thus far within \p ClassDecl.
- ///
- /// \param NumMethods the number of methods in \p Methods
- virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
- unsigned NumMethods) {
- }
-
- /// \brief Code completion for the setter of an Objective-C property
- /// declaration.
- ///
- /// This code completion action is invoked when the code-completion
- /// token is found after the "setter = " in a property declaration.
- ///
- /// \param S the scope in which the property is being declared.
- ///
- /// \param ClassDecl the Objective-C class or category in which the property
- /// is being defined.
- ///
- /// \param Methods the set of methods declared thus far within \p ClassDecl.
- ///
- /// \param NumMethods the number of methods in \p Methods
- virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
- unsigned NumMethods) {
- }
-
- /// \brief Code completion for the receiver in an Objective-C message send.
- ///
- /// This code completion action is invoked when we see a '[' that indicates
- /// the start of an Objective-C message send.
- ///
- /// \param S The scope in which the Objective-C message send occurs.
- virtual void CodeCompleteObjCMessageReceiver(Scope *S) { }
-
- /// \brief Code completion for an ObjC message expression that sends
- /// a message to the superclass.
- ///
- /// This code completion action is invoked when the code-completion token is
- /// found after the class name and after each argument.
- ///
- /// \param S The scope in which the message expression occurs.
- /// \param SuperLoc The location of the 'super' keyword.
- /// \param SelIdents The identifiers that describe the selector (thus far).
- /// \param NumSelIdents The number of identifiers in \p SelIdents.
- virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- /// \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 and after each argument.
- ///
- /// \param S The scope in which the message expression occurs.
- /// \param Receiver The type of the class that is receiving a message.
- /// \param SelIdents The identifiers that describe the selector (thus far).
- /// \param NumSelIdents The number of identifiers in \p SelIdents.
- virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- /// \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 and after each argument.
- ///
- /// \param S the scope in which the operator keyword occurs.
- /// \param Receiver an expression for the receiver of the message.
- /// \param SelIdents the identifiers that describe the selector (thus far).
- /// \param NumSelIdents the number of identifiers in \p SelIdents.
- virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- /// \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) { }
-
- /// \brief Code completion for an Objective-C interface, after the
- /// @interface but before any identifier.
- virtual void CodeCompleteObjCInterfaceDecl(Scope *S) { }
-
- /// \brief Code completion for the superclass of an Objective-C
- /// interface, after the ':'.
- ///
- /// \param S the scope in which the interface declaration occurs.
- ///
- /// \param ClassName the name of the class being defined.
- virtual void CodeCompleteObjCSuperclass(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
- }
-
- /// \brief Code completion for an Objective-C implementation, after the
- /// @implementation but before any identifier.
- virtual void CodeCompleteObjCImplementationDecl(Scope *S) { }
-
- /// \brief Code completion for the category name in an Objective-C interface
- /// declaration.
- ///
- /// This code completion action is invoked after the '(' that indicates
- /// a category name within an Objective-C interface declaration.
- virtual void CodeCompleteObjCInterfaceCategory(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
- }
-
- /// \brief Code completion for the category name in an Objective-C category
- /// implementation.
- ///
- /// This code completion action is invoked after the '(' that indicates
- /// the category name within an Objective-C category implementation.
- virtual void CodeCompleteObjCImplementationCategory(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc) {
- }
-
- /// \brief Code completion for the property names when defining an
- /// Objective-C property.
- ///
- /// This code completion action is invoked after @synthesize or @dynamic and
- /// after each "," within one of those definitions.
- virtual void CodeCompleteObjCPropertyDefinition(Scope *S,
- DeclPtrTy ObjCImpDecl) {
- }
-
- /// \brief Code completion for the instance variable name that should
- /// follow an '=' when synthesizing an Objective-C property.
- ///
- /// This code completion action is invoked after each '=' that occurs within
- /// an @synthesized definition.
- virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
- IdentifierInfo *PropertyName,
- DeclPtrTy ObjCImpDecl) {
- }
-
- /// \brief Code completion for an Objective-C method declaration or
- /// definition, which may occur within an interface, category,
- /// extension, protocol, or implementation thereof (where applicable).
- ///
- /// This code completion action is invoked after the "-" or "+" that
- /// starts a method declaration or definition, and after the return
- /// type such a declaration (e.g., "- (id)").
- ///
- /// \param S The scope in which the completion occurs.
- ///
- /// \param IsInstanceMethod Whether this is an instance method
- /// (introduced with '-'); otherwise, it's a class method
- /// (introduced with '+').
- ///
- /// \param ReturnType If non-NULL, the specified return type of the method
- /// being declared or defined.
- ///
- /// \param IDecl The interface, category, protocol, or
- /// implementation, or category implementation in which this method
- /// declaration or definition occurs.
- virtual void CodeCompleteObjCMethodDecl(Scope *S,
- bool IsInstanceMethod,
- TypeTy *ReturnType,
- DeclPtrTy IDecl) {
- }
-
- /// \brief Code completion for a selector identifier or argument name within
- /// an Objective-C method declaration.
- ///
- /// \param S The scope in which this code completion occurs.
- ///
- /// \param IsInstanceMethod Whether we are parsing an instance method (or,
- /// if false, a class method).
- ///
- /// \param AtParameterName Whether the actual code completion point is at the
- /// argument name.
- ///
- /// \param ReturnType If non-NULL, the specified return type of the method
- /// being declared or defined.
- ///
- /// \param SelIdents The identifiers that occurred in the selector for the
- /// method declaration prior to the code completion point.
- ///
- /// \param NumSelIdents The number of identifiers provided by SelIdents.
- virtual void CodeCompleteObjCMethodDeclSelector(Scope *S,
- bool IsInstanceMethod,
- bool AtParameterName,
- TypeTy *ReturnType,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) { }
-
- //@}
-};
-
-/// MinimalAction - Minimal actions are used by light-weight clients of the
-/// parser that do not need name resolution or significant semantic analysis to
-/// be performed. The actions implemented here are in the form of unresolved
-/// identifiers. By using a simpler interface than the SemanticAction class,
-/// the parser doesn't have to build complex data structures and thus runs more
-/// quickly.
-class MinimalAction : public Action {
- /// Translation Unit Scope - useful to Objective-C actions that need
- /// to lookup file scope declarations in the "ordinary" C decl namespace.
- /// For example, user-defined classes, built-in "id" type, etc.
- Scope *TUScope;
- IdentifierTable &Idents;
- Preprocessor &PP;
- void *TypeNameInfoTablePtr;
-public:
- MinimalAction(Preprocessor &pp);
- ~MinimalAction();
-
- /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to
- /// determine whether the name is a typedef or not in this scope.
- ///
- /// \param II the identifier for which we are performing name lookup
- ///
- /// \param NameLoc the location of the identifier
- ///
- /// \param S the scope in which this name lookup occurs
- ///
- /// \param SS if non-NULL, the C++ scope specifier that precedes the
- /// identifier
- ///
- /// \param isClassName whether this is a C++ class-name production, in
- /// which we can end up referring to a member of an unknown specialization
- /// that we know (from the grammar) is supposed to be a type. For example,
- /// this occurs when deriving from "std::vector<T>::allocator_type", where T
- /// is a template parameter.
- ///
- /// \returns the type referred to by this identifier, or NULL if the type
- /// does not name an identifier.
- virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec *SS,
- bool isClassName = false,
- TypeTy *ObjectType = 0);
-
- /// isCurrentClassName - Always returns false, because MinimalAction
- /// does not support C++ classes with constructors.
- virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S,
- const CXXScopeSpec *SS);
-
- virtual TemplateNameKind isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template,
- bool &MemberOfUnknownSpecialization);
-
-
- /// ActOnDeclarator - If this is a typedef declarator, we modify the
- /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
- /// popped.
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D);
-
- /// ActOnPopScope - When a scope is popped, if any typedefs are now
- /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
- virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
-
- virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
- IdentifierInfo **IdentList,
- SourceLocation *SLocs,
- unsigned NumElts);
-
- virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList);
-};
-
-/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing
-/// something related to a virtualized decl, include that virtualized decl in
-/// the stack trace.
-class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry {
- Action::DeclPtrTy TheDecl;
- SourceLocation Loc;
- Action &Actions;
- SourceManager &SM;
- const char *Message;
-public:
- PrettyStackTraceActionsDecl(Action::DeclPtrTy Decl, SourceLocation L,
- Action &actions, SourceManager &sm,
- const char *Msg)
- : TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {}
-
- virtual void print(llvm::raw_ostream &OS) const;
-};
-
-/// \brief RAII object that enters a new expression evaluation context.
-class EnterExpressionEvaluationContext {
- /// \brief The action object.
- Action &Actions;
-
-public:
- EnterExpressionEvaluationContext(Action &Actions,
- Action::ExpressionEvaluationContext NewContext)
- : Actions(Actions) {
- Actions.PushExpressionEvaluationContext(NewContext);
- }
-
- ~EnterExpressionEvaluationContext() {
- Actions.PopExpressionEvaluationContext();
- }
-};
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h
deleted file mode 100644
index e9a20b7872b5..000000000000
--- a/include/clang/Parse/Ownership.h
+++ /dev/null
@@ -1,845 +0,0 @@
-//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains classes for managing ownership of Stmt and Expr nodes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H
-#define LLVM_CLANG_PARSE_OWNERSHIP_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/PointerIntPair.h"
-
-//===----------------------------------------------------------------------===//
-// OpaquePtr
-//===----------------------------------------------------------------------===//
-
-namespace clang {
- class ActionBase;
-
- /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
- /// Parser doesn't know about but that Sema or another client does. The UID
- /// template argument is used to make sure that "Decl" pointers are not
- /// compatible with "Type" pointers for example.
- template<int UID>
- class OpaquePtr {
- void *Ptr;
- public:
- OpaquePtr() : Ptr(0) {}
-
- template <typename T>
- T* getAs() const {
- return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr);
- }
-
- template <typename T>
- T getAsVal() const {
- return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr);
- }
-
- void *get() const { return Ptr; }
-
- template<typename T>
- static OpaquePtr make(T P) {
- OpaquePtr R; R.set(P); return R;
- }
-
- template<typename T>
- void set(T P) {
- Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P);
- }
-
- operator bool() const { return Ptr != 0; }
- };
-}
-
-namespace llvm {
- template <int UID>
- class PointerLikeTypeTraits<clang::OpaquePtr<UID> > {
- public:
- static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) {
- // FIXME: Doesn't work? return P.getAs< void >();
- return P.get();
- }
- static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) {
- return clang::OpaquePtr<UID>::make(P);
- }
- enum { NumLowBitsAvailable = 3 };
- };
-}
-
-
-
-// -------------------------- About Move Emulation -------------------------- //
-// The smart pointer classes in this file attempt to emulate move semantics
-// as they appear in C++0x with rvalue references. Since C++03 doesn't have
-// rvalue references, some tricks are needed to get similar results.
-// Move semantics in C++0x have the following properties:
-// 1) "Moving" means transferring the value of an object to another object,
-// similar to copying, but without caring what happens to the old object.
-// In particular, this means that the new object can steal the old object's
-// resources instead of creating a copy.
-// 2) Since moving can modify the source object, it must either be explicitly
-// requested by the user, or the modifications must be unnoticeable.
-// 3) As such, C++0x moving is only allowed in three contexts:
-// * By explicitly using std::move() to request it.
-// * From a temporary object, since that object cannot be accessed
-// afterwards anyway, thus making the state unobservable.
-// * On function return, since the object is not observable afterwards.
-//
-// To sum up: moving from a named object should only be possible with an
-// explicit std::move(), or on function return. Moving from a temporary should
-// be implicitly done. Moving from a const object is forbidden.
-//
-// The emulation is not perfect, and has the following shortcomings:
-// * move() is not in namespace std.
-// * move() is required on function return.
-// * There are difficulties with implicit conversions.
-// * Microsoft's compiler must be given the /Za switch to successfully compile.
-//
-// -------------------------- Implementation -------------------------------- //
-// The move emulation relies on the peculiar reference binding semantics of
-// C++03: as a rule, a non-const reference may not bind to a temporary object,
-// except for the implicit object parameter in a member function call, which
-// can refer to a temporary even when not being const.
-// The moveable object has five important functions to facilitate moving:
-// * A private, unimplemented constructor taking a non-const reference to its
-// own class. This constructor serves a two-fold purpose.
-// - It prevents the creation of a copy constructor that takes a const
-// reference. Temporaries would be able to bind to the argument of such a
-// constructor, and that would be bad.
-// - Named objects will bind to the non-const reference, but since it's
-// private, this will fail to compile. This prevents implicit moving from
-// named objects.
-// There's also a copy assignment operator for the same purpose.
-// * An implicit, non-const conversion operator to a special mover type. This
-// type represents the rvalue reference of C++0x. Being a non-const member,
-// its implicit this parameter can bind to temporaries.
-// * A constructor that takes an object of this mover type. This constructor
-// performs the actual move operation. There is an equivalent assignment
-// operator.
-// There is also a free move() function that takes a non-const reference to
-// an object and returns a temporary. Internally, this function uses explicit
-// constructor calls to move the value from the referenced object to the return
-// value.
-//
-// There are now three possible scenarios of use.
-// * Copying from a const object. Constructor overload resolution will find the
-// non-const copy constructor, and the move constructor. The first is not
-// viable because the const object cannot be bound to the non-const reference.
-// The second fails because the conversion to the mover object is non-const.
-// Moving from a const object fails as intended.
-// * Copying from a named object. Constructor overload resolution will select
-// the non-const copy constructor, but fail as intended, because this
-// constructor is private.
-// * Copying from a temporary. Constructor overload resolution cannot select
-// the non-const copy constructor, because the temporary cannot be bound to
-// the non-const reference. It thus selects the move constructor. The
-// temporary can be bound to the implicit this parameter of the conversion
-// operator, because of the special binding rule. Construction succeeds.
-// Note that the Microsoft compiler, as an extension, allows binding
-// temporaries against non-const references. The compiler thus selects the
-// non-const copy constructor and fails, because the constructor is private.
-// Passing /Za (disable extensions) disables this behaviour.
-// The free move() function is used to move from a named object.
-//
-// Note that when passing an object of a different type (the classes below
-// have OwningResult and OwningPtr, which should be mixable), you get a problem.
-// Argument passing and function return use copy initialization rules. The
-// effect of this is that, when the source object is not already of the target
-// type, the compiler will first seek a way to convert the source object to the
-// target type, and only then attempt to copy the resulting object. This means
-// that when passing an OwningResult where an OwningPtr is expected, the
-// compiler will first seek a conversion from OwningResult to OwningPtr, then
-// copy the OwningPtr. The resulting conversion sequence is:
-// OwningResult object -> ResultMover -> OwningResult argument to
-// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
-// This conversion sequence is too complex to be allowed. Thus the special
-// move_* functions, which help the compiler out with some explicit
-// conversions.
-
-// Flip this switch to measure performance impact of the smart pointers.
-// #define DISABLE_SMART_POINTERS
-
-namespace llvm {
- template<>
- class PointerLikeTypeTraits<clang::ActionBase*> {
- typedef clang::ActionBase* PT;
- public:
- static inline void *getAsVoidPointer(PT P) { return P; }
- static inline PT getFromVoidPointer(void *P) {
- return static_cast<PT>(P);
- }
- enum { NumLowBitsAvailable = 2 };
- };
-}
-
-namespace clang {
- // Basic
- class DiagnosticBuilder;
-
- // Determines whether the low bit of the result pointer for the
- // given UID is always zero. If so, ActionResult will use that bit
- // for it's "invalid" flag.
- template<unsigned UID>
- struct IsResultPtrLowBitFree {
- static const bool value = false;
- };
-
- /// ActionBase - A small part split from Action because of the horrible
- /// definition order dependencies between Action and the smart pointers.
- class ActionBase {
- public:
- /// Out-of-line virtual destructor to provide home for this class.
- virtual ~ActionBase();
-
- // Types - Though these don't actually enforce strong typing, they document
- // what types are required to be identical for the actions.
- typedef OpaquePtr<0> DeclPtrTy;
- typedef OpaquePtr<1> DeclGroupPtrTy;
- typedef OpaquePtr<2> TemplateTy;
- typedef void AttrTy;
- typedef void BaseTy;
- typedef void MemInitTy;
- typedef void ExprTy;
- typedef void StmtTy;
- typedef void TemplateParamsTy;
- typedef void CXXScopeTy;
- typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>.
-
- /// ActionResult - This structure is used while parsing/acting on
- /// expressions, stmts, etc. It encapsulates both the object returned by
- /// the action, plus a sense of whether or not it is valid.
- /// When CompressInvalid is true, the "invalid" flag will be
- /// stored in the low bit of the Val pointer.
- template<unsigned UID,
- typename PtrTy = void*,
- bool CompressInvalid = IsResultPtrLowBitFree<UID>::value>
- class ActionResult {
- PtrTy Val;
- bool Invalid;
-
- public:
- ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
- template<typename ActualExprTy>
- ActionResult(ActualExprTy val) : Val(val), Invalid(false) {}
- ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
-
- PtrTy get() const { return Val; }
- void set(PtrTy V) { Val = V; }
- bool isInvalid() const { return Invalid; }
-
- const ActionResult &operator=(PtrTy RHS) {
- Val = RHS;
- Invalid = false;
- return *this;
- }
- };
-
- // This ActionResult partial specialization places the "invalid"
- // flag into the low bit of the pointer.
- template<unsigned UID, typename PtrTy>
- class ActionResult<UID, PtrTy, true> {
- // A pointer whose low bit is 1 if this result is invalid, 0
- // otherwise.
- uintptr_t PtrWithInvalid;
- typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
- public:
- ActionResult(bool Invalid = false)
- : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
-
- template<typename ActualExprTy>
- ActionResult(ActualExprTy *val) {
- PtrTy V(val);
- void *VP = PtrTraits::getAsVoidPointer(V);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- }
-
- ActionResult(PtrTy V) {
- void *VP = PtrTraits::getAsVoidPointer(V);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- }
-
- ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
-
- PtrTy get() const {
- void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
- return PtrTraits::getFromVoidPointer(VP);
- }
-
- void set(PtrTy V) {
- void *VP = PtrTraits::getAsVoidPointer(V);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- }
-
- bool isInvalid() const { return PtrWithInvalid & 0x01; }
-
- const ActionResult &operator=(PtrTy RHS) {
- void *VP = PtrTraits::getAsVoidPointer(RHS);
- PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
- assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
- return *this;
- }
- };
-
- /// Deletion callbacks - Since the parser doesn't know the concrete types of
- /// the AST nodes being generated, it must do callbacks to delete objects
- /// when recovering from errors. These are in ActionBase because the smart
- /// pointers need access to them.
- virtual void DeleteExpr(ExprTy *E) {}
- virtual void DeleteStmt(StmtTy *S) {}
- virtual void DeleteTemplateParams(TemplateParamsTy *P) {}
- };
-
- /// ASTDestroyer - The type of an AST node destruction function pointer.
- typedef void (ActionBase::*ASTDestroyer)(void *);
-
- /// For the transition phase: translate from an ASTDestroyer to its
- /// ActionResult UID.
- template <ASTDestroyer Destroyer> struct DestroyerToUID;
- template <> struct DestroyerToUID<&ActionBase::DeleteExpr> {
- static const unsigned UID = 0;
- };
- template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
- static const unsigned UID = 1;
- };
- /// ASTOwningResult - A moveable smart pointer for AST nodes that also
- /// has an extra flag to indicate an additional success status.
- template <ASTDestroyer Destroyer> class ASTOwningResult;
-
- /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
- /// the individual pointers, not the array holding them.
- template <ASTDestroyer Destroyer> class ASTMultiPtr;
-
-#if !defined(DISABLE_SMART_POINTERS)
- namespace moving {
- /// Move emulation helper for ASTOwningResult. NEVER EVER use this class
- /// directly if you don't know what you're doing.
- template <ASTDestroyer Destroyer>
- class ASTResultMover {
- ASTOwningResult<Destroyer> &Moved;
-
- public:
- ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
-
- ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
- };
-
- /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class
- /// directly if you don't know what you're doing.
- template <ASTDestroyer Destroyer>
- class ASTMultiMover {
- ASTMultiPtr<Destroyer> &Moved;
-
- public:
- ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
-
- ASTMultiPtr<Destroyer> * operator ->() { return &Moved; }
-
- /// Reset the moved object's internal structures.
- void release();
- };
- }
-#else
-
- /// Kept only as a type-safe wrapper for a void pointer, when smart pointers
- /// are disabled. When they are enabled, ASTOwningResult takes over.
- template <ASTDestroyer Destroyer>
- class ASTOwningPtr {
- void *Node;
-
- public:
- explicit ASTOwningPtr(ActionBase &) : Node(0) {}
- ASTOwningPtr(ActionBase &, void *node) : Node(node) {}
- // Normal copying operators are defined implicitly.
- ASTOwningPtr(const ASTOwningResult<Destroyer> &o);
-
- ASTOwningPtr & operator =(void *raw) {
- Node = raw;
- return *this;
- }
-
- /// Access to the raw pointer.
- void * get() const { return Node; }
-
- /// Release the raw pointer.
- void * take() {
- return Node;
- }
-
- /// Take outside ownership of the raw pointer and cast it down.
- template<typename T>
- T *takeAs() {
- return static_cast<T*>(Node);
- }
-
- /// Alias for interface familiarity with unique_ptr.
- void * release() {
- return take();
- }
- };
-#endif
-
- // Important: There are two different implementations of
- // ASTOwningResult below, depending on whether
- // DISABLE_SMART_POINTERS is defined. If you make changes that
- // affect the interface, be sure to compile and test both ways!
-
-#if !defined(DISABLE_SMART_POINTERS)
- template <ASTDestroyer Destroyer>
- class ASTOwningResult {
- llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv;
- void *Ptr;
-
- friend class moving::ASTResultMover<Destroyer>;
-
-#if !(defined(_MSC_VER) && _MSC_VER >= 1600)
- ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT
- ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT
-#endif
-
- void destroy() {
- if (Ptr) {
- assert(ActionInv.getPointer() &&
- "Smart pointer has node but no action.");
- (ActionInv.getPointer()->*Destroyer)(Ptr);
- Ptr = 0;
- }
- }
-
- public:
- typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
-
- explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
- : ActionInv(&actions, invalid), Ptr(0) {}
- ASTOwningResult(ActionBase &actions, void *node)
- : ActionInv(&actions, false), Ptr(node) {}
- ASTOwningResult(ActionBase &actions, const DumbResult &res)
- : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {}
- /// Move from another owning result
- ASTOwningResult(moving::ASTResultMover<Destroyer> mover)
- : ActionInv(mover->ActionInv),
- Ptr(mover->Ptr) {
- mover->Ptr = 0;
- }
-
- ~ASTOwningResult() {
- destroy();
- }
-
- /// Move assignment from another owning result
- ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) {
- destroy();
- ActionInv = mover->ActionInv;
- Ptr = mover->Ptr;
- mover->Ptr = 0;
- return *this;
- }
-
-#if defined(_MSC_VER) && _MSC_VER >= 1600
- // Emulated move semantics don't work with msvc.
- ASTOwningResult(ASTOwningResult &&mover)
- : ActionInv(mover.ActionInv),
- Ptr(mover.Ptr) {
- mover.Ptr = 0;
- }
- ASTOwningResult &operator=(ASTOwningResult &&mover) {
- *this = moving::ASTResultMover<Destroyer>(mover);
- return *this;
- }
-#endif
-
- /// Assignment from a raw pointer. Takes ownership - beware!
- ASTOwningResult &operator=(void *raw) {
- destroy();
- Ptr = raw;
- ActionInv.setInt(false);
- return *this;
- }
-
- /// Assignment from an ActionResult. Takes ownership - beware!
- ASTOwningResult &operator=(const DumbResult &res) {
- destroy();
- Ptr = res.get();
- ActionInv.setInt(res.isInvalid());
- return *this;
- }
-
- /// Access to the raw pointer.
- void *get() const { return Ptr; }
-
- bool isInvalid() const { return ActionInv.getInt(); }
-
- /// Does this point to a usable AST node? To be usable, the node must be
- /// valid and non-null.
- bool isUsable() const { return !isInvalid() && get(); }
-
- /// Take outside ownership of the raw pointer.
- void *take() {
- if (isInvalid())
- return 0;
- void *tmp = Ptr;
- Ptr = 0;
- return tmp;
- }
-
- /// Take outside ownership of the raw pointer and cast it down.
- template<typename T>
- T *takeAs() {
- return static_cast<T*>(take());
- }
-
- /// Alias for interface familiarity with unique_ptr.
- void *release() { return take(); }
-
- /// Pass ownership to a classical ActionResult.
- DumbResult result() {
- if (isInvalid())
- return true;
- return take();
- }
-
- /// Move hook
- operator moving::ASTResultMover<Destroyer>() {
- return moving::ASTResultMover<Destroyer>(*this);
- }
- };
-#else
- template <ASTDestroyer Destroyer>
- class ASTOwningResult {
- public:
- typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult;
-
- private:
- DumbResult Result;
-
- public:
- explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
- : Result(invalid) { }
- ASTOwningResult(ActionBase &actions, void *node) : Result(node) { }
- ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { }
- // Normal copying semantics are defined implicitly.
- ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { }
-
- /// Assignment from a raw pointer. Takes ownership - beware!
- ASTOwningResult & operator =(void *raw) {
- Result = raw;
- return *this;
- }
-
- /// Assignment from an ActionResult. Takes ownership - beware!
- ASTOwningResult & operator =(const DumbResult &res) {
- Result = res;
- return *this;
- }
-
- /// Access to the raw pointer.
- void * get() const { return Result.get(); }
-
- bool isInvalid() const { return Result.isInvalid(); }
-
- /// Does this point to a usable AST node? To be usable, the node must be
- /// valid and non-null.
- bool isUsable() const { return !Result.isInvalid() && get(); }
-
- /// Take outside ownership of the raw pointer.
- void * take() {
- return Result.get();
- }
-
- /// Take outside ownership of the raw pointer and cast it down.
- template<typename T>
- T *takeAs() {
- return static_cast<T*>(take());
- }
-
- /// Alias for interface familiarity with unique_ptr.
- void * release() { return take(); }
-
- /// Pass ownership to a classical ActionResult.
- DumbResult result() { return Result; }
- };
-#endif
-
- template <ASTDestroyer Destroyer>
- class ASTMultiPtr {
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &Actions;
-#endif
- void **Nodes;
- unsigned Count;
-
-#if !defined(DISABLE_SMART_POINTERS)
- friend class moving::ASTMultiMover<Destroyer>;
-
-#if defined(_MSC_VER)
- // Last tested with Visual Studio 2008.
- // Visual C++ appears to have a bug where it does not recognise
- // the return value from ASTMultiMover<Destroyer>::opeator-> as
- // being a pointer to ASTMultiPtr. However, the diagnostics
- // suggest it has the right name, simply that the pointer type
- // is not convertible to itself.
- // Either way, a classic C-style hard cast resolves any issue.
- static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) {
- return (ASTMultiPtr*)source.operator->();
- }
-#endif
-
- ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT
- // Reference member prevents copy assignment.
-
- void destroy() {
- assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
- for (unsigned i = 0; i < Count; ++i) {
- if (Nodes[i])
- (Actions.*Destroyer)(Nodes[i]);
- }
- }
-#endif
-
- public:
-#if !defined(DISABLE_SMART_POINTERS)
- explicit ASTMultiPtr(ActionBase &actions)
- : Actions(actions), Nodes(0), Count(0) {}
- ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count)
- : Actions(actions), Nodes(nodes), Count(count) {}
- /// Move constructor
- ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover)
-#if defined(_MSC_VER)
- // Apply the visual C++ hack supplied above.
- // Last tested with Visual Studio 2008.
- : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) {
-#else
- : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
-#endif
- mover.release();
- }
-#else
- // Normal copying implicitly defined
- explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {}
- ASTMultiPtr(ActionBase &, void **nodes, unsigned count)
- : Nodes(nodes), Count(count) {}
- // Fake mover in Parse/AstGuard.h needs this:
- ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {}
-#endif
-
-#if !defined(DISABLE_SMART_POINTERS)
- /// Move assignment
- ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) {
- destroy();
- Nodes = mover->Nodes;
- Count = mover->Count;
- mover.release();
- return *this;
- }
-#endif
-
- /// Access to the raw pointers.
- void ** get() const { return Nodes; }
-
- /// Access to the count.
- unsigned size() const { return Count; }
-
- void ** release() {
-#if !defined(DISABLE_SMART_POINTERS)
- void **tmp = Nodes;
- Nodes = 0;
- Count = 0;
- return tmp;
-#else
- return Nodes;
-#endif
- }
-
-#if !defined(DISABLE_SMART_POINTERS)
- /// Move hook
- operator moving::ASTMultiMover<Destroyer>() {
- return moving::ASTMultiMover<Destroyer>(*this);
- }
-#endif
- };
-
- class ParsedTemplateArgument;
-
- class ASTTemplateArgsPtr {
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &Actions;
-#endif
- ParsedTemplateArgument *Args;
- mutable unsigned Count;
-
-#if !defined(DISABLE_SMART_POINTERS)
- void destroy();
-#endif
-
- public:
- ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args,
- unsigned count) :
-#if !defined(DISABLE_SMART_POINTERS)
- Actions(actions),
-#endif
- 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), Count(Other.Count) {
-#if !defined(DISABLE_SMART_POINTERS)
- Other.Count = 0;
-#endif
- }
-
- // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
- ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
-#if !defined(DISABLE_SMART_POINTERS)
- Actions = Other.Actions;
-#endif
- Args = Other.Args;
- Count = Other.Count;
-#if !defined(DISABLE_SMART_POINTERS)
- Other.Count = 0;
-#endif
- return *this;
- }
-
-#if !defined(DISABLE_SMART_POINTERS)
- ~ASTTemplateArgsPtr() { destroy(); }
-#endif
-
- ParsedTemplateArgument *getArgs() const { return Args; }
- unsigned size() const { return Count; }
-
- void reset(ParsedTemplateArgument *args, unsigned count) {
-#if !defined(DISABLE_SMART_POINTERS)
- destroy();
-#endif
- Args = args;
- Count = count;
- }
-
- const ParsedTemplateArgument &operator[](unsigned Arg) const;
-
- ParsedTemplateArgument *release() const {
-#if !defined(DISABLE_SMART_POINTERS)
- Count = 0;
-#endif
- return Args;
- }
- };
-
- /// \brief A small vector that owns a set of AST nodes.
- template <ASTDestroyer Destroyer, unsigned N = 8>
- class ASTOwningVector : public llvm::SmallVector<void *, N> {
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &Actions;
- bool Owned;
-#endif
-
- ASTOwningVector(ASTOwningVector &); // do not implement
- ASTOwningVector &operator=(ASTOwningVector &); // do not implement
-
- public:
- explicit ASTOwningVector(ActionBase &Actions)
-#if !defined(DISABLE_SMART_POINTERS)
- : Actions(Actions), Owned(true)
-#endif
- { }
-
-#if !defined(DISABLE_SMART_POINTERS)
- ~ASTOwningVector() {
- if (!Owned)
- return;
-
- for (unsigned I = 0, Last = this->size(); I != Last; ++I)
- (Actions.*Destroyer)((*this)[I]);
- }
-#endif
-
- void **take() {
-#if !defined(DISABLE_SMART_POINTERS)
- Owned = false;
-#endif
- return &this->front();
- }
-
- template<typename T> T **takeAs() { return (T**)take(); }
-
-#if !defined(DISABLE_SMART_POINTERS)
- ActionBase &getActions() const { return Actions; }
-#endif
- };
-
- /// A SmallVector of statements, with stack size 32 (as that is the only one
- /// used.)
- typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector;
- /// A SmallVector of expressions, with stack size 12 (the maximum used.)
- typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector;
-
- template <ASTDestroyer Destroyer, unsigned N> inline
- ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) {
-#if !defined(DISABLE_SMART_POINTERS)
- return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size());
-#else
- return ASTMultiPtr<Destroyer>(vec.take(), vec.size());
-#endif
- }
-
-#if !defined(DISABLE_SMART_POINTERS)
-
- // Out-of-line implementations due to definition dependencies
-
- template <ASTDestroyer Destroyer> inline
- void moving::ASTMultiMover<Destroyer>::release() {
- Moved.Nodes = 0;
- Moved.Count = 0;
- }
-
- // Move overloads.
-
- template <ASTDestroyer Destroyer> inline
- ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) {
- return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr));
- }
-
- template <ASTDestroyer Destroyer> inline
- ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) {
- return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr));
- }
-
-#else
-
- template <ASTDestroyer Destroyer> inline
- ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o)
- : Node(o.get()) { }
-
- // These versions are hopefully no-ops.
- template <ASTDestroyer Destroyer> inline
- ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) {
- return ptr;
- }
-
- template <ASTDestroyer Destroyer> inline
- ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) {
- return ptr;
- }
-
- template <ASTDestroyer Destroyer> inline
- ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) {
- return ptr;
- }
-#endif
-}
-
-#endif
diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Parse/ParseAST.h
index f6cff2a023e6..0d37e21becd3 100644
--- a/include/clang/Sema/ParseAST.h
+++ b/include/clang/Parse/ParseAST.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_PARSEAST_H
-#define LLVM_CLANG_SEMA_PARSEAST_H
+#ifndef LLVM_CLANG_PARSE_PARSEAST_H
+#define LLVM_CLANG_PARSE_PARSEAST_H
namespace clang {
class Preprocessor;
@@ -38,6 +38,10 @@ namespace clang {
bool CompleteTranslationUnit = true,
CodeCompleteConsumer *CompletionConsumer = 0);
+ /// \brief Parse the main file known to the preprocessor, producing an
+ /// abstract syntax tree.
+ void ParseAST(Sema &S, bool PrintStats = false);
+
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index b8c294ada691..41a2fb615791 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -16,8 +16,10 @@
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Action.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Lex/CodeCompletionHandler.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/ADT/OwningPtr.h"
#include <stack>
#include <list>
@@ -27,6 +29,7 @@ namespace clang {
struct CXX0XAttributeList;
class PragmaHandler;
class Scope;
+ class DeclGroupRef;
class DiagnosticBuilder;
class Parser;
class PragmaUnusedHandler;
@@ -69,7 +72,7 @@ namespace prec {
/// parsing units of the grammar, productions are invoked to handle whatever has
/// been read.
///
-class Parser {
+class Parser : public CodeCompletionHandler {
friend class PragmaUnusedHandler;
friend class ColonProtectionRAIIObject;
friend class ParenBraceBracketBalancer;
@@ -90,9 +93,8 @@ class Parser {
unsigned short ParenCount, BracketCount, BraceCount;
/// Actions - These are the callbacks we invoke as we parse various constructs
- /// in the file. This refers to the common base class between MinimalActions
- /// and SemaActions for those uses that don't matter.
- Action &Actions;
+ /// in the file.
+ Sema &Actions;
Diagnostic &Diags;
@@ -110,6 +112,8 @@ class Parser {
IdentifierInfo *Ident_vector;
IdentifierInfo *Ident_pixel;
+ llvm::OwningPtr<PragmaHandler> AlignHandler;
+ llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler;
llvm::OwningPtr<PragmaHandler> OptionsHandler;
llvm::OwningPtr<PragmaHandler> PackHandler;
llvm::OwningPtr<PragmaHandler> UnusedHandler;
@@ -131,61 +135,56 @@ class Parser {
unsigned TemplateParameterDepth;
public:
- Parser(Preprocessor &PP, Action &Actions);
+ Parser(Preprocessor &PP, Sema &Actions);
~Parser();
const LangOptions &getLang() const { return PP.getLangOptions(); }
const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); }
Preprocessor &getPreprocessor() const { return PP; }
- Action &getActions() const { return Actions; }
+ Sema &getActions() const { return Actions; }
const Token &getCurToken() const { return Tok; }
Scope *getCurScope() const { return Actions.getCurScope(); }
// Type forwarding. All of these are statically 'void*', but they may all be
// different actual classes based on the actions in place.
- typedef Action::ExprTy ExprTy;
- typedef Action::StmtTy StmtTy;
- typedef Action::DeclPtrTy DeclPtrTy;
- typedef Action::DeclGroupPtrTy DeclGroupPtrTy;
- typedef Action::TypeTy TypeTy;
- typedef Action::BaseTy BaseTy;
- typedef Action::MemInitTy MemInitTy;
- typedef Action::CXXScopeTy CXXScopeTy;
- typedef Action::TemplateParamsTy TemplateParamsTy;
- typedef Action::TemplateTy TemplateTy;
-
- typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
-
- typedef Action::ExprResult ExprResult;
- typedef Action::StmtResult StmtResult;
- typedef Action::BaseResult BaseResult;
- typedef Action::MemInitResult MemInitResult;
- typedef Action::TypeResult TypeResult;
-
- typedef Action::OwningExprResult OwningExprResult;
- typedef Action::OwningStmtResult OwningStmtResult;
-
- typedef Action::ExprArg ExprArg;
- typedef Action::MultiStmtArg MultiStmtArg;
- typedef Action::FullExprArg FullExprArg;
-
- /// Adorns a ExprResult with Actions to make it an OwningExprResult
- OwningExprResult Owned(ExprResult res) {
- return OwningExprResult(Actions, res);
+ typedef Expr ExprTy;
+ typedef Stmt StmtTy;
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef CXXBaseSpecifier BaseTy;
+ typedef CXXBaseOrMemberInitializer MemInitTy;
+ typedef NestedNameSpecifier CXXScopeTy;
+ typedef TemplateParameterList TemplateParamsTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+
+ typedef llvm::SmallVector<TemplateParameterList *, 4> TemplateParameterLists;
+
+ typedef clang::ExprResult ExprResult;
+ typedef clang::StmtResult StmtResult;
+ typedef clang::BaseResult BaseResult;
+ typedef clang::MemInitResult MemInitResult;
+ typedef clang::TypeResult TypeResult;
+
+ typedef Expr *ExprArg;
+ typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef Sema::FullExprArg FullExprArg;
+
+ /// Adorns a ExprResult with Actions to make it an ExprResult
+ ExprResult Owned(ExprResult res) {
+ return ExprResult(res);
}
- /// Adorns a StmtResult with Actions to make it an OwningStmtResult
- OwningStmtResult Owned(StmtResult res) {
- return OwningStmtResult(Actions, res);
+ /// Adorns a StmtResult with Actions to make it an StmtResult
+ StmtResult Owned(StmtResult res) {
+ return StmtResult(res);
}
- OwningExprResult ExprError() { return OwningExprResult(Actions, true); }
- OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); }
+ ExprResult ExprError() { return ExprResult(true); }
+ StmtResult StmtError() { return StmtResult(true); }
- OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
- OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
+ ExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); }
+ StmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); }
- OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); }
+ ExprResult ExprEmpty() { return ExprResult(false); }
// Parsing methods.
@@ -201,7 +200,7 @@ public:
/// the EOF was encountered.
bool ParseTopLevelDecl(DeclGroupPtrTy &Result);
- DeclGroupPtrTy RetrievePendingObjCImpDecl();
+ DeclGroupPtrTy FinishPendingObjCActions();
private:
//===--------------------------------------------------------------------===//
@@ -349,6 +348,15 @@ private:
return PP.LookAhead(0);
}
+ /// getTypeAnnotation - Read a parsed type out of an annotation token.
+ static ParsedType getTypeAnnotation(Token &Tok) {
+ return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue());
+ }
+
+ static void setTypeAnnotation(Token &Tok, ParsedType T) {
+ Tok.setAnnotationValue(T.getAsOpaquePtr());
+ }
+
/// TryAnnotateTypeOrScopeToken - If the current token position is on a
/// typename (possibly qualified in C++) or a C++ scope specifier not followed
/// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
@@ -538,7 +546,7 @@ private:
// Lexing and parsing of C++ inline methods.
struct LexedMethod {
- Action::DeclPtrTy D;
+ Decl *D;
CachedTokens Toks;
/// \brief Whether this member function had an associated template
@@ -546,7 +554,7 @@ private:
/// othewise, it is a member function declaration.
bool TemplateScope;
- explicit LexedMethod(Action::DeclPtrTy MD) : D(MD), TemplateScope(false) {}
+ explicit LexedMethod(Decl *MD) : D(MD), TemplateScope(false) {}
};
/// LateParsedDefaultArgument - Keeps track of a parameter that may
@@ -554,12 +562,12 @@ private:
/// occurs within a member function declaration inside the class
/// (C++ [class.mem]p2).
struct LateParsedDefaultArgument {
- explicit LateParsedDefaultArgument(Action::DeclPtrTy P,
+ explicit LateParsedDefaultArgument(Decl *P,
CachedTokens *Toks = 0)
: Param(P), Toks(Toks) { }
/// Param - The parameter declaration for this parameter.
- Action::DeclPtrTy Param;
+ Decl *Param;
/// Toks - The sequence of tokens that comprises the default
/// argument expression, not including the '=' or the terminating
@@ -573,11 +581,11 @@ private:
/// until the class itself is completely-defined, such as a default
/// argument (C++ [class.mem]p2).
struct LateParsedMethodDeclaration {
- explicit LateParsedMethodDeclaration(Action::DeclPtrTy M)
+ explicit LateParsedMethodDeclaration(Decl *M)
: Method(M), TemplateScope(false) { }
/// Method - The method declaration.
- Action::DeclPtrTy Method;
+ Decl *Method;
/// \brief Whether this member function had an associated template
/// scope. When true, D is a template declaration.
@@ -608,7 +616,7 @@ private:
/// any member function declarations or definitions that need to be
/// parsed after the corresponding top-level class is complete.
struct ParsingClass {
- ParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass)
+ ParsingClass(Decl *TagOrTemplate, bool TopLevelClass)
: TopLevelClass(TopLevelClass), TemplateScope(false),
TagOrTemplate(TagOrTemplate) { }
@@ -622,7 +630,7 @@ private:
bool TemplateScope : 1;
/// \brief The class or class template whose definition we are parsing.
- DeclPtrTy TagOrTemplate;
+ Decl *TagOrTemplate;
/// MethodDecls - Method declarations that contain pieces whose
/// parsing will be delayed until the class is fully defined.
@@ -651,15 +659,28 @@ private:
/// variable's initializer, but not when parsing the body of a
/// class or function definition.
class ParsingDeclRAIIObject {
- Action &Actions;
- Action::ParsingDeclStackState State;
+ Sema &Actions;
+ Sema::ParsingDeclStackState State;
bool Popped;
-
+
public:
ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
push();
}
+ ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *Other)
+ : Actions(P.Actions) {
+ if (Other) steal(*Other);
+ else push();
+ }
+
+ /// Creates a RAII object which steals the state from a different
+ /// object instead of pushing.
+ ParsingDeclRAIIObject(ParsingDeclRAIIObject &Other)
+ : Actions(Other.Actions) {
+ steal(Other);
+ }
+
~ParsingDeclRAIIObject() {
abort();
}
@@ -673,21 +694,27 @@ private:
/// Signals that the context was completed without an appropriate
/// declaration being parsed.
void abort() {
- pop(DeclPtrTy());
+ pop(0);
}
- void complete(DeclPtrTy D) {
+ void complete(Decl *D) {
assert(!Popped && "ParsingDeclaration has already been popped!");
pop(D);
}
private:
+ void steal(ParsingDeclRAIIObject &Other) {
+ State = Other.State;
+ Popped = Other.Popped;
+ Other.Popped = true;
+ }
+
void push() {
State = Actions.PushParsingDeclaration();
Popped = false;
}
- void pop(DeclPtrTy D) {
+ void pop(Decl *D) {
if (!Popped) {
Actions.PopParsingDeclaration(State, D);
Popped = true;
@@ -700,10 +727,12 @@ private:
ParsingDeclRAIIObject ParsingRAII;
public:
- ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
- }
+ ParsingDeclSpec(Parser &P) : ParsingRAII(P) {}
+ ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {}
+ ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
+ : ParsingRAII(P, RAII) {}
- void complete(DeclPtrTy D) {
+ void complete(Decl *D) {
ParsingRAII.complete(D);
}
@@ -734,7 +763,7 @@ private:
ParsingRAII.reset();
}
- void complete(DeclPtrTy D) {
+ void complete(Decl *D) {
ParsingRAII.complete(D);
}
};
@@ -745,7 +774,7 @@ private:
bool Popped;
public:
- ParsingClassDefinition(Parser &P, DeclPtrTy TagOrTemplate, bool TopLevelClass)
+ ParsingClassDefinition(Parser &P, Decl *TagOrTemplate, bool TopLevelClass)
: P(P), Popped(false) {
P.PushParsingClass(TagOrTemplate, TopLevelClass);
}
@@ -811,12 +840,12 @@ private:
bool LastParameterListWasEmpty;
};
- void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass);
+ void PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass);
void DeallocateParsedClasses(ParsingClass *Class);
void PopParsingClass();
- DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
- const ParsedTemplateInfo &TemplateInfo);
+ Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo);
void ParseLexedMethodDeclarations(ParsingClass &Class);
void ParseLexedMethodDefs(ParsingClass &Class);
bool ConsumeAndStoreUntil(tok::TokenKind T1,
@@ -832,7 +861,8 @@ private:
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
- DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr);
+ DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr,
+ ParsingDeclSpec *DS = 0);
bool isDeclarationAfterDeclarator() const;
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
@@ -841,40 +871,40 @@ private:
AttributeList *Attr,
AccessSpecifier AS = AS_none);
- DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
+ Decl *ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
void ParseKNRParamDeclarations(Declarator &D);
// EndLoc, if non-NULL, is filled with the location of the last token of
// the simple-asm.
- OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
- OwningExprResult ParseAsmStringLiteral();
+ ExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0);
+ ExprResult ParseAsmStringLiteral();
// Objective-C External Declarations
- DeclPtrTy ParseObjCAtDirectives();
- DeclPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
+ Decl *ParseObjCAtDirectives();
+ Decl *ParseObjCAtClassDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtInterfaceDeclaration(SourceLocation atLoc,
AttributeList *prefixAttrs = 0);
- void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
+ void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
tok::ObjCKeywordKind visibility,
SourceLocation atLoc);
- bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P,
+ bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &P,
llvm::SmallVectorImpl<SourceLocation> &PLocs,
bool WarnOnDeclarations,
SourceLocation &LAngleLoc,
SourceLocation &EndProtoLoc);
- void ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
+ void ParseObjCInterfaceDeclList(Decl *interfaceDecl,
tok::ObjCKeywordKind contextKey);
- DeclPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
+ Decl *ParseObjCAtProtocolDeclaration(SourceLocation atLoc,
AttributeList *prefixAttrs = 0);
- DeclPtrTy ObjCImpDecl;
- llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl;
+ Decl *ObjCImpDecl;
+ llvm::SmallVector<Decl *, 4> PendingObjCImpDecl;
- DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd);
- DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc);
- DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc);
- DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc);
+ Decl *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCAtEndDeclaration(SourceRange atEnd);
+ Decl *ParseObjCAtAliasDeclaration(SourceLocation atLoc);
+ Decl *ParseObjCPropertySynthesize(SourceLocation atLoc);
+ Decl *ParseObjCPropertyDynamic(SourceLocation atLoc);
IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation);
// Definitions for Objective-c context sensitive keywords recognition.
@@ -886,58 +916,69 @@ private:
bool isTokIdentifier_in() const;
- TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS);
+ ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter);
void ParseObjCMethodRequirement();
- DeclPtrTy ParseObjCMethodPrototype(DeclPtrTy classOrCat,
+ Decl *ParseObjCMethodPrototype(Decl *classOrCat,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
- DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
- DeclPtrTy classDecl,
+ Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType,
+ Decl *classDecl,
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
- void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods, unsigned NumMethods);
+ void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
+ Decl **Methods, unsigned NumMethods);
- DeclPtrTy ParseObjCMethodDefinition();
+ Decl *ParseObjCMethodDefinition();
//===--------------------------------------------------------------------===//
// C99 6.5: Expressions.
- OwningExprResult ParseExpression();
- OwningExprResult ParseConstantExpression();
+ ExprResult ParseExpression();
+ ExprResult ParseConstantExpression();
// Expr that doesn't include commas.
- OwningExprResult ParseAssignmentExpression();
+ ExprResult ParseAssignmentExpression();
- OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
+ ExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc);
- OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
+ ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc);
- OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS,
+ ExprResult ParseRHSOfBinaryExpression(ExprResult LHS,
prec::Level MinPrec);
- OwningExprResult ParseCastExpression(bool isUnaryExpression,
+ ExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
- TypeTy *TypeOfCast);
- OwningExprResult ParseCastExpression(bool isUnaryExpression,
+ ParsedType TypeOfCast);
+ ExprResult ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand = false,
- TypeTy *TypeOfCast = 0);
- OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS);
- OwningExprResult ParseSizeofAlignofExpression();
- OwningExprResult ParseBuiltinPrimaryExpression();
+ ParsedType TypeOfCast = ParsedType());
+
+ /// Returns true if the next token would start a postfix-expression
+ /// suffix.
+ bool isPostfixExpressionSuffixStart() {
+ tok::TokenKind K = Tok.getKind();
+ return (K == tok::l_square || K == tok::l_paren ||
+ K == tok::period || K == tok::arrow ||
+ K == tok::plusplus || K == tok::minusminus);
+ }
- OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
+ ExprResult ParsePostfixExpressionSuffix(ExprResult LHS);
+ ExprResult ParseSizeofAlignofExpression();
+ ExprResult ParseBuiltinPrimaryExpression();
+
+ ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
- TypeTy *&CastTy,
+ ParsedType &CastTy,
SourceRange &CastRange);
- static const unsigned ExprListSize = 12;
- typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;
- typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy;
+ typedef llvm::SmallVector<Expr*, 20> ExprListTy;
+ typedef llvm::SmallVector<SourceLocation, 20> CommaLocsTy;
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
- bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
- void (Action::*Completer)(Scope *S, void *Data,
- ExprTy **Args,
- unsigned NumArgs) = 0,
- void *Data = 0);
+ bool ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
+ llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
+ void (Sema::*Completer)(Scope *S,
+ Expr *Data,
+ Expr **Args,
+ unsigned NumArgs) = 0,
+ Expr *Data = 0);
/// ParenParseOption - Control what ParseParenExpression will parse.
enum ParenParseOption {
@@ -946,67 +987,67 @@ private:
CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
CastExpr // Also allow '(' type-name ')' <anything>
};
- OwningExprResult ParseParenExpression(ParenParseOption &ExprType,
+ ExprResult ParseParenExpression(ParenParseOption &ExprType,
bool stopIfCastExpr,
- TypeTy *TypeOfCast,
- TypeTy *&CastTy,
+ ParsedType TypeOfCast,
+ ParsedType &CastTy,
SourceLocation &RParenLoc);
- OwningExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
- TypeTy *&CastTy,
+ ExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
+ ParsedType &CastTy,
SourceLocation LParenLoc,
SourceLocation &RParenLoc);
- OwningExprResult ParseCompoundLiteralExpression(TypeTy *Ty,
+ ExprResult ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
SourceLocation RParenLoc);
- OwningExprResult ParseStringLiteralExpression();
+ ExprResult ParseStringLiteralExpression();
//===--------------------------------------------------------------------===//
// C++ Expressions
- OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
+ ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
bool EnteringContext,
bool *MayBePseudoDestructor = 0);
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
- OwningExprResult ParseCXXCasts();
+ ExprResult ParseCXXCasts();
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Type Identification
- OwningExprResult ParseCXXTypeid();
+ ExprResult ParseCXXTypeid();
//===--------------------------------------------------------------------===//
// C++ 5.2.4: C++ Pseudo-Destructor Expressions
- OwningExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ ExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
- Action::TypeTy *ObjectType);
+ ParsedType ObjectType);
//===--------------------------------------------------------------------===//
// C++ 9.3.2: C++ 'this' pointer
- OwningExprResult ParseCXXThis();
+ ExprResult ParseCXXThis();
//===--------------------------------------------------------------------===//
// C++ 15: C++ Throw Expression
- OwningExprResult ParseThrowExpression();
+ ExprResult ParseThrowExpression();
// EndLoc is filled with the location of the last token of the specification.
bool ParseExceptionSpecification(SourceLocation &EndLoc,
- llvm::SmallVector<TypeTy*, 2> &Exceptions,
- llvm::SmallVector<SourceRange, 2> &Ranges,
+ llvm::SmallVectorImpl<ParsedType> &Exns,
+ llvm::SmallVectorImpl<SourceRange> &Ranges,
bool &hasAnyExceptionSpec);
//===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
- OwningExprResult ParseCXXBoolLiteral();
+ ExprResult ParseCXXBoolLiteral();
//===--------------------------------------------------------------------===//
// C++ 5.2.3: Explicit type conversion (functional notation)
- OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
+ ExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS);
bool isCXXSimpleTypeSpecifier() const;
@@ -1019,15 +1060,16 @@ private:
//===--------------------------------------------------------------------===//
// C++ 5.3.4 and 5.3.5: C++ new and delete
- bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D);
+ bool ParseExpressionListOrTypeId(llvm::SmallVectorImpl<Expr*> &Exprs,
+ Declarator &D);
void ParseDirectNewDeclarator(Declarator &D);
- OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
- OwningExprResult ParseCXXDeleteExpression(bool UseGlobal,
+ ExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start);
+ ExprResult ParseCXXDeleteExpression(bool UseGlobal,
SourceLocation Start);
//===--------------------------------------------------------------------===//
// C++ if/switch/while condition expression.
- bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult,
+ bool ParseCXXCondition(ExprResult &ExprResult, Decl *&DeclResult,
SourceLocation Loc, bool ConvertToBoolean);
//===--------------------------------------------------------------------===//
@@ -1040,65 +1082,65 @@ private:
/// initializer: [C99 6.7.8]
/// assignment-expression
/// '{' ...
- OwningExprResult ParseInitializer() {
+ ExprResult ParseInitializer() {
if (Tok.isNot(tok::l_brace))
return ParseAssignmentExpression();
return ParseBraceInitializer();
}
- OwningExprResult ParseBraceInitializer();
- OwningExprResult ParseInitializerWithPotentialDesignator();
+ ExprResult ParseBraceInitializer();
+ ExprResult ParseInitializerWithPotentialDesignator();
//===--------------------------------------------------------------------===//
// clang Expressions
- OwningExprResult ParseBlockLiteralExpression(); // ^{...}
+ ExprResult ParseBlockLiteralExpression(); // ^{...}
//===--------------------------------------------------------------------===//
// Objective-C Expressions
- OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation);
- OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
- OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
- OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
- OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCAtExpression(SourceLocation AtLocation);
+ ExprResult ParseObjCStringLiteral(SourceLocation AtLoc);
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCSelectorExpression(SourceLocation AtLoc);
+ ExprResult ParseObjCProtocolExpression(SourceLocation AtLoc);
bool isSimpleObjCMessageExpression();
- OwningExprResult ParseObjCMessageExpression();
- OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
+ ExprResult ParseObjCMessageExpression();
+ ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc,
SourceLocation SuperLoc,
- TypeTy *ReceiverType,
+ ParsedType ReceiverType,
ExprArg ReceiverExpr);
- OwningExprResult ParseAssignmentExprWithObjCMessageExprStart(
+ ExprResult ParseAssignmentExprWithObjCMessageExprStart(
SourceLocation LBracloc, SourceLocation SuperLoc,
- TypeTy *ReceiverType, ExprArg ReceiverExpr);
+ ParsedType ReceiverType, ExprArg ReceiverExpr);
bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr);
//===--------------------------------------------------------------------===//
// C99 6.8: Statements and Blocks.
- OwningStmtResult ParseStatement() {
+ StmtResult ParseStatement() {
return ParseStatementOrDeclaration(true);
}
- OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
- OwningStmtResult ParseLabeledStatement(AttributeList *Attr);
- OwningStmtResult ParseCaseStatement(AttributeList *Attr);
- OwningStmtResult ParseDefaultStatement(AttributeList *Attr);
- OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
+ StmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
+ StmtResult ParseLabeledStatement(AttributeList *Attr);
+ StmtResult ParseCaseStatement(AttributeList *Attr);
+ StmtResult ParseDefaultStatement(AttributeList *Attr);
+ StmtResult ParseCompoundStatement(AttributeList *Attr,
bool isStmtExpr = false);
- OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
- bool ParseParenExprOrCondition(OwningExprResult &ExprResult,
- DeclPtrTy &DeclResult,
+ StmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
+ bool ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean);
- OwningStmtResult ParseIfStatement(AttributeList *Attr);
- OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
- OwningStmtResult ParseWhileStatement(AttributeList *Attr);
- OwningStmtResult ParseDoStatement(AttributeList *Attr);
- OwningStmtResult ParseForStatement(AttributeList *Attr);
- OwningStmtResult ParseGotoStatement(AttributeList *Attr);
- OwningStmtResult ParseContinueStatement(AttributeList *Attr);
- OwningStmtResult ParseBreakStatement(AttributeList *Attr);
- OwningStmtResult ParseReturnStatement(AttributeList *Attr);
- OwningStmtResult ParseAsmStatement(bool &msAsm);
- OwningStmtResult FuzzyParseMicrosoftAsmStatement();
+ StmtResult ParseIfStatement(AttributeList *Attr);
+ StmtResult ParseSwitchStatement(AttributeList *Attr);
+ StmtResult ParseWhileStatement(AttributeList *Attr);
+ StmtResult ParseDoStatement(AttributeList *Attr);
+ StmtResult ParseForStatement(AttributeList *Attr);
+ StmtResult ParseGotoStatement(AttributeList *Attr);
+ StmtResult ParseContinueStatement(AttributeList *Attr);
+ StmtResult ParseBreakStatement(AttributeList *Attr);
+ StmtResult ParseReturnStatement(AttributeList *Attr);
+ StmtResult ParseAsmStatement(bool &msAsm);
+ StmtResult FuzzyParseMicrosoftAsmStatement();
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
llvm::SmallVectorImpl<ExprTy *> &Constraints,
llvm::SmallVectorImpl<ExprTy *> &Exprs);
@@ -1106,17 +1148,17 @@ private:
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
- OwningStmtResult ParseCXXTryBlock(AttributeList *Attr);
- OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
- OwningStmtResult ParseCXXCatchBlock();
+ StmtResult ParseCXXTryBlock(AttributeList *Attr);
+ StmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
+ StmtResult ParseCXXCatchBlock();
//===--------------------------------------------------------------------===//
// Objective-C Statements
- OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc);
- OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc);
- OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc);
- OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+ StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ StmtResult ParseObjCTryStmt(SourceLocation atLoc);
+ StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
+ StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
//===--------------------------------------------------------------------===//
@@ -1140,10 +1182,10 @@ private:
DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
bool AllowFunctionDefinitions,
SourceLocation *DeclEnd = 0);
- DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
+ Decl *ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
- DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
+ Decl *ParseFunctionStatementBody(Decl *Decl);
+ Decl *ParseFunctionTryBlock(Decl *Decl);
bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
@@ -1161,16 +1203,16 @@ private:
void ParseSpecifierQualifierList(DeclSpec &DS);
- void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
+ void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter);
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none);
- void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
+ void ParseEnumBody(SourceLocation StartLoc, Decl *TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
- DeclPtrTy TagDecl);
+ Decl *TagDecl);
struct FieldCallback {
- virtual DeclPtrTy invoke(FieldDeclarator &Field) = 0;
+ virtual Decl *invoke(FieldDeclarator &Field) = 0;
virtual ~FieldCallback() {}
private:
@@ -1323,10 +1365,11 @@ private:
AttributeList *ParseGNUAttributes(SourceLocation *EndLoc = 0);
AttributeList *ParseMicrosoftDeclSpec(AttributeList* CurrAttr = 0);
AttributeList *ParseMicrosoftTypeAttributes(AttributeList* CurrAttr = 0);
+ AttributeList *ParseBorlandTypeAttributes(AttributeList* CurrAttr = 0);
void ParseTypeofSpecifier(DeclSpec &DS);
void ParseDecltypeSpecifier(DeclSpec &DS);
- OwningExprResult ParseCXX0XAlignArgument(SourceLocation Start);
+ ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
/// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
/// enter a new C++ declarator scope and exit it when the function is
@@ -1386,21 +1429,21 @@ private:
bool isCXX0XAttributeSpecifier(bool FullLookahead = false,
tok::TokenKind *After = 0);
- DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd);
- DeclPtrTy ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
- DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- CXX0XAttributeList Attrs);
- DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
- SourceLocation &DeclEnd,
- AttributeList *Attr);
- DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
- SourceLocation &DeclEnd,
- AccessSpecifier AS = AS_none);
- DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
- DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc,
- SourceLocation AliasLoc, IdentifierInfo *Alias,
- SourceLocation &DeclEnd);
+ Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
+ Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
+ Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
+ SourceLocation &DeclEnd,
+ CXX0XAttributeList Attrs);
+ Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc,
+ SourceLocation &DeclEnd, AttributeList *Attr);
+ Decl *ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc,
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS = AS_none);
+ Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd);
+ Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ SourceLocation &DeclEnd);
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
@@ -1412,64 +1455,65 @@ private:
AccessSpecifier AS = AS_none,
bool SuppressDeclarations = false);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
- DeclPtrTy TagDecl);
+ Decl *TagDecl);
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- void ParseConstructorInitializer(DeclPtrTy ConstructorDecl);
- MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl);
+ const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
+ ParsingDeclRAIIObject *DiagsFromTParams = 0);
+ void ParseConstructorInitializer(Decl *ConstructorDecl);
+ MemInitResult ParseMemInitializer(Decl *ConstructorDecl);
void HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
- DeclPtrTy ThisDecl);
+ Decl *ThisDecl);
//===--------------------------------------------------------------------===//
// C++ 10: Derived classes [class.derived]
- void ParseBaseClause(DeclPtrTy ClassDecl);
- BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
+ void ParseBaseClause(Decl *ClassDecl);
+ BaseResult ParseBaseSpecifier(Decl *ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;
bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Id,
bool AssumeTemplateId,
SourceLocation TemplateKWLoc);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Result);
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
bool AllowConstructorName,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Result);
//===--------------------------------------------------------------------===//
// C++ 14: Templates [temp]
- typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList;
// C++ 14.1: Template Parameters [temp.param]
- DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context,
+ Decl *ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS = AS_none);
- DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context,
+ Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS);
- DeclPtrTy ParseSingleDeclarationAfterTemplate(
+ Decl *ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromParams,
SourceLocation &DeclEnd,
AccessSpecifier AS=AS_none);
bool ParseTemplateParameters(unsigned Depth,
- TemplateParameterList &TemplateParams,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc);
bool ParseTemplateParameterList(unsigned Depth,
- TemplateParameterList &TemplateParams);
+ llvm::SmallVectorImpl<Decl*> &TemplateParams);
bool isStartOfTemplateTypeParameter();
- DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position);
- DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position);
- DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
- DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTypeParameter(unsigned Depth, unsigned Position);
+ Decl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ Decl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList;
@@ -1491,13 +1535,24 @@ private:
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
- DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- SourceLocation &DeclEnd);
+ Decl *ParseExplicitInstantiation(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd);
//===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
- OwningExprResult ParseUnaryTypeTrait();
+ ExprResult ParseUnaryTypeTrait();
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor code-completion pass-through
+ virtual void CodeCompleteDirective(bool InConditional);
+ virtual void CodeCompleteInConditionalExclusion();
+ virtual void CodeCompleteMacroName(bool IsDefinition);
+ virtual void CodeCompletePreprocessorExpression();
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex);
+ virtual void CodeCompleteNaturalLanguage();
};
} // end namespace clang
diff --git a/include/clang/Rewrite/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h
index 4ebcef0fff61..9b2e0160c5d6 100644
--- a/include/clang/Rewrite/FixItRewriter.h
+++ b/include/clang/Rewrite/FixItRewriter.h
@@ -27,13 +27,16 @@ namespace clang {
class SourceManager;
class FileEntry;
-class FixItPathRewriter {
+class FixItOptions {
public:
- virtual ~FixItPathRewriter();
+ virtual ~FixItOptions();
/// \brief This file is about to be rewritten. Return the name of the file
/// that is okay to write to.
virtual std::string RewriteFilename(const std::string &Filename) = 0;
+
+ /// \brief Whether to abort fixing a file when not all errors could be fixed.
+ bool FixWhatYouCan;
};
class FixItRewriter : public DiagnosticClient {
@@ -50,7 +53,7 @@ class FixItRewriter : public DiagnosticClient {
/// \brief Turn an input path into an output path. NULL implies overwriting
/// the original.
- FixItPathRewriter *PathRewriter;
+ FixItOptions *FixItOpts;
/// \brief The number of rewriter failures.
unsigned NumFailures;
@@ -60,7 +63,7 @@ public:
/// \brief Initialize a new fix-it rewriter.
FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
- const LangOptions &LangOpts, FixItPathRewriter *PathRewriter);
+ const LangOptions &LangOpts, FixItOptions *FixItOpts);
/// \brief Destroy the fix-it rewriter.
~FixItRewriter();
diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h
index 2ff8d0a5b60a..2b5f88ccee9d 100644
--- a/include/clang/Rewrite/FrontendActions.h
+++ b/include/clang/Rewrite/FrontendActions.h
@@ -16,7 +16,7 @@
namespace clang {
class FixItRewriter;
-class FixItPathRewriter;
+class FixItOptions;
//===----------------------------------------------------------------------===//
// AST Consumer Actions
@@ -31,7 +31,7 @@ protected:
class FixItAction : public ASTFrontendAction {
protected:
llvm::OwningPtr<FixItRewriter> Rewriter;
- llvm::OwningPtr<FixItPathRewriter> PathRewriter;
+ llvm::OwningPtr<FixItOptions> FixItOpts;
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile);
diff --git a/lib/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h
index dea19ba28ccf..0a6656e97e1b 100644
--- a/lib/Sema/AnalysisBasedWarnings.h
+++ b/include/clang/Sema/AnalysisBasedWarnings.h
@@ -19,6 +19,11 @@
namespace clang {
+class BlockExpr;
+class Decl;
+class FunctionDecl;
+class ObjCMethodDecl;
+class QualType;
class Sema;
namespace sema {
@@ -42,12 +47,16 @@ private:
enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
+ void IssueWarnings(Policy P, const Decl *D, QualType BlockTy);
+
public:
AnalysisBasedWarnings(Sema &s);
Policy getDefaultPolicy() { return DefaultPolicy; }
- void IssueWarnings(Policy P, const Decl *D, QualType BlockTy = QualType());
+ void IssueWarnings(Policy P, const BlockExpr *E);
+ void IssueWarnings(Policy P, const FunctionDecl *D);
+ void IssueWarnings(Policy P, const ObjCMethodDecl *D);
};
}} // end namespace clang::sema
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Sema/AttributeList.h
index b60a94025e09..53316477e1c5 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Sema/AttributeList.h
@@ -1,4 +1,4 @@
-//===--- AttributeList.h ----------------------------------------*- C++ -*-===//
+//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,20 +7,21 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AttributeList class interface.
+// This file defines the AttributeList class, which is used to collect
+// parsed attributes.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_ATTRLIST_H
-#define LLVM_CLANG_ATTRLIST_H
+#ifndef LLVM_CLANG_SEMA_ATTRLIST_H
+#define LLVM_CLANG_SEMA_ATTRLIST_H
-#include "clang/Parse/Ownership.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
namespace clang {
class IdentifierInfo;
- class Action;
+ class Expr;
/// AttributeList - Represents GCC's __attribute__ declaration. There are
/// 4 forms of this construct...they are:
@@ -37,7 +38,7 @@ class AttributeList {
SourceLocation ScopeLoc;
IdentifierInfo *ParmName;
SourceLocation ParmLoc;
- ActionBase::ExprTy **Args;
+ Expr **Args;
unsigned NumArgs;
AttributeList *Next;
bool DeclspecAttribute, CXX0XAttribute;
@@ -48,7 +49,7 @@ public:
AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc,
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
IdentifierInfo *ParmName, SourceLocation ParmLoc,
- ActionBase::ExprTy **args, unsigned numargs,
+ Expr **args, unsigned numargs,
AttributeList *Next, bool declspec = false, bool cxx0x = false);
~AttributeList();
@@ -97,7 +98,11 @@ public:
AT_ns_returns_retained, // Clang-specific.
AT_objc_gc,
AT_overloadable, // Clang-specific.
+ AT_ownership_holds, // Clang-specific.
+ AT_ownership_returns, // Clang-specific.
+ AT_ownership_takes, // Clang-specific.
AT_packed,
+ AT_pascal,
AT_pure,
AT_regparm,
AT_section,
@@ -108,6 +113,7 @@ public:
AT_unavailable,
AT_unused,
AT_used,
+ AT_vecreturn, // PS3 PPU-specific.
AT_vector_size,
AT_visibility,
AT_warn_unused_result,
@@ -145,16 +151,16 @@ public:
unsigned getNumArgs() const { return NumArgs; }
/// getArg - Return the specified argument.
- ActionBase::ExprTy *getArg(unsigned Arg) const {
+ Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
return Args[Arg];
}
class arg_iterator {
- ActionBase::ExprTy** X;
+ Expr** X;
unsigned Idx;
public:
- arg_iterator(ActionBase::ExprTy** x, unsigned idx) : X(x), Idx(idx) {}
+ arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {}
arg_iterator& operator++() {
++Idx;
@@ -171,7 +177,7 @@ public:
return !operator==(I);
}
- ActionBase::ExprTy* operator*() const {
+ Expr* operator*() const {
return X[Idx];
}
diff --git a/lib/Sema/CXXFieldCollector.h b/include/clang/Sema/CXXFieldCollector.h
index 63c6ee3f74ba..63c6ee3f74ba 100644
--- a/lib/Sema/CXXFieldCollector.h
+++ b/include/clang/Sema/CXXFieldCollector.h
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h
index 1d9d25073177..6c1ecbf2cc29 100644
--- a/include/clang/Sema/CodeCompleteConsumer.h
+++ b/include/clang/Sema/CodeCompleteConsumer.h
@@ -13,20 +13,30 @@
#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+#include "clang/AST/Type.h"
+#include "clang/AST/CanonicalType.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "clang-c/Index.h"
#include <memory>
#include <string>
namespace llvm {
-class raw_ostream;
+ class raw_ostream;
}
namespace clang {
+class Decl;
+
/// \brief Default priority values for code-completion results based
/// on their kind.
enum {
+ /// \brief Priority for the next initialization in a constructor initializer
+ /// list.
+ CCP_NextInitializer = 7,
+ /// \brief Priority for a send-to-super completion.
+ CCP_SuperCompletion = 8,
/// \brief Priority for a declaration that is in the local scope.
CCP_LocalDeclaration = 8,
/// \brief Priority for a member declaration found from the current
@@ -37,12 +47,12 @@ enum {
CCP_Keyword = 30,
/// \brief Priority for a code pattern.
CCP_CodePattern = 30,
- /// \brief Priority for a type.
- CCP_Type = 40,
/// \brief Priority for a non-type declaration.
CCP_Declaration = 50,
/// \brief Priority for a constant value (e.g., enumerator).
CCP_Constant = 60,
+ /// \brief Priority for a type.
+ CCP_Type = 65,
/// \brief Priority for a preprocessor macro.
CCP_Macro = 70,
/// \brief Priority for a nested-name-specifier.
@@ -52,11 +62,23 @@ enum {
CCP_Unlikely = 80
};
-/// \brief Priority value deltas that are applied to code-completion results
+/// \brief Priority value deltas that are added to code-completion results
/// based on the context of the result.
enum {
/// \brief The result is in a base class.
- CCD_InBaseClass = 2
+ CCD_InBaseClass = 2,
+ /// \brief The result is a type match against void.
+ ///
+ /// Since everything converts to "void", we don't give as drastic an
+ /// adjustment for matching void.
+ CCD_VoidMatch = -5,
+ /// \brief The result is a C++ non-static member function whose qualifiers
+ /// exactly match the object type on which the member function can be called.
+ CCD_ObjectQualifierMatch = -1,
+ /// \brief The selector of the given message exactly matches the selector
+ /// of the current method, which might imply that some kind of delegation
+ /// is occurring.
+ CCD_SelectorMatch = -3
};
/// \brief Priority value factors by which we will divide or multiply the
@@ -70,6 +92,41 @@ enum {
/// Objective-C object pointer types).
CCF_SimilarTypeMatch = 2
};
+
+/// \brief A simplified classification of types used when determining
+/// "similar" types for code completion.
+enum SimplifiedTypeClass {
+ STC_Arithmetic,
+ STC_Array,
+ STC_Block,
+ STC_Function,
+ STC_ObjectiveC,
+ STC_Other,
+ STC_Pointer,
+ STC_Record,
+ STC_Void
+};
+
+/// \brief Determine the simplified type class of the given canonical type.
+SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
+
+/// \brief Determine the type that this declaration will have if it is used
+/// as a type or in an expression.
+QualType getDeclUsageType(ASTContext &C, NamedDecl *ND);
+
+/// \brief Determine the priority to be given to a macro code completion result
+/// with the given name.
+///
+/// \param MacroName The name of the macro.
+///
+/// \param PreferredTypeIsPointer Whether the preferred type for the context
+/// of this macro is a pointer type.
+unsigned getMacroUsagePriority(llvm::StringRef MacroName,
+ bool PreferredTypeIsPointer = false);
+
+/// \brief Determine the libclang cursor kind associated with the given
+/// declaration.
+CXCursorKind getCursorKindForDecl(Decl *D);
class FunctionDecl;
class FunctionType;
@@ -79,6 +136,121 @@ class NamedDecl;
class NestedNameSpecifier;
class Sema;
+/// \brief The context in which code completion occurred, so that the
+/// code-completion consumer can process the results accordingly.
+class CodeCompletionContext {
+public:
+ enum Kind {
+ /// \brief An unspecified code-completion context.
+ CCC_Other,
+ /// \brief Code completion occurred within a "top-level" completion context,
+ /// e.g., at namespace or global scope.
+ CCC_TopLevel,
+ /// \brief Code completion occurred within an Objective-C interface,
+ /// protocol, or category interface.
+ CCC_ObjCInterface,
+ /// \brief Code completion occurred within an Objective-C implementation
+ /// or category implementation.
+ CCC_ObjCImplementation,
+ /// \brief Code completion occurred within the instance variable list of
+ /// an Objective-C interface, implementation, or category implementation.
+ CCC_ObjCIvarList,
+ /// \brief Code completion occurred within a class, struct, or union.
+ CCC_ClassStructUnion,
+ /// \brief Code completion occurred where a statement (or declaration) is
+ /// expected in a function, method, or block.
+ CCC_Statement,
+ /// \brief Code completion occurred where an expression is expected.
+ CCC_Expression,
+ /// \brief Code completion occurred where an Objective-C message receiver
+ /// is expected.
+ CCC_ObjCMessageReceiver,
+ /// \brief Code completion occurred on the right-hand side of a member
+ /// access expression.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_MemberAccess,
+ /// \brief Code completion occurred after the "enum" keyword, to indicate
+ /// an enumeration name.
+ CCC_EnumTag,
+ /// \brief Code completion occurred after the "union" keyword, to indicate
+ /// a union name.
+ CCC_UnionTag,
+ /// \brief Code completion occurred after the "struct" or "class" keyword,
+ /// to indicate a struct or class name.
+ CCC_ClassOrStructTag,
+ /// \brief Code completion occurred where a protocol name is expected.
+ CCC_ObjCProtocolName,
+ /// \brief Code completion occurred where a namespace or namespace alias
+ /// is expected.
+ CCC_Namespace,
+ /// \brief Code completion occurred where a type name is expected.
+ CCC_Type,
+ /// \brief Code completion occurred where a new name is expected.
+ CCC_Name,
+ /// \brief Code completion occurred where a new name is expected and a
+ /// qualified name is permissible.
+ CCC_PotentiallyQualifiedName,
+ /// \brief Code completion occurred where an macro is being defined.
+ CCC_MacroName,
+ /// \brief Code completion occurred where a macro name is expected
+ /// (without any arguments, in the case of a function-like macro).
+ CCC_MacroNameUse,
+ /// \brief Code completion occurred within a preprocessor expression.
+ CCC_PreprocessorExpression,
+ /// \brief Code completion occurred where a preprocessor directive is
+ /// expected.
+ CCC_PreprocessorDirective,
+ /// \brief Code completion occurred in a context where natural language is
+ /// expected, e.g., a comment or string literal.
+ ///
+ /// This context usually implies that no completions should be added,
+ /// unless they come from an appropriate natural-language dictionary.
+ CCC_NaturalLanguage,
+ /// \brief Code completion for a selector, as in an @selector expression.
+ CCC_SelectorName,
+ /// \brief Code completion within a type-qualifier list.
+ CCC_TypeQualifiers
+ };
+
+private:
+ enum Kind Kind;
+
+ /// \brief The type that would prefer to see at this point (e.g., the type
+ /// of an initializer or function parameter).
+ QualType PreferredType;
+
+ /// \brief The type of the base object in a member access expression.
+ QualType BaseType;
+
+public:
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind) : Kind(Kind) { }
+
+ /// \brief Construct a new code-completion context of the given kind.
+ CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) {
+ if (Kind == CCC_MemberAccess)
+ BaseType = T;
+ else
+ PreferredType = T;
+ }
+
+ /// \brief Retrieve the kind of code-completion context.
+ enum Kind getKind() const { return Kind; }
+
+ /// \brief Retrieve the type that this expression would prefer to have, e.g.,
+ /// if the expression is a variable initializer or a function argument, the
+ /// type of the corresponding variable or function parameter.
+ QualType getPreferredType() const { return PreferredType; }
+
+ /// \brief Retrieve the type of the base object in a member-access
+ /// expression.
+ QualType getBaseType() const { return BaseType; }
+};
+
+
/// \brief A "string" used to describe how code completion can
/// be performed for an entity.
///
@@ -274,7 +446,10 @@ public:
std::string getAsString() const;
/// \brief Clone this code-completion string.
- CodeCompletionString *Clone() const;
+ ///
+ /// \param Result If non-NULL, points to an empty code-completion
+ /// result that will be given a cloned copy of
+ CodeCompletionString *Clone(CodeCompletionString *Result = 0) const;
/// \brief Serialize this code-completion string to the given stream.
void Serialize(llvm::raw_ostream &OS) const;
@@ -284,140 +459,193 @@ public:
/// \returns true if successful, false otherwise.
bool Deserialize(const char *&Str, const char *StrEnd);
};
-
-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;
-
- /// \brief Whether to include code patterns (such as for loops) within
- /// the completion results.
- bool IncludeCodePatterns;
-
- /// \brief Whether the output format for the code-completion consumer is
- /// binary.
- bool OutputIsBinary;
-
+/// \brief Captures a result of code completion.
+class CodeCompletionResult {
public:
- /// \brief Captures a result of code completion.
- struct Result {
- /// \brief Describes the kind of result generated.
- enum ResultKind {
- RK_Declaration = 0, //< Refers to a declaration
- RK_Keyword, //< Refers to a keyword or symbol.
- RK_Macro, //< Refers to a macro
- RK_Pattern //< Refers to a precomputed pattern.
- };
+ /// \brief Describes the kind of result generated.
+ enum ResultKind {
+ RK_Declaration = 0, //< Refers to a declaration
+ RK_Keyword, //< Refers to a keyword or symbol.
+ RK_Macro, //< Refers to a macro
+ RK_Pattern //< Refers to a precomputed pattern.
+ };
- /// \brief The kind of result stored here.
- ResultKind Kind;
+ /// \brief The kind of result stored here.
+ ResultKind Kind;
- union {
- /// \brief When Kind == RK_Declaration, the declaration we are referring
- /// to.
- NamedDecl *Declaration;
+ union {
+ /// \brief When Kind == RK_Declaration, the declaration we are referring
+ /// to.
+ NamedDecl *Declaration;
- /// \brief When Kind == RK_Keyword, the string representing the keyword
- /// or symbol's spelling.
- const char *Keyword;
+ /// \brief When Kind == RK_Keyword, the string representing the keyword
+ /// or symbol's spelling.
+ const char *Keyword;
- /// \brief When Kind == RK_Pattern, the code-completion string that
- /// describes the completion text to insert.
- CodeCompletionString *Pattern;
+ /// \brief When Kind == RK_Pattern, the code-completion string that
+ /// describes the completion text to insert.
+ CodeCompletionString *Pattern;
- /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
- IdentifierInfo *Macro;
- };
+ /// \brief When Kind == RK_Macro, the identifier that refers to a macro.
+ IdentifierInfo *Macro;
+ };
- /// \brief The priority of this particular code-completion result.
- unsigned Priority;
+ /// \brief The priority of this particular code-completion result.
+ unsigned Priority;
- /// \brief Specifies which parameter (of a function, Objective-C method,
- /// macro, etc.) we should start with when formatting the result.
- unsigned StartParameter;
+ /// \brief The cursor kind that describes this result.
+ CXCursorKind CursorKind;
+
+ /// \brief The availability of this result.
+ CXAvailabilityKind Availability;
- /// \brief Whether this result is hidden by another name.
- bool Hidden : 1;
+ /// \brief Specifies which parameter (of a function, Objective-C method,
+ /// macro, etc.) we should start with when formatting the result.
+ unsigned StartParameter;
- /// \brief Whether this result was found via lookup into a base class.
- bool QualifierIsInformative : 1;
+ /// \brief Whether this result is hidden by another name.
+ bool Hidden : 1;
- /// \brief Whether this declaration is the beginning of a
- /// nested-name-specifier and, therefore, should be followed by '::'.
- bool StartsNestedNameSpecifier : 1;
+ /// \brief Whether this result was found via lookup into a base class.
+ bool QualifierIsInformative : 1;
+
+ /// \brief Whether this declaration is the beginning of a
+ /// nested-name-specifier and, therefore, should be followed by '::'.
+ bool StartsNestedNameSpecifier : 1;
- /// \brief Whether all parameters (of a function, Objective-C
- /// method, etc.) should be considered "informative".
- bool AllParametersAreInformative : 1;
+ /// \brief Whether all parameters (of a function, Objective-C
+ /// method, etc.) should be considered "informative".
+ bool AllParametersAreInformative : 1;
- /// \brief Whether we're completing a declaration of the given entity,
- /// rather than a use of that entity.
- bool DeclaringEntity : 1;
+ /// \brief Whether we're completing a declaration of the given entity,
+ /// rather than a use of that entity.
+ bool DeclaringEntity : 1;
- /// \brief If the result should have a nested-name-specifier, this is it.
- /// When \c QualifierIsInformative, the nested-name-specifier is
- /// informative rather than required.
- NestedNameSpecifier *Qualifier;
+ /// \brief If the result should have a nested-name-specifier, this is it.
+ /// When \c QualifierIsInformative, the nested-name-specifier is
+ /// informative rather than required.
+ NestedNameSpecifier *Qualifier;
- /// \brief Build a result that refers to a declaration.
- Result(NamedDecl *Declaration,
- NestedNameSpecifier *Qualifier = 0,
- bool QualifierIsInformative = false)
- : Kind(RK_Declaration), Declaration(Declaration),
- Priority(getPriorityFromDecl(Declaration)), StartParameter(0),
- Hidden(false), QualifierIsInformative(QualifierIsInformative),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(Qualifier) {
- }
+ /// \brief Build a result that refers to a declaration.
+ CodeCompletionResult(NamedDecl *Declaration,
+ NestedNameSpecifier *Qualifier = 0,
+ bool QualifierIsInformative = false)
+ : Kind(RK_Declaration), Declaration(Declaration),
+ Priority(getPriorityFromDecl(Declaration)),
+ Availability(CXAvailability_Available), StartParameter(0),
+ Hidden(false), QualifierIsInformative(QualifierIsInformative),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(Qualifier) {
+ computeCursorKindAndAvailability();
+ }
- /// \brief Build a result that refers to a keyword or symbol.
- Result(const char *Keyword, unsigned Priority = CCP_Keyword)
- : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
- StartParameter(0), Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) { }
+ /// \brief Build a result that refers to a keyword or symbol.
+ CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
+ : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
+ Availability(CXAvailability_Available),
+ StartParameter(0), Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0) {
+ computeCursorKindAndAvailability();
+ }
- /// \brief Build a result that refers to a macro.
- Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
- : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0),
- Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) { }
-
- /// \brief Build a result that refers to a pattern.
- Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern)
- : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
- StartParameter(0), Hidden(false), QualifierIsInformative(0),
- StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
- DeclaringEntity(false), Qualifier(0) { }
+ /// \brief Build a result that refers to a macro.
+ CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
+ : Kind(RK_Macro), Macro(Macro), Priority(Priority),
+ Availability(CXAvailability_Available), StartParameter(0),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// \brief Build a result that refers to a pattern.
+ CodeCompletionResult(CodeCompletionString *Pattern,
+ unsigned Priority = CCP_CodePattern,
+ CXCursorKind CursorKind = CXCursor_NotImplemented,
+ CXAvailabilityKind Availability = CXAvailability_Available)
+ : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
+ CursorKind(CursorKind), Availability(Availability), StartParameter(0),
+ Hidden(false), QualifierIsInformative(0),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), Qualifier(0)
+ {
+ }
- /// \brief Retrieve the declaration stored in this result.
- NamedDecl *getDeclaration() const {
- assert(Kind == RK_Declaration && "Not a declaration result");
- return Declaration;
- }
+ /// \brief Retrieve the declaration stored in this result.
+ NamedDecl *getDeclaration() const {
+ assert(Kind == RK_Declaration && "Not a declaration result");
+ return Declaration;
+ }
- /// \brief Retrieve the keyword stored in this result.
- const char *getKeyword() const {
- assert(Kind == RK_Keyword && "Not a keyword result");
- return Keyword;
- }
+ /// \brief Retrieve the keyword stored in this result.
+ const char *getKeyword() const {
+ assert(Kind == RK_Keyword && "Not a keyword result");
+ return Keyword;
+ }
- /// \brief Create a new code-completion string that describes how to insert
- /// this result into a program.
- CodeCompletionString *CreateCodeCompletionString(Sema &S);
+ /// \brief Create a new code-completion string that describes how to insert
+ /// this result into a program.
+ ///
+ /// \param S The semantic analysis that created the result.
+ ///
+ /// \param Result If non-NULL, the already-allocated, empty
+ /// code-completion string that will be populated with the
+ /// appropriate code completion string for this result.
+ CodeCompletionString *CreateCodeCompletionString(Sema &S,
+ CodeCompletionString *Result = 0);
- void Destroy();
+ void Destroy();
- /// brief Determine a base priority for the given declaration.
- static unsigned getPriorityFromDecl(NamedDecl *ND);
- };
+ /// brief Determine a base priority for the given declaration.
+ static unsigned getPriorityFromDecl(NamedDecl *ND);
+private:
+ void computeCursorKindAndAvailability();
+};
+
+bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y);
+
+inline bool operator>(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return Y < X;
+}
+
+inline bool operator<=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(Y < X);
+}
+
+inline bool operator>=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(X < Y);
+}
+
+
+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;
+
+ /// \brief Whether to include code patterns (such as for loops) within
+ /// the completion results.
+ bool IncludeCodePatterns;
+
+ /// \brief Whether to include global (top-level) declarations and names in
+ /// the completion results.
+ bool IncludeGlobals;
+
+ /// \brief Whether the output format for the code-completion consumer is
+ /// binary.
+ bool OutputIsBinary;
+
+public:
class OverloadCandidate {
public:
/// \brief Describes the type of overload candidate.
@@ -482,12 +710,13 @@ public:
Sema &S) const;
};
- CodeCompleteConsumer() : IncludeMacros(false), OutputIsBinary(false) { }
+ CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false),
+ IncludeGlobals(true), OutputIsBinary(false) { }
CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- bool OutputIsBinary)
+ bool IncludeGlobals, bool OutputIsBinary)
: IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns),
- OutputIsBinary(OutputIsBinary) { }
+ IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { }
/// \brief Whether the code-completion consumer wants to see macros.
bool includeMacros() const { return IncludeMacros; }
@@ -495,6 +724,9 @@ public:
/// \brief Whether the code-completion consumer wants to see code patterns.
bool includeCodePatterns() const { return IncludeCodePatterns; }
+ /// \brief Whether to include global (top-level) declaration results.
+ bool includeGlobals() const { return IncludeGlobals; }
+
/// \brief Determine whether the output of this consumer is binary.
bool isOutputBinary() const { return OutputIsBinary; }
@@ -504,7 +736,9 @@ public:
/// \name Code-completion callbacks
//@{
/// \brief Process the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults) { }
/// \param S the semantic-analyzer object for which code-completion is being
@@ -520,7 +754,7 @@ public:
unsigned NumCandidates) { }
//@}
};
-
+
/// \brief A simple code-completion consumer that prints the results it
/// receives in a simple format.
class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
@@ -531,11 +765,15 @@ public:
/// \brief Create a new printing code-completion consumer that prints its
/// results to the given raw output stream.
PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeGlobals,
llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {}
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ false), OS(OS) {}
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults);
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
@@ -554,18 +792,21 @@ public:
/// results to the given raw output stream in a format readable to the CIndex
/// library.
CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns,
- llvm::raw_ostream &OS)
- : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {}
+ bool IncludeGlobals, llvm::raw_ostream &OS)
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ true), OS(OS) {}
/// \brief Prints the finalized code-completion results.
- virtual void ProcessCodeCompleteResults(Sema &S, Result *Results,
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults);
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
OverloadCandidate *Candidates,
unsigned NumCandidates);
};
-
+
} // end namespace clang
#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 0e6dbecb36d6..0893ae7e4958 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -1,4 +1,4 @@
-//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- C++ -*-===//
+//===--- DeclSpec.h - Parsed declaration specifiers -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,21 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines interfaces used for Declaration Specifiers and Declarators.
+// This file defines the classes used to store parsed information about
+// declaration-specifiers and declarators.
+//
+// static const int volatile x, *y, *(*(*z)[10])(const void *x);
+// ------------------------- - -- ---------------------------
+// declaration-specifiers \ | /
+// declarators
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_DECLSPEC_H
-#define LLVM_CLANG_PARSE_DECLSPEC_H
+#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
+#define LLVM_CLANG_SEMA_DECLSPEC_H
-#include "clang/Parse/AttributeList.h"
+#include "clang/Sema/AttributeList.h"
+#include "clang/Sema/Ownership.h"
#include "clang/Lex/Token.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
@@ -24,6 +31,7 @@ namespace clang {
class LangOptions;
class Diagnostic;
class IdentifierInfo;
+ class NestedNameSpecifier;
class Preprocessor;
class Declarator;
struct TemplateIdAnnotation;
@@ -41,7 +49,7 @@ namespace clang {
/// The actual scope is described by getScopeRep().
class CXXScopeSpec {
SourceRange Range;
- void *ScopeRep;
+ NestedNameSpecifier *ScopeRep;
public:
CXXScopeSpec() : Range(), ScopeRep() { }
@@ -53,8 +61,8 @@ public:
SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
- ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; }
- void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; }
+ NestedNameSpecifier *getScopeRep() const { return ScopeRep; }
+ void setScopeRep(NestedNameSpecifier *S) { ScopeRep = S; }
/// No scope specifier.
bool isEmpty() const { return !Range.isValid(); }
@@ -162,6 +170,7 @@ private:
// storage-class-specifier
/*SCS*/unsigned StorageClassSpec : 3;
bool SCS_thread_specified : 1;
+ bool SCS_extern_in_linkage_spec : 1;
// type-specifier
/*TSW*/unsigned TypeSpecWidth : 2;
@@ -189,10 +198,11 @@ private:
/*SCS*/unsigned StorageClassSpecAsWritten : 3;
- /// TypeRep - This contains action-specific information about a specific TST.
- /// For example, for a typedef or struct, it might contain the declaration for
- /// these.
- void *TypeRep;
+ union {
+ UnionParsedType TypeRep;
+ Decl *DeclRep;
+ Expr *ExprRep;
+ };
// attributes.
AttributeList *AttrList;
@@ -203,7 +213,7 @@ private:
// List of protocol qualifiers for objective-c classes. Used for
// protocol-qualified interfaces "NString<foo>" and protocol-qualified id
// "id<foo>".
- const ActionBase::DeclPtrTy *ProtocolQualifiers;
+ Decl * const *ProtocolQualifiers;
unsigned NumProtocolQualifiers;
SourceLocation ProtocolLAngleLoc;
SourceLocation *ProtocolLocs;
@@ -221,8 +231,17 @@ private:
WrittenBuiltinSpecs writtenBS;
void SaveWrittenBuiltinSpecs();
- void SaveStorageSpecifierAsWritten() {
- StorageClassSpecAsWritten = StorageClassSpec;
+ void SaveStorageSpecifierAsWritten();
+
+ static bool isTypeRep(TST T) {
+ return (T == TST_typename || T == TST_typeofType);
+ }
+ static bool isExprRep(TST T) {
+ return (T == TST_typeofExpr || T == TST_decltype);
+ }
+ static bool isDeclRep(TST T) {
+ return (T == TST_enum || T == TST_struct ||
+ T == TST_union || T == TST_class);
}
DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT
@@ -232,6 +251,7 @@ public:
DeclSpec()
: StorageClassSpec(SCS_unspecified),
SCS_thread_specified(false),
+ SCS_extern_in_linkage_spec(false),
TypeSpecWidth(TSW_unspecified),
TypeSpecComplex(TSC_unspecified),
TypeSpecSign(TSS_unspecified),
@@ -247,7 +267,6 @@ public:
Friend_specified(false),
Constexpr_specified(false),
StorageClassSpecAsWritten(SCS_unspecified),
- TypeRep(0),
AttrList(0),
ProtocolQualifiers(0),
NumProtocolQualifiers(0),
@@ -262,6 +281,10 @@ public:
// storage-class-specifier
SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
bool isThreadSpecified() const { return SCS_thread_specified; }
+ bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; }
+ void setExternInLinkageSpec(bool Value) {
+ SCS_extern_in_linkage_spec = Value;
+ }
SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
@@ -269,6 +292,7 @@ public:
void ClearStorageClassSpecs() {
StorageClassSpec = DeclSpec::SCS_unspecified;
SCS_thread_specified = false;
+ SCS_extern_in_linkage_spec = false;
StorageClassSpecLoc = SourceLocation();
SCS_threadLoc = SourceLocation();
}
@@ -282,7 +306,18 @@ public:
bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; }
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
bool isTypeSpecOwned() const { return TypeSpecOwned; }
- void *getTypeRep() const { return TypeRep; }
+ ParsedType getRepAsType() const {
+ assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
+ return TypeRep;
+ }
+ Decl *getRepAsDecl() const {
+ assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
+ return DeclRep;
+ }
+ Expr *getRepAsExpr() const {
+ assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
+ return ExprRep;
+ }
CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
@@ -379,13 +414,30 @@ public:
bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
- unsigned &DiagID, void *Rep = 0, bool Owned = false);
+ unsigned &DiagID);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Expr *Rep);
bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID);
bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
const char *&PrevSpec, unsigned &DiagID);
bool SetTypeSpecError();
- void UpdateTypeRep(void *Rep) { TypeRep = Rep; }
+ void UpdateDeclRep(Decl *Rep) {
+ assert(isDeclRep((TST) TypeSpecType));
+ DeclRep = Rep;
+ }
+ void UpdateTypeRep(ParsedType Rep) {
+ assert(isTypeRep((TST) TypeSpecType));
+ TypeRep = Rep;
+ }
+ void UpdateExprRep(Expr *Rep) {
+ assert(isExprRep((TST) TypeSpecType));
+ ExprRep = Rep;
+ }
bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, const LangOptions &Lang);
@@ -436,7 +488,7 @@ public:
return AL;
}
- typedef const ActionBase::DeclPtrTy *ProtocolQualifierListTy;
+ typedef Decl * const *ProtocolQualifierListTy;
ProtocolQualifierListTy getProtocolQualifiers() const {
return ProtocolQualifiers;
}
@@ -445,7 +497,7 @@ public:
return NumProtocolQualifiers;
}
SourceLocation getProtocolLAngleLoc() const { return ProtocolLAngleLoc; }
- void setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP,
+ void setProtocolQualifiers(Decl * const *Protos, unsigned NP,
SourceLocation *ProtoLocs,
SourceLocation LAngleLoc);
@@ -577,15 +629,15 @@ public:
/// \brief When Kind == IK_ConversionFunctionId, the type that the
/// conversion function names.
- ActionBase::TypeTy *ConversionFunctionId;
+ UnionParsedType ConversionFunctionId;
/// \brief When Kind == IK_ConstructorName, the class-name of the type
/// whose constructor is being referenced.
- ActionBase::TypeTy *ConstructorName;
+ UnionParsedType ConstructorName;
/// \brief When Kind == IK_DestructorName, the type referred to by the
/// class-name.
- ActionBase::TypeTy *DestructorName;
+ UnionParsedType DestructorName;
/// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId,
/// the template-id annotation that contains the template name and
@@ -662,7 +714,7 @@ public:
///
/// \param EndLoc the location of the last token that makes up the type name.
void setConversionFunctionId(SourceLocation OperatorLoc,
- ActionBase::TypeTy *Ty,
+ ParsedType Ty,
SourceLocation EndLoc) {
Kind = IK_ConversionFunctionId;
StartLocation = OperatorLoc;
@@ -693,7 +745,7 @@ public:
/// \param ClassNameLoc the location of the class name.
///
/// \param EndLoc the location of the last token that makes up the type name.
- void setConstructorName(ActionBase::TypeTy *ClassType,
+ void setConstructorName(ParsedType ClassType,
SourceLocation ClassNameLoc,
SourceLocation EndLoc) {
Kind = IK_ConstructorName;
@@ -716,7 +768,8 @@ public:
/// name.
///
/// \param ClassType the name of the class referred to by the destructor name.
- void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType,
+ void setDestructorName(SourceLocation TildeLoc,
+ ParsedType ClassType,
SourceLocation EndLoc) {
Kind = IK_DestructorName;
StartLocation = TildeLoc;
@@ -788,7 +841,7 @@ struct DeclaratorChunk {
/// This is the size of the array, or null if [] or [*] was specified.
/// Since the parser is multi-purpose, and we don't want to impose a root
/// expression class on all clients, NumElts is untyped.
- ActionBase::ExprTy *NumElts;
+ Expr *NumElts;
void destroy() {}
};
@@ -801,7 +854,7 @@ struct DeclaratorChunk {
struct ParamInfo {
IdentifierInfo *Ident;
SourceLocation IdentLoc;
- ActionBase::DeclPtrTy Param;
+ Decl *Param;
/// DefaultArgTokens - When the parameter's default argument
/// cannot be parsed immediately (because it occurs within the
@@ -812,14 +865,14 @@ struct DeclaratorChunk {
ParamInfo() {}
ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
- ActionBase::DeclPtrTy param,
+ Decl *param,
CachedTokens *DefArgTokens = 0)
: Ident(ident), IdentLoc(iloc), Param(param),
DefaultArgTokens(DefArgTokens) {}
};
struct TypeAndRange {
- ActionBase::TypeTy *Ty;
+ ParsedType Ty;
SourceRange Range;
};
@@ -999,7 +1052,7 @@ struct DeclaratorChunk {
/// getArray - Return a DeclaratorChunk for an array.
///
static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic,
- bool isStar, void *NumElts,
+ bool isStar, Expr *NumElts,
SourceLocation LBLoc, SourceLocation RBLoc) {
DeclaratorChunk I;
I.Kind = Array;
@@ -1020,7 +1073,7 @@ struct DeclaratorChunk {
unsigned TypeQuals, bool hasExceptionSpec,
SourceLocation ThrowLoc,
bool hasAnyExceptionSpec,
- ActionBase::TypeTy **Exceptions,
+ ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
SourceLocation LPLoc, SourceLocation RPLoc,
@@ -1104,7 +1157,7 @@ private:
AttributeList *AttrList;
/// AsmLabel - The asm label, if specified.
- ActionBase::ExprTy *AsmLabel;
+ Expr *AsmLabel;
/// InlineParams - This is a local array used for the first function decl
/// chunk to avoid going to the heap for the common case when we have one
@@ -1303,8 +1356,8 @@ public:
return false;
}
- void setAsmLabel(ActionBase::ExprTy *E) { AsmLabel = E; }
- ActionBase::ExprTy *getAsmLabel() const { return AsmLabel; }
+ void setAsmLabel(Expr *E) { AsmLabel = E; }
+ Expr *getAsmLabel() const { return AsmLabel; }
void setExtension(bool Val = true) { Extension = Val; }
bool getExtension() const { return Extension; }
@@ -1322,7 +1375,7 @@ public:
/// structure field declarators, which is basically just a bitfield size.
struct FieldDeclarator {
Declarator D;
- ActionBase::ExprTy *BitfieldSize;
+ Expr *BitfieldSize;
explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) {
BitfieldSize = 0;
}
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
new file mode 100644
index 000000000000..6a9a1bf5b608
--- /dev/null
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -0,0 +1,168 @@
+//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- 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 DelayedDiagnostic class, which is used to
+// record diagnostics that are being conditionally produced during
+// declarator parsing. Certain kinds of diagnostics --- notably
+// deprecation and access control --- are suppressed based on
+// semantic properties of the parsed declaration that aren't known
+// until it is fully parsed.
+//
+// This file also defines AccessedEntity.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H
+
+#include "clang/AST/DeclCXX.h"
+
+namespace clang {
+namespace sema {
+
+/// A declaration being accessed, together with information about how
+/// it was accessed.
+class AccessedEntity {
+public:
+ /// A member declaration found through lookup. The target is the
+ /// member.
+ enum MemberNonce { Member };
+
+ /// A hierarchy (base-to-derived or derived-to-base) conversion.
+ /// The target is the base class.
+ enum BaseNonce { Base };
+
+ bool isMemberAccess() const { return IsMember; }
+
+ AccessedEntity(ASTContext &Context,
+ MemberNonce _,
+ CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl,
+ QualType BaseObjectType)
+ : Access(FoundDecl.getAccess()), IsMember(true),
+ Target(FoundDecl.getDecl()), NamingClass(NamingClass),
+ BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) {
+ }
+
+ AccessedEntity(ASTContext &Context,
+ BaseNonce _,
+ CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass,
+ AccessSpecifier Access)
+ : Access(Access), IsMember(false),
+ Target(BaseClass),
+ NamingClass(DerivedClass),
+ Diag(0, Context.getDiagAllocator()) {
+ }
+
+ bool isQuiet() const { return Diag.getDiagID() == 0; }
+
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ // These apply to member decls...
+ NamedDecl *getTargetDecl() const { return Target; }
+ CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
+ // ...and these apply to hierarchy conversions.
+ CXXRecordDecl *getBaseClass() const {
+ assert(!IsMember); return cast<CXXRecordDecl>(Target);
+ }
+ CXXRecordDecl *getDerivedClass() const { return NamingClass; }
+
+ /// Retrieves the base object type, important when accessing
+ /// an instance member.
+ QualType getBaseObjectType() const { return BaseObjectType; }
+
+ /// Sets a diagnostic to be performed. The diagnostic is given
+ /// four (additional) arguments:
+ /// %0 - 0 if the entity was private, 1 if protected
+ /// %1 - the DeclarationName of the entity
+ /// %2 - the TypeDecl type of the naming class
+ /// %3 - the TypeDecl type of the declaring class
+ void setDiag(const PartialDiagnostic &PDiag) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ Diag = PDiag;
+ }
+ PartialDiagnostic &setDiag(unsigned DiagID) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ assert(DiagID && "creating null diagnostic");
+ Diag.Reset(DiagID);
+ return Diag;
+ }
+ const PartialDiagnostic &getDiag() const {
+ return Diag;
+ }
+
+private:
+ unsigned Access : 2;
+ bool IsMember;
+ NamedDecl *Target;
+ CXXRecordDecl *NamingClass;
+ QualType BaseObjectType;
+ PartialDiagnostic Diag;
+};
+
+/// A diagnostic message which has been conditionally emitted pending
+/// the complete parsing of the current declaration.
+class DelayedDiagnostic {
+public:
+ enum DDKind { Deprecation, Access };
+
+ unsigned char Kind; // actually a DDKind
+ bool Triggered;
+
+ SourceLocation Loc;
+
+ union {
+ /// Deprecation.
+ struct { NamedDecl *Decl; } DeprecationData;
+
+ /// Access control.
+ char AccessData[sizeof(AccessedEntity)];
+ };
+
+ void destroy() {
+ switch (Kind) {
+ case Access: getAccessData().~AccessedEntity(); break;
+ case Deprecation: break;
+ }
+ }
+
+ static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
+ NamedDecl *D) {
+ DelayedDiagnostic DD;
+ DD.Kind = Deprecation;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ DD.DeprecationData.Decl = D;
+ return DD;
+ }
+
+ static DelayedDiagnostic makeAccess(SourceLocation Loc,
+ const AccessedEntity &Entity) {
+ DelayedDiagnostic DD;
+ DD.Kind = Access;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ new (&DD.getAccessData()) AccessedEntity(Entity);
+ return DD;
+ }
+
+ AccessedEntity &getAccessData() {
+ return *reinterpret_cast<AccessedEntity*>(AccessData);
+ }
+ const AccessedEntity &getAccessData() const {
+ return *reinterpret_cast<const AccessedEntity*>(AccessData);
+ }
+};
+
+}
+}
+
+#endif
diff --git a/include/clang/Parse/Designator.h b/include/clang/Sema/Designator.h
index 255af5901819..6fe7ab24f0a2 100644
--- a/include/clang/Parse/Designator.h
+++ b/include/clang/Sema/Designator.h
@@ -7,19 +7,26 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines interfaces used to represent Designators in the parser and
-// is the input to Actions module.
+// This file defines interfaces used to represent designators (a la
+// C99 designated initializers) during parsing.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H
-#define LLVM_CLANG_PARSE_DESIGNATOR_H
+#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H
+#define LLVM_CLANG_SEMA_DESIGNATOR_H
-#include "clang/Parse/Action.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
namespace clang {
-/// Designator - This class is a discriminated union which holds the various
+class Expr;
+class IdentifierInfo;
+class Sema;
+
+/// Designator - A designator in a C99 designated initializer.
+///
+/// This class is a discriminated union which holds the various
/// different sorts of designators possible. A Designation is an array of
/// these. An example of a designator are things like this:
/// [8] .field [47] // C99 designation: 3 designators
@@ -41,12 +48,12 @@ private:
unsigned NameLoc;
};
struct ArrayDesignatorInfo {
- ActionBase::ExprTy *Index;
+ Expr *Index;
unsigned LBracketLoc;
mutable unsigned RBracketLoc;
};
struct ArrayRangeDesignatorInfo {
- ActionBase::ExprTy *Start, *End;
+ Expr *Start, *End;
unsigned LBracketLoc, EllipsisLoc;
mutable unsigned RBracketLoc;
};
@@ -79,16 +86,16 @@ public:
return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc);
}
- ActionBase::ExprTy *getArrayIndex() const {
+ Expr *getArrayIndex() const {
assert(isArrayDesignator() && "Invalid accessor");
return ArrayInfo.Index;
}
- ActionBase::ExprTy *getArrayRangeStart() const {
+ Expr *getArrayRangeStart() const {
assert(isArrayRangeDesignator() && "Invalid accessor");
return ArrayRangeInfo.Start;
}
- ActionBase::ExprTy *getArrayRangeEnd() const {
+ Expr *getArrayRangeEnd() const {
assert(isArrayRangeDesignator() && "Invalid accessor");
return ArrayRangeInfo.End;
}
@@ -126,7 +133,7 @@ public:
return D;
}
- static Designator getArray(ActionBase::ExprTy *Index,
+ static Designator getArray(Expr *Index,
SourceLocation LBracketLoc) {
Designator D;
D.Kind = ArrayDesignator;
@@ -136,8 +143,8 @@ public:
return D;
}
- static Designator getArrayRange(ActionBase::ExprTy *Start,
- ActionBase::ExprTy *End,
+ static Designator getArrayRange(Expr *Start,
+ Expr *End,
SourceLocation LBracketLoc,
SourceLocation EllipsisLoc) {
Designator D;
@@ -159,35 +166,13 @@ public:
ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
}
- /// ClearExprs - Null out any expression references, which prevents them from
- /// being 'delete'd later.
- void ClearExprs(Action &Actions) {
- switch (Kind) {
- case FieldDesignator: return;
- case ArrayDesignator:
- ArrayInfo.Index = 0;
- return;
- case ArrayRangeDesignator:
- ArrayRangeInfo.Start = 0;
- ArrayRangeInfo.End = 0;
- return;
- }
- }
+ /// ClearExprs - Null out any expression references, which prevents
+ /// them from being 'delete'd later.
+ void ClearExprs(Sema &Actions) {}
- /// FreeExprs - Release any unclaimed memory for the expressions in this
- /// designator.
- void FreeExprs(Action &Actions) {
- switch (Kind) {
- case FieldDesignator: return; // nothing to free.
- case ArrayDesignator:
- Actions.DeleteExpr(getArrayIndex());
- return;
- case ArrayRangeDesignator:
- Actions.DeleteExpr(getArrayRangeStart());
- Actions.DeleteExpr(getArrayRangeEnd());
- return;
- }
- }
+ /// FreeExprs - Release any unclaimed memory for the expressions in
+ /// this designator.
+ void FreeExprs(Sema &Actions) {}
};
@@ -221,17 +206,11 @@ public:
/// ClearExprs - Null out any expression references, which prevents them from
/// being 'delete'd later.
- void ClearExprs(Action &Actions) {
- for (unsigned i = 0, e = Designators.size(); i != e; ++i)
- Designators[i].ClearExprs(Actions);
- }
+ void ClearExprs(Sema &Actions) {}
/// FreeExprs - Release any unclaimed memory for the expressions in this
/// designation.
- void FreeExprs(Action &Actions) {
- for (unsigned i = 0, e = Designators.size(); i != e; ++i)
- Designators[i].FreeExprs(Actions);
- }
+ void FreeExprs(Sema &Actions) {}
};
} // end namespace clang
diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h
index ad42a847fa48..7be003390b10 100644
--- a/include/clang/Sema/ExternalSemaSource.h
+++ b/include/clang/Sema/ExternalSemaSource.h
@@ -13,8 +13,8 @@
#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H
-#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/Sema/ObjCMethodList.h"
namespace clang {
diff --git a/lib/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h
index 59bd834073f3..7e9d338293ee 100644
--- a/lib/Sema/IdentifierResolver.h
+++ b/include/clang/Sema/IdentifierResolver.h
@@ -16,13 +16,16 @@
#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H
#include "clang/Basic/IdentifierTable.h"
-#include "clang/Parse/Scope.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclarationName.h"
-#include "clang/AST/DeclCXX.h"
namespace clang {
+class ASTContext;
+class Decl;
+class DeclContext;
+class DeclarationName;
+class NamedDecl;
+class Scope;
+
/// IdentifierResolver - Keeps track of shadowed decls on enclosing
/// scopes. It manages the shadowing chains of declaration names and
/// implements efficent decl lookup based on a declaration name.
@@ -95,6 +98,8 @@ public:
}
friend class IdentifierResolver;
+
+ void incrementSlowCase();
public:
iterator() : Ptr(0) {}
@@ -116,18 +121,8 @@ public:
iterator& operator++() {
if (!isIterator()) // common case.
Ptr = 0;
- else {
- NamedDecl *D = **this;
- void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
- assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
- IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
-
- BaseIter I = getIterator();
- if (I != Info->decls_begin())
- *this = iterator(I-1);
- else // No more decls.
- *this = iterator();
- }
+ else
+ incrementSlowCase();
return *this;
}
@@ -169,7 +164,7 @@ public:
/// \brief Link the declaration into the chain of declarations for
/// the given identifier.
///
- /// This is a lower-level routine used by the PCH reader to link a
+ /// This is a lower-level routine used by the AST reader to link a
/// declaration into a specific IdentifierInfo before the
/// declaration actually has a name.
void AddDeclToIdentifierChain(IdentifierInfo *II, NamedDecl *D);
diff --git a/lib/Sema/SemaInit.h b/include/clang/Sema/Initialization.h
index 44c36a735bc8..0062b3a29adc 100644
--- a/lib/Sema/SemaInit.h
+++ b/include/clang/Sema/Initialization.h
@@ -10,13 +10,13 @@
// This file provides supporting data types for initialization of objects.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SEMA_INIT_H
-#define LLVM_CLANG_SEMA_INIT_H
+#ifndef LLVM_CLANG_SEMA_INITIALIZATION_H
+#define LLVM_CLANG_SEMA_INITIALIZATION_H
-#include "SemaOverload.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Overload.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
-#include "clang/Parse/Action.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
@@ -382,6 +382,8 @@ public:
return Locations[1];
}
+ bool isCopyInit() const { return Kind == SIK_Copy; }
+
/// \brief Retrieve the source range containing the locations of the open
/// and closing parentheses for value and direct initializations.
SourceRange getParenRange() const {
@@ -445,6 +447,8 @@ public:
SK_ResolveAddressOfOverloadedFunction,
/// \brief Perform a derived-to-base cast, producing an rvalue.
SK_CastDerivedToBaseRValue,
+ /// \brief Perform a derived-to-base cast, producing an xvalue.
+ SK_CastDerivedToBaseXValue,
/// \brief Perform a derived-to-base cast, producing an lvalue.
SK_CastDerivedToBaseLValue,
/// \brief Reference binding to an lvalue.
@@ -460,6 +464,8 @@ public:
SK_UserConversion,
/// \brief Perform a qualification conversion, producing an rvalue.
SK_QualificationConversionRValue,
+ /// \brief Perform a qualification conversion, producing an xvalue.
+ SK_QualificationConversionXValue,
/// \brief Perform a qualification conversion, producing an lvalue.
SK_QualificationConversionLValue,
/// \brief Perform an implicit conversion sequence.
@@ -473,7 +479,10 @@ public:
/// \brief C assignment
SK_CAssignment,
/// \brief Initialization by string
- SK_StringInit
+ SK_StringInit,
+ /// \brief An initialization that "converts" an Objective-C object
+ /// (not a point to an object) to another Objective-C object type.
+ SK_ObjCObjectConversion
};
/// \brief A single step in the initialization sequence.
@@ -616,11 +625,11 @@ public:
/// \returns an expression that performs the actual object initialization, if
/// the initialization is well-formed. Otherwise, emits diagnostics
/// and returns an invalid expression.
- Action::OwningExprResult Perform(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- Action::MultiExprArg Args,
- QualType *ResultType = 0);
+ ExprResult Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ QualType *ResultType = 0);
/// \brief Diagnose an potentially-invalid initialization sequence.
///
@@ -670,7 +679,8 @@ public:
///
/// \param IsLValue true if the result of this cast will be treated as
/// an lvalue.
- void AddDerivedToBaseCastStep(QualType BaseType, bool IsLValue);
+ void AddDerivedToBaseCastStep(QualType BaseType,
+ ExprValueKind Category);
/// \brief Add a new step binding a reference to an object.
///
@@ -702,7 +712,8 @@ public:
/// \brief Add a new step that performs a qualification conversion to the
/// given type.
- void AddQualificationConversionStep(QualType Ty, bool IsLValue);
+ void AddQualificationConversionStep(QualType Ty,
+ ExprValueKind Category);
/// \brief Add a new step that applies an implicit conversion sequence.
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
@@ -729,6 +740,10 @@ public:
/// \brief Add a string init step.
void AddStringInitStep(QualType T);
+ /// \brief Add an Objective-C object conversion step, which is
+ /// always a no-op.
+ void AddObjCObjectConversionStep(QualType T);
+
/// \brief Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;
@@ -762,4 +777,4 @@ public:
} // end namespace clang
-#endif // LLVM_CLANG_SEMA_INIT_H
+#endif // LLVM_CLANG_SEMA_INITIALIZATION_H
diff --git a/lib/Sema/Lookup.h b/include/clang/Sema/Lookup.h
index 271bb5bcd4a7..1c7720abb1e1 100644
--- a/lib/Sema/Lookup.h
+++ b/include/clang/Sema/Lookup.h
@@ -15,7 +15,8 @@
#ifndef LLVM_CLANG_SEMA_LOOKUP_H
#define LLVM_CLANG_SEMA_LOOKUP_H
-#include "Sema.h"
+#include "clang/Sema/Sema.h"
+#include "clang/AST/DeclCXX.h"
namespace clang {
@@ -125,15 +126,34 @@ public:
typedef UnresolvedSetImpl::iterator iterator;
- LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
+ LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo,
Sema::LookupNameKind LookupKind,
Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
: ResultKind(NotFound),
Paths(0),
NamingClass(0),
SemaRef(SemaRef),
- Name(Name),
- NameLoc(NameLoc),
+ NameInfo(NameInfo),
+ LookupKind(LookupKind),
+ IDNS(0),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ HideTags(true),
+ Diagnose(Redecl == Sema::NotForRedeclaration)
+ {
+ configure();
+ }
+
+ // TODO: consider whether this constructor should be restricted to take
+ // as input a const IndentifierInfo* (instead of Name),
+ // forcing other cases towards the constructor taking a DNInfo.
+ LookupResult(Sema &SemaRef, DeclarationName Name,
+ SourceLocation NameLoc, Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : ResultKind(NotFound),
+ Paths(0),
+ NamingClass(0),
+ SemaRef(SemaRef),
+ NameInfo(Name, NameLoc),
LookupKind(LookupKind),
IDNS(0),
Redecl(Redecl != Sema::NotForRedeclaration),
@@ -151,8 +171,7 @@ public:
Paths(0),
NamingClass(0),
SemaRef(Other.SemaRef),
- Name(Other.Name),
- NameLoc(Other.NameLoc),
+ NameInfo(Other.NameInfo),
LookupKind(Other.LookupKind),
IDNS(Other.IDNS),
Redecl(Other.Redecl),
@@ -165,14 +184,24 @@ public:
if (Paths) deletePaths(Paths);
}
+ /// Gets the name info to look up.
+ const DeclarationNameInfo &getLookupNameInfo() const {
+ return NameInfo;
+ }
+
+ /// \brief Sets the name info to look up.
+ void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
+ this->NameInfo = NameInfo;
+ }
+
/// Gets the name to look up.
DeclarationName getLookupName() const {
- return Name;
+ return NameInfo.getName();
}
/// \brief Sets the name to look up.
void setLookupName(DeclarationName Name) {
- this->Name = Name;
+ NameInfo.setName(Name);
}
/// Gets the kind of lookup to perform.
@@ -337,10 +366,15 @@ public:
if (ResultKind != NotFoundInCurrentInstantiation)
ResultKind = NotFound;
} else {
+ AmbiguityKind SavedAK = Ambiguity;
ResultKind = Found;
resolveKind();
-
- if (Paths && (ResultKind != Ambiguous)) {
+
+ // If we didn't make the lookup unambiguous, restore the old
+ // ambiguity kind.
+ if (ResultKind == Ambiguous) {
+ Ambiguity = SavedAK;
+ } else if (Paths) {
deletePaths(Paths);
Paths = 0;
}
@@ -426,7 +460,7 @@ public:
/// Determines whether this lookup is suppressing diagnostics.
bool isSuppressingDiagnostics() const {
- return Diagnose;
+ return !Diagnose;
}
/// Sets a 'context' source range.
@@ -444,7 +478,7 @@ public:
/// Gets the location of the identifier. This isn't always defined:
/// sometimes we're doing lookups on synthesized names.
SourceLocation getNameLoc() const {
- return NameLoc;
+ return NameInfo.getLoc();
}
/// \brief Get the Sema object that this lookup result is searching
@@ -539,19 +573,11 @@ private:
void configure();
// Sanity checks.
- void sanity() const {
- assert(ResultKind != NotFound || Decls.size() == 0);
- assert(ResultKind != Found || Decls.size() == 1);
- assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
- (Decls.size() == 1 &&
- isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl())));
- assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
- assert(ResultKind != Ambiguous || Decls.size() > 1 ||
- (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects));
- assert((Paths != NULL) == (ResultKind == Ambiguous &&
- (Ambiguity == AmbiguousBaseSubobjectTypes ||
- Ambiguity == AmbiguousBaseSubobjects)));
- }
+#ifndef NDEBUG
+ void sanity() const;
+#else
+ void sanity() const {}
+#endif
bool sanityCheckUnresolved() const {
for (iterator I = begin(), E = end(); I != E; ++I)
@@ -572,8 +598,7 @@ private:
// Parameters.
Sema &SemaRef;
- DeclarationName Name;
- SourceLocation NameLoc;
+ DeclarationNameInfo NameInfo;
SourceRange NameContextRange;
Sema::LookupNameKind LookupKind;
unsigned IDNS; // set by configure()
diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h
new file mode 100644
index 000000000000..225c13776c59
--- /dev/null
+++ b/include/clang/Sema/ObjCMethodList.h
@@ -0,0 +1,38 @@
+//===--- ObjCMethodList.h - A singly linked list of methods -----*- 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 ObjCMethodList, a singly-linked list of methods.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
+#define LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H
+
+namespace clang {
+
+class ObjCMethodDecl;
+
+/// ObjCMethodList - a linked list of methods with different signatures.
+struct ObjCMethodList {
+ ObjCMethodDecl *Method;
+ ObjCMethodList *Next;
+
+ ObjCMethodList() {
+ Method = 0;
+ Next = 0;
+ }
+ ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
+ Method = M;
+ Next = C;
+ }
+};
+
+}
+
+#endif
diff --git a/lib/Sema/SemaOverload.h b/include/clang/Sema/Overload.h
index eb4fc6581796..851d68ac4d79 100644
--- a/lib/Sema/SemaOverload.h
+++ b/include/clang/Sema/Overload.h
@@ -29,6 +29,7 @@ namespace clang {
class CXXConstructorDecl;
class CXXConversionDecl;
class FunctionDecl;
+ class Sema;
/// OverloadingResult - Capture the result of performing overload
/// resolution.
@@ -38,7 +39,16 @@ namespace clang {
OR_Ambiguous, ///< Ambiguous candidates found.
OR_Deleted ///< Succeeded, but refers to a deleted function.
};
-
+
+ enum OverloadCandidateDisplayKind {
+ /// Requests that all candidates be shown. Viable candidates will
+ /// be printed first.
+ OCD_AllCandidates,
+
+ /// Requests that only viable candidates be shown.
+ OCD_ViableCandidates
+ };
+
/// ImplicitConversionKind - The kind of implicit conversion used to
/// convert an argument to a parameter's type. The enumerator values
/// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that
@@ -104,7 +114,8 @@ namespace clang {
/// specified as separate members (rather than in an array) so that
/// we can keep the size of a standard conversion sequence to a
/// single word.
- struct StandardConversionSequence {
+ class StandardConversionSequence {
+ public:
/// First -- The first conversion can be an lvalue-to-rvalue
/// conversion, array-to-pointer conversion, or
/// function-to-pointer conversion.
@@ -314,7 +325,8 @@ namespace clang {
/// sequence, which may be a standard conversion sequence
/// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
/// or an ellipsis conversion sequence (C++ 13.3.3.1.3).
- struct ImplicitConversionSequence {
+ class ImplicitConversionSequence {
+ public:
/// Kind - The kind of implicit conversion sequence. BadConversion
/// specifies that there is no conversion from the source type to
/// the target type. AmbiguousConversion represents the unique
@@ -461,6 +473,10 @@ namespace clang {
Worse = 1
};
+ void DiagnoseAmbiguousConversion(Sema &S,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) const;
+
void DebugPrint() const;
};
@@ -611,7 +627,22 @@ namespace clang {
void clear();
~OverloadCandidateSet() { clear(); }
+
+ /// Find the best viable function on this overload set, if it exists.
+ OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
+ OverloadCandidateSet::iterator& Best);
+
+ void NoteCandidates(Sema &S,
+ OverloadCandidateDisplayKind OCD,
+ Expr **Args, unsigned NumArgs,
+ const char *Opc = 0,
+ SourceLocation Loc = SourceLocation());
};
+
+ bool isBetterOverloadCandidate(Sema &S,
+ const OverloadCandidate& Cand1,
+ const OverloadCandidate& Cand2,
+ SourceLocation Loc);
} // end namespace clang
#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
new file mode 100644
index 000000000000..7739f3a5d229
--- /dev/null
+++ b/include/clang/Sema/Ownership.h
@@ -0,0 +1,462 @@
+//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains classes for managing ownership of Stmt and Expr nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
+#define LLVM_CLANG_SEMA_OWNERSHIP_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+//===----------------------------------------------------------------------===//
+// OpaquePtr
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ class Attr;
+ class CXXBaseOrMemberInitializer;
+ class CXXBaseSpecifier;
+ class Decl;
+ class DeclGroupRef;
+ class Expr;
+ class NestedNameSpecifier;
+ class QualType;
+ class Sema;
+ class Stmt;
+ class TemplateName;
+ class TemplateParameterList;
+
+ /// OpaquePtr - This is a very simple POD type that wraps a pointer that the
+ /// Parser doesn't know about but that Sema or another client does. The UID
+ /// template argument is used to make sure that "Decl" pointers are not
+ /// compatible with "Type" pointers for example.
+ template <class PtrTy>
+ class OpaquePtr {
+ void *Ptr;
+ explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
+
+ typedef llvm::PointerLikeTypeTraits<PtrTy> Traits;
+
+ public:
+ OpaquePtr() : Ptr(0) {}
+
+ static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
+
+ template <typename T> T* getAs() const {
+ return get();
+ }
+
+ template <typename T> T getAsVal() const {
+ return get();
+ }
+
+ PtrTy get() const {
+ return Traits::getFromVoidPointer(Ptr);
+ }
+
+ void set(PtrTy P) {
+ Ptr = Traits::getAsVoidPointer(P);
+ }
+
+ operator bool() const { return Ptr != 0; }
+
+ void *getAsOpaquePtr() const { return Ptr; }
+ static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
+ };
+
+ /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
+ /// in a union.
+ template <class T> struct UnionOpaquePtr {
+ void *Ptr;
+
+ static UnionOpaquePtr make(OpaquePtr<T> P) {
+ UnionOpaquePtr OP = { P.getAsOpaquePtr() };
+ return OP;
+ }
+
+ OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
+ operator OpaquePtr<T>() const { return get(); }
+
+ UnionOpaquePtr &operator=(OpaquePtr<T> P) {
+ Ptr = P.getAsOpaquePtr();
+ return *this;
+ }
+ };
+}
+
+namespace llvm {
+ template <class T>
+ class PointerLikeTypeTraits<clang::OpaquePtr<T> > {
+ public:
+ static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
+ // FIXME: Doesn't work? return P.getAs< void >();
+ return P.getAsOpaquePtr();
+ }
+ static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
+ return clang::OpaquePtr<T>::getFromOpaquePtr(P);
+ }
+ enum { NumLowBitsAvailable = 0 };
+ };
+}
+
+
+
+// -------------------------- About Move Emulation -------------------------- //
+// The smart pointer classes in this file attempt to emulate move semantics
+// as they appear in C++0x with rvalue references. Since C++03 doesn't have
+// rvalue references, some tricks are needed to get similar results.
+// Move semantics in C++0x have the following properties:
+// 1) "Moving" means transferring the value of an object to another object,
+// similar to copying, but without caring what happens to the old object.
+// In particular, this means that the new object can steal the old object's
+// resources instead of creating a copy.
+// 2) Since moving can modify the source object, it must either be explicitly
+// requested by the user, or the modifications must be unnoticeable.
+// 3) As such, C++0x moving is only allowed in three contexts:
+// * By explicitly using std::move() to request it.
+// * From a temporary object, since that object cannot be accessed
+// afterwards anyway, thus making the state unobservable.
+// * On function return, since the object is not observable afterwards.
+//
+// To sum up: moving from a named object should only be possible with an
+// explicit std::move(), or on function return. Moving from a temporary should
+// be implicitly done. Moving from a const object is forbidden.
+//
+// The emulation is not perfect, and has the following shortcomings:
+// * move() is not in namespace std.
+// * move() is required on function return.
+// * There are difficulties with implicit conversions.
+// * Microsoft's compiler must be given the /Za switch to successfully compile.
+//
+// -------------------------- Implementation -------------------------------- //
+// The move emulation relies on the peculiar reference binding semantics of
+// C++03: as a rule, a non-const reference may not bind to a temporary object,
+// except for the implicit object parameter in a member function call, which
+// can refer to a temporary even when not being const.
+// The moveable object has five important functions to facilitate moving:
+// * A private, unimplemented constructor taking a non-const reference to its
+// own class. This constructor serves a two-fold purpose.
+// - It prevents the creation of a copy constructor that takes a const
+// reference. Temporaries would be able to bind to the argument of such a
+// constructor, and that would be bad.
+// - Named objects will bind to the non-const reference, but since it's
+// private, this will fail to compile. This prevents implicit moving from
+// named objects.
+// There's also a copy assignment operator for the same purpose.
+// * An implicit, non-const conversion operator to a special mover type. This
+// type represents the rvalue reference of C++0x. Being a non-const member,
+// its implicit this parameter can bind to temporaries.
+// * A constructor that takes an object of this mover type. This constructor
+// performs the actual move operation. There is an equivalent assignment
+// operator.
+// There is also a free move() function that takes a non-const reference to
+// an object and returns a temporary. Internally, this function uses explicit
+// constructor calls to move the value from the referenced object to the return
+// value.
+//
+// There are now three possible scenarios of use.
+// * Copying from a const object. Constructor overload resolution will find the
+// non-const copy constructor, and the move constructor. The first is not
+// viable because the const object cannot be bound to the non-const reference.
+// The second fails because the conversion to the mover object is non-const.
+// Moving from a const object fails as intended.
+// * Copying from a named object. Constructor overload resolution will select
+// the non-const copy constructor, but fail as intended, because this
+// constructor is private.
+// * Copying from a temporary. Constructor overload resolution cannot select
+// the non-const copy constructor, because the temporary cannot be bound to
+// the non-const reference. It thus selects the move constructor. The
+// temporary can be bound to the implicit this parameter of the conversion
+// operator, because of the special binding rule. Construction succeeds.
+// Note that the Microsoft compiler, as an extension, allows binding
+// temporaries against non-const references. The compiler thus selects the
+// non-const copy constructor and fails, because the constructor is private.
+// Passing /Za (disable extensions) disables this behaviour.
+// The free move() function is used to move from a named object.
+//
+// Note that when passing an object of a different type (the classes below
+// have OwningResult and OwningPtr, which should be mixable), you get a problem.
+// Argument passing and function return use copy initialization rules. The
+// effect of this is that, when the source object is not already of the target
+// type, the compiler will first seek a way to convert the source object to the
+// target type, and only then attempt to copy the resulting object. This means
+// that when passing an OwningResult where an OwningPtr is expected, the
+// compiler will first seek a conversion from OwningResult to OwningPtr, then
+// copy the OwningPtr. The resulting conversion sequence is:
+// OwningResult object -> ResultMover -> OwningResult argument to
+// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr
+// This conversion sequence is too complex to be allowed. Thus the special
+// move_* functions, which help the compiler out with some explicit
+// conversions.
+
+namespace clang {
+ // Basic
+ class DiagnosticBuilder;
+
+ // Determines whether the low bit of the result pointer for the
+ // given UID is always zero. If so, ActionResult will use that bit
+ // for it's "invalid" flag.
+ template<class Ptr>
+ struct IsResultPtrLowBitFree {
+ static const bool value = false;
+ };
+
+ /// ActionResult - This structure is used while parsing/acting on
+ /// expressions, stmts, etc. It encapsulates both the object returned by
+ /// the action, plus a sense of whether or not it is valid.
+ /// When CompressInvalid is true, the "invalid" flag will be
+ /// stored in the low bit of the Val pointer.
+ template<class PtrTy,
+ bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
+ class ActionResult {
+ PtrTy Val;
+ bool Invalid;
+
+ public:
+ ActionResult(bool Invalid = false)
+ : Val(PtrTy()), Invalid(Invalid) {}
+ ActionResult(PtrTy val) : Val(val), Invalid(false) {}
+ ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *);
+ ActionResult(volatile void *);
+
+ bool isInvalid() const { return Invalid; }
+ bool isUsable() const { return !Invalid && Val; }
+
+ PtrTy get() const { return Val; }
+ PtrTy release() const { return Val; }
+ PtrTy take() const { return Val; }
+ template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) { Val = V; }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ Val = RHS;
+ Invalid = false;
+ return *this;
+ }
+ };
+
+ // This ActionResult partial specialization places the "invalid"
+ // flag into the low bit of the pointer.
+ template<typename PtrTy>
+ class ActionResult<PtrTy, true> {
+ // A pointer whose low bit is 1 if this result is invalid, 0
+ // otherwise.
+ uintptr_t PtrWithInvalid;
+ typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits;
+ public:
+ ActionResult(bool Invalid = false)
+ : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { }
+
+ ActionResult(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+ ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { }
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *);
+ ActionResult(volatile void *);
+
+ bool isInvalid() const { return PtrWithInvalid & 0x01; }
+ bool isUsable() const { return PtrWithInvalid > 0x01; }
+
+ PtrTy get() const {
+ void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
+ return PtrTraits::getFromVoidPointer(VP);
+ }
+ PtrTy take() const { return get(); }
+ PtrTy release() const { return get(); }
+ template <typename T> T *takeAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ void *VP = PtrTraits::getAsVoidPointer(RHS);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ return *this;
+ }
+ };
+
+ /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
+ /// the individual pointers, not the array holding them.
+ template <typename PtrTy> class ASTMultiPtr;
+
+ template <class PtrTy>
+ class ASTMultiPtr {
+ PtrTy *Nodes;
+ unsigned Count;
+
+ public:
+ // Normal copying implicitly defined
+ ASTMultiPtr() : Nodes(0), Count(0) {}
+ explicit ASTMultiPtr(Sema &) : Nodes(0), Count(0) {}
+ ASTMultiPtr(Sema &, PtrTy *nodes, unsigned count)
+ : Nodes(nodes), Count(count) {}
+ // Fake mover in Parse/AstGuard.h needs this:
+ ASTMultiPtr(PtrTy *nodes, unsigned count) : Nodes(nodes), Count(count) {}
+
+ /// Access to the raw pointers.
+ PtrTy *get() const { return Nodes; }
+
+ /// Access to the count.
+ unsigned size() const { return Count; }
+
+ PtrTy *release() {
+ return Nodes;
+ }
+ };
+
+ class ParsedTemplateArgument;
+
+ class ASTTemplateArgsPtr {
+ ParsedTemplateArgument *Args;
+ mutable unsigned Count;
+
+ public:
+ ASTTemplateArgsPtr(Sema &actions, ParsedTemplateArgument *args,
+ unsigned count) :
+ Args(args), Count(count) { }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) :
+ Args(Other.Args), Count(Other.Count) {
+ }
+
+ // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'.
+ ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) {
+ Args = Other.Args;
+ Count = Other.Count;
+ return *this;
+ }
+
+ ParsedTemplateArgument *getArgs() const { return Args; }
+ unsigned size() const { return Count; }
+
+ void reset(ParsedTemplateArgument *args, unsigned count) {
+ Args = args;
+ Count = count;
+ }
+
+ const ParsedTemplateArgument &operator[](unsigned Arg) const;
+
+ ParsedTemplateArgument *release() const {
+ return Args;
+ }
+ };
+
+ /// \brief A small vector that owns a set of AST nodes.
+ template <class PtrTy, unsigned N = 8>
+ class ASTOwningVector : public llvm::SmallVector<PtrTy, N> {
+ ASTOwningVector(ASTOwningVector &); // do not implement
+ ASTOwningVector &operator=(ASTOwningVector &); // do not implement
+
+ public:
+ explicit ASTOwningVector(Sema &Actions)
+ { }
+
+ PtrTy *take() {
+ return &this->front();
+ }
+
+ template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); }
+ };
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef ASTOwningVector<Stmt*, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef ASTOwningVector<Expr*, 12> ExprVector;
+
+ template <class T, unsigned N> inline
+ ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) {
+ return ASTMultiPtr<T>(vec.take(), vec.size());
+ }
+
+ // These versions are hopefully no-ops.
+ template <class T, bool C>
+ inline ActionResult<T,C> move(ActionResult<T,C> &ptr) {
+ return ptr;
+ }
+
+ template <class T> inline
+ ASTMultiPtr<T>& move(ASTMultiPtr<T> &ptr) {
+ return ptr;
+ }
+
+ // We can re-use the low bit of expression, statement, base, and
+ // member-initializer pointers for the "invalid" flag of
+ // ActionResult.
+ template<> struct IsResultPtrLowBitFree<Expr*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<Stmt*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXBaseOrMemberInitializer*> {
+ static const bool value = true;
+ };
+
+ /// An opaque type for threading parsed type information through the
+ /// parser.
+ typedef OpaquePtr<QualType> ParsedType;
+ typedef UnionOpaquePtr<QualType> UnionParsedType;
+
+ typedef ActionResult<Expr*> ExprResult;
+ typedef ActionResult<Stmt*> StmtResult;
+ typedef ActionResult<ParsedType> TypeResult;
+ typedef ActionResult<CXXBaseSpecifier*> BaseResult;
+ typedef ActionResult<CXXBaseOrMemberInitializer*> MemInitResult;
+
+ typedef ActionResult<Decl*> DeclResult;
+ typedef OpaquePtr<TemplateName> ParsedTemplateTy;
+
+ inline Expr *move(Expr *E) { return E; }
+ inline Stmt *move(Stmt *S) { return S; }
+
+ typedef ASTMultiPtr<Expr*> MultiExprArg;
+ typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg;
+
+ inline ExprResult ExprError() { return ExprResult(true); }
+ inline StmtResult StmtError() { return StmtResult(true); }
+
+ inline ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
+ inline StmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); }
+
+ inline ExprResult ExprEmpty() { return ExprResult(false); }
+ inline StmtResult StmtEmpty() { return StmtResult(false); }
+
+ inline Expr *AssertSuccess(ExprResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+
+ inline Stmt *AssertSuccess(StmtResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+}
+
+#endif
diff --git a/include/clang/Parse/Template.h b/include/clang/Sema/ParsedTemplate.h
index 84f4ed96b4c3..da68a494bf7b 100644
--- a/include/clang/Parse/Template.h
+++ b/include/clang/Sema/ParsedTemplate.h
@@ -1,4 +1,4 @@
-//===--- Template.h - Template Parsing Data Types -------------------------===//
+//===--- ParsedTemplate.h - Template Parsing Data Types -------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,11 +11,11 @@
// templates.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_TEMPLATE_H
-#define LLVM_CLANG_PARSE_TEMPLATE_H
+#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Ownership.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
#include <cassert>
namespace clang {
@@ -52,9 +52,10 @@ namespace clang {
///
/// \param TemplateLoc the location of the template name.
ParsedTemplateArgument(const CXXScopeSpec &SS,
- ActionBase::TemplateTy Template,
+ ParsedTemplateTy Template,
SourceLocation TemplateLoc)
- : Kind(ParsedTemplateArgument::Template), Arg(Template.get()),
+ : Kind(ParsedTemplateArgument::Template),
+ Arg(Template.getAsOpaquePtr()),
Loc(TemplateLoc), SS(SS) { }
/// \brief Determine whether the given template argument is invalid.
@@ -64,21 +65,21 @@ namespace clang {
KindType getKind() const { return Kind; }
/// \brief Retrieve the template type argument's type.
- ActionBase::TypeTy *getAsType() const {
+ ParsedType getAsType() const {
assert(Kind == Type && "Not a template type argument");
- return Arg;
+ return ParsedType::getFromOpaquePtr(Arg);
}
/// \brief Retrieve the non-type template argument's expression.
- ActionBase::ExprTy *getAsExpr() const {
+ Expr *getAsExpr() const {
assert(Kind == NonType && "Not a non-type template argument");
- return Arg;
+ return static_cast<Expr*>(Arg);
}
/// \brief Retrieve the template template argument's template name.
- ActionBase::TemplateTy getAsTemplate() const {
+ ParsedTemplateTy getAsTemplate() const {
assert(Kind == Template && "Not a template template argument");
- return ActionBase::TemplateTy::make(Arg);
+ return ParsedTemplateTy::getFromOpaquePtr(Arg);
}
/// \brief Retrieve the location of the template argument.
@@ -128,8 +129,8 @@ namespace clang {
OverloadedOperatorKind Operator;
/// The declaration of the template corresponding to the
- /// template-name. This is an Action::TemplateTy.
- void *Template;
+ /// template-name.
+ ParsedTemplateTy Template;
/// The kind of template that Template refers to.
TemplateNameKind Kind;
@@ -161,18 +162,6 @@ namespace clang {
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 {
diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/Sema/PrettyDeclStackTrace.h
new file mode 100644
index 000000000000..b78a1c01e5e3
--- /dev/null
+++ b/include/clang/Sema/PrettyDeclStackTrace.h
@@ -0,0 +1,46 @@
+//===- PrettyDeclStackTrace.h - Stack trace for decl processing -*- 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 an llvm::PrettyStackTraceEntry object for showing
+// that a particular declaration was being processed when a crash
+// occurred.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H
+#define LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+namespace clang {
+
+class Decl;
+class Sema;
+class SourceManager;
+
+/// PrettyDeclStackTraceEntry - If a crash occurs in the parser while
+/// parsing something related to a declaration, include that
+/// declaration in the stack trace.
+class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry {
+ Sema &S;
+ Decl *TheDecl;
+ SourceLocation Loc;
+ const char *Message;
+
+public:
+ PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, const char *Msg)
+ : S(S), TheDecl(D), Loc(Loc), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+}
+
+#endif
diff --git a/include/clang/Parse/Scope.h b/include/clang/Sema/Scope.h
index 023f40d3957c..4229c6c62748 100644
--- a/include/clang/Parse/Scope.h
+++ b/include/clang/Sema/Scope.h
@@ -11,14 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_PARSE_SCOPE_H
-#define LLVM_CLANG_PARSE_SCOPE_H
+#ifndef LLVM_CLANG_SEMA_SCOPE_H
+#define LLVM_CLANG_SEMA_SCOPE_H
-#include "clang/Parse/Action.h"
#include "llvm/ADT/SmallPtrSet.h"
namespace clang {
+class Decl;
+class UsingDirectiveDecl;
+
/// Scope - A scope is a transient data structure that is used while parsing the
/// program. It assists with resolving identifiers to the appropriate
/// declaration.
@@ -72,11 +74,7 @@ public:
/// ObjCMethodScope - This scope corresponds to an Objective-C method body.
/// It always has FnScope and DeclScope set as well.
- ObjCMethodScope = 0x400,
-
- /// ElseScope - This scope corresponds to an 'else' scope of an if/then/else
- /// statement.
- ElseScope = 0x800
+ ObjCMethodScope = 0x400
};
private:
/// The parent scope for this scope. This is null for the translation-unit
@@ -121,7 +119,7 @@ private:
/// popped, these declarations are removed from the IdentifierTable's notion
/// of current declaration. It is up to the current Action implementation to
/// implement these semantics.
- typedef llvm::SmallPtrSet<Action::DeclPtrTy, 32> DeclSetTy;
+ typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy;
DeclSetTy DeclsInScope;
/// Entity - The entity with which this scope is associated. For
@@ -130,7 +128,7 @@ private:
/// maintained by the Action implementation.
void *Entity;
- typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy;
+ typedef llvm::SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy;
UsingDirectivesTy UsingDirectives;
/// \brief The number of errors at the start of the given scope.
@@ -199,17 +197,17 @@ public:
decl_iterator decl_end() const { return DeclsInScope.end(); }
bool decl_empty() const { return DeclsInScope.empty(); }
- void AddDecl(Action::DeclPtrTy D) {
+ void AddDecl(Decl *D) {
DeclsInScope.insert(D);
}
- void RemoveDecl(Action::DeclPtrTy D) {
+ void RemoveDecl(Decl *D) {
DeclsInScope.erase(D);
}
/// isDeclScope - Return true if this is the scope that the specified decl is
/// declared in.
- bool isDeclScope(Action::DeclPtrTy D) {
+ bool isDeclScope(Decl *D) {
return DeclsInScope.count(D) != 0;
}
@@ -270,7 +268,7 @@ public:
typedef UsingDirectivesTy::iterator udir_iterator;
typedef UsingDirectivesTy::const_iterator const_udir_iterator;
- void PushUsingDirective(Action::DeclPtrTy UDir) {
+ void PushUsingDirective(UsingDirectiveDecl *UDir) {
UsingDirectives.push_back(UDir);
}
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
new file mode 100644
index 000000000000..50cfa9bb5672
--- /dev/null
+++ b/include/clang/Sema/ScopeInfo.h
@@ -0,0 +1,137 @@
+//===--- ScopeInfo.h - Information about a semantic context -----*- 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 FunctionScopeInfo and BlockScopeInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
+#define LLVM_CLANG_SEMA_SCOPE_INFO_H
+
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class BlockDecl;
+class IdentifierInfo;
+class LabelStmt;
+class ReturnStmt;
+class Scope;
+class SwitchStmt;
+
+namespace sema {
+
+/// \brief Retains information about a function, method, or block that is
+/// currently being parsed.
+class FunctionScopeInfo {
+public:
+
+ /// \brief Whether this scope information structure defined information for
+ /// a block.
+ bool IsBlockInfo;
+
+ /// \brief Whether this function contains a VLA, @try, try, C++
+ /// initializer, or anything else that can't be jumped past.
+ bool HasBranchProtectedScope;
+
+ /// \brief Whether this function contains any switches or direct gotos.
+ bool HasBranchIntoScope;
+
+ /// \brief Whether this function contains any indirect gotos.
+ bool HasIndirectGoto;
+
+ /// \brief The number of errors that had occurred before starting this
+ /// function or block.
+ unsigned NumErrorsAtStartOfFunction;
+
+ /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
+ /// it (which acts like the label decl in some ways). Forward referenced
+ /// labels have a LabelStmt created for them with a null location & SubStmt.
+ llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
+
+ /// SwitchStack - This is the current set of active switch statements in the
+ /// block.
+ llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
+
+ /// \brief The list of return statements that occur within the function or
+ /// block, if there is any chance of applying the named return value
+ /// optimization.
+ llvm::SmallVector<ReturnStmt *, 4> Returns;
+
+ void setHasBranchIntoScope() {
+ HasBranchIntoScope = true;
+ }
+
+ void setHasBranchProtectedScope() {
+ HasBranchProtectedScope = true;
+ }
+
+ void setHasIndirectGoto() {
+ HasIndirectGoto = true;
+ }
+
+ bool NeedsScopeChecking() const {
+ return HasIndirectGoto ||
+ (HasBranchProtectedScope && HasBranchIntoScope);
+ }
+
+ FunctionScopeInfo(unsigned NumErrors)
+ : IsBlockInfo(false),
+ HasBranchProtectedScope(false),
+ HasBranchIntoScope(false),
+ HasIndirectGoto(false),
+ NumErrorsAtStartOfFunction(NumErrors) { }
+
+ virtual ~FunctionScopeInfo();
+
+ /// \brief Clear out the information in this function scope, making it
+ /// suitable for reuse.
+ void Clear(unsigned NumErrors);
+
+ static bool classof(const FunctionScopeInfo *FSI) { return true; }
+};
+
+/// \brief Retains information about a block that is currently being parsed.
+class BlockScopeInfo : public FunctionScopeInfo {
+public:
+ bool hasBlockDeclRefExprs;
+
+ BlockDecl *TheDecl;
+
+ /// TheScope - This is the scope for the block itself, which contains
+ /// arguments etc.
+ Scope *TheScope;
+
+ /// ReturnType - The return type of the block, or null if the block
+ /// signature didn't provide an explicit return type.
+ QualType ReturnType;
+
+ /// BlockType - The function type of the block, if one was given.
+ /// Its return type may be BuiltinType::Dependent.
+ QualType FunctionType;
+
+ BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
+ : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
+ TheDecl(Block), TheScope(BlockScope)
+ {
+ IsBlockInfo = true;
+ }
+
+ virtual ~BlockScopeInfo();
+
+ static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
+ static bool classof(const BlockScopeInfo *BSI) { return true; }
+};
+
+}
+}
+
+#endif
diff --git a/lib/Sema/Sema.h b/include/clang/Sema/Sema.h
index 8336918c134e..4741028cb0c9 100644
--- a/lib/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -12,178 +12,142 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_SEMA_H
-#define LLVM_CLANG_AST_SEMA_H
-
-#include "IdentifierResolver.h"
-#include "CXXFieldCollector.h"
-#include "SemaOverload.h"
-#include "SemaTemplate.h"
-#include "AnalysisBasedWarnings.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclBase.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/FullExpr.h"
-#include "clang/Parse/Action.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SmallPtrSet.h"
+#ifndef LLVM_CLANG_SEMA_SEMA_H
+#define LLVM_CLANG_SEMA_SEMA_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/OperationKinds.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include <deque>
-#include <list>
-#include <map>
#include <string>
-#include <vector>
namespace llvm {
class APSInt;
+ template <typename ValueT> struct DenseMapInfo;
+ template <typename ValueT, typename ValueInfoT> class DenseSet;
}
namespace clang {
- class ASTContext;
+ class ADLResult;
class ASTConsumer;
+ class ASTContext;
+ class ArrayType;
+ class AttributeList;
+ class BlockDecl;
+ class CXXBasePath;
+ class CXXBasePaths;
+ typedef llvm::SmallVector<CXXBaseSpecifier*, 4> CXXCastPath;
+ class CXXConstructorDecl;
+ class CXXConversionDecl;
+ class CXXDestructorDecl;
+ class CXXFieldCollector;
+ class CXXMemberCallExpr;
+ class CXXMethodDecl;
+ class CXXScopeSpec;
+ class CXXTemporary;
+ class CXXTryStmt;
+ class CallExpr;
+ class ClassTemplateDecl;
+ class ClassTemplatePartialSpecializationDecl;
+ class ClassTemplateSpecializationDecl;
class CodeCompleteConsumer;
- class Preprocessor;
+ class CodeCompletionResult;
class Decl;
+ class DeclAccessPair;
class DeclContext;
- class DeclSpec;
- class ExternalSemaSource;
- class NamedDecl;
- class Stmt;
- class Expr;
- class InitListExpr;
- class ParenListExpr;
- class DesignatedInitExpr;
- class CallExpr;
class DeclRefExpr;
- class UnresolvedLookupExpr;
- class UnresolvedMemberExpr;
- class VarDecl;
- class ParmVarDecl;
- class TypedefDecl;
+ class DeclaratorDecl;
+ class DeducedTemplateArgument;
+ class DependentDiagnostic;
+ class DesignatedInitExpr;
+ class Designation;
+ class EnumConstantDecl;
+ class Expr;
+ class ExtVectorType;
+ class ExternalSemaSource;
+ class FormatAttr;
+ class FriendDecl;
+ class FullExpr;
class FunctionDecl;
- class QualType;
- class LangOptions;
- class Token;
+ class FunctionProtoType;
+ class FunctionTemplateDecl;
+ class ImplicitConversionSequence;
+ class InitListExpr;
+ class InitializationKind;
+ class InitializationSequence;
+ class InitializedEntity;
class IntegerLiteral;
- class StringLiteral;
- class ArrayType;
class LabelStmt;
- class SwitchStmt;
- class CXXTryStmt;
- class ExtVectorType;
- class TypedefDecl;
- class TemplateDecl;
- class TemplateArgument;
- class TemplateArgumentLoc;
- class TemplateArgumentList;
- class TemplateParameterList;
- class TemplateTemplateParmDecl;
- class ClassTemplatePartialSpecializationDecl;
- class ClassTemplateDecl;
- class ObjCInterfaceDecl;
+ class LangOptions;
+ class LocalInstantiationScope;
+ class LookupResult;
+ class MacroInfo;
+ class MultiLevelTemplateArgumentList;
+ class NamedDecl;
+ class NonNullAttr;
+ class ObjCCategoryDecl;
+ class ObjCCategoryImplDecl;
class ObjCCompatibleAliasDecl;
- class ObjCProtocolDecl;
+ class ObjCContainerDecl;
class ObjCImplDecl;
class ObjCImplementationDecl;
- class ObjCCategoryImplDecl;
- class ObjCCategoryDecl;
+ class ObjCInterfaceDecl;
class ObjCIvarDecl;
+ template <class T> class ObjCList;
class ObjCMethodDecl;
class ObjCPropertyDecl;
- class ObjCContainerDecl;
+ class ObjCProtocolDecl;
+ class OverloadCandidateSet;
+ class ParenListExpr;
+ class ParmVarDecl;
+ class Preprocessor;
class PseudoDestructorTypeStorage;
- class FunctionProtoType;
- class CXXBasePath;
- class CXXBasePaths;
- class CXXTemporary;
- class LookupResult;
- class InitializedEntity;
- class InitializationKind;
- class InitializationSequence;
- class VisibleDeclConsumer;
+ class QualType;
+ class StandardConversionSequence;
+ class Stmt;
+ class StringLiteral;
+ class SwitchStmt;
class TargetAttributesSema;
- class ADLResult;
-
-/// \brief Retains information about a function, method, or block that is
-/// currently being parsed.
-struct FunctionScopeInfo {
- /// \brief Whether this scope information structure defined information for
- /// a block.
- bool IsBlockInfo;
-
- /// \brief Set true when a function, method contains a VLA or ObjC try block,
- /// which introduce scopes that need to be checked for goto conditions. If a
- /// function does not contain this, then it need not have the jump checker run
- /// on it.
- bool NeedsScopeChecking;
-
- /// \brief The number of errors that had occurred before starting this
- /// function or block.
- unsigned NumErrorsAtStartOfFunction;
-
- /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
- /// it (which acts like the label decl in some ways). Forward referenced
- /// labels have a LabelStmt created for them with a null location & SubStmt.
- llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
-
- /// SwitchStack - This is the current set of active switch statements in the
- /// block.
- llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
-
- /// \brief The list of return statements that occur within the function or
- /// block, if there is any chance of applying the named return value
- /// optimization.
- llvm::SmallVector<ReturnStmt *, 4> Returns;
-
- FunctionScopeInfo(unsigned NumErrors)
- : IsBlockInfo(false), NeedsScopeChecking(false),
- NumErrorsAtStartOfFunction(NumErrors) { }
-
- virtual ~FunctionScopeInfo();
-
- /// \brief Clear out the information in this function scope, making it
- /// suitable for reuse.
- void Clear(unsigned NumErrors);
-
- static bool classof(const FunctionScopeInfo *FSI) { return true; }
-};
-
-
-/// \brief Retains information about a block that is currently being parsed.
-struct BlockScopeInfo : FunctionScopeInfo {
- bool hasBlockDeclRefExprs;
-
- BlockDecl *TheDecl;
-
- /// TheScope - This is the scope for the block itself, which contains
- /// arguments etc.
- Scope *TheScope;
-
- /// ReturnType - The return type of the block, or null if the block
- /// signature didn't provide an explicit return type.
- QualType ReturnType;
-
- /// BlockType - The function type of the block, if one was given.
- /// Its return type may be BuiltinType::Dependent.
- QualType FunctionType;
-
- BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
- : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
- TheDecl(Block), TheScope(BlockScope)
- {
- IsBlockInfo = true;
- }
-
- virtual ~BlockScopeInfo();
+ class TemplateArgument;
+ class TemplateArgumentList;
+ class TemplateArgumentListBuilder;
+ class TemplateArgumentLoc;
+ class TemplateDecl;
+ class TemplateParameterList;
+ class TemplatePartialOrderingContext;
+ class TemplateTemplateParmDecl;
+ class Token;
+ class TypedefDecl;
+ class UnqualifiedId;
+ class UnresolvedLookupExpr;
+ class UnresolvedMemberExpr;
+ class UnresolvedSetImpl;
+ class UnresolvedSetIterator;
+ class UsingDecl;
+ class UsingShadowDecl;
+ class ValueDecl;
+ class VarDecl;
+ class VisibilityAttr;
+ class VisibleDeclConsumer;
- static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
- static bool classof(const BlockScopeInfo *BSI) { return true; }
-};
+namespace sema {
+ class AccessedEntity;
+ class BlockScopeInfo;
+ class DelayedDiagnostic;
+ class FunctionScopeInfo;
+ class TemplateDeductionInfo;
+}
/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
/// parsing.
@@ -210,7 +174,7 @@ public:
QualType getType() const { return getCanonicalTypeInternal(); }
TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; }
- virtual void getAsStringInternal(std::string &Str,
+ void getAsStringInternal(std::string &Str,
const PrintingPolicy &Policy) const;
static bool classof(const Type *T) {
@@ -220,11 +184,22 @@ public:
};
/// Sema - This implements semantic analysis and AST building for C.
-class Sema : public Action {
+class Sema {
Sema(const Sema&); // DO NOT IMPLEMENT
void operator=(const Sema&); // DO NOT IMPLEMENT
mutable const TargetAttributesSema* TheTargetAttributesSema;
public:
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+ typedef OpaquePtr<QualType> TypeTy;
+ typedef Attr AttrTy;
+ typedef CXXBaseSpecifier BaseTy;
+ typedef CXXBaseOrMemberInitializer MemInitTy;
+ typedef Expr ExprTy;
+ typedef Stmt StmtTy;
+ typedef TemplateParameterList TemplateParamsTy;
+ typedef NestedNameSpecifier CXXScopeTy;
+
const LangOptions &LangOpts;
Preprocessor &PP;
ASTContext &Context;
@@ -273,16 +248,16 @@ public:
/// of 0 indicates default alignment.
void *PackContext; // Really a "PragmaPackStack*"
- /// \brief Stack containing information about each of the nested function,
- /// block, and method scopes that are currently active.
- llvm::SmallVector<FunctionScopeInfo *, 4> FunctionScopes;
+ /// VisContext - Manages the stack for #pragma GCC visibility.
+ void *VisContext; // Really a "PragmaVisStack*"
- /// \brief Cached function scope object used for the top function scope
- /// and when there is no function scope (in error cases).
+ /// \brief Stack containing information about each of the nested
+ /// function, block, and method scopes that are currently active.
///
- /// This should never be accessed directly; rather, it's address will be
- /// pushed into \c FunctionScopes when we want to re-use it.
- FunctionScopeInfo TopFunctionScope;
+ /// This array is never empty. Clients should ignore the first
+ /// element, which is used to cache a single FunctionScopeInfo
+ /// that's used to parse every top-level function.
+ llvm::SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
/// ExprTemporaries - This is the stack of temporaries that are created by
/// the current full expression.
@@ -331,142 +306,15 @@ public:
llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls;
/// \brief All the tentative definitions encountered in the TU.
- std::vector<VarDecl *> TentativeDefinitions;
-
- /// \brief The set of static functions seen so far that have not been used.
- std::vector<FunctionDecl*> UnusedStaticFuncs;
-
- class AccessedEntity {
- public:
- /// A member declaration found through lookup. The target is the
- /// member.
- enum MemberNonce { Member };
-
- /// A hierarchy (base-to-derived or derived-to-base) conversion.
- /// The target is the base class.
- enum BaseNonce { Base };
-
- bool isMemberAccess() const { return IsMember; }
-
- AccessedEntity(ASTContext &Context,
- MemberNonce _,
- CXXRecordDecl *NamingClass,
- DeclAccessPair FoundDecl,
- QualType BaseObjectType)
- : Access(FoundDecl.getAccess()), IsMember(true),
- Target(FoundDecl.getDecl()), NamingClass(NamingClass),
- BaseObjectType(BaseObjectType), Diag(0, Context.getDiagAllocator()) {
- }
-
- AccessedEntity(ASTContext &Context,
- BaseNonce _,
- CXXRecordDecl *BaseClass,
- CXXRecordDecl *DerivedClass,
- AccessSpecifier Access)
- : Access(Access), IsMember(false),
- Target(BaseClass), NamingClass(DerivedClass),
- Diag(0, Context.getDiagAllocator()) {
- }
-
- bool isQuiet() const { return Diag.getDiagID() == 0; }
-
- AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
-
- // These apply to member decls...
- NamedDecl *getTargetDecl() const { return Target; }
- CXXRecordDecl *getNamingClass() const { return NamingClass; }
-
- // ...and these apply to hierarchy conversions.
- CXXRecordDecl *getBaseClass() const { return cast<CXXRecordDecl>(Target); }
- CXXRecordDecl *getDerivedClass() const { return NamingClass; }
-
- /// Retrieves the base object type, important when accessing
- /// an instance member.
- QualType getBaseObjectType() const { return BaseObjectType; }
-
- /// Sets a diagnostic to be performed. The diagnostic is given
- /// four (additional) arguments:
- /// %0 - 0 if the entity was private, 1 if protected
- /// %1 - the DeclarationName of the entity
- /// %2 - the TypeDecl type of the naming class
- /// %3 - the TypeDecl type of the declaring class
- void setDiag(const PartialDiagnostic &PDiag) {
- assert(isQuiet() && "partial diagnostic already defined");
- Diag = PDiag;
- }
- PartialDiagnostic &setDiag(unsigned DiagID) {
- assert(isQuiet() && "partial diagnostic already defined");
- assert(DiagID && "creating null diagnostic");
- Diag.Reset(DiagID);
- return Diag;
- }
- const PartialDiagnostic &getDiag() const {
- return Diag;
- }
-
- private:
- unsigned Access : 2;
- bool IsMember;
- NamedDecl *Target;
- CXXRecordDecl *NamingClass;
- QualType BaseObjectType;
- PartialDiagnostic Diag;
- };
-
- struct DelayedDiagnostic {
- enum DDKind { Deprecation, Access };
-
- unsigned char Kind; // actually a DDKind
- bool Triggered;
+ llvm::SmallVector<VarDecl *, 2> TentativeDefinitions;
- SourceLocation Loc;
-
- union {
- /// Deprecation.
- struct { NamedDecl *Decl; } DeprecationData;
-
- /// Access control.
- char AccessData[sizeof(AccessedEntity)];
- };
-
- void destroy() {
- switch (Kind) {
- case Access: getAccessData().~AccessedEntity(); break;
- case Deprecation: break;
- }
- }
-
- static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
- NamedDecl *D) {
- DelayedDiagnostic DD;
- DD.Kind = Deprecation;
- DD.Triggered = false;
- DD.Loc = Loc;
- DD.DeprecationData.Decl = D;
- return DD;
- }
-
- static DelayedDiagnostic makeAccess(SourceLocation Loc,
- const AccessedEntity &Entity) {
- DelayedDiagnostic DD;
- DD.Kind = Access;
- DD.Triggered = false;
- DD.Loc = Loc;
- new (&DD.getAccessData()) AccessedEntity(Entity);
- return DD;
- }
-
- AccessedEntity &getAccessData() {
- return *reinterpret_cast<AccessedEntity*>(AccessData);
- }
- const AccessedEntity &getAccessData() const {
- return *reinterpret_cast<const AccessedEntity*>(AccessData);
- }
- };
+ /// \brief The set of file scoped decls seen so far that have not been used
+ /// and must warn if not used. Only contains the first declaration.
+ llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls;
/// \brief The stack of diagnostics that were delayed due to being
/// produced during the parsing of a declaration.
- llvm::SmallVector<DelayedDiagnostic, 8> DelayedDiagnostics;
+ llvm::SmallVector<sema::DelayedDiagnostic, 0> DelayedDiagnostics;
/// \brief The depth of the current ParsingDeclaration stack.
/// If nonzero, we are currently parsing a declaration (and
@@ -511,11 +359,11 @@ public:
Scope *TUScope;
/// \brief The C++ "std" namespace, where the standard library resides.
- NamespaceDecl *StdNamespace;
+ LazyDeclPtr StdNamespace;
/// \brief The C++ "std::bad_alloc" class, which is defined by the C++
/// standard library.
- CXXRecordDecl *StdBadAlloc;
+ LazyDeclPtr StdBadAlloc;
/// A flag to remember whether the implicit forms of operator new and delete
/// have been declared.
@@ -523,13 +371,36 @@ public:
/// \brief The set of declarations that have been referenced within
/// a potentially evaluated expression.
- typedef std::vector<std::pair<SourceLocation, Decl *> >
+ typedef llvm::SmallVector<std::pair<SourceLocation, Decl *>, 10>
PotentiallyReferencedDecls;
/// \brief A set of diagnostics that may be emitted.
- typedef std::vector<std::pair<SourceLocation, PartialDiagnostic> >
+ typedef llvm::SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10>
PotentiallyEmittedDiagnostics;
+ /// \brief Describes how the expressions currently being parsed are
+ /// evaluated at run-time, if at all.
+ enum ExpressionEvaluationContext {
+ /// \brief The current expression and its subexpressions occur within an
+ /// unevaluated operand (C++0x [expr]p8), such as a constant expression
+ /// or the subexpression of \c sizeof, where the type or the value of the
+ /// expression may be significant but no code will be generated to evaluate
+ /// the value of the expression at run time.
+ Unevaluated,
+
+ /// \brief The current expression is potentially evaluated at run time,
+ /// which means that code may be generated to evaluate the value of the
+ /// expression at run time.
+ PotentiallyEvaluated,
+
+ /// \brief The current expression may be potentially evaluated or it may
+ /// be unevaluated, but it is impossible to tell from the lexical context.
+ /// This evaluation context is used primary for the operand of the C++
+ /// \c typeid expression, whose argument is potentially evaluated only when
+ /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
+ PotentiallyPotentiallyEvaluated
+ };
+
/// \brief Data structure used to record current or nested
/// expression evaluation contexts.
struct ExpressionEvaluationContextRecord {
@@ -597,16 +468,21 @@ public:
/// \brief The number of SFINAE diagnostics that have been trapped.
unsigned NumSFINAEErrors;
- typedef llvm::DenseMap<Selector, ObjCMethodList> MethodPool;
+ typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
+ typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
+
+ /// Method Pool - allows efficient lookup when typechecking messages to "id".
+ /// We need to maintain a list, since selectors can have differing signatures
+ /// across classes. In Cocoa, this happens to be extremely uncommon (only 1%
+ /// of selectors are "overloaded").
+ GlobalMethodPool MethodPool;
+
+ /// Method selectors used in a @selector expression. Used for implementation
+ /// of -Wselector.
+ llvm::DenseMap<Selector, SourceLocation> ReferencedSelectors;
- /// Instance/Factory Method Pools - allows efficient lookup when typechecking
- /// messages to "id". We need to maintain a list, since selectors can have
- /// differing signatures across classes. In Cocoa, this happens to be
- /// extremely uncommon (only 1% of selectors are "overloaded").
- MethodPool InstanceMethodPool;
- MethodPool FactoryMethodPool;
- MethodPool::iterator ReadMethodPool(Selector Sel, bool isInstance);
+ GlobalMethodPool::iterator ReadMethodPool(Selector Sel);
/// Private Helper predicate to check for 'self'.
bool isSelfExpr(Expr *RExpr);
@@ -615,12 +491,19 @@ public:
bool CompleteTranslationUnit = true,
CodeCompleteConsumer *CompletionConsumer = 0);
~Sema();
-
+
+ /// \brief Perform initialization that occurs after the parser has been
+ /// initialized but before it parses anything.
+ void Initialize();
+
const LangOptions &getLangOptions() const { return LangOpts; }
Diagnostic &getDiagnostics() const { return Diags; }
SourceManager &getSourceManager() const { return SourceMgr; }
const TargetAttributesSema &getTargetAttributesSema() const;
-
+ Preprocessor &getPreprocessor() const { return PP; }
+ ASTContext &getASTContext() const { return Context; }
+ ASTConsumer &getASTConsumer() const { return Consumer; }
+
/// \brief Helper class that creates diagnostics with optional
/// template instantiation stacks.
///
@@ -651,29 +534,13 @@ public:
SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
/// \brief Build a partial diagnostic.
- PartialDiagnostic PDiag(unsigned DiagID = 0) {
- return PartialDiagnostic(DiagID, Context.getDiagAllocator());
- }
+ PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
- virtual void DeleteExpr(ExprTy *E);
- virtual void DeleteStmt(StmtTy *S);
+ ExprResult Owned(Expr* E) { return E; }
+ ExprResult Owned(ExprResult R) { return R; }
+ StmtResult Owned(Stmt* S) { return S; }
- OwningExprResult Owned(Expr* E) {
- assert(!E || E->isRetained());
- return OwningExprResult(*this, E);
- }
- OwningExprResult Owned(ExprResult R) {
- if (R.isInvalid())
- return ExprError();
- assert(!R.get() || ((Expr*) R.get())->isRetained());
- return OwningExprResult(*this, R.get());
- }
- OwningStmtResult Owned(Stmt* S) {
- assert(!S || S->isRetained());
- return OwningStmtResult(*this, S);
- }
-
- virtual void ActOnEndOfTranslationUnit();
+ void ActOnEndOfTranslationUnit();
Scope *getScopeForContext(DeclContext *Ctx);
@@ -681,37 +548,14 @@ public:
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
void PopFunctionOrBlockScope();
- /// getLabelMap() - Return the current label map. If we're in a block, we
- /// return it.
- llvm::DenseMap<IdentifierInfo*, LabelStmt*> &getLabelMap() {
- if (FunctionScopes.empty())
- return TopFunctionScope.LabelMap;
-
- return FunctionScopes.back()->LabelMap;
- }
-
- /// getSwitchStack - This is returns the switch stack for the current block or
- /// function.
- llvm::SmallVector<SwitchStmt*,8> &getSwitchStack() {
- if (FunctionScopes.empty())
- return TopFunctionScope.SwitchStack;
-
- return FunctionScopes.back()->SwitchStack;
- }
-
- /// \brief Determine whether the current function or block needs scope
- /// checking.
- bool &FunctionNeedsScopeChecking() {
- if (FunctionScopes.empty())
- return TopFunctionScope.NeedsScopeChecking;
-
- return FunctionScopes.back()->NeedsScopeChecking;
+ sema::FunctionScopeInfo *getCurFunction() const {
+ return FunctionScopes.back();
}
bool hasAnyErrorsInThisFunction() const;
/// \brief Retrieve the current block, if any.
- BlockScopeInfo *getCurBlock();
+ sema::BlockScopeInfo *getCurBlock();
/// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
llvm::SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
@@ -732,12 +576,13 @@ public:
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity);
- QualType BuildExtVectorType(QualType T, ExprArg ArraySize,
+ QualType BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc);
QualType BuildFunctionType(QualType T,
QualType *ParamTypes, unsigned NumParamTypes,
bool Variadic, unsigned Quals,
- SourceLocation Loc, DeclarationName Entity);
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionType::ExtInfo &Info);
QualType BuildMemberPointerType(QualType T, QualType Class,
SourceLocation Loc,
DeclarationName Entity);
@@ -747,11 +592,11 @@ public:
TagDecl **OwnedDecl = 0);
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
- /// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
- QualType CreateLocInfoType(QualType T, TypeSourceInfo *TInfo);
- DeclarationName GetNameForDeclarator(Declarator &D);
- DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name);
- static QualType GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo = 0);
+ /// \brief Package the given type and TSI into a ParsedType.
+ ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
+ DeclarationNameInfo GetNameForDeclarator(Declarator &D);
+ DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
+ static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
@@ -772,7 +617,7 @@ public:
const FunctionProtoType *Target, SourceLocation TargetLoc,
const FunctionProtoType *Source, SourceLocation SourceLoc);
- virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
+ TypeResult ActOnTypeName(Scope *S, Declarator &D);
bool RequireCompleteType(SourceLocation Loc, QualType T,
const PartialDiagnostic &PD,
@@ -792,36 +637,33 @@ public:
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
//
- /// getDeclName - Return a pretty name for the specified decl if possible, or
- /// an empty string if not. This is used for pretty crash reporting.
- virtual std::string getDeclName(DeclPtrTy D);
-
- DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr);
-
- virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec *SS,
- bool isClassName = false,
- TypeTy *ObjectType = 0);
- virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S);
- virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- CXXScopeSpec *SS,
- TypeTy *&SuggestedType);
-
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
- return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
- }
+ DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr);
+
+ void DiagnoseUseOfUnimplementedSelectors();
- DeclPtrTy HandleDeclarator(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParameterLists,
- bool IsFunctionDefinition);
+ ParsedType getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS = 0,
+ bool isClassName = false,
+ ParsedType ObjectType = ParsedType());
+ TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
+ bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ CXXScopeSpec *SS,
+ ParsedType &SuggestedType);
+
+ Decl *ActOnDeclarator(Scope *S, Declarator &D);
+
+ Decl *HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool IsFunctionDefinition);
void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
const LookupResult &Previous,
Scope *S);
void DiagnoseFunctionSpecifiers(Declarator& D);
void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
void CheckShadow(Scope *S, VarDecl *D);
+ void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, TypeSourceInfo *TInfo,
LookupResult &Previous, bool &Redeclaration);
@@ -845,7 +687,7 @@ public:
bool &Redeclaration,
bool &OverloadableAttrRequired);
void CheckMain(FunctionDecl *FD);
- virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
+ Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
SourceLocation Loc,
QualType T);
@@ -853,16 +695,16 @@ public:
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
SourceLocation NameLoc,
- VarDecl::StorageClass StorageClass,
- VarDecl::StorageClass StorageClassAsWritten);
- virtual void ActOnParamDefaultArgument(DeclPtrTy param,
+ StorageClass SC,
+ StorageClass SCAsWritten);
+ void ActOnParamDefaultArgument(Decl *param,
+ SourceLocation EqualLoc,
+ Expr *defarg);
+ void ActOnParamUnparsedDefaultArgument(Decl *param,
SourceLocation EqualLoc,
- ExprArg defarg);
- virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- SourceLocation ArgLoc);
- virtual void ActOnParamDefaultArgumentError(DeclPtrTy param);
- bool SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
+ SourceLocation ArgLoc);
+ void ActOnParamDefaultArgumentError(Decl *param);
+ bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
SourceLocation EqualLoc);
@@ -870,88 +712,76 @@ public:
// argument locations.
llvm::DenseMap<ParmVarDecl *,SourceLocation> UnparsedDefaultArgLocs;
- virtual void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init);
- void AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit);
- void ActOnUninitializedDecl(DeclPtrTy dcl, bool TypeContainsUndeducedAuto);
- virtual void ActOnInitializerError(DeclPtrTy Dcl);
- virtual void SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc);
- virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
- DeclPtrTy *Group,
- unsigned NumDecls);
- virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
- SourceLocation LocAfterDecls);
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, Declarator &D);
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *S, DeclPtrTy D);
- virtual void ActOnStartOfObjCMethodDef(Scope *S, DeclPtrTy D);
-
- virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body);
- DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body,
- bool IsInstantiation);
+ void AddInitializerToDecl(Decl *dcl, Expr *init);
+ void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
+ void ActOnUninitializedDecl(Decl *dcl, bool TypeContainsUndeducedAuto);
+ void ActOnInitializerError(Decl *Dcl);
+ void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ Decl **Group,
+ unsigned NumDecls);
+ void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
+ void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
+ Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
/// \brief Diagnose any unused parameters in the given sequence of
/// ParmVarDecl pointers.
- template<typename InputIterator>
- void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) {
- if (Diags.getDiagnosticLevel(diag::warn_unused_parameter) ==
- Diagnostic::Ignored)
- return;
-
- // Don't diagnose unused-parameter errors in template instantiations; we
- // will already have done so in the template itself.
- if (!ActiveTemplateInstantiations.empty())
- return;
-
- for (; Param != ParamEnd; ++Param) {
- if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
- !(*Param)->template hasAttr<UnusedAttr>()) {
- Diag((*Param)->getLocation(), diag::warn_unused_parameter)
- << (*Param)->getDeclName();
- }
- }
- }
+ void DiagnoseUnusedParameters(ParmVarDecl * const *Begin,
+ ParmVarDecl * const *End);
void DiagnoseInvalidJumps(Stmt *Body);
- virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
+ Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr);
/// Scope actions.
- virtual void ActOnPopScope(SourceLocation Loc, Scope *S);
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S);
+ void ActOnPopScope(SourceLocation Loc, Scope *S);
+ void ActOnTranslationUnitScope(Scope *S);
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
- virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
- DeclSpec &DS);
+ Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS);
- virtual DeclPtrTy BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
- AccessSpecifier AS,
- RecordDecl *Record);
+ Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+ AccessSpecifier AS,
+ RecordDecl *Record);
bool isAcceptableTagRedeclaration(const TagDecl *Previous,
- TagDecl::TagKind NewTag,
+ TagTypeKind NewTag,
SourceLocation NewTagLoc,
const IdentifierInfo &Name);
- virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
- MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent);
+ enum TagUseKind {
+ TUK_Reference, // Reference to a tag: 'struct foo *X;'
+ TUK_Declaration, // Fwd decl of a tag: 'struct foo;'
+ TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;'
+ TUK_Friend // Friend declaration: 'friend struct foo;'
+ };
+
+ Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr, AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent);
- virtual TypeResult ActOnDependentTag(Scope *S,
- unsigned TagSpec,
- TagUseKind TUK,
- const CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation TagLoc,
- SourceLocation NameLoc);
+ TypeResult ActOnDependentTag(Scope *S,
+ unsigned TagSpec,
+ TagUseKind TUK,
+ const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation TagLoc,
+ SourceLocation NameLoc);
- virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
- IdentifierInfo *ClassName,
- llvm::SmallVectorImpl<DeclPtrTy> &Decls);
- virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
- SourceLocation DeclStart,
- Declarator &D, ExprTy *BitfieldWidth);
+ void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ IdentifierInfo *ClassName,
+ llvm::SmallVectorImpl<Decl *> &Decls);
+ Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth);
FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
Declarator &D, Expr *BitfieldWidth,
@@ -972,55 +802,54 @@ public:
CXXCopyAssignment = 2,
CXXDestructor = 3
};
+ bool CheckNontrivialField(FieldDecl *FD);
void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
-
- virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
- DeclPtrTy IntfDecl,
- Declarator &D, ExprTy *BitfieldWidth,
- tok::ObjCKeywordKind visibility);
+ void ActOnLastBitfield(SourceLocation DeclStart, Decl *IntfDecl,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls);
+ Decl *ActOnIvar(Scope *S, SourceLocation DeclStart, Decl *IntfDecl,
+ Declarator &D, Expr *BitfieldWidth,
+ tok::ObjCKeywordKind visibility);
// This is used for both record definitions and ObjC interface declarations.
- virtual void ActOnFields(Scope* S,
- SourceLocation RecLoc, DeclPtrTy TagDecl,
- DeclPtrTy *Fields, unsigned NumFields,
- SourceLocation LBrac, SourceLocation RBrac,
- AttributeList *AttrList);
+ void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl,
+ Decl **Fields, unsigned NumFields,
+ SourceLocation LBrac, SourceLocation RBrac,
+ AttributeList *AttrList);
/// ActOnTagStartDefinition - Invoked when we have entered the
/// scope of a tag's definition (e.g., for an enumeration, class,
/// struct, or union).
- virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl);
+ void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
/// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
/// C++ record definition's base-specifiers clause and are starting its
/// member declarations.
- virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl,
- SourceLocation LBraceLoc);
+ void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
+ SourceLocation LBraceLoc);
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
/// the definition of a tag (enumeration, class, struct, or union).
- virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl,
- SourceLocation RBraceLoc);
+ void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
+ SourceLocation RBraceLoc);
/// ActOnTagDefinitionError - Invoked when there was an unrecoverable
/// error parsing the definition of a tag.
- virtual void ActOnTagDefinitionError(Scope *S, DeclPtrTy TagDecl);
+ void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
EnumConstantDecl *LastEnumConst,
SourceLocation IdLoc,
IdentifierInfo *Id,
- ExprArg val);
+ Expr *val);
- virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
- DeclPtrTy LastEnumConstant,
- SourceLocation IdLoc, IdentifierInfo *Id,
- SourceLocation EqualLoc, ExprTy *Val);
- virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
- DeclPtrTy *Elements, unsigned NumElements,
- Scope *S, AttributeList *Attr);
+ Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, Expr *Val);
+ void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc, Decl *EnumDecl,
+ Decl **Elements, unsigned NumElements,
+ Scope *S, AttributeList *Attr);
DeclContext *getContainingDC(DeclContext *DC);
@@ -1060,16 +889,7 @@ public:
/// Finds the scope corresponding to the given decl context, if it
/// happens to be an enclosing scope. Otherwise return NULL.
- Scope *getScopeForDeclContext(Scope *S, DeclContext *DC) {
- DeclContext *TargetDC = DC->getPrimaryContext();
- do {
- if (DeclContext *ScopeDC = (DeclContext*) S->getEntity())
- if (ScopeDC->getPrimaryContext() == TargetDC)
- return S;
- } while ((S = S->getParent()));
-
- return NULL;
- }
+ static Scope *getScopeForDeclContext(Scope *S, DeclContext *DC);
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
@@ -1120,14 +940,6 @@ public:
bool AllowExplicit,
bool InOverloadResolution);
- ImplicitConversionSequence
- TryImplicitConversion(Expr* From, QualType ToType,
- bool SuppressUserConversions,
- bool AllowExplicit,
- bool InOverloadResolution);
- bool IsStandardConversion(Expr *From, QualType ToType,
- bool InOverloadResolution,
- StandardConversionSequence& SCS);
bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
bool IsComplexPromotion(QualType FromType, QualType ToType);
@@ -1140,59 +952,33 @@ public:
FunctionProtoType* NewType);
bool CheckPointerConversion(Expr *From, QualType ToType,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray& BasePath,
+ CastKind &Kind,
+ CXXCastPath& BasePath,
bool IgnoreBaseAccess);
bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
bool InOverloadResolution,
QualType &ConvertedType);
bool CheckMemberPointerConversion(Expr *From, QualType ToType,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
bool IgnoreBaseAccess);
bool IsQualificationConversion(QualType FromType, QualType ToType);
- OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
- UserDefinedConversionSequence& User,
- OverloadCandidateSet& Conversions,
- bool AllowExplicit);
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
- ImplicitConversionSequence::CompareKind
- CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
- const ImplicitConversionSequence& ICS2);
-
- ImplicitConversionSequence::CompareKind
- CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
- const StandardConversionSequence& SCS2);
-
- ImplicitConversionSequence::CompareKind
- CompareQualificationConversions(const StandardConversionSequence& SCS1,
- const StandardConversionSequence& SCS2);
-
- ImplicitConversionSequence::CompareKind
- CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
- const StandardConversionSequence& SCS2);
-
- OwningExprResult PerformCopyInitialization(const InitializedEntity &Entity,
- SourceLocation EqualLoc,
- OwningExprResult Init);
- ImplicitConversionSequence
- TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method,
- CXXRecordDecl *ActingContext);
+ ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init);
bool PerformObjectArgumentInitialization(Expr *&From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
CXXMethodDecl *Method);
- ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
bool PerformContextuallyConvertToBool(Expr *&From);
-
- ImplicitConversionSequence TryContextuallyConvertToObjCId(Expr *From);
bool PerformContextuallyConvertToObjCId(Expr *&From);
- OwningExprResult
- ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
+ ExprResult
+ ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,
const PartialDiagnostic &NotIntDiag,
const PartialDiagnostic &IncompleteDiag,
const PartialDiagnostic &ExplicitConvDiag,
@@ -1287,31 +1073,8 @@ public:
const TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading = false);
- bool isBetterOverloadCandidate(const OverloadCandidate& Cand1,
- const OverloadCandidate& Cand2,
- SourceLocation Loc);
- OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet,
- SourceLocation Loc,
- OverloadCandidateSet::iterator& Best);
-
- enum OverloadCandidateDisplayKind {
- /// Requests that all candidates be shown. Viable candidates will
- /// be printed first.
- OCD_AllCandidates,
-
- /// Requests that only viable candidates be shown.
- OCD_ViableCandidates
- };
- void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
- OverloadCandidateDisplayKind OCD,
- Expr **Args, unsigned NumArgs,
- const char *Opc = 0,
- SourceLocation Loc = SourceLocation());
void NoteOverloadCandidate(FunctionDecl *Fn);
- void DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
- SourceLocation CaretLoc,
- const PartialDiagnostic &PDiag);
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool Complain,
@@ -1321,37 +1084,37 @@ public:
Expr *FixOverloadedFunctionReference(Expr *E,
DeclAccessPair FoundDecl,
FunctionDecl *Fn);
- OwningExprResult FixOverloadedFunctionReference(OwningExprResult,
- DeclAccessPair FoundDecl,
- FunctionDecl *Fn);
+ ExprResult FixOverloadedFunctionReference(ExprResult,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading = false);
- OwningExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
- UnresolvedLookupExpr *ULE,
- SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
- OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
- unsigned Opc,
- const UnresolvedSetImpl &Fns,
- ExprArg input);
+ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ unsigned Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *input);
- OwningExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
- unsigned Opc,
- const UnresolvedSetImpl &Fns,
- Expr *LHS, Expr *RHS);
+ ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
+ unsigned Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *LHS, Expr *RHS);
- OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
- SourceLocation RLoc,
- ExprArg Base,ExprArg Idx);
+ ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ Expr *Base,Expr *Idx);
- OwningExprResult
+ ExprResult
BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
SourceLocation LParenLoc, Expr **Args,
unsigned NumArgs, SourceLocation *CommaLocs,
@@ -1362,8 +1125,8 @@ public:
SourceLocation *CommaLocs,
SourceLocation RParenLoc);
- OwningExprResult BuildOverloadedArrowExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc);
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc);
/// CheckCallReturnType - Checks that a call expression's return type is
/// complete. Returns true on failure. The location passed in is the location
@@ -1439,7 +1202,9 @@ public:
/// C99 6.2.2p4-5 and C++ [basic.link]p6.
LookupRedeclarationWithLinkage,
/// Look up the name of an Objective-C protocol.
- LookupObjCProtocolName
+ LookupObjCProtocolName,
+ /// \brief Look up any declaration with any name.
+ LookupAnyName
};
/// \brief Specifies whether (or how) name lookup is being performed for a
@@ -1479,7 +1244,8 @@ public:
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
UnresolvedSetImpl &Functions);
- DeclContext::lookup_result LookupConstructors(CXXRecordDecl *Class);
+
+ DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
@@ -1487,9 +1253,11 @@ public:
ADLResult &Functions);
void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
- VisibleDeclConsumer &Consumer);
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
- VisibleDeclConsumer &Consumer);
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope = true);
/// \brief The context in which typo-correction occurs.
///
@@ -1551,6 +1319,8 @@ public:
bool isPropertyReadonly(ObjCPropertyDecl *PropertyDecl,
ObjCInterfaceDecl *IDecl);
+ typedef llvm::DenseSet<Selector, llvm::DenseMapInfo<Selector> > SelectorSet;
+
/// CheckProtocolMethodDefs - This routine checks unimplemented
/// methods declared in protocol, and those referenced by it.
/// \param IDecl - Used for checking for methods which may have been
@@ -1558,8 +1328,8 @@ public:
void CheckProtocolMethodDefs(SourceLocation ImpLoc,
ObjCProtocolDecl *PDecl,
bool& IncompleteImpl,
- const llvm::DenseSet<Selector> &InsMap,
- const llvm::DenseSet<Selector> &ClsMap,
+ const SelectorSet &InsMap,
+ const SelectorSet &ClsMap,
ObjCContainerDecl *CDecl);
/// CheckImplementationIvars - This routine checks if the instance variables
@@ -1578,7 +1348,7 @@ public:
/// which must be implemented by this implementation.
void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
ObjCContainerDecl *CDecl,
- const llvm::DenseSet<Selector>& InsMap);
+ const SelectorSet &InsMap);
/// DefaultSynthesizeProperties - This routine default synthesizes all
/// properties which must be synthesized in class's @implementation.
@@ -1599,18 +1369,18 @@ public:
/// Called by ActOnProperty to handle @property declarations in
//// class extensions.
- DeclPtrTy HandlePropertyInClassExtension(Scope *S,
- ObjCCategoryDecl *CDecl,
- SourceLocation AtLoc,
- FieldDeclarator &FD,
- Selector GetterSel,
- Selector SetterSel,
- const bool isAssign,
- const bool isReadWrite,
- const unsigned Attributes,
- bool *isOverridingProperty,
- TypeSourceInfo *T,
- tok::ObjCKeywordKind MethodImplKind);
+ Decl *HandlePropertyInClassExtension(Scope *S,
+ ObjCCategoryDecl *CDecl,
+ SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ Selector GetterSel,
+ Selector SetterSel,
+ const bool isAssign,
+ const bool isReadWrite,
+ const unsigned Attributes,
+ bool *isOverridingProperty,
+ TypeSourceInfo *T,
+ tok::ObjCKeywordKind MethodImplKind);
/// Called by ActOnProperty and HandlePropertyInClassExtension to
/// handle creating the ObjcPropertyDecl for a category or @interface.
@@ -1639,177 +1409,234 @@ public:
/// true, or false, accordingly.
bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
const ObjCMethodDecl *PrevMethod,
- bool matchBasedOnSizeAndAlignment = false);
+ bool matchBasedOnSizeAndAlignment = false,
+ bool matchBasedOnStrictEqulity = false);
/// MatchAllMethodDeclarations - Check methods declaraed in interface or
/// or protocol against those declared in their implementations.
- void MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
- const llvm::DenseSet<Selector> &ClsMap,
- llvm::DenseSet<Selector> &InsMapSeen,
- llvm::DenseSet<Selector> &ClsMapSeen,
+ void MatchAllMethodDeclarations(const SelectorSet &InsMap,
+ const SelectorSet &ClsMap,
+ SelectorSet &InsMapSeen,
+ SelectorSet &ClsMapSeen,
ObjCImplDecl* IMPDecl,
ObjCContainerDecl* IDecl,
bool &IncompleteImpl,
bool ImmediateClass);
+private:
+ /// AddMethodToGlobalPool - Add an instance or factory method to the global
+ /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+ void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+
+ /// LookupMethodInGlobalPool - Returns the instance or factory method and
+ /// optionally warns if there are multiple signatures.
+ ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass,
+ bool warn, bool instance);
+
+public:
/// AddInstanceMethodToGlobalPool - All instance methods in a translation
/// unit are added to a global pool. This allows us to efficiently associate
/// a selector with a method declaraation for purposes of typechecking
/// messages sent to "id" (where the class of the object is unknown).
- void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method);
+ void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/true);
+ }
+
+ /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+ void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/false);
+ }
/// LookupInstanceMethodInGlobalPool - Returns the method and warns if
/// there are multiple signatures.
ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
- bool warn=true);
+ bool receiverIdOrClass=false,
+ bool warn=true) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ warn, /*instance*/true);
+ }
/// LookupFactoryMethodInGlobalPool - Returns the method and warns if
/// there are multiple signatures.
- ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R);
+ ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass=false,
+ bool warn=true) {
+ return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+ warn, /*instance*/false);
+ }
- /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
- void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method);
+ /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+ /// implementation.
+ ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
/// initialization.
- void CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
+ void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.
public:
- virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr);
-
- virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc);
- virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
- MultiStmtArg Elts,
- bool isStmtExpr);
- virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- virtual void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
- virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal,
- SourceLocation DotDotDotLoc, ExprArg RHSVal,
- SourceLocation ColonLoc);
- virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt);
-
- virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
- SourceLocation ColonLoc,
- StmtArg SubStmt, Scope *CurScope);
- virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation ColonLoc,
- StmtArg SubStmt);
- virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
- FullExprArg CondVal, DeclPtrTy CondVar,
- StmtArg ThenVal,
- SourceLocation ElseLoc, StmtArg ElseVal);
- virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
- ExprArg Cond,
- DeclPtrTy CondVar);
- virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
- StmtArg Switch, StmtArg Body);
- virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
- FullExprArg Cond,
- DeclPtrTy CondVar, StmtArg Body);
- virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
- SourceLocation WhileLoc,
- SourceLocation CondLParen, ExprArg Cond,
- SourceLocation CondRParen);
-
- virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
+ class FullExprArg {
+ public:
+ FullExprArg(Sema &actions) : E(0) { }
+
+ // FIXME: The const_cast here is ugly. RValue references would make this
+ // much nicer (or we could duplicate a bunch of the move semantics
+ // emulation code from Ownership.h).
+ FullExprArg(const FullExprArg& Other): E(Other.E) {}
+
+ ExprResult release() {
+ return move(E);
+ }
+
+ Expr *get() const { return E; }
+
+ Expr *operator->() {
+ return E;
+ }
+
+ private:
+ // FIXME: No need to make the entire Sema class a friend when it's just
+ // Sema::FullExpr that needs access to the constructor below.
+ friend class Sema;
+
+ explicit FullExprArg(Expr *expr) : E(expr) {}
+
+ Expr *E;
+ };
+
+ FullExprArg MakeFullExpr(Expr *Arg) {
+ return FullExprArg(ActOnFinishFullExpr(Arg).release());
+ }
+
+ StmtResult ActOnExprStmt(FullExprArg Expr);
+
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc);
+ StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ MultiStmtArg Elts,
+ bool isStmtExpr);
+ StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
+ StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
+ SourceLocation DotDotDotLoc, Expr *RHSVal,
+ SourceLocation ColonLoc);
+ void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
+
+ StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt, Scope *CurScope);
+ StmtResult ActOnLabelStmt(SourceLocation IdentLoc,
+ IdentifierInfo *II,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt);
+ StmtResult ActOnIfStmt(SourceLocation IfLoc,
+ FullExprArg CondVal, Decl *CondVar,
+ Stmt *ThenVal,
+ SourceLocation ElseLoc, Stmt *ElseVal);
+ StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+ Expr *Cond,
+ Decl *CondVar);
+ StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body);
+ StmtResult ActOnWhileStmt(SourceLocation WhileLoc,
+ FullExprArg Cond,
+ Decl *CondVar, Stmt *Body);
+ StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+ SourceLocation WhileLoc,
+ SourceLocation CondLParen, Expr *Cond,
+ SourceLocation CondRParen);
+
+ StmtResult ActOnForStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *First, FullExprArg Second,
+ Decl *SecondVar,
+ FullExprArg Third,
+ SourceLocation RParenLoc,
+ Stmt *Body);
+ StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
SourceLocation LParenLoc,
- StmtArg First, FullExprArg Second,
- DeclPtrTy SecondVar,
- FullExprArg Third,
- SourceLocation RParenLoc,
- StmtArg Body);
- virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
- SourceLocation LParenLoc,
- StmtArg First, ExprArg Second,
- SourceLocation RParenLoc, StmtArg Body);
-
- virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
- SourceLocation LabelLoc,
- IdentifierInfo *LabelII);
- virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
- SourceLocation StarLoc,
- ExprArg DestExp);
- virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
- Scope *CurScope);
- virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
- Scope *CurScope);
-
- virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
- ExprArg RetValExp);
- OwningStmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc,
- Expr *RetValExp);
-
- virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
- bool IsSimple,
- bool IsVolatile,
- unsigned NumOutputs,
- unsigned NumInputs,
- IdentifierInfo **Names,
- MultiExprArg Constraints,
- MultiExprArg Exprs,
- ExprArg AsmString,
- MultiExprArg Clobbers,
- SourceLocation RParenLoc,
- bool MSAsm = false);
+ Stmt *First, Expr *Second,
+ SourceLocation RParenLoc, Stmt *Body);
+
+ StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
+ SourceLocation LabelLoc,
+ IdentifierInfo *LabelII);
+ StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+ SourceLocation StarLoc,
+ Expr *DestExp);
+ StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
+ StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope);
+
+ StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+ StmtResult ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+
+ StmtResult ActOnAsmStmt(SourceLocation AsmLoc,
+ bool IsSimple, bool IsVolatile,
+ unsigned NumOutputs, unsigned NumInputs,
+ IdentifierInfo **Names,
+ MultiExprArg Constraints,
+ MultiExprArg Exprs,
+ Expr *AsmString,
+ MultiExprArg Clobbers,
+ SourceLocation RParenLoc,
+ bool MSAsm = false);
VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
IdentifierInfo *Name, SourceLocation NameLoc,
bool Invalid = false);
- virtual DeclPtrTy ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+ Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
- virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
- SourceLocation RParen,
- DeclPtrTy Parm, StmtArg Body);
+ StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+ Decl *Parm, Stmt *Body);
- virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
- StmtArg Body);
+ StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
- virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
- StmtArg Try,
- MultiStmtArg Catch,
- StmtArg Finally);
+ StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg Catch, Stmt *Finally);
- virtual OwningStmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg Throw);
- virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg Throw,
- Scope *CurScope);
- virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
- ExprArg SynchExpr,
- StmtArg SynchBody);
+ StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw);
+ StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
+ Scope *CurScope);
+ StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ Expr *SynchExpr,
+ Stmt *SynchBody);
VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
TypeSourceInfo *TInfo,
IdentifierInfo *Name,
SourceLocation Loc,
SourceRange Range);
- virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D);
-
- virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
- DeclPtrTy ExDecl,
- StmtArg HandlerBlock);
- virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
- StmtArg TryBlock,
- MultiStmtArg Handlers);
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+
+ StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+ Decl *ExDecl, Stmt *HandlerBlock);
+ StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ MultiStmtArg Handlers);
void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+ bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+
+ /// \brief If it's a file scoped decl that must warn if not used, keep track
+ /// of it.
+ void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+
/// DiagnoseUnusedExprResult - If the statement passed in is an expression
/// whose result is unused, warn.
void DiagnoseUnusedExprResult(const Stmt *S);
void DiagnoseUnusedDecl(const NamedDecl *ND);
+ typedef uintptr_t ParsingDeclStackState;
+
ParsingDeclStackState PushParsingDeclaration();
- void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D);
+ void PopParsingDeclaration(ParsingDeclStackState S, Decl *D);
void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
- void HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Decl *Ctx);
+ void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
@@ -1821,105 +1648,95 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
- virtual void
- PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
+ void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
- virtual void PopExpressionEvaluationContext();
+ void PopExpressionEvaluationContext();
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
bool DiagRuntimeBehavior(SourceLocation Loc, const PartialDiagnostic &PD);
// Primary Expressions.
- virtual SourceRange getExprRange(ExprTy *E) const;
+ SourceRange getExprRange(Expr *E) const;
- virtual OwningExprResult ActOnIdExpression(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- bool HasTrailingLParen,
- bool IsAddressOfOperand);
+ ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name,
+ bool HasTrailingLParen, bool IsAddressOfOperand);
bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
CorrectTypoContext CTC = CTC_Unknown);
- OwningExprResult LookupInObjCMethod(LookupResult &R,
- Scope *S,
- IdentifierInfo *II,
- bool AllowBuiltinCreation=false);
+ ExprResult LookupInObjCMethod(LookupResult &R, Scope *S, IdentifierInfo *II,
+ bool AllowBuiltinCreation=false);
- OwningExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc,
- bool isAddressOfOperand,
+ ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool isAddressOfOperand,
const TemplateArgumentListInfo *TemplateArgs);
- OwningExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
- SourceLocation Loc,
- const CXXScopeSpec *SS = 0);
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS = 0);
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ const DeclarationNameInfo &NameInfo,
+ const CXXScopeSpec *SS = 0);
VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
llvm::SmallVectorImpl<FieldDecl *> &Path);
- OwningExprResult
+ ExprResult
BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
FieldDecl *Field,
Expr *BaseObjectExpr = 0,
SourceLocation OpLoc = SourceLocation());
- OwningExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
- LookupResult &R,
+ ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs);
- OwningExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
- LookupResult &R,
+ ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- bool IsDefiniteInstance);
+ bool IsDefiniteInstance);
bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
const LookupResult &R,
bool HasTrailingLParen);
- OwningExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc);
- OwningExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc,
+ ExprResult BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo);
+ ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- LookupResult &R,
- bool ADL);
- OwningExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- SourceLocation Loc,
- NamedDecl *D);
-
- virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
- tok::TokenKind Kind);
- virtual OwningExprResult ActOnNumericConstant(const Token &);
- virtual OwningExprResult ActOnCharacterConstant(const Token &);
- virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
- ExprArg Val);
- virtual OwningExprResult ActOnParenOrParenListExpr(SourceLocation L,
- SourceLocation R,
- MultiExprArg Val,
- TypeTy *TypeOfCast=0);
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool ADL);
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ NamedDecl *D);
+
+ ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+ ExprResult ActOnNumericConstant(const Token &);
+ ExprResult ActOnCharacterConstant(const Token &);
+ ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *Val);
+ ExprResult ActOnParenOrParenListExpr(SourceLocation L,
+ SourceLocation R,
+ MultiExprArg Val,
+ ParsedType TypeOfCast = ParsedType());
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz").
- virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
- unsigned NumToks);
+ ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks);
// Binary/Unary Operators. 'Tok' is the token for the operator.
- OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc,
- unsigned OpcIn,
- ExprArg InputArg);
- OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
- UnaryOperator::Opcode Opc, ExprArg input);
- virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg Input);
-
- OwningExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T,
- SourceLocation OpLoc,
- bool isSizeOf, SourceRange R);
- OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
- bool isSizeOf, SourceRange R);
- virtual OwningExprResult
+ ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
+ Expr *InputArg);
+ ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc, Expr *input);
+ ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input);
+
+ ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T,
+ SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
+ bool isSizeOf, SourceRange R);
+ ExprResult
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange);
@@ -1927,67 +1744,55 @@ public:
bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc,
const SourceRange &R, bool isSizeof);
- virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind,
- ExprArg Input);
-
- virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
- SourceLocation LLoc,
- ExprArg Idx,
- SourceLocation RLoc);
- OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base,
- SourceLocation LLoc,
- ExprArg Idx,
- SourceLocation RLoc);
-
- OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
- QualType BaseType,
- SourceLocation OpLoc,
- bool IsArrow,
- CXXScopeSpec &SS,
- NamedDecl *FirstQualifierInScope,
- DeclarationName Name,
- SourceLocation NameLoc,
+ ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input);
+
+ ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+ ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+
+ ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
- QualType BaseType,
- SourceLocation OpLoc, bool IsArrow,
- const CXXScopeSpec &SS,
- NamedDecl *FirstQualifierInScope,
- LookupResult &R,
+ ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
+ SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- bool SuppressQualifierCheck = false);
+ bool SuppressQualifierCheck = false);
- OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
- bool &IsArrow, SourceLocation OpLoc,
- CXXScopeSpec &SS,
- DeclPtrTy ObjCImpDecl,
- bool HasTemplateArgs);
+ ExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
+ bool &IsArrow, SourceLocation OpLoc,
+ CXXScopeSpec &SS,
+ Decl *ObjCImpDecl,
+ bool HasTemplateArgs);
bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
const CXXScopeSpec &SS,
const LookupResult &R);
- OwningExprResult ActOnDependentMemberExpr(ExprArg Base,
- QualType BaseType,
- bool IsArrow,
- SourceLocation OpLoc,
- const CXXScopeSpec &SS,
- NamedDecl *FirstQualifierInScope,
- DeclarationName Name,
- SourceLocation NameLoc,
+ ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &Member,
- DeclPtrTy ObjCImpDecl,
- bool HasTrailingLParen);
+ ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Member,
+ Decl *ObjCImpDecl,
+ bool HasTrailingLParen);
- virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl);
+ void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
@@ -1997,155 +1802,172 @@ public:
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
- virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
- OwningExprResult BuildResolvedCallExpr(Expr *Fn,
- NamedDecl *NDecl,
- SourceLocation LParenLoc,
- Expr **Args, unsigned NumArgs,
- SourceLocation RParenLoc);
+ ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+ MultiExprArg Args, SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
+ ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation RParenLoc);
- virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- TypeTy *Ty, SourceLocation RParenLoc,
- ExprArg Op);
- OwningExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
- TypeSourceInfo *Ty,
- SourceLocation RParenLoc,
- ExprArg Op);
+ ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ ParsedType Ty, SourceLocation RParenLoc,
+ Expr *Op);
+ ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
- virtual bool TypeIsVectorType(TypeTy *Ty) {
+ bool TypeIsVectorType(ParsedType Ty) {
return GetTypeFromParser(Ty)->isVectorType();
}
- OwningExprResult MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg ME);
- OwningExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
- SourceLocation RParenLoc, ExprArg E,
- TypeSourceInfo *TInfo);
+ ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+ ExprResult ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *E,
+ TypeSourceInfo *TInfo);
- virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
- TypeTy *Ty,
- SourceLocation RParenLoc,
- ExprArg Op);
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
- OwningExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
- TypeSourceInfo *TInfo,
- SourceLocation RParenLoc,
- ExprArg InitExpr);
+ ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *InitExpr);
- virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
- MultiExprArg InitList,
- SourceLocation RParenLoc);
+ ExprResult ActOnInitList(SourceLocation LParenLoc,
+ MultiExprArg InitList,
+ SourceLocation RParenLoc);
- virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig,
- SourceLocation Loc,
- bool GNUSyntax,
- OwningExprResult Init);
+ ExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ bool GNUSyntax,
+ ExprResult Init);
- virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
- tok::TokenKind Kind,
- ExprArg LHS, ExprArg RHS);
- OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
- BinaryOperator::Opcode Opc,
- Expr *lhs, Expr *rhs);
- OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
- unsigned Opc, Expr *lhs, Expr *rhs);
+ ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind, Expr *LHS, Expr *RHS);
+ ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opc, Expr *lhs, Expr *rhs);
+ ExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
+ unsigned Opc, Expr *lhs, Expr *rhs);
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
- virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
- SourceLocation ColonLoc,
- ExprArg Cond, ExprArg LHS,
- ExprArg RHS);
+ ExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+ SourceLocation ColonLoc,
+ Expr *Cond, Expr *LHS, Expr *RHS);
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
- virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
- IdentifierInfo *LabelII);
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc,
+ SourceLocation LabLoc,
+ IdentifierInfo *LabelII);
- virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt,
- SourceLocation RPLoc); // "({..})"
+ ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc); // "({..})"
+
+ // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+ struct OffsetOfComponent {
+ SourceLocation LocStart, LocEnd;
+ bool isBrackets; // true if [expr], false if .ident
+ union {
+ IdentifierInfo *IdentInfo;
+ ExprTy *E;
+ } U;
+ };
/// __builtin_offsetof(type, a.b[123][456].c)
- OwningExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
- TypeSourceInfo *TInfo,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
- SourceLocation RParenLoc);
- virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
- SourceLocation BuiltinLoc,
- SourceLocation TypeLoc,
- TypeTy *Arg1,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
- SourceLocation RParenLoc);
+ ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc);
+ ExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ ParsedType Arg1,
+ OffsetOfComponent *CompPtr,
+ unsigned NumComponents,
+ SourceLocation RParenLoc);
// __builtin_types_compatible_p(type1, type2)
- virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
- TypeTy *arg1, TypeTy *arg2,
- SourceLocation RPLoc);
+ ExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ ParsedType arg1,
+ ParsedType arg2,
+ SourceLocation RPLoc);
+ ExprResult BuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ TypeSourceInfo *argTInfo1,
+ TypeSourceInfo *argTInfo2,
+ SourceLocation RPLoc);
// __builtin_choose_expr(constExpr, expr1, expr2)
- virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
- ExprArg cond, ExprArg expr1,
- ExprArg expr2, SourceLocation RPLoc);
+ ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *cond, Expr *expr1,
+ Expr *expr2, SourceLocation RPLoc);
// __builtin_va_arg(expr, type)
- virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
- ExprArg expr, TypeTy *type,
- SourceLocation RPLoc);
+ ExprResult ActOnVAArg(SourceLocation BuiltinLoc,
+ Expr *expr, ParsedType type,
+ SourceLocation RPLoc);
+ ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *expr, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc);
// __null
- virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+ ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
//===------------------------- "Block" Extension ------------------------===//
/// ActOnBlockStart - This callback is invoked when a block literal is
/// started.
- virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+ void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
/// ActOnBlockArguments - This callback allows processing of block arguments.
/// If there are no arguments, this is still invoked.
- virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
+ void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope);
/// ActOnBlockError - If there is an error parsing a block, this callback
/// is invoked to pop the information about the block from the action impl.
- virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
+ void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
/// ActOnBlockStmtExpr - This is called when the body of a block statement
/// literal was successfully completed. ^(int x){...}
- virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
- StmtArg Body, Scope *CurScope);
+ ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ Stmt *Body, Scope *CurScope);
//===---------------------------- C++ Features --------------------------===//
// Act on C++ namespaces
- virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
- IdentifierInfo *Ident,
- SourceLocation LBrace,
- AttributeList *AttrList);
- virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace);
-
- NamespaceDecl *getStdNamespace();
- virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList);
+ Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident,
+ SourceLocation LBrace,
+ AttributeList *AttrList);
+ void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
+
+ CXXRecordDecl *getStdBadAlloc() const;
+
+ Decl *ActOnUsingDirective(Scope *CurScope,
+ SourceLocation UsingLoc,
+ SourceLocation NamespcLoc,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ AttributeList *AttrList);
void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
- virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *Ident);
+ Decl *ActOnNamespaceAliasDef(Scope *CurScope,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident);
void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
@@ -2165,31 +1987,30 @@ public:
NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- DeclarationName Name,
+ const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
bool IsTypeName,
SourceLocation TypenameLoc);
- virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
- AccessSpecifier AS,
- bool HasUsingKeyword,
- SourceLocation UsingLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- bool IsTypeName,
- SourceLocation TypenameLoc);
+ Decl *ActOnUsingDeclaration(Scope *CurScope,
+ AccessSpecifier AS,
+ bool HasUsingKeyword,
+ SourceLocation UsingLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ AttributeList *AttrList,
+ bool IsTypeName,
+ SourceLocation TypenameLoc);
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
/// e.g: "int x(1);"
- virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ void AddCXXDirectInitializerToDecl(Decl *Dcl,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
/// InitializeVarWithConstructor - Creates an CXXConstructExpr
/// and sets it as the initializer for the the passed in VarDecl.
@@ -2199,27 +2020,26 @@ public:
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
/// including handling of its default argument expressions.
- OwningExprResult
+ ///
+ /// \param ConstructKind - a CXXConstructExpr::ConstructionKind
+ ExprResult
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, MultiExprArg Exprs,
- bool RequiresZeroInit = false,
- CXXConstructExpr::ConstructionKind ConstructKind =
- CXXConstructExpr::CK_Complete);
+ bool RequiresZeroInit, unsigned ConstructKind);
// FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
// the constructor can be elidable?
- OwningExprResult
+ ExprResult
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
- MultiExprArg Exprs, bool RequiresZeroInit = false,
- CXXConstructExpr::ConstructionKind ConstructKind =
- CXXConstructExpr::CK_Complete);
+ MultiExprArg Exprs, bool RequiresZeroInit,
+ unsigned ConstructKind);
/// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
/// the default expr if needed.
- OwningExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
- FunctionDecl *FD,
- ParmVarDecl *Param);
+ ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ FunctionDecl *FD,
+ ParmVarDecl *Param);
/// FinalizeVarWithDestructor - Prepare for calling destructor on the
/// constructed variable.
@@ -2291,98 +2111,96 @@ public:
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
/// it simply returns the passed in expression.
- OwningExprResult MaybeBindToTemporary(Expr *E);
+ ExprResult MaybeBindToTemporary(Expr *E);
bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
SourceLocation Loc,
- ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs);
+ ASTOwningVector<Expr*> &ConvertedArgs);
- virtual TypeTy *getDestructorName(SourceLocation TildeLoc,
- IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec &SS,
- TypeTy *ObjectType,
- bool EnteringContext);
+ ParsedType getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext);
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
- virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc,
- TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc,
- ExprArg E,
- SourceLocation RParenLoc);
-
- OwningExprResult BuildCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- TypeSourceInfo *Ty,
- ExprArg E,
- SourceRange AngleBrackets,
- SourceRange Parens);
-
- OwningExprResult BuildCXXTypeId(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- TypeSourceInfo *Operand,
- SourceLocation RParenLoc);
- OwningExprResult BuildCXXTypeId(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- ExprArg Operand,
- SourceLocation RParenLoc);
+ ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc,
+ ParsedType Ty,
+ SourceLocation RAngleBracketLoc,
+ SourceLocation LParenLoc,
+ Expr *E,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ TypeSourceInfo *Ty,
+ Expr *E,
+ SourceRange AngleBrackets,
+ SourceRange Parens);
+
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc);
/// ActOnCXXTypeid - Parse typeid( something ).
- virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
- SourceLocation RParenLoc);
+ ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
//// ActOnCXXThis - Parse 'this' pointer.
- virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc);
+ ExprResult ActOnCXXThis(SourceLocation ThisLoc);
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
- virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
- tok::TokenKind Kind);
+ ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
- virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+ ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
//// ActOnCXXThrow - Parse throw expressions.
- virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc,
- ExprArg expr);
+ ExprResult ActOnCXXThrow(SourceLocation OpLoc, Expr *expr);
bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E);
/// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
/// Can be interpreted either as function-style casting ("int(x)")
/// or class type construction ("ClassType(x,y,z)")
/// or creation of a value-initialized type ("int()").
- virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
- TypeTy *TypeRep,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ ExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
+ ParsedType TypeRep,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
/// ActOnCXXNew - Parsed a C++ 'new' expression.
- virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
- SourceLocation PlacementLParen,
- MultiExprArg PlacementArgs,
- SourceLocation PlacementRParen,
- SourceRange TypeIdParens, Declarator &D,
- SourceLocation ConstructorLParen,
- MultiExprArg ConstructorArgs,
- SourceLocation ConstructorRParen);
- OwningExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
- SourceLocation PlacementLParen,
- MultiExprArg PlacementArgs,
- SourceLocation PlacementRParen,
- SourceRange TypeIdParens,
- QualType AllocType,
- SourceLocation TypeLoc,
- SourceRange TypeRange,
- ExprArg ArraySize,
- SourceLocation ConstructorLParen,
- MultiExprArg ConstructorArgs,
- SourceLocation ConstructorRParen);
+ ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens, Declarator &D,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen);
+ ExprResult BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
+ SourceLocation PlacementLParen,
+ MultiExprArg PlacementArgs,
+ SourceLocation PlacementRParen,
+ SourceRange TypeIdParens,
+ QualType AllocType,
+ SourceLocation TypeLoc,
+ SourceRange TypeRange,
+ Expr *ArraySize,
+ SourceLocation ConstructorLParen,
+ MultiExprArg ConstructorArgs,
+ SourceLocation ConstructorRParen);
bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
SourceRange R);
@@ -2404,62 +2222,60 @@ public:
DeclarationName Name, FunctionDecl* &Operator);
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
- virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
- bool UseGlobal, bool ArrayForm,
- ExprArg Operand);
+ ExprResult ActOnCXXDelete(SourceLocation StartLoc,
+ bool UseGlobal, bool ArrayForm,
+ Expr *Operand);
- virtual DeclResult ActOnCXXConditionDeclaration(Scope *S,
- Declarator &D);
- OwningExprResult CheckConditionVariable(VarDecl *ConditionVar,
- SourceLocation StmtLoc,
- bool ConvertToBoolean);
+ DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
+ ExprResult CheckConditionVariable(VarDecl *ConditionVar,
+ SourceLocation StmtLoc,
+ bool ConvertToBoolean);
/// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
/// pseudo-functions.
- virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
- SourceLocation KWLoc,
- SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen);
-
- virtual OwningExprResult ActOnStartCXXMemberReference(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- TypeTy *&ObjectType,
- bool &MayBePseudoDestructor);
-
- OwningExprResult DiagnoseDtorReference(SourceLocation NameLoc,
- ExprArg MemExpr);
-
- OwningExprResult BuildPseudoDestructorExpr(ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TypeSourceInfo *ScopeType,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
+ ExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ SourceLocation LParen,
+ ParsedType Ty,
+ SourceLocation RParen);
+
+ ExprResult ActOnStartCXXMemberReference(Scope *S,
+ Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ ParsedType &ObjectType,
+ bool &MayBePseudoDestructor);
+
+ ExprResult DiagnoseDtorReference(SourceLocation NameLoc, Expr *MemExpr);
+
+ ExprResult BuildPseudoDestructorExpr(Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
PseudoDestructorTypeStorage DestroyedType,
- bool HasTrailingLParen);
-
- virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen);
+ bool HasTrailingLParen);
+
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName,
+ bool HasTrailingLParen);
/// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is
/// non-empty, will create a new CXXExprWithTemporaries expression.
/// Otherwise, just returs the passed in expression.
Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr);
- OwningExprResult MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr);
+ ExprResult MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr);
FullExpr CreateFullExpr(Expr *SubExpr);
- virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr);
+ ExprResult ActOnFinishFullExpr(Expr *Expr);
// Marks SS invalid if it represents an incomplete type.
bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
@@ -2473,40 +2289,39 @@ public:
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
- virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
- SourceLocation CCLoc);
+ NestedNameSpecifier *
+ ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc);
bool isAcceptableNestedNameSpecifier(NamedDecl *SD);
NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
- virtual bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
- SourceLocation IdLoc,
- IdentifierInfo &II,
- TypeTy *ObjectType);
-
- CXXScopeTy *BuildCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- QualType ObjectType,
- NamedDecl *ScopeLookupResult,
- bool EnteringContext,
- bool ErrorRecoveryLookup);
-
- virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation IdLoc,
- SourceLocation CCLoc,
- IdentifierInfo &II,
- TypeTy *ObjectType,
- bool EnteringContext);
-
- virtual bool IsInvalidUnlessNestedName(Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo &II,
- TypeTy *ObjectType,
- bool EnteringContext);
+ bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType);
+
+ NestedNameSpecifier *BuildCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ QualType ObjectType,
+ NamedDecl *ScopeLookupResult,
+ bool EnteringContext,
+ bool ErrorRecoveryLookup);
+
+ NestedNameSpecifier *ActOnCXXNestedNameSpecifier(Scope *S,
+ CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ IdentifierInfo &II,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo &II,
+ ParsedType ObjectType,
+ bool EnteringContext);
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
/// nested-name-specifier that involves a template-id, e.g.,
@@ -2516,13 +2331,13 @@ public:
/// specialization (or other template-id that names a type), \p
/// TypeRange is the source range where the type is located, and \p
/// CCLoc is the location of the trailing '::'.
- virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
- const CXXScopeSpec &SS,
- TypeTy *Type,
- SourceRange TypeRange,
- SourceLocation CCLoc);
+ CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ ParsedType Type,
+ SourceRange TypeRange,
+ SourceLocation CCLoc);
- virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+ bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
/// scope or nested-name-specifier) is parsed, part of a declarator-id.
@@ -2530,30 +2345,30 @@ public:
/// looked up in the declarator-id's scope, until the declarator is parsed and
/// ActOnCXXExitDeclaratorScope is called.
/// The 'SS' should be a non-empty valid CXXScopeSpec.
- virtual bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS);
+ bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS);
/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
/// Used to indicate that names should revert to being looked up in the
/// defining scope.
- virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+ void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
/// initializer for the declaration 'Dcl'.
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
/// class X.
- virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl);
+ void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl);
/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
/// initializer for the declaration 'Dcl'.
- virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl);
+ void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
// ParseObjCStringLiteral - Parse Objective-C string literals.
- virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
- ExprTy **Strings,
- unsigned NumStrings);
+ ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ Expr **Strings,
+ unsigned NumStrings);
Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
TypeSourceInfo *EncodedTypeInfo,
@@ -2562,66 +2377,66 @@ public:
NamedDecl *FoundDecl,
CXXMethodDecl *Method);
- virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
- SourceLocation EncodeLoc,
- SourceLocation LParenLoc,
- TypeTy *Ty,
- SourceLocation RParenLoc);
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc);
// ParseObjCSelectorExpression - Build selector expression for @selector
- virtual ExprResult ParseObjCSelectorExpression(Selector Sel,
- SourceLocation AtLoc,
- SourceLocation SelLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ ExprResult ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
// ParseObjCProtocolExpression - Build protocol expression for @protocol
- virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
- SourceLocation AtLoc,
- SourceLocation ProtoLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
//===--------------------------------------------------------------------===//
// C++ Declarations
//
- virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation LangLoc,
- llvm::StringRef Lang,
- SourceLocation LBraceLoc);
- virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S,
- DeclPtrTy LinkageSpec,
- SourceLocation RBraceLoc);
+ Decl *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation LangLoc,
+ llvm::StringRef Lang,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc);
//===--------------------------------------------------------------------===//
// C++ Classes
//
- virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
- const CXXScopeSpec *SS);
+ bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0);
- virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier Access,
- SourceLocation ASLoc,
- SourceLocation ColonLoc);
+ Decl *ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc);
- virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
- Declarator &D,
+ Decl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+ Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
- ExprTy *BitfieldWidth,
- ExprTy *Init, bool IsDefinition,
- bool Deleted = false);
-
- virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- TypeTy *TemplateTypeTy,
- SourceLocation IdLoc,
- SourceLocation LParenLoc,
- ExprTy **Args, unsigned NumArgs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc);
+ Expr *BitfieldWidth,
+ Expr *Init, bool IsDefinition,
+ bool Deleted = false);
+
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ Expr **Args, unsigned NumArgs,
+ SourceLocation *CommaLocs,
+ SourceLocation RParenLoc);
MemInitResult BuildMemberInitializer(FieldDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
@@ -2669,7 +2484,7 @@ public:
void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
bool DefinitionRequired = false);
- /// MarkVirtualMembersReferenced - Will mark all virtual members of the given
+ /// MarkVirtualMembersReferenced - Will mark all members of the given
/// CXXRecordDecl referenced.
void MarkVirtualMembersReferenced(SourceLocation Loc,
const CXXRecordDecl *RD);
@@ -2683,49 +2498,45 @@ public:
void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
- virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
- SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits,
- bool AnyErrors);
+ void ActOnMemInitializers(Decl *ConstructorDecl,
+ SourceLocation ColonLoc,
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors);
void CheckCompletedCXXClass(CXXRecordDecl *Record);
- virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- DeclPtrTy TagDecl,
- SourceLocation LBrac,
- SourceLocation RBrac,
- AttributeList *AttrList);
-
- virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template);
- virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
- DeclPtrTy Record);
- virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method);
- virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param);
- virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method);
- virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
- DeclPtrTy Record);
-
- virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
- ExprArg AssertExpr,
- ExprArg AssertMessageExpr);
+ void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
+ Decl *TagDecl,
+ SourceLocation LBrac,
+ SourceLocation RBrac,
+ AttributeList *AttrList);
+
+ void ActOnReenterTemplateScope(Scope *S, Decl *Template);
+ void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
+ void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
+ void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+ void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+
+ Decl *ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr);
FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc,
TypeSourceInfo *TSInfo);
- DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TemplateParams);
- DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
+ Decl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
MultiTemplateParamsArg TemplateParams);
QualType CheckConstructorDeclarator(Declarator &D, QualType R,
- FunctionDecl::StorageClass& SC);
+ StorageClass& SC);
void CheckConstructor(CXXConstructorDecl *Constructor);
QualType CheckDestructorDeclarator(Declarator &D, QualType R,
- FunctionDecl::StorageClass& SC);
+ StorageClass& SC);
bool CheckDestructor(CXXDestructorDecl *Destructor);
void CheckConversionDeclarator(Declarator &D, QualType &R,
- FunctionDecl::StorageClass& SC);
- DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+ StorageClass& SC);
+ Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
//===--------------------------------------------------------------------===//
// C++ Derived Classes
@@ -2735,8 +2546,7 @@ public:
CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- QualType BaseType,
- SourceLocation BaseLoc);
+ TypeSourceInfo *TInfo);
/// SetClassDeclAttributesFromBase - Copies class decl traits
/// (such as whether the class has a trivial constructor,
@@ -2745,36 +2555,34 @@ public:
const CXXRecordDecl *BaseClass,
bool BaseIsVirtual);
- virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl,
- SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
- TypeTy *basetype, SourceLocation
- BaseLoc);
+ BaseResult ActOnBaseSpecifier(Decl *classdecl,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ ParsedType basetype, SourceLocation
+ BaseLoc);
bool AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
unsigned NumBases);
- virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
- unsigned NumBases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases, unsigned NumBases);
bool IsDerivedFrom(QualType Derived, QualType Base);
bool IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths);
// FIXME: I don't like this name.
- void BuildBasePathArray(const CXXBasePaths &Paths,
- CXXBaseSpecifierArray &BasePath);
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
- bool BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath);
+ bool BasePathInvolvesVirtualBase(const CXXCastPath &BasePath);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
- CXXBaseSpecifierArray *BasePath = 0,
+ CXXCastPath *BasePath = 0,
bool IgnoreAccess = false);
bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
unsigned InaccessibleBaseID,
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name,
- CXXBaseSpecifierArray *BasePath);
+ CXXCastPath *BasePath);
std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
@@ -2848,7 +2656,7 @@ public:
void PerformDependentDiagnostics(const DeclContext *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs);
- void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx);
+ void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
/// A flag to suppress access checking.
bool SuppressAccessChecking;
@@ -2861,16 +2669,16 @@ public:
AbstractReturnType,
AbstractParamType,
AbstractVariableType,
- AbstractFieldType
+ AbstractFieldType,
+ AbstractArrayType
};
bool RequireNonAbstractType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD,
- const CXXRecordDecl *CurrentRD = 0);
+ const PartialDiagnostic &PD);
+ void DiagnoseAbstractType(const CXXRecordDecl *RD);
bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
- AbstractDiagSelID SelID = AbstractNone,
- const CXXRecordDecl *CurrentRD = 0);
+ AbstractDiagSelID SelID = AbstractNone);
//===--------------------------------------------------------------------===//
// C++ Overloaded Operators [C++ 13.5]
@@ -2887,55 +2695,56 @@ public:
QualType ObjectType, bool EnteringContext,
bool &MemberOfUnknownSpecialization);
- virtual TemplateNameKind isTemplateName(Scope *S,
+ TemplateNameKind isTemplateName(Scope *S,
CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
UnqualifiedId &Name,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Template,
bool &MemberOfUnknownSpecialization);
- virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- const CXXScopeSpec *SS,
- TemplateTy &SuggestedTemplate,
- TemplateNameKind &SuggestedKind);
+ bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind);
bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
- TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl);
+ TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+
+ Decl *ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg);
- virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
- SourceLocation EllipsisLoc,
- SourceLocation KeyLoc,
+ QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+ Decl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ Expr *DefaultArg);
+ Decl *ActOnTemplateTemplateParameter(Scope *S,
+ SourceLocation TmpLoc,
+ TemplateParamsTy *Params,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position,
+ unsigned Depth,
+ unsigned Position,
SourceLocation EqualLoc,
- TypeTy *DefaultArg);
+ const ParsedTemplateArgument &DefaultArg);
- QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
- virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- ExprArg DefaultArg);
- virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S,
- SourceLocation TmpLoc,
- TemplateParamsTy *Params,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- const ParsedTemplateArgument &DefaultArg);
-
- virtual TemplateParamsTy *
+ TemplateParamsTy *
ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- DeclPtrTy *Params, unsigned NumParams,
+ Decl **Params, unsigned NumParams,
SourceLocation RAngleLoc);
/// \brief The context in which we are checking a template parameter
@@ -2973,40 +2782,39 @@ public:
SourceLocation TemplateLoc,
const TemplateArgumentListInfo &TemplateArgs);
- virtual TypeResult
+ TypeResult
ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
SourceLocation RAngleLoc);
- virtual TypeResult ActOnTagTemplateIdType(TypeResult Type,
+ TypeResult ActOnTagTemplateIdType(TypeResult Type,
TagUseKind TUK,
- DeclSpec::TST TagSpec,
+ TypeSpecifierType TagSpec,
SourceLocation TagLoc);
- OwningExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
- LookupResult &R,
- bool RequiresADL,
+ ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL,
const TemplateArgumentListInfo &TemplateArgs);
- OwningExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc,
+ ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo &TemplateArgs);
- virtual TemplateNameKind ActOnDependentTemplateName(Scope *S,
- SourceLocation TemplateKWLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringContext,
- TemplateTy &Template);
+ TemplateNameKind ActOnDependentTemplateName(Scope *S,
+ SourceLocation TemplateKWLoc,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template);
bool CheckClassTemplatePartialSpecializationArgs(
TemplateParameterList *TemplateParams,
const TemplateArgumentListBuilder &TemplateArgs,
bool &MirrorsPrimaryTemplate);
- virtual DeclResult
+ DeclResult
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc,
CXXScopeSpec &SS,
@@ -3018,13 +2826,13 @@ public:
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists);
- virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D);
+ Decl *ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
- virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+ Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D);
+ Declarator &D);
bool
CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
@@ -3043,7 +2851,7 @@ public:
LookupResult &Previous);
bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
- virtual DeclResult
+ DeclResult
ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
@@ -3057,7 +2865,7 @@ public:
SourceLocation RAngleLoc,
AttributeList *Attr);
- virtual DeclResult
+ DeclResult
ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
@@ -3068,10 +2876,10 @@ public:
SourceLocation NameLoc,
AttributeList *Attr);
- virtual DeclResult ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- Declarator &D);
+ DeclResult ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ Declarator &D);
TemplateArgumentLoc
SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
@@ -3125,11 +2933,11 @@ public:
bool CheckTemplateArgument(TemplateTemplateParmDecl *Param,
const TemplateArgumentLoc &Arg);
- OwningExprResult
+ ExprResult
BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ParamType,
SourceLocation Loc);
- OwningExprResult
+ ExprResult
BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc);
@@ -3184,7 +2992,7 @@ public:
/// \param SS the nested-name-specifier following the typename (e.g., 'T::').
/// \param II the identifier we're retrieving (e.g., 'type' in the example).
/// \param IdLoc the location of the identifier.
- virtual TypeResult
+ TypeResult
ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS, const IdentifierInfo &II,
SourceLocation IdLoc);
@@ -3198,10 +3006,10 @@ public:
/// \param SS the nested-name-specifier following the typename (e.g., 'T::').
/// \param TemplateLoc the location of the 'template' keyword, if any.
/// \param Ty the type that the typename specifier refers to.
- virtual TypeResult
+ TypeResult
ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS, SourceLocation TemplateLoc,
- TypeTy *Ty);
+ ParsedType Ty);
QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS,
@@ -3215,6 +3023,8 @@ public:
DeclarationName Name);
bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+ ExprResult RebuildExprInCurrentInstantiation(Expr *E);
+
std::string
getTemplateArgumentBindingsText(const TemplateParameterList *Params,
const TemplateArgumentList &Args);
@@ -3249,7 +3059,7 @@ public:
/// cv-qualifiers on a template parameter type that would
/// otherwise be deduced, e.g., we tried to deduce T in "const T"
/// but were given a non-const "X".
- TDK_InconsistentQuals,
+ TDK_Underqualified,
/// \brief Substitution of the deduced template argument values
/// resulted in an error.
TDK_SubstitutionFailure,
@@ -3272,93 +3082,10 @@ public:
TDK_FailedOverloadResolution
};
- /// \brief Provides information about an attempted template argument
- /// deduction, whose success or failure was described by a
- /// TemplateDeductionResult value.
- class TemplateDeductionInfo {
- /// \brief The context in which the template arguments are stored.
- ASTContext &Context;
-
- /// \brief The deduced template argument list.
- ///
- TemplateArgumentList *Deduced;
-
- /// \brief The source location at which template argument
- /// deduction is occurring.
- SourceLocation Loc;
-
- // do not implement these
- TemplateDeductionInfo(const TemplateDeductionInfo&);
- TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
-
- public:
- TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
- : Context(Context), Deduced(0), Loc(Loc) { }
-
- ~TemplateDeductionInfo() {
- // FIXME: if (Deduced) Deduced->Destroy(Context);
- }
-
- /// \brief Returns the location at which template argument is
- /// occuring.
- SourceLocation getLocation() const {
- return Loc;
- }
-
- /// \brief Take ownership of the deduced template argument list.
- TemplateArgumentList *take() {
- TemplateArgumentList *Result = Deduced;
- Deduced = 0;
- return Result;
- }
-
- /// \brief Provide a new template argument list that contains the
- /// results of template argument deduction.
- void reset(TemplateArgumentList *NewDeduced) {
- // FIXME: if (Deduced) Deduced->Destroy(Context);
- Deduced = NewDeduced;
- }
-
- /// \brief The template parameter to which a template argument
- /// deduction failure refers.
- ///
- /// Depending on the result of template argument deduction, this
- /// template parameter may have different meanings:
- ///
- /// TDK_Incomplete: this is the first template parameter whose
- /// corresponding template argument was not deduced.
- ///
- /// TDK_Inconsistent: this is the template parameter for which
- /// two different template argument values were deduced.
- TemplateParameter Param;
-
- /// \brief The first template argument to which the template
- /// argument deduction failure refers.
- ///
- /// Depending on the result of the template argument deduction,
- /// this template argument may have different meanings:
- ///
- /// TDK_Inconsistent: this argument is the first value deduced
- /// for the corresponding template parameter.
- ///
- /// TDK_SubstitutionFailure: this argument is the template
- /// argument we were instantiating when we encountered an error.
- ///
- /// TDK_NonDeducedMismatch: this is the template argument
- /// provided in the source code.
- TemplateArgument FirstArg;
-
- /// \brief The second template argument to which the template
- /// argument deduction failure refers.
- ///
- /// FIXME: Finish documenting this.
- TemplateArgument SecondArg;
- };
-
TemplateDeductionResult
DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
@@ -3366,40 +3093,40 @@ public:
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
llvm::SmallVectorImpl<QualType> &ParamTypes,
QualType *FunctionType,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned NumExplicitlySpecified,
FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ArgFunctionType,
FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType ToType,
CXXConversionDecl *&Specialization,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
FunctionDecl *&Specialization,
- TemplateDeductionInfo &Info);
+ sema::TemplateDeductionInfo &Info);
FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
@@ -3715,88 +3442,6 @@ public:
}
};
- /// \brief A stack-allocated class that identifies which local
- /// variable declaration instantiations are present in this scope.
- ///
- /// A new instance of this class type will be created whenever we
- /// instantiate a new function declaration, which will have its own
- /// set of parameter declarations.
- class LocalInstantiationScope {
- /// \brief Reference to the semantic analysis that is performing
- /// this template instantiation.
- Sema &SemaRef;
-
- /// \brief A mapping from local declarations that occur
- /// within a template to their instantiations.
- ///
- /// This mapping is used during instantiation to keep track of,
- /// e.g., function parameter and variable declarations. For example,
- /// given:
- ///
- /// \code
- /// template<typename T> T add(T x, T y) { return x + y; }
- /// \endcode
- ///
- /// when we instantiate add<int>, we will introduce a mapping from
- /// the ParmVarDecl for 'x' that occurs in the template to the
- /// instantiated ParmVarDecl for 'x'.
- llvm::DenseMap<const Decl *, Decl *> LocalDecls;
-
- /// \brief The outer scope, which contains local variable
- /// definitions from some other instantiation (that may not be
- /// relevant to this particular scope).
- LocalInstantiationScope *Outer;
-
- /// \brief Whether we have already exited this scope.
- bool Exited;
-
- /// \brief Whether to combine this scope with the outer scope, such that
- /// lookup will search our outer scope.
- bool CombineWithOuterScope;
-
- // This class is non-copyable
- LocalInstantiationScope(const LocalInstantiationScope &);
- LocalInstantiationScope &operator=(const LocalInstantiationScope &);
-
- public:
- LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
- : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
- Exited(false), CombineWithOuterScope(CombineWithOuterScope)
- {
- SemaRef.CurrentInstantiationScope = this;
- }
-
- ~LocalInstantiationScope() {
- Exit();
- }
-
- /// \brief Exit this local instantiation scope early.
- void Exit() {
- if (Exited)
- return;
-
- SemaRef.CurrentInstantiationScope = Outer;
- Exited = true;
- }
-
- Decl *getInstantiationOf(const Decl *D);
-
- VarDecl *getInstantiationOf(const VarDecl *Var) {
- return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
- }
-
- ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
- return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
- }
-
- NonTypeTemplateParmDecl *getInstantiationOf(
- const NonTypeTemplateParmDecl *Var) {
- return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
- }
-
- void InstantiatedLocal(const Decl *D, Decl *Inst);
- };
-
/// \brief The current instantiation scope used to store local
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
@@ -3819,7 +3464,7 @@ public:
/// \brief The queue of implicit template instantiations that are required
/// but have not yet been performed.
- std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations;
+ std::deque<PendingImplicitInstantiation> PendingInstantiations;
/// \brief The queue of implicit template instantiations that are required
/// and must be performed within the current local scope.
@@ -3830,7 +3475,7 @@ public:
/// types, static variables, enumerators, etc.
std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
- void PerformPendingImplicitInstantiations(bool LocalOnly = false);
+ void PerformPendingInstantiations(bool LocalOnly = false);
TypeSourceInfo *SubstType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &TemplateArgs,
@@ -3846,11 +3491,11 @@ public:
DeclarationName Entity);
ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs);
- OwningExprResult SubstExpr(Expr *E,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ ExprResult SubstExpr(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
- OwningStmtResult SubstStmt(Stmt *S,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ StmtResult SubstStmt(Stmt *S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
Decl *SubstDecl(Decl *D, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -3867,6 +3512,9 @@ public:
TemplateSpecializationKind TSK,
bool Complain = true);
+ void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+ Decl *Pattern, Decl *Inst);
+
bool
InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
@@ -3887,7 +3535,9 @@ public:
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
const MultiLevelTemplateArgumentList &TemplateArgs);
-
+ DeclarationNameInfo
+ SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
TemplateName
SubstTemplateName(TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs);
@@ -3914,18 +3564,18 @@ public:
const MultiLevelTemplateArgumentList &TemplateArgs);
// Objective-C declarations.
- virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList);
-
- virtual DeclPtrTy ActOnCompatiblityAlias(
+ Decl *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *SuperName,
+ SourceLocation SuperLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc,
+ AttributeList *AttrList);
+
+ Decl *ActOnCompatiblityAlias(
SourceLocation AtCompatibilityAliasLoc,
IdentifierInfo *AliasName, SourceLocation AliasLocation,
IdentifierInfo *ClassName, SourceLocation ClassLocation);
@@ -3935,56 +3585,55 @@ public:
SourceLocation &PLoc, SourceLocation PrevLoc,
const ObjCList<ObjCProtocolDecl> &PList);
- virtual DeclPtrTy ActOnStartProtocolInterface(
+ Decl *ActOnStartProtocolInterface(
SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
- const DeclPtrTy *ProtoRefNames, unsigned NumProtoRefs,
+ Decl * const *ProtoRefNames, unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
AttributeList *AttrList);
- virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *CategoryName,
- SourceLocation CategoryLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc);
-
- virtual DeclPtrTy ActOnStartClassImplementation(
+ Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CategoryName,
+ SourceLocation CategoryLoc,
+ Decl * const *ProtoRefs,
+ unsigned NumProtoRefs,
+ const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc);
+
+ Decl *ActOnStartClassImplementation(
SourceLocation AtClassImplLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
SourceLocation SuperClassLoc);
- virtual DeclPtrTy ActOnStartCategoryImplementation(
- SourceLocation AtCatImplLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *CatName,
- SourceLocation CatLoc);
+ Decl *ActOnStartCategoryImplementation(SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc);
- virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
- IdentifierInfo **IdentList,
- SourceLocation *IdentLocs,
- unsigned NumElts);
+ Decl *ActOnForwardClassDeclaration(SourceLocation Loc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ unsigned NumElts);
- virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
- const IdentifierLocPair *IdentList,
- unsigned NumElts,
- AttributeList *attrList);
+ Decl *ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+ const IdentifierLocPair *IdentList,
+ unsigned NumElts,
+ AttributeList *attrList);
- virtual void FindProtocolDeclaration(bool WarnOnDeclarations,
- const IdentifierLocPair *ProtocolId,
- unsigned NumProtocols,
- llvm::SmallVectorImpl<DeclPtrTy> &Protocols);
+ void FindProtocolDeclaration(bool WarnOnDeclarations,
+ const IdentifierLocPair *ProtocolId,
+ unsigned NumProtocols,
+ llvm::SmallVectorImpl<Decl *> &Protocols);
/// Ensure attributes are consistent with type.
/// \param [in, out] Attributes The attributes to check; they will
/// be modified to be consistent with \arg PropertyTy.
- void CheckObjCPropertyAttributes(DeclPtrTy PropertyPtrTy,
+ void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
SourceLocation Loc,
unsigned &Attributes);
void ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *DC);
@@ -3997,7 +3646,7 @@ public:
ObjCMethodDecl *MethodDecl,
bool IsInstance);
- void CompareProperties(Decl *CDecl, DeclPtrTy MergeProtocols);
+ void CompareProperties(Decl *CDecl, Decl *MergeProtocols);
void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
ObjCInterfaceDecl *ID);
@@ -4005,31 +3654,42 @@ public:
void MatchOneProtocolPropertiesInClass(Decl *CDecl,
ObjCProtocolDecl *PDecl);
- virtual void ActOnAtEnd(Scope *S, SourceRange AtEnd,
- DeclPtrTy classDecl,
- DeclPtrTy *allMethods = 0, unsigned allNum = 0,
- DeclPtrTy *allProperties = 0, unsigned pNum = 0,
- DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
-
- virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc,
- FieldDeclarator &FD, ObjCDeclSpec &ODS,
- Selector GetterSel, Selector SetterSel,
- DeclPtrTy ClassCategory,
- bool *OverridingProperty,
- tok::ObjCKeywordKind MethodImplKind);
-
- virtual DeclPtrTy ActOnPropertyImplDecl(Scope *S,
- SourceLocation AtLoc,
- SourceLocation PropertyLoc,
- bool ImplKind,DeclPtrTy ClassImplDecl,
- IdentifierInfo *PropertyId,
- IdentifierInfo *PropertyIvar);
-
- virtual DeclPtrTy ActOnMethodDeclaration(
+ void ActOnAtEnd(Scope *S, SourceRange AtEnd, Decl *classDecl,
+ Decl **allMethods = 0, unsigned allNum = 0,
+ Decl **allProperties = 0, unsigned pNum = 0,
+ DeclGroupPtrTy *allTUVars = 0, unsigned tuvNum = 0);
+
+ Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
+ FieldDeclarator &FD, ObjCDeclSpec &ODS,
+ Selector GetterSel, Selector SetterSel,
+ Decl *ClassCategory,
+ bool *OverridingProperty,
+ tok::ObjCKeywordKind MethodImplKind);
+
+ Decl *ActOnPropertyImplDecl(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation PropertyLoc,
+ bool ImplKind,Decl *ClassImplDecl,
+ IdentifierInfo *PropertyId,
+ IdentifierInfo *PropertyIvar);
+
+ struct ObjCArgInfo {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ // The Type is null if no type was specified, and the DeclSpec is invalid
+ // in this case.
+ ParsedType Type;
+ ObjCDeclSpec DeclSpec;
+
+ /// ArgAttrs - Attribute list for this argument.
+ AttributeList *ArgAttrs;
+ };
+
+ Decl *ActOnMethodDeclaration(
SourceLocation BeginLoc, // location of the + or -.
SourceLocation EndLoc, // location of the ; or {.
tok::TokenKind MethodType,
- DeclPtrTy ClassDecl, ObjCDeclSpec &ReturnQT, TypeTy *ReturnType,
+ Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
Selector Sel,
// optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs().
@@ -4047,101 +3707,133 @@ public:
ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel,
ObjCInterfaceDecl *ClassDecl);
- OwningExprResult
+ ExprResult
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Expr *BaseExpr,
DeclarationName MemberName,
SourceLocation MemberLoc);
- virtual OwningExprResult
+ ExprResult
ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
IdentifierInfo &propertyName,
SourceLocation receiverNameLoc,
SourceLocation propertyNameLoc);
- virtual ObjCMessageKind getObjCMessageKind(Scope *S,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- bool IsSuper,
- bool HasTrailingDot,
- TypeTy *&ReceiverType);
-
- virtual OwningExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args);
-
- OwningExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
- QualType ReceiverType,
- SourceLocation SuperLoc,
- Selector Sel,
- ObjCMethodDecl *Method,
- SourceLocation LBracLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args);
-
- virtual OwningExprResult ActOnClassMessage(Scope *S,
- TypeTy *Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args);
-
- OwningExprResult BuildInstanceMessage(ExprArg Receiver,
- QualType ReceiverType,
- SourceLocation SuperLoc,
- Selector Sel,
- ObjCMethodDecl *Method,
- SourceLocation LBracLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args);
-
- virtual OwningExprResult ActOnInstanceMessage(Scope *S,
- ExprArg Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args);
-
+ /// \brief Describes the kind of message expression indicated by a message
+ /// send that starts with an identifier.
+ enum ObjCMessageKind {
+ /// \brief The message is sent to 'super'.
+ ObjCSuperMessage,
+ /// \brief The message is an instance message.
+ ObjCInstanceMessage,
+ /// \brief The message is a class message, and the identifier is a type
+ /// name.
+ ObjCClassMessage
+ };
+
+ ObjCMessageKind getObjCMessageKind(Scope *S,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsSuper,
+ bool HasTrailingDot,
+ ParsedType &ReceiverType);
+
+ ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildInstanceMessage(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+
+ enum PragmaOptionsAlignKind {
+ POAK_Native, // #pragma options align=native
+ POAK_Natural, // #pragma options align=natural
+ POAK_Packed, // #pragma options align=packed
+ POAK_Power, // #pragma options align=power
+ POAK_Mac68k, // #pragma options align=mac68k
+ POAK_Reset // #pragma options align=reset
+ };
/// ActOnPragmaOptionsAlign - Called on well formed #pragma options align.
- virtual void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
- SourceLocation PragmaLoc,
- SourceLocation KindLoc);
+ void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+ SourceLocation PragmaLoc,
+ SourceLocation KindLoc);
+
+ enum PragmaPackKind {
+ PPK_Default, // #pragma pack([n])
+ PPK_Show, // #pragma pack(show), only supported by MSVC.
+ PPK_Push, // #pragma pack(push, [identifier], [n])
+ PPK_Pop // #pragma pack(pop, [identifier], [n])
+ };
/// ActOnPragmaPack - Called on well formed #pragma pack(...).
- virtual void ActOnPragmaPack(PragmaPackKind Kind,
- IdentifierInfo *Name,
- ExprTy *Alignment,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ void ActOnPragmaPack(PragmaPackKind Kind,
+ IdentifierInfo *Name,
+ Expr *Alignment,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
/// ActOnPragmaUnused - Called on well-formed '#pragma unused'.
- virtual void ActOnPragmaUnused(const Token *Identifiers,
- unsigned NumIdentifiers, Scope *curScope,
- SourceLocation PragmaLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc);
+ void ActOnPragmaUnused(const Token *Identifiers,
+ unsigned NumIdentifiers, Scope *curScope,
+ SourceLocation PragmaLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc);
+
+ /// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
+ void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc);
NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II);
void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
/// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
- virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc);
+ void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc);
/// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident.
- virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc,
- SourceLocation AliasNameLoc);
+ void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
+ IdentifierInfo* AliasName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc,
+ SourceLocation AliasNameLoc);
/// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
/// a the record decl, to handle '#pragma pack' and '#pragma options align'.
@@ -4150,16 +3842,35 @@ public:
/// FreePackedContext - Deallocate and null out PackContext.
void FreePackedContext();
+ /// PushVisibilityAttr - Note that we've entered a context with a
+ /// visibility attribute.
+ void PushVisibilityAttr(const VisibilityAttr *Attr);
+
+ /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
+ /// add an appropriate visibility attribute.
+ void AddPushedVisibilityAttribute(Decl *RD);
+
+ /// PopPragmaVisibility - Pop the top element of the visibility stack; used
+ /// for '#pragma GCC visibility' and visibility attributes on namespaces.
+ void PopPragmaVisibility();
+
+ /// FreeVisContext - Deallocate and null out VisContext.
+ void FreeVisContext();
+
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
+ void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *T);
+
+ /// CastCategory - Get the correct forwarded implicit cast result category
+ /// from the inner expression.
+ ExprValueKind CastCategory(Expr *E);
/// 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.
- void ImpCastExprToType(Expr *&Expr, QualType Type, CastExpr::CastKind Kind,
- bool isLvalue = false,
- CXXBaseSpecifierArray BasePath =
- CXXBaseSpecifierArray());
+ void ImpCastExprToType(Expr *&Expr, QualType Type, CastKind CK,
+ ExprValueKind VK = VK_RValue,
+ const CXXCastPath *BasePath = 0);
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1).
@@ -4420,12 +4131,13 @@ public:
ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
QualType T1, QualType T2,
- bool& DerivedToBase);
+ bool &DerivedToBase,
+ bool &ObjCConversion);
/// CheckCastTypes - Check type constraints for casting between types under
/// C semantics, or forward to CXXCheckCStyleCast in C++.
bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind, CXXBaseSpecifierArray &BasePath,
+ CastKind &Kind, CXXCastPath &BasePath,
bool FunctionalStyle = false);
// CheckVectorCast - check type constraints for vectors.
@@ -4433,7 +4145,7 @@ public:
// We allow casting between vectors and integer datatypes of the same size.
// returns true if the cast is invalid
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
- CastExpr::CastKind &Kind);
+ CastKind &Kind);
// CheckExtVectorCast - check type constraints for extended vectors.
// Since vectors are an extension, there are no C standard reference for this.
@@ -4441,13 +4153,12 @@ public:
// or vectors and the element type of that vector.
// returns true if the cast is invalid
bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind);
+ CastKind &Kind);
/// CXXCheckCStyleCast - Check constraints of a C-style or function-style
/// cast under C++ semantics.
bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CastKind &Kind, CXXCastPath &BasePath,
bool FunctionalStyle);
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
@@ -4469,8 +4180,8 @@ public:
/// \return true iff there were any errors
bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc);
- virtual OwningExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,
- ExprArg SubExpr);
+ ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc,
+ Expr *SubExpr);
/// DiagnoseAssignmentAsCondition - Given that an expression is
/// being used as a boolean condition, warn if it's an assignment.
@@ -4508,82 +4219,156 @@ public:
/// \name Code completion
//@{
- virtual void CodeCompleteOrdinaryName(Scope *S,
- CodeCompletionContext CompletionContext);
- virtual void CodeCompleteExpression(Scope *S, QualType T);
- virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
- SourceLocation OpLoc,
- bool IsArrow);
- virtual void CodeCompleteTag(Scope *S, unsigned TagSpec);
- virtual void CodeCompleteCase(Scope *S);
- virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
- ExprTy **Args, unsigned NumArgs);
- virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D);
- virtual void CodeCompleteReturn(Scope *S);
- virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS);
+ /// \brief Describes the context in which code completion occurs.
+ enum ParserCompletionContext {
+ /// \brief Code completion occurs at top-level or namespace context.
+ PCC_Namespace,
+ /// \brief Code completion occurs within a class, struct, or union.
+ PCC_Class,
+ /// \brief Code completion occurs within an Objective-C interface, protocol,
+ /// or category.
+ PCC_ObjCInterface,
+ /// \brief Code completion occurs within an Objective-C implementation or
+ /// category implementation
+ PCC_ObjCImplementation,
+ /// \brief Code completion occurs within the list of instance variables
+ /// in an Objective-C interface, protocol, category, or implementation.
+ PCC_ObjCInstanceVariableList,
+ /// \brief Code completion occurs following one or more template
+ /// headers.
+ PCC_Template,
+ /// \brief Code completion occurs following one or more template
+ /// headers within a class.
+ PCC_MemberTemplate,
+ /// \brief Code completion occurs within an expression.
+ PCC_Expression,
+ /// \brief Code completion occurs within a statement, which may
+ /// also be an expression or a declaration.
+ PCC_Statement,
+ /// \brief Code completion occurs at the beginning of the
+ /// initialization statement (or expression) in a for loop.
+ PCC_ForInit,
+ /// \brief Code completion occurs within the condition of an if,
+ /// while, switch, or for statement.
+ PCC_Condition,
+ /// \brief Code completion occurs within the body of a function on a
+ /// recovery path, where we do not have a specific handle on our position
+ /// in the grammar.
+ PCC_RecoveryInFunction,
+ /// \brief Code completion occurs where only a type is permitted.
+ PCC_Type
+ };
+
+ void CodeCompleteOrdinaryName(Scope *S,
+ ParserCompletionContext CompletionContext);
+ void CodeCompleteDeclarator(Scope *S,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers);
- virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
- bool EnteringContext);
- virtual void CodeCompleteUsing(Scope *S);
- virtual void CodeCompleteUsingDirective(Scope *S);
- virtual void CodeCompleteNamespaceDecl(Scope *S);
- virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
- virtual void CodeCompleteOperatorName(Scope *S);
-
- virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
- bool InInterface);
- virtual void CodeCompleteObjCAtVisibility(Scope *S);
- virtual void CodeCompleteObjCAtStatement(Scope *S);
- virtual void CodeCompleteObjCAtExpression(Scope *S);
- virtual void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
- virtual void CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
- unsigned NumMethods);
- virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
- unsigned NumMethods);
- virtual void CodeCompleteObjCMessageReceiver(Scope *S);
- virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- virtual void CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
- unsigned NumProtocols);
- virtual void CodeCompleteObjCProtocolDecl(Scope *S);
- virtual void CodeCompleteObjCInterfaceDecl(Scope *S);
- virtual void CodeCompleteObjCSuperclass(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc);
- virtual void CodeCompleteObjCImplementationDecl(Scope *S);
- virtual void CodeCompleteObjCInterfaceCategory(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc);
- virtual void CodeCompleteObjCImplementationCategory(Scope *S,
- IdentifierInfo *ClassName,
- SourceLocation ClassNameLoc);
- virtual void CodeCompleteObjCPropertyDefinition(Scope *S,
- DeclPtrTy ObjCImpDecl);
- virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
- IdentifierInfo *PropertyName,
- DeclPtrTy ObjCImpDecl);
- virtual void CodeCompleteObjCMethodDecl(Scope *S,
- bool IsInstanceMethod,
- TypeTy *ReturnType,
- DeclPtrTy IDecl);
- virtual void CodeCompleteObjCMethodDeclSelector(Scope *S,
- bool IsInstanceMethod,
- bool AtParameterName,
- TypeTy *ReturnType,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
+ struct CodeCompleteExpressionData;
+ void CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data);
+ void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool IsArrow);
+ void CodeCompleteTag(Scope *S, unsigned TagSpec);
+ void CodeCompleteTypeQualifiers(DeclSpec &DS);
+ void CodeCompleteCase(Scope *S);
+ void CodeCompleteCall(Scope *S, Expr *Fn, Expr **Args, unsigned NumArgs);
+ void CodeCompleteInitializer(Scope *S, Decl *D);
+ void CodeCompleteReturn(Scope *S);
+ void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS);
+
+ void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext);
+ void CodeCompleteUsing(Scope *S);
+ void CodeCompleteUsingDirective(Scope *S);
+ void CodeCompleteNamespaceDecl(Scope *S);
+ void CodeCompleteNamespaceAliasDecl(Scope *S);
+ void CodeCompleteOperatorName(Scope *S);
+ void CodeCompleteConstructorInitializer(Decl *Constructor,
+ CXXBaseOrMemberInitializer** Initializers,
+ unsigned NumInitializers);
+ void CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
+ bool InInterface);
+ void CodeCompleteObjCAtVisibility(Scope *S);
+ void CodeCompleteObjCAtStatement(Scope *S);
+ void CodeCompleteObjCAtExpression(Scope *S);
+ void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+ void CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
+ Decl **Methods,
+ unsigned NumMethods);
+ void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl,
+ Decl **Methods,
+ unsigned NumMethods);
+ void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS);
+ void CodeCompleteObjCMessageReceiver(Scope *S);
+ void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool IsSuper);
+ void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool IsSuper);
+ void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar);
+ void CodeCompleteObjCSelector(Scope *S,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
+ unsigned NumProtocols);
+ void CodeCompleteObjCProtocolDecl(Scope *S);
+ void CodeCompleteObjCInterfaceDecl(Scope *S);
+ void CodeCompleteObjCSuperclass(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCImplementationDecl(Scope *S);
+ void CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassNameLoc);
+ void CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl);
+ void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ Decl *ObjCImpDecl);
+ void CodeCompleteObjCMethodDecl(Scope *S,
+ bool IsInstanceMethod,
+ ParsedType ReturnType,
+ Decl *IDecl);
+ void CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ ParsedType ReturnType,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents);
+ void CodeCompletePreprocessorDirective(bool InConditional);
+ void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
+ void CodeCompletePreprocessorMacroName(bool IsDefinition);
+ void CodeCompletePreprocessorExpression();
+ void CodeCompletePreprocessorMacroArgument(Scope *S,
+ IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned Argument);
+ void CodeCompleteNaturalLanguage();
+ void GatherGlobalCodeCompletions(
+ llvm::SmallVectorImpl<CodeCompletionResult> &Results);
//@}
+ void PrintStats() const {}
+
//===--------------------------------------------------------------------===//
// Extra semantic analysis beyond the C type system
@@ -4598,8 +4383,7 @@ private:
bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall);
bool CheckObjCString(Expr *Arg);
- Action::OwningExprResult CheckBuiltinFunctionCall(unsigned BuiltinID,
- CallExpr *TheCall);
+ ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
@@ -4609,45 +4393,63 @@ private:
public:
// Used by C++ template instantiation.
- Action::OwningExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+ ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
private:
bool SemaBuiltinPrefetch(CallExpr *TheCall);
bool SemaBuiltinObjectSize(CallExpr *TheCall);
bool SemaBuiltinLongjmp(CallExpr *TheCall);
- OwningExprResult SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult);
+ ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
llvm::APSInt &Result);
+
bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
bool HasVAListArg, unsigned format_idx,
- unsigned firstDataArg);
- void CheckPrintfString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
+ unsigned firstDataArg, bool isPrintf);
+
+ void CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr,
const CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg);
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf);
+
void CheckNonNullArguments(const NonNullAttr *NonNull,
const CallExpr *TheCall);
- void CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg);
+
+ void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf);
+
void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc);
void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);
void CheckImplicitConversions(Expr *E);
+
+ /// \brief The parser's current scope.
+ ///
+ /// The parser maintains this state here.
+ Scope *CurScope;
+
+protected:
+ friend class Parser;
+
+ /// \brief Retrieve the parser's current scope.
+ Scope *getCurScope() const { return CurScope; }
};
-//===--------------------------------------------------------------------===//
-// Typed version of Parser::ExprArg (smart pointer for wrapping Expr pointers).
-template <typename T>
-class ExprOwningPtr : public Action::ExprArg {
-public:
- ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {}
+/// \brief RAII object that enters a new expression evaluation context.
+class EnterExpressionEvaluationContext {
+ Sema &Actions;
- void reset(T* p) { Action::ExprArg::operator=(p); }
- T* get() const { return static_cast<T*>(Action::ExprArg::get()); }
- T* take() { return static_cast<T*>(Action::ExprArg::take()); }
- T* release() { return take(); }
+public:
+ EnterExpressionEvaluationContext(Sema &Actions,
+ Sema::ExpressionEvaluationContext NewContext)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(NewContext);
+ }
- T& operator*() const { return *get(); }
- T* operator->() const { return get(); }
+ ~EnterExpressionEvaluationContext() {
+ Actions.PopExpressionEvaluationContext();
+ }
};
} // end namespace clang
diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h
new file mode 100644
index 000000000000..64b83e3bf612
--- /dev/null
+++ b/include/clang/Sema/SemaInternal.h
@@ -0,0 +1,30 @@
+//===--- SemaInternal.h - Internal Sema Interfaces --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides common API and #includes for the internal
+// implementation of Sema.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+#define LLVM_CLANG_SEMA_SEMA_INTERNAL_H
+
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+
+inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
+ return PartialDiagnostic(DiagID, Context.getDiagAllocator());
+}
+
+}
+
+#endif
diff --git a/lib/Sema/SemaTemplate.h b/include/clang/Sema/Template.h
index b3f46519ab7f..a7b3b8461854 100644
--- a/lib/Sema/SemaTemplate.h
+++ b/include/clang/Sema/Template.h
@@ -101,7 +101,7 @@ namespace clang {
};
/// \brief The context in which partial ordering of function templates occurs.
- enum TemplatePartialOrderingContext {
+ enum TPOC {
/// \brief Partial ordering of function templates for a function call.
TPOC_Call,
/// \brief Partial ordering of function templates for a call to a
@@ -113,6 +113,17 @@ namespace clang {
TPOC_Other
};
+ // This is lame but unavoidable in a world without forward
+ // declarations of enums. The alternatives are to either pollute
+ // Sema.h (by including this file) or sacrifice type safety (by
+ // making Sema.h declare things as enums).
+ class TemplatePartialOrderingContext {
+ TPOC Value;
+ public:
+ TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
+ operator TPOC() const { return Value; }
+ };
+
/// \brief Captures a template argument whose value has been deduced
/// via c++ template argument deduction.
class DeducedTemplateArgument : public TemplateArgument {
@@ -146,6 +157,88 @@ namespace clang {
DeducedFromArrayBound = Deduced;
}
};
+
+ /// \brief A stack-allocated class that identifies which local
+ /// variable declaration instantiations are present in this scope.
+ ///
+ /// A new instance of this class type will be created whenever we
+ /// instantiate a new function declaration, which will have its own
+ /// set of parameter declarations.
+ class LocalInstantiationScope {
+ /// \brief Reference to the semantic analysis that is performing
+ /// this template instantiation.
+ Sema &SemaRef;
+
+ /// \brief A mapping from local declarations that occur
+ /// within a template to their instantiations.
+ ///
+ /// This mapping is used during instantiation to keep track of,
+ /// e.g., function parameter and variable declarations. For example,
+ /// given:
+ ///
+ /// \code
+ /// template<typename T> T add(T x, T y) { return x + y; }
+ /// \endcode
+ ///
+ /// when we instantiate add<int>, we will introduce a mapping from
+ /// the ParmVarDecl for 'x' that occurs in the template to the
+ /// instantiated ParmVarDecl for 'x'.
+ llvm::DenseMap<const Decl *, Decl *> LocalDecls;
+
+ /// \brief The outer scope, which contains local variable
+ /// definitions from some other instantiation (that may not be
+ /// relevant to this particular scope).
+ LocalInstantiationScope *Outer;
+
+ /// \brief Whether we have already exited this scope.
+ bool Exited;
+
+ /// \brief Whether to combine this scope with the outer scope, such that
+ /// lookup will search our outer scope.
+ bool CombineWithOuterScope;
+
+ // This class is non-copyable
+ LocalInstantiationScope(const LocalInstantiationScope &);
+ LocalInstantiationScope &operator=(const LocalInstantiationScope &);
+
+ public:
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ Exited(false), CombineWithOuterScope(CombineWithOuterScope)
+ {
+ SemaRef.CurrentInstantiationScope = this;
+ }
+
+ ~LocalInstantiationScope() {
+ Exit();
+ }
+
+ /// \brief Exit this local instantiation scope early.
+ void Exit() {
+ if (Exited)
+ return;
+
+ SemaRef.CurrentInstantiationScope = Outer;
+ Exited = true;
+ }
+
+ Decl *getInstantiationOf(const Decl *D);
+
+ VarDecl *getInstantiationOf(const VarDecl *Var) {
+ return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
+ ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
+ return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
+ NonTypeTemplateParmDecl *getInstantiationOf(
+ const NonTypeTemplateParmDecl *Var) {
+ return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
+ }
+
+ void InstantiatedLocal(const Decl *D, Decl *Inst);
+ };
}
#endif // LLVM_CLANG_SEMA_TEMPLATE_H
diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h
new file mode 100644
index 000000000000..ac32e9c24f6d
--- /dev/null
+++ b/include/clang/Sema/TemplateDeduction.h
@@ -0,0 +1,111 @@
+//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===/
+//
+// This file provides types used with Sema's template argument deduction
+// routines.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
+
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+
+class ASTContext;
+class TemplateArgumentList;
+
+namespace sema {
+
+/// \brief Provides information about an attempted template argument
+/// deduction, whose success or failure was described by a
+/// TemplateDeductionResult value.
+class TemplateDeductionInfo {
+ /// \brief The context in which the template arguments are stored.
+ ASTContext &Context;
+
+ /// \brief The deduced template argument list.
+ ///
+ TemplateArgumentList *Deduced;
+
+ /// \brief The source location at which template argument
+ /// deduction is occurring.
+ SourceLocation Loc;
+
+ // do not implement these
+ TemplateDeductionInfo(const TemplateDeductionInfo&);
+ TemplateDeductionInfo &operator=(const TemplateDeductionInfo&);
+
+public:
+ TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc)
+ : Context(Context), Deduced(0), Loc(Loc) { }
+
+ ~TemplateDeductionInfo() {
+ // FIXME: if (Deduced) Deduced->Destroy(Context);
+ }
+
+ /// \brief Returns the location at which template argument is
+ /// occuring.
+ SourceLocation getLocation() const {
+ return Loc;
+ }
+
+ /// \brief Take ownership of the deduced template argument list.
+ TemplateArgumentList *take() {
+ TemplateArgumentList *Result = Deduced;
+ Deduced = 0;
+ return Result;
+ }
+
+ /// \brief Provide a new template argument list that contains the
+ /// results of template argument deduction.
+ void reset(TemplateArgumentList *NewDeduced) {
+ // FIXME: if (Deduced) Deduced->Destroy(Context);
+ Deduced = NewDeduced;
+ }
+
+ /// \brief The template parameter to which a template argument
+ /// deduction failure refers.
+ ///
+ /// Depending on the result of template argument deduction, this
+ /// template parameter may have different meanings:
+ ///
+ /// TDK_Incomplete: this is the first template parameter whose
+ /// corresponding template argument was not deduced.
+ ///
+ /// TDK_Inconsistent: this is the template parameter for which
+ /// two different template argument values were deduced.
+ TemplateParameter Param;
+
+ /// \brief The first template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// Depending on the result of the template argument deduction,
+ /// this template argument may have different meanings:
+ ///
+ /// TDK_Inconsistent: this argument is the first value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_SubstitutionFailure: this argument is the template
+ /// argument we were instantiating when we encountered an error.
+ ///
+ /// TDK_NonDeducedMismatch: this is the template argument
+ /// provided in the source code.
+ TemplateArgument FirstArg;
+
+ /// \brief The second template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// FIXME: Finish documenting this.
+ TemplateArgument SecondArg;
+};
+
+}
+}
+
+#endif
diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 27a2b7d0b951..0fa446dd34de 100644
--- a/include/clang/Frontend/PCHBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -1,4 +1,4 @@
-//===- PCHBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
+//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This header defines Bitcode enum values for Clang precompiled header files.
+// This header defines Bitcode enum values for Clang serialized AST files.
//
// The enum values defined in this file should be considered permanent. If
// new features are added, they should have values added at the end of the
@@ -17,42 +17,44 @@
#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
+#include "clang/AST/Type.h"
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/System/DataTypes.h"
+#include "llvm/ADT/DenseMap.h"
namespace clang {
- namespace pch {
- /// \brief PCH major version number supported by this version of
+ namespace serialization {
+ /// \brief AST file major version number supported by this version of
/// Clang.
///
- /// Whenever the PCH format changes in a way that makes it
+ /// Whenever the AST file format changes in a way that makes it
/// incompatible with previous versions (such that a reader
/// designed for the previous version could not support reading
/// the new version), this number should be increased.
///
- /// Version 4 of PCH files also requires that the version control branch and
+ /// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
- /// PCH files at this time.
+ /// AST files at this time.
const unsigned VERSION_MAJOR = 4;
- /// \brief PCH minor version number supported by this version of
+ /// \brief AST file minor version number supported by this version of
/// Clang.
///
- /// Whenever the PCH format changes in a way that is still
+ /// Whenever the AST format changes in a way that is still
/// compatible with previous versions (such that a reader designed
/// for the previous version could still support reading the new
/// version by ignoring new kinds of subblocks), this number
/// should be increased.
const unsigned VERSION_MINOR = 0;
- /// \brief An ID number that refers to a declaration in a PCH file.
+ /// \brief An ID number that refers to a declaration in an AST file.
///
/// The ID numbers of declarations are consecutive (in order of
/// discovery) and start at 2. 0 is reserved for NULL, and 1 is
/// reserved for the translation unit declaration.
typedef uint32_t DeclID;
- /// \brief An ID number that refers to a type in a PCH file.
+ /// \brief An ID number that refers to a type in an AST file.
///
/// The ID of a type is partitioned into two parts: the lower
/// three bits are used to store the const/volatile/restrict
@@ -64,18 +66,64 @@ namespace clang {
/// other types that have serialized representations.
typedef uint32_t TypeID;
- /// \brief An ID number that refers to an identifier in a PCH
+ /// \brief A type index; the type ID with the qualifier bits removed.
+ class TypeIdx {
+ uint32_t Idx;
+ public:
+ TypeIdx() : Idx(0) { }
+ explicit TypeIdx(uint32_t index) : Idx(index) { }
+
+ uint32_t getIndex() const { return Idx; }
+ TypeID asTypeID(unsigned FastQuals) const {
+ return (Idx << Qualifiers::FastWidth) | FastQuals;
+ }
+ static TypeIdx fromTypeID(TypeID ID) {
+ return TypeIdx(ID >> Qualifiers::FastWidth);
+ }
+ };
+
+ /// A structure for putting "fast"-unqualified QualTypes into a
+ /// DenseMap. This uses the standard pointer hash function.
+ struct UnsafeQualTypeDenseMapInfo {
+ static inline bool isEqual(QualType A, QualType B) { return A == B; }
+ static inline QualType getEmptyKey() {
+ return QualType::getFromOpaquePtr((void*) 1);
+ }
+ static inline QualType getTombstoneKey() {
+ return QualType::getFromOpaquePtr((void*) 2);
+ }
+ static inline unsigned getHashValue(QualType T) {
+ 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);
+ }
+ };
+
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ typedef llvm::DenseMap<QualType, TypeIdx, UnsafeQualTypeDenseMapInfo>
+ TypeIdxMap;
+
+ /// \brief An ID number that refers to an identifier in an AST
/// file.
typedef uint32_t IdentID;
typedef uint32_t SelectorID;
/// \brief Describes the various kinds of blocks that occur within
- /// a PCH file.
+ /// an AST file.
enum BlockIDs {
- /// \brief The PCH block, which acts as a container around the
- /// full PCH block.
- PCH_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+ /// \brief The AST block, which acts as a container around the
+ /// full AST block.
+ AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
/// \brief The block containing information about the source
/// manager.
@@ -86,16 +134,16 @@ namespace clang {
PREPROCESSOR_BLOCK_ID,
/// \brief The block containing the definitions of all of the
- /// types and decls used within the PCH file.
+ /// types and decls used within the AST file.
DECLTYPES_BLOCK_ID
};
- /// \brief Record types that occur within the PCH block itself.
- enum PCHRecordTypes {
+ /// \brief Record types that occur within the AST block itself.
+ enum ASTRecordTypes {
/// \brief Record code for the offsets of each type.
///
/// The TYPE_OFFSET constant describes the record that occurs
- /// within the PCH block. The record itself is an array of offsets that
+ /// within the AST block. The record itself is an array of offsets that
/// point into the declarations and types block (identified by
/// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
/// of a type. For a given type ID @c T, the lower three bits of
@@ -110,7 +158,7 @@ namespace clang {
///
/// The DECL_OFFSET constant describes the record that occurs
/// within the block identified by DECL_OFFSETS_BLOCK_ID within
- /// the PCH block. The record itself is an array of offsets that
+ /// the AST block. The record itself is an array of offsets that
/// point into the declarations and types block (identified by
/// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
/// record, after subtracting one to account for the use of
@@ -126,8 +174,8 @@ namespace clang {
/// actually important to check.
LANGUAGE_OPTIONS = 3,
- /// \brief PCH metadata, including the PCH file version number
- /// and the target triple used to build the PCH file.
+ /// \brief AST file metadata, including the AST file version number
+ /// and the target triple used to build the AST file.
METADATA = 4,
/// \brief Record code for the table of offsets of each
@@ -142,7 +190,7 @@ namespace clang {
///
/// The identifier table is a simple blob that contains
/// NULL-terminated strings for all of the identifiers
- /// referenced by the PCH file. The IDENTIFIER_OFFSET table
+ /// referenced by the AST file. The IDENTIFIER_OFFSET table
/// contains the mapping from identifier IDs to the characters
/// in this blob. Note that the starting offsets of all of the
/// identifiers are odd, so that, when the identifier offset
@@ -154,10 +202,10 @@ namespace clang {
/// \brief Record code for the array of external definitions.
///
- /// The PCH file contains a list of all of the unnamed external
+ /// The AST file contains a list of all of the unnamed external
/// definitions present within the parsed headers, stored as an
/// array of declaration IDs. These external definitions will be
- /// reported to the AST consumer after the PCH file has been
+ /// reported to the AST consumer after the AST file has been
/// read, since their presence can affect the semantics of the
/// program (e.g., for code generation).
EXTERNAL_DEFINITIONS = 7,
@@ -172,7 +220,7 @@ namespace clang {
SPECIAL_TYPES = 8,
/// \brief Record code for the extra statistics we gather while
- /// generating a PCH file.
+ /// generating an AST file.
STATISTICS = 9,
/// \brief Record code for the array of tentative definitions.
@@ -198,7 +246,7 @@ namespace clang {
SOURCE_LOCATION_OFFSETS = 15,
/// \brief Record code for the set of source location entries
- /// that need to be preloaded by the PCH reader.
+ /// that need to be preloaded by the AST reader.
///
/// This set contains the source location entry for the
/// predefines buffer and for any file entries that need to be
@@ -212,17 +260,17 @@ namespace clang {
EXT_VECTOR_DECLS = 18,
/// \brief Record code for the original file that was used to
- /// generate the precompiled header.
+ /// generate the AST file.
ORIGINAL_FILE_NAME = 19,
/// Record #20 intentionally left blank.
/// \brief Record code for the version control branch and revision
- /// information of the compiler used to build this PCH file.
+ /// information of the compiler used to build this AST file.
VERSION_CONTROL_BRANCH_REVISION = 21,
- /// \brief Record code for the array of unused static functions.
- UNUSED_STATIC_FUNCS = 22,
+ /// \brief Record code for the array of unused file scoped decls.
+ UNUSED_FILESCOPED_DECLS = 22,
/// \brief Record code for the table of offsets to macro definition
/// entries in the preprocessing record.
@@ -234,10 +282,45 @@ namespace clang {
/// \brief Record code for the array of dynamic classes.
DYNAMIC_CLASSES = 25,
- /// \brief Record code for the chained PCH metadata, including the
- /// PCH version and the name of the PCH this is chained to.
- CHAINED_METADATA = 26
+ /// \brief Record code for the chained AST metadata, including the
+ /// AST file version and the name of the PCH this depends on.
+ CHAINED_METADATA = 26,
+
+ /// \brief Record code for referenced selector pool.
+ REFERENCED_SELECTOR_POOL = 27,
+
+ /// \brief Record code for an update to the TU's lexically contained
+ /// declarations.
+ TU_UPDATE_LEXICAL = 28,
+ /// \brief Record code for an update to first decls pointing to the
+ /// latest redeclarations.
+ REDECLS_UPDATE_LATEST = 29,
+
+ /// \brief Record code for declarations that Sema keeps references of.
+ SEMA_DECL_REFS = 30,
+
+ /// \brief Record code for weak undeclared identifiers.
+ WEAK_UNDECLARED_IDENTIFIERS = 31,
+
+ /// \brief Record code for pending implicit instantiations.
+ PENDING_IMPLICIT_INSTANTIATIONS = 32,
+
+ /// \brief Record code for a decl replacement block.
+ ///
+ /// If a declaration is modified after having been deserialized, and then
+ /// written to a dependent AST file, its ID and offset must be added to
+ /// the replacement block.
+ DECL_REPLACEMENTS = 33,
+
+ /// \brief Record code for an update to a decl context's lookup table.
+ ///
+ /// In practice, this should only be used for the TU and namespaces.
+ UPDATE_VISIBLE = 34,
+
+ /// \brief Record code for template specializations introduced after
+ /// serializations of the original template decl.
+ ADDITIONAL_TEMPLATE_SPECIALIZATIONS = 35
};
/// \brief Record types used within a source manager block.
@@ -286,10 +369,10 @@ namespace clang {
PP_MACRO_DEFINITION = 5
};
- /// \defgroup PCHAST Precompiled header AST constants
+ /// \defgroup ASTAST AST file AST constants
///
/// The constants in this group describe various components of the
- /// abstract syntax tree within a precompiled header.
+ /// abstract syntax tree within an AST file.
///
/// @{
@@ -371,7 +454,7 @@ namespace clang {
/// \brief Record codes for each kind of type.
///
/// These constants describe the type records that can occur within a
- /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each
+ /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
/// constant describes a record for a specific type class in the
/// AST.
enum TypeCode {
@@ -545,8 +628,8 @@ namespace clang {
/// \brief A record that stores the set of declarations that are
/// lexically stored within a given DeclContext.
///
- /// The record itself is an array of declaration IDs, in the
- /// order in which those declarations were added to the
+ /// The record itself is a blob that is an array of declaration IDs,
+ /// in the order in which those declarations were added to the
/// declaration context. This data is used when iterating over
/// the contents of a DeclContext, e.g., via
/// DeclContext::decls_begin()/DeclContext::decls_end().
@@ -588,17 +671,25 @@ namespace clang {
/// \brief An AccessSpecDecl record.
DECL_ACCESS_SPEC,
- // FIXME: Implement serialization for these decl types. This just
- // allocates the order in which
+ /// \brief A FriendDecl record.
DECL_FRIEND,
+ /// \brief A FriendTemplateDecl record.
DECL_FRIEND_TEMPLATE,
+ /// \brief A ClassTemplateDecl record.
DECL_CLASS_TEMPLATE,
+ /// \brief A ClassTemplateSpecializationDecl record.
DECL_CLASS_TEMPLATE_SPECIALIZATION,
+ /// \brief A ClassTemplatePartialSpecializationDecl record.
DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+ /// \brief A FunctionTemplateDecl record.
DECL_FUNCTION_TEMPLATE,
+ /// \brief A TemplateTypeParmDecl record.
DECL_TEMPLATE_TYPE_PARM,
+ /// \brief A NonTypeTemplateParmDecl record.
DECL_NON_TYPE_TEMPLATE_PARM,
+ /// \brief A TemplateTemplateParmDecl record.
DECL_TEMPLATE_TEMPLATE_PARM,
+ /// \brief A StaticAssertDecl record.
DECL_STATIC_ASSERT
};
@@ -755,6 +846,11 @@ namespace clang {
STMT_OBJC_AT_THROW,
// C++
+
+ /// \brief A CXXCatchStmt record.
+ STMT_CXX_CATCH,
+ /// \brief A CXXTryStmt record.
+ STMT_CXX_TRY,
/// \brief A CXXOperatorCallExpr record.
EXPR_CXX_OPERATOR_CALL,
@@ -764,17 +860,17 @@ namespace clang {
EXPR_CXX_CONSTRUCT,
/// \brief A CXXTemporaryObjectExpr record.
EXPR_CXX_TEMPORARY_OBJECT,
- // \brief A CXXStaticCastExpr record.
+ /// \brief A CXXStaticCastExpr record.
EXPR_CXX_STATIC_CAST,
- // \brief A CXXDynamicCastExpr record.
+ /// \brief A CXXDynamicCastExpr record.
EXPR_CXX_DYNAMIC_CAST,
- // \brief A CXXReinterpretCastExpr record.
+ /// \brief A CXXReinterpretCastExpr record.
EXPR_CXX_REINTERPRET_CAST,
- // \brief A CXXConstCastExpr record.
+ /// \brief A CXXConstCastExpr record.
EXPR_CXX_CONST_CAST,
- // \brief A CXXFunctionalCastExpr record.
+ /// \brief A CXXFunctionalCastExpr record.
EXPR_CXX_FUNCTIONAL_CAST,
- // \brief A CXXBoolLiteralExpr record.
+ /// \brief A CXXBoolLiteralExpr record.
EXPR_CXX_BOOL_LITERAL,
EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
@@ -783,7 +879,6 @@ namespace clang {
EXPR_CXX_THROW, // CXXThrowExpr
EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
- EXPR_CXX_BIND_REFERENCE, // CXXBindReferenceExpr
EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
EXPR_CXX_NEW, // CXXNewExpr
diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h
new file mode 100644
index 000000000000..f8114de5f15a
--- /dev/null
+++ b/include/clang/Serialization/ASTDeserializationListener.h
@@ -0,0 +1,49 @@
+//===- ASTDeserializationListener.h - Decl/Type PCH Read Events -*- 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 ASTDeserializationListener class, which is notified
+// by the ASTReader whenever a type or declaration is deserialized.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+#define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+
+namespace clang {
+
+class Decl;
+class ASTReader;
+class QualType;
+
+class ASTDeserializationListener {
+protected:
+ virtual ~ASTDeserializationListener() {}
+
+public:
+ /// \brief Tell the listener about the reader.
+ virtual void SetReader(ASTReader *Reader) = 0;
+
+ /// \brief An identifier was deserialized from the AST file.
+ virtual void IdentifierRead(serialization::IdentID ID,
+ IdentifierInfo *II) = 0;
+ /// \brief A type was deserialized from the AST file. The ID here has the
+ /// qualifier bits already removed, and T is guaranteed to be locally
+ /// unqualified.
+ virtual void TypeRead(serialization::TypeIdx Idx, QualType T) = 0;
+ /// \brief A decl was deserialized from the AST file.
+ virtual void DeclRead(serialization::DeclID ID, const Decl *D) = 0;
+ /// \brief A selector was read from the AST file.
+ virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) = 0;
+};
+
+}
+
+#endif
diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Serialization/ASTReader.h
index 47e871f50aeb..d31be88a3e3d 100644
--- a/include/clang/Frontend/PCHReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1,4 +1,4 @@
-//===--- PCHReader.h - Precompiled Headers Reader ---------------*- C++ -*-===//
+//===--- ASTReader.h - AST File Reader --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,18 +7,17 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the PCHReader class, which reads a precompiled header.
+// This file defines the ASTReader class, which reads AST files.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_PCH_READER_H
-#define LLVM_CLANG_FRONTEND_PCH_READER_H
+#ifndef LLVM_CLANG_FRONTEND_AST_READER_H
+#define LLVM_CLANG_FRONTEND_AST_READER_H
-#include "clang/Frontend/PCHBitCodes.h"
-#include "clang/AST/DeclarationName.h"
+#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/AST/Type.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/PreprocessingRecord.h"
@@ -28,7 +27,6 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -59,11 +57,12 @@ class GotoStmt;
class LabelStmt;
class MacroDefinition;
class NamedDecl;
-class PCHDeserializationListener;
+class ASTDeserializationListener;
class Preprocessor;
class Sema;
class SwitchCase;
-class PCHReader;
+class ASTReader;
+class ASTDeclReader;
struct HeaderFileInfo;
struct PCHPredefinesBlock {
@@ -75,15 +74,15 @@ struct PCHPredefinesBlock {
};
typedef llvm::SmallVector<PCHPredefinesBlock, 2> PCHPredefinesBlocks;
-/// \brief Abstract interface for callback invocations by the PCHReader.
+/// \brief Abstract interface for callback invocations by the ASTReader.
///
-/// While reading a PCH file, the PCHReader will call the methods of the
+/// While reading an AST file, the ASTReader will call the methods of the
/// listener to pass on specific information. Some of the listener methods can
-/// return true to indicate to the PCHReader that the information (and
-/// consequently the PCH file) is invalid.
-class PCHReaderListener {
+/// return true to indicate to the ASTReader that the information (and
+/// consequently the AST file) is invalid.
+class ASTReaderListener {
public:
- virtual ~PCHReaderListener();
+ virtual ~ASTReaderListener();
/// \brief Receives the language options.
///
@@ -103,8 +102,8 @@ public:
///
/// \param Buffers Information about the predefines buffers.
///
- /// \param OriginalFileName The original file name for the PCH, which will
- /// appear as an entry in the predefines buffer.
+ /// \param OriginalFileName The original file name for the AST file, which
+ /// will appear as an entry in the predefines buffer.
///
/// \param SuggestedPredefines If necessary, additional definitions are added
/// here.
@@ -123,16 +122,16 @@ public:
virtual void ReadCounter(unsigned Value) {}
};
-/// \brief PCHReaderListener implementation to validate the information of
+/// \brief ASTReaderListener implementation to validate the information of
/// the PCH file against an initialized Preprocessor.
-class PCHValidator : public PCHReaderListener {
+class PCHValidator : public ASTReaderListener {
Preprocessor &PP;
- PCHReader &Reader;
+ ASTReader &Reader;
unsigned NumHeaderInfos;
public:
- PCHValidator(Preprocessor &PP, PCHReader &Reader)
+ PCHValidator(Preprocessor &PP, ASTReader &Reader)
: PP(PP), Reader(Reader), NumHeaderInfos(0) {}
virtual bool ReadLanguageOptions(const LangOptions &LangOpts);
@@ -147,19 +146,19 @@ private:
void Error(const char *Msg);
};
-/// \brief Reads a precompiled head containing the contents of a
-/// translation unit.
+/// \brief Reads an AST files chain containing the contents of a translation
+/// unit.
///
-/// The PCHReader class reads a bitstream (produced by the PCHWriter
+/// The ASTReader class reads bitstreams (produced by the ASTWriter
/// class) containing the serialized representation of a given
/// abstract syntax tree and its supporting data structures. An
-/// instance of the PCHReader can be attached to an ASTContext object,
-/// which will provide access to the contents of the PCH file.
+/// instance of the ASTReader can be attached to an ASTContext object,
+/// which will provide access to the contents of the AST files.
///
-/// The PCH reader provides lazy de-serialization of declarations, as
+/// The AST reader provides lazy de-serialization of declarations, as
/// required when traversing the AST. Only those AST nodes that are
/// actually required will be de-serialized.
-class PCHReader
+class ASTReader
: public ExternalPreprocessorSource,
public ExternalPreprocessingRecordSource,
public ExternalSemaSource,
@@ -167,110 +166,226 @@ class PCHReader
public ExternalIdentifierLookup,
public ExternalSLocEntrySource {
public:
- enum PCHReadResult { Success, Failure, IgnorePCH };
+ enum ASTReadResult { Success, Failure, IgnorePCH };
friend class PCHValidator;
+ friend class ASTDeclReader;
private:
- /// \brief The receiver of some callbacks invoked by PCHReader.
- llvm::OwningPtr<PCHReaderListener> Listener;
+ /// \brief The receiver of some callbacks invoked by ASTReader.
+ llvm::OwningPtr<ASTReaderListener> Listener;
/// \brief The receiver of deserialization events.
- PCHDeserializationListener *DeserializationListener;
+ ASTDeserializationListener *DeserializationListener;
SourceManager &SourceMgr;
FileManager &FileMgr;
Diagnostic &Diags;
/// \brief The semantic analysis object that will be processing the
- /// PCH file and the translation unit that uses it.
+ /// AST files and the translation unit that uses it.
Sema *SemaObj;
/// \brief The preprocessor that will be loading the source file.
Preprocessor *PP;
- /// \brief The AST context into which we'll read the PCH file.
+ /// \brief The AST context into which we'll read the AST files.
ASTContext *Context;
-
- /// \brief The PCH stat cache installed by this PCHReader, if any.
- ///
- /// The dynamic type of this stat cache is always PCHStatCache
- void *StatCache;
/// \brief The AST consumer.
ASTConsumer *Consumer;
- /// \brief The bitstream reader from which we'll read the PCH file.
- llvm::BitstreamReader StreamFile;
- llvm::BitstreamCursor Stream;
+ /// \brief Information that is needed for every file in the chain.
+ struct PerFileData {
+ PerFileData();
+ ~PerFileData();
+
+ /// \brief The AST stat cache installed for this file, if any.
+ ///
+ /// The dynamic type of this stat cache is always ASTStatCache
+ void *StatCache;
+
+ /// \brief The bitstream reader from which we'll read the AST file.
+ llvm::BitstreamReader StreamFile;
+ llvm::BitstreamCursor Stream;
+
+ /// \brief The size of this file, in bits.
+ uint64_t SizeInBits;
- /// \brief The cursor to the start of the preprocessor block, which stores
- /// all of the macro definitions.
- llvm::BitstreamCursor MacroCursor;
+ /// \brief The cursor to the start of the preprocessor block, which stores
+ /// all of the macro definitions.
+ llvm::BitstreamCursor MacroCursor;
- /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
- /// has read all the abbreviations at the start of the block and is ready to
- /// jump around with these in context.
- llvm::BitstreamCursor DeclsCursor;
+ /// DeclsCursor - This is a cursor to the start of the DECLS_BLOCK block. It
+ /// has read all the abbreviations at the start of the block and is ready to
+ /// jump around with these in context.
+ llvm::BitstreamCursor DeclsCursor;
- /// \brief The file name of the PCH file.
- std::string FileName;
+ /// \brief The file name of the AST file.
+ std::string FileName;
- /// \brief The memory buffer that stores the data associated with
- /// this PCH file.
- llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
+ /// \brief The memory buffer that stores the data associated with
+ /// this AST file.
+ llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
- /// \brief Offset type for all of the source location entries in the
- /// PCH file.
- const uint32_t *SLocOffsets;
+ /// \brief Cursor used to read source location entries.
+ llvm::BitstreamCursor SLocEntryCursor;
- /// \brief The number of source location entries in the PCH file.
- unsigned TotalNumSLocEntries;
+ /// \brief The number of source location entries in this AST file.
+ unsigned LocalNumSLocEntries;
+
+ /// \brief Offsets for all of the source location entries in the
+ /// AST file.
+ const uint32_t *SLocOffsets;
+
+ /// \brief The number of types in this AST file.
+ unsigned LocalNumTypes;
+
+ /// \brief Offset of each type within the bitstream, indexed by the
+ /// type ID, or the representation of a Type*.
+ const uint32_t *TypeOffsets;
+
+ /// \brief The number of declarations in this AST file.
+ unsigned LocalNumDecls;
+
+ /// \brief Offset of each declaration within the bitstream, indexed
+ /// by the declaration ID (-1).
+ const uint32_t *DeclOffsets;
+
+ /// \brief The number of identifiers in this AST file.
+ unsigned LocalNumIdentifiers;
- /// \brief Cursor used to read source location entries.
- llvm::BitstreamCursor SLocEntryCursor;
+ /// \brief Offsets into the identifier table data.
+ ///
+ /// This array is indexed by the identifier ID (-1), and provides
+ /// the offset into IdentifierTableData where the string data is
+ /// stored.
+ const uint32_t *IdentifierOffsets;
- /// \brief Offset of each type within the bitstream, indexed by the
- /// type ID, or the representation of a Type*.
- const uint32_t *TypeOffsets;
+ /// \brief Actual data for the on-disk hash table.
+ ///
+ // This pointer points into a memory buffer, where the on-disk hash
+ // table for identifiers actually lives.
+ const char *IdentifierTableData;
- /// \brief Types that have already been loaded from the PCH file.
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// IdentifierHashTable.
+ void *IdentifierLookupTable;
+
+ /// \brief The number of macro definitions in this file.
+ unsigned LocalNumMacroDefinitions;
+
+ /// \brief Offsets of all of the macro definitions in the preprocessing
+ /// record in the AST file.
+ const uint32_t *MacroDefinitionOffsets;
+
+ /// \brief The number of preallocated preprocessing entities in the
+ /// preprocessing record.
+ unsigned NumPreallocatedPreprocessingEntities;
+
+ /// \brief A pointer to an on-disk hash table of opaque type
+ /// ASTSelectorLookupTable.
+ ///
+ /// This hash table provides the IDs of all selectors, and the associated
+ /// instance and factory methods.
+ void *SelectorLookupTable;
+
+ /// \brief A pointer to the character data that comprises the selector table
+ ///
+ /// The SelectorOffsets table refers into this memory.
+ const unsigned char *SelectorLookupTableData;
+
+ /// \brief Offsets into the method pool lookup table's data array
+ /// where each selector resides.
+ const uint32_t *SelectorOffsets;
+
+ /// \brief The number of selectors new to this file.
+ ///
+ /// This is the number of entries in SelectorOffsets.
+ unsigned LocalNumSelectors;
+ };
+
+ /// \brief The chain of AST files. The first entry is the one named by the
+ /// user, the last one is the one that doesn't depend on anything further.
+ /// That is, the entry I was created with -include-pch I+1.
+ llvm::SmallVector<PerFileData*, 2> Chain;
+
+ /// \brief Types that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the type with
- /// ID = (I + 1) << 3 has already been loaded from the PCH file.
+ /// ID = (I + 1) << FastQual::Width has already been loaded
std::vector<QualType> TypesLoaded;
- /// \brief Offset of each declaration within the bitstream, indexed
- /// by the declaration ID (-1).
- const uint32_t *DeclOffsets;
+ /// \brief Map that provides the ID numbers of each type within the
+ /// output stream, plus those deserialized from a chained PCH.
+ ///
+ /// The ID numbers of types are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL. When types are actually
+ /// stored in the stream, the ID number is shifted by 2 bits to
+ /// allow for the const/volatile qualifiers.
+ ///
+ /// Keys in the map never have const/volatile qualifiers.
+ serialization::TypeIdxMap TypeIdxs;
- /// \brief Declarations that have already been loaded from the PCH file.
+ /// \brief Declarations that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the declaration with ID
/// = I + 1 has already been loaded.
std::vector<Decl *> DeclsLoaded;
- typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> >
- DeclContextOffsetsMap;
+ typedef llvm::DenseMap<serialization::DeclID,
+ std::pair<PerFileData *, uint64_t> >
+ DeclReplacementMap;
+ /// \brief Declarations that have been replaced in a later file in the chain.
+ DeclReplacementMap ReplacedDecls;
+
+ /// \brief Information about the contents of a DeclContext.
+ struct DeclContextInfo {
+ void *NameLookupTableData; // a ASTDeclContextNameLookupTable.
+ const serialization::DeclID *LexicalDecls;
+ unsigned NumLexicalDecls;
+ };
+ // In a full chain, there could be multiple updates to every decl context,
+ // so this is a vector. However, typically a chain is only two elements long,
+ // with only one file containing updates, so there will be only one update
+ // per decl context.
+ typedef llvm::SmallVector<DeclContextInfo, 1> DeclContextInfos;
+ typedef llvm::DenseMap<const DeclContext *, DeclContextInfos>
+ DeclContextOffsetsMap;
+ // Updates for visible decls can occur for other contexts than just the
+ // TU, and when we read those update records, the actual context will not
+ // be available yet (unless it's the TU), so have this pending map using the
+ // ID as a key. It will be realized when the context is actually loaded.
+ typedef llvm::SmallVector<void *, 1> DeclContextVisibleUpdates;
+ typedef llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
+ DeclContextVisibleUpdatesPending;
/// \brief Offsets of the lexical and visible declarations for each
/// DeclContext.
DeclContextOffsetsMap DeclContextOffsets;
- /// \brief Actual data for the on-disk hash table.
- ///
- // This pointer points into a memory buffer, where the on-disk hash
- // table for identifiers actually lives.
- const char *IdentifierTableData;
+ /// \brief Updates to the visible declarations of declaration contexts that
+ /// haven't been loaded yet.
+ DeclContextVisibleUpdatesPending PendingVisibleUpdates;
- /// \brief A pointer to an on-disk hash table of opaque type
- /// IdentifierHashTable.
- void *IdentifierLookupTable;
+ typedef llvm::DenseMap<serialization::DeclID, serialization::DeclID>
+ FirstLatestDeclIDMap;
+ /// \brief Map of first declarations from a chained PCH that point to the
+ /// most recent declarations in another AST file.
+ FirstLatestDeclIDMap FirstLatestDeclIDs;
- /// \brief Offsets into the identifier table data.
- ///
- /// This array is indexed by the identifier ID (-1), and provides
- /// the offset into IdentifierTableData where the string data is
- /// stored.
- const uint32_t *IdentifierOffsets;
+ typedef llvm::SmallVector<serialization::DeclID, 4>
+ AdditionalTemplateSpecializations;
+ typedef llvm::DenseMap<serialization::DeclID,
+ AdditionalTemplateSpecializations>
+ AdditionalTemplateSpecializationsMap;
+
+ /// \brief Additional specializations (including partial) of templates that
+ /// were introduced after the template was serialized.
+ AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializationsPending;
+
+ /// \brief Read the records that describe the contents of declcontexts.
+ bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
+ const std::pair<uint64_t, uint64_t> &Offsets,
+ DeclContextInfo &Info);
/// \brief A vector containing identifiers that have already been
/// loaded.
@@ -280,29 +395,6 @@ private:
/// been loaded.
std::vector<IdentifierInfo *> IdentifiersLoaded;
- /// \brief A pointer to an on-disk hash table of opaque type
- /// PCHMethodPoolLookupTable.
- ///
- /// This hash table provides the instance and factory methods
- /// associated with every selector known in the PCH file.
- void *MethodPoolLookupTable;
-
- /// \brief A pointer to the character data that comprises the method
- /// pool.
- ///
- /// The SelectorOffsets table refers into this memory.
- const unsigned char *MethodPoolLookupTableData;
-
- /// \brief The number of selectors stored in the method pool itself.
- unsigned TotalSelectorsInMethodPool;
-
- /// \brief Offsets into the method pool lookup table's data array
- /// where each selector resides.
- const uint32_t *SelectorOffsets;
-
- /// \brief The total number of selectors stored in the PCH file.
- unsigned TotalNumSelectors;
-
/// \brief A vector containing selectors that have already been loaded.
///
/// This vector is indexed by the Selector ID (-1). NULL selector
@@ -310,52 +402,102 @@ private:
/// been loaded.
llvm::SmallVector<Selector, 16> SelectorsLoaded;
- /// \brief Offsets of all of the macro definitions in the preprocessing
- /// record in the PCH file.
- const uint32_t *MacroDefinitionOffsets;
-
/// \brief The macro definitions we have already loaded.
llvm::SmallVector<MacroDefinition *, 16> MacroDefinitionsLoaded;
-
- /// \brief The number of preallocated preprocessing entities in the
- /// preprocessing record.
- unsigned NumPreallocatedPreprocessingEntities;
-
- /// \brief The set of external definitions stored in the the PCH
- /// file.
+
+ /// \name CodeGen-relevant special data
+ /// \brief Fields containing data that is relevant to CodeGen.
+ //@{
+
+ /// \brief The IDs of all declarations that fulfill the criteria of
+ /// "interesting" decls.
+ ///
+ /// This contains the data loaded from all EXTERNAL_DEFINITIONS blocks in the
+ /// chain. The referenced declarations are deserialized and passed to the
+ /// consumer eagerly.
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
- /// \brief The set of tentative definitions stored in the the PCH
- /// file.
+ /// \brief The IDs of all tentative definitions stored in the the chain.
+ ///
+ /// Sema keeps track of all tentative definitions in a TU because it has to
+ /// complete them and pass them on to CodeGen. Thus, tentative definitions in
+ /// the PCH chain must be eagerly deserialized.
llvm::SmallVector<uint64_t, 16> TentativeDefinitions;
-
- /// \brief The set of unused static functions stored in the the PCH
- /// file.
- llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs;
- /// \brief The set of locally-scoped external declarations stored in
- /// the the PCH file.
- llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
+ /// \brief The IDs of all CXXRecordDecls stored in the chain whose VTables are
+ /// used.
+ ///
+ /// CodeGen has to emit VTables for these records, so they have to be eagerly
+ /// deserialized.
+ llvm::SmallVector<uint64_t, 64> VTableUses;
+
+ //@}
+
+ /// \name Diagnostic-relevant special data
+ /// \brief Fields containing data that is used for generating diagnostics
+ //@{
- /// \brief The set of ext_vector type declarations stored in the the
- /// PCH file.
+ /// \brief Method selectors used in a @selector expression. Used for
+ /// implementation of -Wselector.
+ llvm::SmallVector<uint64_t, 64> ReferencedSelectorsData;
+
+ /// \brief A snapshot of Sema's unused file-scoped variable tracking, for
+ /// generating warnings.
+ llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls;
+
+ /// \brief A snapshot of Sema's weak undeclared identifier tracking, for
+ /// generating warnings.
+ llvm::SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers;
+
+ /// \brief The IDs of type aliases for ext_vectors that exist in the chain.
+ ///
+ /// Used by Sema for finding sugared names for ext_vectors in diagnostics.
llvm::SmallVector<uint64_t, 4> ExtVectorDecls;
- /// \brief The set of VTable uses of CXXRecordDecls stored in the PCH file.
- llvm::SmallVector<uint64_t, 64> VTableUses;
+ //@}
+
+ /// \name Sema-relevant special data
+ /// \brief Fields containing data that is used for semantic analysis
+ //@{
- /// \brief The set of dynamic CXXRecord declarations stored in the PCH file.
+ /// \brief The IDs of all locally scoped external decls in the chain.
+ ///
+ /// Sema tracks these to validate that the types are consistent across all
+ /// local external declarations.
+ llvm::SmallVector<uint64_t, 16> LocallyScopedExternalDecls;
+
+ /// \brief A snapshot of the pwnsinf instantiations in the chain.
+ ///
+ /// This record tracks the instantiations that Sema has to perform at the end
+ /// of the TU. It consists of a pair of values for every pending instantiation
+ /// where the first value is the ID of the decl and the second is the
+ /// instantiation location.
+ llvm::SmallVector<uint64_t, 64> PendingInstantiations;
+
+ /// \brief The IDs of all dynamic class declarations in the chain.
+ ///
+ /// Sema tracks these because it checks for the key functions being defined
+ /// at the end of the TU, in which case it directs CodeGen to emit the VTable.
llvm::SmallVector<uint64_t, 16> DynamicClasses;
- /// \brief The set of Objective-C category definitions stored in the
- /// the PCH file.
- llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls;
+ /// \brief The IDs of the declarations Sema stores directly.
+ ///
+ /// Sema tracks a few important decls, such as namespace std, directly.
+ llvm::SmallVector<uint64_t, 4> SemaDeclRefs;
+
+ /// \brief The IDs of the types ASTContext stores directly.
+ ///
+ /// The AST context tracks a few important types, such as va_list, directly.
+ llvm::SmallVector<uint64_t, 16> SpecialTypes;
- /// \brief The original file name that was used to build the PCH file, which
- /// may have been modified for relocatable-pch support.
+ //@}
+
+ /// \brief The original file name that was used to build the primary AST 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.
+ /// \brief The actual original file name that was used to build the primary
+ /// AST file.
std::string ActualOriginalFileName;
/// \brief Whether this precompiled header is a relocatable PCH file.
@@ -365,12 +507,20 @@ private:
/// precompiled header.
const char *isysroot;
- /// \brief Mapping from switch-case IDs in the PCH file to
- /// switch-case statements.
+ /// \brief Whether to disable the normal validation performed on precompiled
+ /// headers when they are loaded.
+ bool DisableValidation;
+
+ /// \brief Mapping from switch-case IDs in the chain to switch-case statements
+ ///
+ /// Statements usually don't have IDs, but switch cases need them, so that the
+ /// switch statement can refer to them.
std::map<unsigned, SwitchCase *> SwitchCaseStmts;
- /// \brief Mapping from label statement IDs in the PCH file to label
- /// statements.
+ /// \brief Mapping from label statement IDs in the chain to label statements.
+ ///
+ /// Statements usually don't have IDs, but labeled statements need them, so
+ /// that goto statements and address-of-label expressions can refer to them.
std::map<unsigned, LabelStmt *> LabelStmts;
/// \brief Mapping from label IDs to the set of "goto" statements
@@ -391,52 +541,44 @@ private:
/// the PCH file.
unsigned NumSLocEntriesRead;
+ /// \brief The number of source location entries in the chain.
+ unsigned TotalNumSLocEntries;
+
/// \brief The number of statements (and expressions) de-serialized
- /// from the PCH file.
+ /// from the chain.
unsigned NumStatementsRead;
/// \brief The total number of statements (and expressions) stored
- /// in the PCH file.
+ /// in the chain.
unsigned TotalNumStatements;
- /// \brief The number of macros de-serialized from the PCH file.
+ /// \brief The number of macros de-serialized from the chain.
unsigned NumMacrosRead;
+ /// \brief The total number of macros stored in the chain.
+ unsigned TotalNumMacros;
+
+ /// \brief The number of selectors that have been read.
+ unsigned NumSelectorsRead;
+
/// \brief The number of method pool entries that have been read.
- unsigned NumMethodPoolSelectorsRead;
+ unsigned NumMethodPoolEntriesRead;
- /// \brief The number of times we have looked into the global method
- /// pool and not found anything.
+ /// \brief The number of times we have looked up a selector in the method
+ /// pool and not found anything interesting.
unsigned NumMethodPoolMisses;
- /// \brief The total number of macros stored in the PCH file.
- unsigned TotalNumMacros;
+ /// \brief The total number of method pool entries in the selector table.
+ unsigned TotalNumMethodPoolEntries;
/// Number of lexical decl contexts read/total.
unsigned NumLexicalDeclContextsRead, TotalLexicalDeclContexts;
/// Number of visible decl contexts read/total.
unsigned NumVisibleDeclContextsRead, TotalVisibleDeclContexts;
-
- /// \brief When a type or declaration is being loaded from the PCH file, an
- /// instantance of this RAII object will be available on the stack to
- /// indicate when we are in a recursive-loading situation.
- class LoadingTypeOrDecl {
- PCHReader &Reader;
- LoadingTypeOrDecl *Parent;
-
- LoadingTypeOrDecl(const LoadingTypeOrDecl&); // do not implement
- LoadingTypeOrDecl &operator=(const LoadingTypeOrDecl&); // do not implement
-
- public:
- explicit LoadingTypeOrDecl(PCHReader &Reader);
- ~LoadingTypeOrDecl();
- };
- friend class LoadingTypeOrDecl;
-
- /// \brief If we are currently loading a type or declaration, points to the
- /// most recent LoadingTypeOrDecl object on the stack.
- LoadingTypeOrDecl *CurrentlyLoadingTypeOrDecl;
+
+ /// \brief Number of Decl/types that are currently deserializing.
+ unsigned NumCurrentElementsDeserializing;
/// \brief An IdentifierInfo that has been loaded but whose top-level
/// declarations of the same name have not (yet) been loaded.
@@ -445,16 +587,13 @@ private:
llvm::SmallVector<uint32_t, 4> DeclIDs;
};
- /// \brief The set of identifiers that were read while the PCH reader was
+ /// \brief The set of identifiers that were read while the AST reader was
/// (recursively) loading declarations.
///
/// The declarations on the identifier chain for these identifiers will be
/// loaded once the recursive loading has completed.
std::deque<PendingIdentifierInfo> PendingIdentifierInfos;
- /// \brief FIXME: document!
- llvm::SmallVector<uint64_t, 16> SpecialTypes;
-
/// \brief Contains declarations and definitions that will be
/// "interesting" to the ASTConsumer, when we get that AST consumer.
///
@@ -476,14 +615,14 @@ private:
/// \brief RAII object to change the reading kind.
class ReadingKindTracker {
- PCHReader &Reader;
+ ASTReader &Reader;
enum ReadingKind PrevKind;
ReadingKindTracker(const ReadingKindTracker&); // do not implement
ReadingKindTracker &operator=(const ReadingKindTracker&);// do not implement
public:
- ReadingKindTracker(enum ReadingKind newKind, PCHReader &reader)
+ ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader)
: Reader(reader), PrevKind(Reader.ReadingKind) {
Reader.ReadingKind = newKind;
}
@@ -491,7 +630,7 @@ private:
~ReadingKindTracker() { Reader.ReadingKind = PrevKind; }
};
- /// \brief All predefines buffers in all PCH files, to be treated as if
+ /// \brief All predefines buffers in the chain, to be treated as if
/// concatenated.
PCHPredefinesBlocks PCHPredefinesBuffers;
@@ -510,31 +649,37 @@ private:
void MaybeAddSystemRootToFilename(std::string &Filename);
- PCHReadResult ReadPCHBlock();
+ ASTReadResult ReadASTCore(llvm::StringRef FileName);
+ ASTReadResult ReadASTBlock(PerFileData &F);
bool CheckPredefinesBuffers();
bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record);
- PCHReadResult ReadSourceManagerBlock();
- PCHReadResult ReadSLocEntryRecord(unsigned ID);
-
+ ASTReadResult ReadSourceManagerBlock(PerFileData &F);
+ ASTReadResult ReadSLocEntryRecord(unsigned ID);
+ llvm::BitstreamCursor &SLocCursorForID(unsigned ID);
bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
- QualType ReadTypeRecord(uint64_t Offset);
+
+ typedef std::pair<llvm::BitstreamCursor *, uint64_t> RecordLocation;
+
+ QualType ReadTypeRecord(unsigned Index);
+ RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D);
- Decl *ReadDeclRecord(uint64_t Offset, unsigned Index);
+ Decl *ReadDeclRecord(unsigned Index, serialization::DeclID ID);
+ RecordLocation DeclCursorForIndex(unsigned Index, serialization::DeclID ID);
void PassInterestingDeclsToConsumer();
/// \brief Produce an error diagnostic and return true.
///
/// This routine should only be used for fatal errors that have to
- /// do with non-routine failures (e.g., corrupted PCH file).
+ /// do with non-routine failures (e.g., corrupted AST file).
void Error(const char *Msg);
- PCHReader(const PCHReader&); // do not implement
- PCHReader &operator=(const PCHReader &); // do not implement
+ ASTReader(const ASTReader&); // do not implement
+ ASTReader &operator=(const ASTReader &); // do not implement
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
- /// \brief Load the PCH file and validate its contents against the given
+ /// \brief Load the AST file and validate its contents against the given
/// Preprocessor.
///
/// \param PP the preprocessor associated with the context in which this
@@ -546,41 +691,48 @@ public:
/// \param isysroot If non-NULL, the system include path specified by the
/// user. This is only used with relocatable PCH files. If non-NULL,
/// a relocatable PCH file will use the default path "/".
- PCHReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0);
+ ///
+ /// \param DisableValidation If true, the AST reader will suppress most
+ /// of its regular consistency checking, allowing the use of precompiled
+ /// headers that cannot be determined to be compatible.
+ ASTReader(Preprocessor &PP, ASTContext *Context, const char *isysroot = 0,
+ bool DisableValidation = false);
- /// \brief Load the PCH file without using any pre-initialized Preprocessor.
+ /// \brief Load the AST file without using any pre-initialized Preprocessor.
///
/// The necessary information to initialize a Preprocessor later can be
- /// obtained by setting a PCHReaderListener.
+ /// obtained by setting a ASTReaderListener.
///
- /// \param SourceMgr the source manager into which the precompiled header
- /// will be loaded.
+ /// \param SourceMgr the source manager into which the AST file will be loaded
///
- /// \param FileMgr the file manager into which the precompiled header will
- /// be loaded.
+ /// \param FileMgr the file manager into which the AST file will be loaded.
///
/// \param Diags the diagnostics system to use for reporting errors and
- /// warnings relevant to loading the precompiled header.
+ /// warnings relevant to loading the AST file.
///
/// \param isysroot If non-NULL, the system include path specified by the
/// user. This is only used with relocatable PCH files. If non-NULL,
/// a relocatable PCH file will use the default path "/".
- PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
- Diagnostic &Diags, const char *isysroot = 0);
- ~PCHReader();
+ ///
+ /// \param DisableValidation If true, the AST reader will suppress most
+ /// of its regular consistency checking, allowing the use of precompiled
+ /// headers that cannot be determined to be compatible.
+ ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags, const char *isysroot = 0,
+ bool DisableValidation = false);
+ ~ASTReader();
/// \brief Load the precompiled header designated by the given file
/// name.
- PCHReadResult ReadPCH(const std::string &FileName);
+ ASTReadResult ReadAST(const std::string &FileName);
- /// \brief Set the PCH callbacks listener.
- void setListener(PCHReaderListener *listener) {
+ /// \brief Set the AST callbacks listener.
+ void setListener(ASTReaderListener *listener) {
Listener.reset(listener);
}
- void setDeserializationListener(PCHDeserializationListener *Listener) {
- DeserializationListener = Listener;
- }
+ /// \brief Set the AST deserialization listener.
+ void setDeserializationListener(ASTDeserializationListener *Listener);
/// \brief Set the Preprocessor to use.
void setPreprocessor(Preprocessor &pp);
@@ -588,16 +740,15 @@ public:
/// \brief Sets and initializes the given Context.
void InitializeContext(ASTContext &Context);
- /// \brief Retrieve the name of the PCH file
- const std::string &getFileName() const { return FileName; }
+ /// \brief Retrieve the name of the named (primary) AST file
+ const std::string &getFileName() const { return Chain[0]->FileName; }
/// \brief Retrieve the name of the original source file name
const std::string &getOriginalSourceFile() { return OriginalFileName; }
- /// \brief Retrieve the name of the original source file name
- /// directly from the PCH file, without actually loading the PCH
- /// file.
- static std::string getOriginalSourceFile(const std::string &PCHFileName,
+ /// \brief Retrieve the name of the original source file name directly from
+ /// the AST file, without actually loading the AST file.
+ static std::string getOriginalSourceFile(const std::string &ASTFileName,
Diagnostic &Diags);
/// \brief Returns the suggested contents of the predefines buffer,
@@ -608,40 +759,67 @@ public:
/// \brief Read preprocessed entities into the
virtual void ReadPreprocessedEntities();
- /// \brief Returns the number of types found in this file.
+ /// \brief Returns the number of source locations found in the chain.
+ unsigned getTotalNumSLocs() const {
+ return TotalNumSLocEntries;
+ }
+
+ /// \brief Returns the number of identifiers found in the chain.
+ unsigned getTotalNumIdentifiers() const {
+ return static_cast<unsigned>(IdentifiersLoaded.size());
+ }
+
+ /// \brief Returns the number of types found in the chain.
unsigned getTotalNumTypes() const {
return static_cast<unsigned>(TypesLoaded.size());
}
- /// \brief Returns the number of declarations found in this file.
+ /// \brief Returns the number of declarations found in the chain.
unsigned getTotalNumDecls() const {
return static_cast<unsigned>(DeclsLoaded.size());
}
+ /// \brief Returns the number of selectors found in the chain.
+ unsigned getTotalNumSelectors() const {
+ return static_cast<unsigned>(SelectorsLoaded.size());
+ }
+
/// \brief Reads a TemplateArgumentLocInfo appropriate for the
/// given TemplateArgument kind.
TemplateArgumentLocInfo
GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ llvm::BitstreamCursor &DeclsCursor,
const RecordData &Record, unsigned &Idx);
/// \brief Reads a TemplateArgumentLoc.
- TemplateArgumentLoc ReadTemplateArgumentLoc(const RecordData &Record,
- unsigned &Idx);
+ TemplateArgumentLoc
+ ReadTemplateArgumentLoc(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx);
/// \brief Reads a declarator info from the given record.
- TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record,
- unsigned &Idx);
+ TypeSourceInfo *GetTypeSourceInfo(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx);
/// \brief Resolve and return the translation unit declaration.
TranslationUnitDecl *GetTranslationUnitDecl();
/// \brief Resolve a type ID into a type, potentially building a new
/// type.
- QualType GetType(pch::TypeID ID);
+ QualType GetType(serialization::TypeID ID);
+
+ /// \brief Returns the type ID associated with the given type.
+ /// If the type didn't come from the AST file the ID that is returned is
+ /// marked as "doesn't exist in AST".
+ serialization::TypeID GetTypeID(QualType T) const;
+
+ /// \brief Returns the type index associated with the given type.
+ /// If the type didn't come from the AST file the index that is returned is
+ /// marked as "doesn't exist in AST".
+ serialization::TypeIdx GetTypeIdx(QualType T) const;
/// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration.
- Decl *GetDecl(pch::DeclID ID);
+ Decl *GetDecl(serialization::DeclID ID);
virtual Decl *GetExternalDecl(uint32_t ID);
/// \brief Resolve the offset of a statement into a statement.
@@ -663,6 +841,8 @@ public:
FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name);
+ virtual void MaterializeVisibleDecls(const DeclContext *DC);
+
/// \brief Read all of the declarations lexically stored in a
/// declaration context.
///
@@ -679,6 +859,15 @@ public:
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Decls);
+ /// \brief Notify ASTReader that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ virtual void StartedDeserializing() { ++NumCurrentElementsDeserializing; }
+
+ /// \brief Notify ASTReader that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ virtual void FinishedDeserializing();
+
/// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source.
///
@@ -686,7 +875,7 @@ public:
/// the ASTConsumer.
virtual void StartTranslationUnit(ASTConsumer *Consumer);
- /// \brief Print some statistics about PCH usage.
+ /// \brief Print some statistics about AST usage.
virtual void PrintStats();
/// \brief Initialize the semantic source with the Sema instance
@@ -716,6 +905,9 @@ public:
virtual std::pair<ObjCMethodList, ObjCMethodList>
ReadMethodPool(Selector Sel);
+ /// \brief Load a selector from disk, registering its ID if it exists.
+ void LoadSelector(Selector Sel);
+
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
@@ -759,7 +951,8 @@ public:
TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx);
/// \brief Read a template argument.
- TemplateArgument ReadTemplateArgument(const RecordData &Record,unsigned &Idx);
+ TemplateArgument ReadTemplateArgument(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record,unsigned &Idx);
/// \brief Read a template parameter list.
TemplateParameterList *ReadTemplateParameterList(const RecordData &Record,
@@ -768,6 +961,7 @@ public:
/// \brief Read a template argument array.
void
ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
+ llvm::BitstreamCursor &DeclsCursor,
const RecordData &Record, unsigned &Idx);
/// \brief Read a UnresolvedSet structure.
@@ -775,7 +969,13 @@ public:
const RecordData &Record, unsigned &Idx);
/// \brief Read a C++ base specifier.
- CXXBaseSpecifier ReadCXXBaseSpecifier(const RecordData &Record,unsigned &Idx);
+ CXXBaseSpecifier ReadCXXBaseSpecifier(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record,unsigned &Idx);
+
+ /// \brief Read a CXXBaseOrMemberInitializer array.
+ std::pair<CXXBaseOrMemberInitializer **, unsigned>
+ ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx);
/// \brief Read a source location.
SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) {
@@ -800,13 +1000,13 @@ public:
CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx);
/// \brief Reads attributes from the current stream position.
- Attr *ReadAttributes();
+ void ReadAttributes(llvm::BitstreamCursor &DeclsCursor, AttrVec &Attrs);
/// \brief Reads a statement.
- Stmt *ReadStmt();
+ Stmt *ReadStmt(llvm::BitstreamCursor &Cursor);
/// \brief Reads an expression.
- Expr *ReadExpr();
+ Expr *ReadExpr(llvm::BitstreamCursor &Cursor);
/// \brief Reads a sub-statement operand during statement reading.
Stmt *ReadSubStmt() {
@@ -822,16 +1022,15 @@ public:
Expr *ReadSubExpr();
/// \brief Reads the macro record located at the given offset.
- void ReadMacroRecord(uint64_t Offset);
+ void ReadMacroRecord(llvm::BitstreamCursor &Stream, uint64_t Offset);
/// \brief Read the set of macros defined by this external macro source.
virtual void ReadDefinedMacros();
/// \brief Retrieve the macro definition with the given ID.
- MacroDefinition *getMacroDefinition(pch::IdentID ID);
-
- /// \brief Retrieve the AST context that this PCH reader
- /// supplements.
+ MacroDefinition *getMacroDefinition(serialization::IdentID ID);
+
+ /// \brief Retrieve the AST context that this AST reader supplements.
ASTContext *getContext() { return Context; }
// \brief Contains declarations that were loaded before we have
@@ -843,10 +1042,6 @@ public:
/// imported.
Sema *getSema() { return SemaObj; }
- /// \brief Retrieve the stream that this PCH reader is reading from.
- llvm::BitstreamCursor &getStream() { return Stream; }
- llvm::BitstreamCursor &getDeclsCursor() { return DeclsCursor; }
-
/// \brief Retrieve the identifier table associated with the
/// preprocessor.
IdentifierTable &getIdentifierTable();
diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Serialization/ASTWriter.h
index 70ad1d7c7e78..426fc4780148 100644
--- a/include/clang/Frontend/PCHWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -1,4 +1,4 @@
-//===--- PCHWriter.h - Precompiled Headers Writer ---------------*- C++ -*-===//
+//===--- ASTWriter.h - AST File Writer --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,25 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the PCHWriter class, which writes a precompiled
-// header containing a serialized representation of a translation
-// unit.
+// This file defines the ASTWriter class, which writes an AST file
+// containing a serialized representation of a translation unit.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_PCH_WRITER_H
-#define LLVM_CLANG_FRONTEND_PCH_WRITER_H
+#ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H
+#define LLVM_CLANG_FRONTEND_AST_WRITER_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/TemplateBase.h"
-#include "clang/Frontend/PCHBitCodes.h"
-#include "clang/Frontend/PCHDeserializationListener.h"
-#include "llvm/ADT/DenseMap.h"
+#include "clang/Serialization/ASTBitCodes.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
#include <map>
#include <queue>
+#include <vector>
namespace llvm {
class APFloat;
@@ -40,50 +42,32 @@ class CXXBaseOrMemberInitializer;
class LabelStmt;
class MacroDefinition;
class MemorizeStatCalls;
-class PCHReader;
+class ASTReader;
class Preprocessor;
class Sema;
class SourceManager;
class SwitchCase;
class TargetInfo;
-/// A structure for putting "fast"-unqualified QualTypes into a
-/// DenseMap. This uses the standard pointer hash function.
-struct UnsafeQualTypeDenseMapInfo {
- static inline bool isEqual(QualType A, QualType B) { return A == B; }
- static inline QualType getEmptyKey() {
- return QualType::getFromOpaquePtr((void*) 1);
- }
- static inline QualType getTombstoneKey() {
- return QualType::getFromOpaquePtr((void*) 2);
- }
- static inline unsigned getHashValue(QualType T) {
- 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);
- }
-};
-
-/// \brief Writes a precompiled header containing the contents of a
-/// translation unit.
+/// \brief Writes an AST file containing the contents of a translation unit.
///
-/// The PCHWriter class produces a bitstream containing the serialized
+/// The ASTWriter class produces a bitstream containing the serialized
/// representation of a given abstract syntax tree and its supporting
/// data structures. This bitstream can be de-serialized via an
-/// instance of the PCHReader class.
-class PCHWriter : public PCHDeserializationListener {
+/// instance of the ASTReader class.
+class ASTWriter : public ASTDeserializationListener {
public:
typedef llvm::SmallVector<uint64_t, 64> RecordData;
+ friend class ASTDeclWriter;
private:
/// \brief The bitstream writer used to emit this precompiled header.
llvm::BitstreamWriter &Stream;
- /// \brief The reader of existing PCH files, if we're chaining.
- PCHReader *Chain;
+ /// \brief The reader of existing AST files, if we're chaining.
+ ASTReader *Chain;
- /// \brief Stores a declaration or a type to be written to the PCH file.
+ /// \brief Stores a declaration or a type to be written to the AST file.
class DeclOrType {
public:
DeclOrType(Decl *D) : Stored(D), IsType(false) { }
@@ -106,24 +90,36 @@ private:
void *Stored;
bool IsType;
};
-
+
/// \brief The declarations and types to emit.
std::queue<DeclOrType> DeclTypesToEmit;
-
+
+ /// \brief The first ID number we can use for our own declarations.
+ serialization::DeclID FirstDeclID;
+
+ /// \brief The decl ID that will be assigned to the next new decl.
+ serialization::DeclID NextDeclID;
+
/// \brief Map that provides the ID numbers of each declaration within
- /// the output stream.
+ /// the output stream, as well as those deserialized from a chained PCH.
///
/// The ID numbers of declarations are consecutive (in order of
/// discovery) and start at 2. 1 is reserved for the translation
/// unit, while 0 is reserved for NULL.
- llvm::DenseMap<const Decl *, pch::DeclID> DeclIDs;
+ llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs;
/// \brief Offset of each declaration in the bitstream, indexed by
/// the declaration's ID.
std::vector<uint32_t> DeclOffsets;
+ /// \brief The first ID number we can use for our own types.
+ serialization::TypeID FirstTypeID;
+
+ /// \brief The type ID that will be assigned to the next new type.
+ serialization::TypeID NextTypeID;
+
/// \brief Map that provides the ID numbers of each type within the
- /// output stream.
+ /// output stream, plus those deserialized from a chained PCH.
///
/// The ID numbers of types are consecutive (in order of discovery)
/// and start at 1. 0 is reserved for NULL. When types are actually
@@ -131,14 +127,17 @@ private:
/// allow for the const/volatile qualifiers.
///
/// Keys in the map never have const/volatile qualifiers.
- llvm::DenseMap<QualType, pch::TypeID, UnsafeQualTypeDenseMapInfo> TypeIDs;
+ serialization::TypeIdxMap TypeIdxs;
/// \brief Offset of each type in the bitstream, indexed by
/// the type's ID.
std::vector<uint32_t> TypeOffsets;
- /// \brief The type ID that will be assigned to the next new type.
- pch::TypeID NextTypeID;
+ /// \brief The first ID number we can use for our own identifiers.
+ serialization::IdentID FirstIdentID;
+
+ /// \brief The identifier ID that will be assigned to the next new identifier.
+ serialization::IdentID NextIdentID;
/// \brief Map that provides the ID numbers of each identifier in
/// the output stream.
@@ -146,22 +145,25 @@ private:
/// The ID numbers for identifiers are consecutive (in order of
/// discovery), starting at 1. An ID of zero refers to a NULL
/// IdentifierInfo.
- llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs;
+ llvm::DenseMap<const IdentifierInfo *, serialization::IdentID> IdentifierIDs;
/// \brief Offsets of each of the identifier IDs into the identifier
/// table.
std::vector<uint32_t> IdentifierOffsets;
+ /// \brief The first ID number we can use for our own selectors.
+ serialization::SelectorID FirstSelectorID;
+
+ /// \brief The selector ID that will be assigned to the next new identifier.
+ serialization::SelectorID NextSelectorID;
+
/// \brief Map that provides the ID numbers of each Selector.
- llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs;
+ llvm::DenseMap<Selector, serialization::SelectorID> SelectorIDs;
/// \brief Offset of each selector within the method pool/selector
/// table, indexed by the Selector ID (-1).
std::vector<uint32_t> SelectorOffsets;
- /// \brief A vector of all Selectors (ordered by ID).
- std::vector<Selector> SelVector;
-
/// \brief Offsets of each of the macro identifiers into the
/// bitstream.
///
@@ -172,19 +174,25 @@ private:
/// \brief Mapping from macro definitions (as they occur in the preprocessing
/// record) to the index into the macro definitions table.
- llvm::DenseMap<const MacroDefinition *, pch::IdentID> MacroDefinitions;
+ llvm::DenseMap<const MacroDefinition *, serialization::IdentID>
+ MacroDefinitions;
/// \brief Mapping from the macro definition indices in \c MacroDefinitions
/// to the corresponding offsets within the preprocessor block.
std::vector<uint32_t> MacroDefinitionOffsets;
+
+ typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap;
+ /// \brief Map of first declarations from a chained PCH that point to the
+ /// most recent declarations in another PCH.
+ FirstLatestDeclMap FirstLatestDecls;
/// \brief Declarations encountered that might be external
/// definitions.
///
/// We keep track of external definitions (as well as tentative
- /// definitions) as we are emitting declarations to the PCH
- /// file. The PCH file contains a separate record for these external
- /// definitions, which are provided to the AST consumer by the PCH
+ /// definitions) as we are emitting declarations to the AST
+ /// file. The AST file contains a separate record for these external
+ /// definitions, which are provided to the AST consumer by the AST
/// reader. This is behavior is required to properly cope with,
/// e.g., tentative variable definitions that occur within
/// headers. The declarations themselves are stored as declaration
@@ -192,11 +200,38 @@ private:
/// record.
llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
+ /// \brief Namespaces that have received extensions since their serialized
+ /// form.
+ ///
+ /// Basically, when we're chaining and encountering a namespace, we check if
+ /// its primary namespace comes from the chain. If it does, we add the primary
+ /// to this set, so that we can write out lexical content updates for it.
+ llvm::SmallPtrSet<const NamespaceDecl *, 16> UpdatedNamespaces;
+
+ /// \brief Decls that have been replaced in the current dependent AST file.
+ ///
+ /// When a decl changes fundamentally after being deserialized (this shouldn't
+ /// happen, but the ObjC AST nodes are designed this way), it will be
+ /// serialized again. In this case, it is registered here, so that the reader
+ /// knows to read the updated version.
+ llvm::SmallVector<std::pair<serialization::DeclID, uint64_t>, 16>
+ ReplacedDecls;
+
+ typedef llvm::SmallVector<serialization::DeclID, 4>
+ AdditionalTemplateSpecializationsList;
+ typedef llvm::DenseMap<serialization::DeclID,
+ AdditionalTemplateSpecializationsList>
+ AdditionalTemplateSpecializationsMap;
+
+ /// \brief Additional specializations (including partial) of templates that
+ /// were introduced after the template was serialized.
+ AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializations;
+
/// \brief Statements that we've encountered while serializing a
/// declaration or type.
llvm::SmallVector<Stmt *, 16> StmtsToEmit;
-
- /// \brief Statements collection to use for PCHWriter::AddStmt().
+
+ /// \brief Statements collection to use for ASTWriter::AddStmt().
/// It will point to StmtsToEmit unless it is overriden.
llvm::SmallVector<Stmt *, 16> *CollectedStmts;
@@ -206,17 +241,17 @@ private:
/// \brief Mapping from LabelStmt statements to IDs.
std::map<LabelStmt *, unsigned> LabelIDs;
- /// \brief The number of statements written to the PCH file.
+ /// \brief The number of statements written to the AST file.
unsigned NumStatements;
- /// \brief The number of macros written to the PCH file.
+ /// \brief The number of macros written to the AST file.
unsigned NumMacros;
- /// \brief The number of lexical declcontexts written to the PCH
+ /// \brief The number of lexical declcontexts written to the AST
/// file.
unsigned NumLexicalDeclContexts;
- /// \brief The number of visible declcontexts written to the PCH
+ /// \brief The number of visible declcontexts written to the AST
/// file.
unsigned NumVisibleDeclContexts;
@@ -234,24 +269,31 @@ private:
void WriteType(QualType T);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
-
- void WriteMethodPool(Sema &SemaRef);
+ void WriteTypeDeclOffsets();
+ void WriteSelectors(Sema &SemaRef);
+ void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP);
- void WriteAttributeRecord(const Attr *Attr);
+ void WriteAttributeRecord(const AttrVec &Attrs);
+ void WriteDeclUpdateBlock();
+ void WriteDeclContextVisibleUpdate(const DeclContext *DC);
+ void WriteAdditionalTemplateSpecializations();
unsigned ParmVarDeclAbbrev;
+ unsigned DeclContextLexicalAbbrev;
+ unsigned DeclContextVisibleLookupAbbrev;
+ unsigned UpdateVisibleAbbrev;
void WriteDeclsBlockAbbrevs();
void WriteDecl(ASTContext &Context, Decl *D);
- void WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ void WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
- void WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ void WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
public:
/// \brief Create a new precompiled header writer that outputs to
/// the given bitstream.
- PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain);
+ ASTWriter(llvm::BitstreamWriter &Stream);
/// \brief Write a precompiled header for the given semantic analysis.
///
@@ -266,7 +308,7 @@ public:
///
/// \param PPRec Record of the preprocessing actions that occurred while
/// preprocessing this file, e.g., macro instantiations
- void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+ void WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char* isysroot);
/// \brief Emit a source location.
@@ -292,10 +334,12 @@ public:
/// \brief Emit a CXXTemporary.
void AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record);
+
+ /// \brief Get the unique number used to refer to the given selector.
+ serialization::SelectorID getSelectorRef(Selector Sel);
- /// \brief Get the unique number used to refer to the given
- /// identifier.
- pch::IdentID getIdentifierRef(const IdentifierInfo *II);
+ /// \brief Get the unique number used to refer to the given identifier.
+ serialization::IdentID getIdentifierRef(const IdentifierInfo *II);
/// \brief Retrieve the offset of the macro definition for the given
/// identifier.
@@ -309,11 +353,23 @@ public:
/// \brief Retrieve the ID number corresponding to the given macro
/// definition.
- pch::IdentID getMacroDefinitionID(MacroDefinition *MD);
+ serialization::IdentID getMacroDefinitionID(MacroDefinition *MD);
/// \brief Emit a reference to a type.
void AddTypeRef(QualType T, RecordData &Record);
+ /// \brief Force a type to be emitted and get its ID.
+ serialization::TypeID GetOrCreateTypeID(QualType T);
+
+ /// \brief Determine the type ID of an already-emitted type.
+ serialization::TypeID getTypeID(QualType T) const;
+
+ /// \brief Force a type to be emitted and get its index.
+ serialization::TypeIdx GetOrCreateTypeIdx(QualType T);
+
+ /// \brief Determine the type index of an already-emitted type.
+ serialization::TypeIdx getTypeIdx(QualType T) const;
+
/// \brief Emits a reference to a declarator info.
void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record);
@@ -329,9 +385,12 @@ public:
/// \brief Emit a reference to a declaration.
void AddDeclRef(const Decl *D, RecordData &Record);
+ /// \brief Force a declaration to be emitted and get its ID.
+ serialization::DeclID GetDeclRef(const Decl *D);
+
/// \brief Determine the declaration ID of an already-emitted
/// declaration.
- pch::DeclID getDeclID(const Decl *D);
+ serialization::DeclID getDeclID(const Decl *D);
/// \brief Emit a declaration name.
void AddDeclarationName(DeclarationName Name, RecordData &Record);
@@ -356,11 +415,28 @@ public:
/// \brief Emit a UnresolvedSet structure.
void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record);
- /// brief Emit a C++ base specifier.
+ /// \brief Emit a C++ base specifier.
void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordData &Record);
+ /// \brief Emit a CXXBaseOrMemberInitializer array.
+ void AddCXXBaseOrMemberInitializers(
+ const CXXBaseOrMemberInitializer * const *BaseOrMembers,
+ unsigned NumBaseOrMembers, RecordData &Record);
+
/// \brief Add a string to the given record.
- void AddString(const std::string &Str, RecordData &Record);
+ void AddString(llvm::StringRef Str, RecordData &Record);
+
+ /// \brief Mark a namespace as needing an update.
+ void AddUpdatedNamespace(const NamespaceDecl *NS) {
+ UpdatedNamespaces.insert(NS);
+ }
+
+ /// \brief Record a template specialization or partial specialization of
+ /// a template from a previous PCH file.
+ void AddAdditionalTemplateSpecialization(serialization::DeclID Templ,
+ serialization::DeclID Spec) {
+ AdditionalTemplateSpecializations[Templ].push_back(Spec);
+ }
/// \brief Note that the identifier II occurs at the given offset
/// within the identifier table.
@@ -398,9 +474,38 @@ public:
unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
- // PCHDeserializationListener implementation
- void TypeRead(pch::TypeID ID, QualType T);
- void DeclRead(pch::DeclID ID, const Decl *D);
+ bool hasChain() const { return Chain; }
+
+ // ASTDeserializationListener implementation
+ void SetReader(ASTReader *Reader);
+ void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II);
+ void TypeRead(serialization::TypeIdx Idx, QualType T);
+ void DeclRead(serialization::DeclID ID, const Decl *D);
+ void SelectorRead(serialization::SelectorID iD, Selector Sel);
+};
+
+/// \brief AST and semantic-analysis consumer that generates a
+/// precompiled header from the parsed source code.
+class PCHGenerator : public SemaConsumer {
+ const Preprocessor &PP;
+ const char *isysroot;
+ llvm::raw_ostream *Out;
+ Sema *SemaPtr;
+ MemorizeStatCalls *StatCalls; // owned by the FileManager
+ std::vector<unsigned char> Buffer;
+ llvm::BitstreamWriter Stream;
+ ASTWriter Writer;
+
+protected:
+ ASTWriter &getWriter() { return Writer; }
+ const ASTWriter &getWriter() const { return Writer; }
+
+public:
+ PCHGenerator(const Preprocessor &PP, bool Chaining,
+ const char *isysroot, llvm::raw_ostream *Out);
+ virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+ virtual ASTDeserializationListener *GetASTDeserializationListener();
};
} // end namespace clang
diff --git a/include/clang/Serialization/CMakeLists.txt b/include/clang/Serialization/CMakeLists.txt
new file mode 100644
index 000000000000..3712009bf37d
--- /dev/null
+++ b/include/clang/Serialization/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td)
+tablegen(AttrPCHRead.inc
+ -gen-clang-attr-pch-read
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrPCHRead
+ DEPENDS AttrPCHRead.inc)
+
+tablegen(AttrPCHWrite.inc
+ -gen-clang-attr-pch-write
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
+add_custom_target(ClangAttrPCHWrite
+ DEPENDS AttrPCHWrite.inc)
diff --git a/include/clang/Serialization/Makefile b/include/clang/Serialization/Makefile
new file mode 100644
index 000000000000..79486b11bc68
--- /dev/null
+++ b/include/clang/Serialization/Makefile
@@ -0,0 +1,19 @@
+CLANG_LEVEL := ../../..
+TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
+BUILT_SOURCES = AttrPCHRead.inc AttrPCHWrite.inc
+
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+$(ObjDir)/AttrPCHRead.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang PCH reader with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-pch-read -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
+$(ObjDir)/AttrPCHWrite.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang PCH writer with tblgen"
+ $(Verb) $(TableGen) -gen-clang-attr-pch-write -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index f37cbdea5480..04a084a06a44 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -17,3 +17,6 @@ using namespace clang;
void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
+ HandleTopLevelDecl(D);
+}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d41051f5dcad..4591a0f3c55c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -28,6 +28,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include "CXXABI.h"
using namespace clang;
@@ -134,11 +135,25 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
return CanonTTP;
}
+CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
+ if (!LangOpts.CPlusPlus) return 0;
+
+ switch (T.getCXXABI()) {
+ case CXXABI_ARM:
+ return CreateARMCXXABI(*this);
+ case CXXABI_Itanium:
+ return CreateItaniumCXXABI(*this);
+ case CXXABI_Microsoft:
+ return CreateMicrosoftCXXABI(*this);
+ }
+ return 0;
+}
+
ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
- bool FreeMem, unsigned size_reserve) :
+ unsigned size_reserve) :
TemplateSpecializationTypes(this_()),
DependentTemplateSpecializationTypes(this_()),
GlobalNestedNameSpecifier(0), IsInt128Installed(false),
@@ -146,7 +161,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
NullTypeSourceInfo(QualType()),
- SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t),
+ SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), Target(t),
Idents(idents), Selectors(sels),
BuiltinInfo(builtins),
DeclarationNames(*this),
@@ -155,7 +170,7 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) {
ObjCIdRedefinitionType = QualType();
ObjCClassRedefinitionType = QualType();
- ObjCSelRedefinitionType = QualType();
+ ObjCSelRedefinitionType = QualType();
if (size_reserve > 0) Types.reserve(size_reserve);
TUDecl = TranslationUnitDecl::Create(*this);
InitBuiltinTypes();
@@ -166,11 +181,9 @@ ASTContext::~ASTContext() {
// FIXME: Is this the ideal solution?
ReleaseDeclContextMaps();
- if (!FreeMemory) {
- // Call all of the deallocation functions.
- for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
- Deallocations[I].first(Deallocations[I].second);
- }
+ // Call all of the deallocation functions.
+ for (unsigned I = 0, N = Deallocations.size(); I != N; ++I)
+ Deallocations[I].first(Deallocations[I].second);
// Release all of the memory associated with overridden C++ methods.
for (llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::iterator
@@ -178,51 +191,26 @@ ASTContext::~ASTContext() {
OM != OMEnd; ++OM)
OM->second.Destroy();
- if (FreeMemory) {
- // Deallocate all the types.
- while (!Types.empty()) {
- Types.back()->Destroy(*this);
- Types.pop_back();
- }
-
- for (llvm::FoldingSet<ExtQuals>::iterator
- I = ExtQualNodes.begin(), E = ExtQualNodes.end(); I != E; ) {
- // Increment in loop to prevent using deallocated memory.
- Deallocate(&*I++);
- }
-
- for (llvm::DenseMap<const ObjCContainerDecl*,
- const ASTRecordLayout*>::iterator
- I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) {
- // Increment in loop to prevent using deallocated memory.
- if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
- R->Destroy(*this);
- }
- }
-
// ASTRecordLayout objects in ASTRecordLayouts must always be destroyed
- // even when using the BumpPtrAllocator because they can contain
- // DenseMaps.
- for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
- I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
+ // because they can contain DenseMaps.
+ for (llvm::DenseMap<const ObjCContainerDecl*,
+ const ASTRecordLayout*>::iterator
+ I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; )
// Increment in loop to prevent using deallocated memory.
if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
R->Destroy(*this);
- }
- // Destroy nested-name-specifiers.
- for (llvm::FoldingSet<NestedNameSpecifier>::iterator
- NNS = NestedNameSpecifiers.begin(),
- NNSEnd = NestedNameSpecifiers.end();
- NNS != NNSEnd; ) {
+ for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
+ I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
// Increment in loop to prevent using deallocated memory.
- (*NNS++).Destroy(*this);
+ if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second))
+ R->Destroy(*this);
}
-
- if (GlobalNestedNameSpecifier)
- GlobalNestedNameSpecifier->Destroy(*this);
-
- TUDecl->Destroy(*this);
+
+ for (llvm::DenseMap<const Decl*, AttrVec*>::iterator A = DeclAttrs.begin(),
+ AEnd = DeclAttrs.end();
+ A != AEnd; ++A)
+ A->second->~AttrVec();
}
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
@@ -275,16 +263,12 @@ void ASTContext::PrintStats() const {
fprintf(stderr, " %u/%u implicit destructors created\n",
NumImplicitDestructorsDeclared, NumImplicitDestructors);
- if (!FreeMemory)
- BumpAlloc.PrintStats();
-
if (ExternalSource.get()) {
fprintf(stderr, "\n");
ExternalSource->PrintStats();
}
- if (!FreeMemory)
- BumpAlloc.PrintStats();
+ BumpAlloc.PrintStats();
}
@@ -385,6 +369,26 @@ void ASTContext::InitBuiltinTypes() {
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
}
+AttrVec& ASTContext::getDeclAttrs(const Decl *D) {
+ AttrVec *&Result = DeclAttrs[D];
+ if (!Result) {
+ void *Mem = Allocate(sizeof(AttrVec));
+ Result = new (Mem) AttrVec;
+ }
+
+ return *Result;
+}
+
+/// \brief Erase the attributes corresponding to the given declaration.
+void ASTContext::eraseDeclAttrs(const Decl *D) {
+ llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D);
+ if (Pos != DeclAttrs.end()) {
+ Pos->second->~AttrVec();
+ DeclAttrs.erase(Pos);
+ }
+}
+
+
MemberSpecializationInfo *
ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
assert(Var->isStaticDataMember() && "Not a static data member");
@@ -499,20 +503,6 @@ void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
OverriddenMethods[Method].push_back(Overridden);
}
-namespace {
- class BeforeInTranslationUnit
- : std::binary_function<SourceRange, SourceRange, bool> {
- SourceManager *SourceMgr;
-
- public:
- explicit BeforeInTranslationUnit(SourceManager *SM) : SourceMgr(SM) { }
-
- bool operator()(SourceRange X, SourceRange Y) {
- return SourceMgr->isBeforeInTranslationUnit(X.getBegin(), Y.getBegin());
- }
- };
-}
-
//===----------------------------------------------------------------------===//
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//
@@ -538,8 +528,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const {
CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) {
unsigned Align = Target.getCharWidth();
- if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
- Align = std::max(Align, AA->getMaxAlignment());
+ Align = std::max(Align, D->getMaxAlignment());
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
QualType T = VD->getType();
@@ -716,6 +705,12 @@ ASTContext::getTypeInfo(const Type *T) {
Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
Align = Target.getPointerAlign(0); // == sizeof(void*)
break;
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ Width = Target.getPointerWidth(0);
+ Align = Target.getPointerAlign(0);
+ break;
}
break;
case Type::ObjCObjectPointer:
@@ -744,12 +739,10 @@ ASTContext::getTypeInfo(const Type *T) {
break;
}
case Type::MemberPointer: {
- QualType Pointee = cast<MemberPointerType>(T)->getPointeeType();
+ const MemberPointerType *MPT = cast<MemberPointerType>(T);
std::pair<uint64_t, unsigned> PtrDiffInfo =
getTypeInfo(getPointerDiffType());
- Width = PtrDiffInfo.first;
- if (Pointee->isFunctionType())
- Width *= 2;
+ Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT);
Align = PtrDiffInfo.second;
break;
}
@@ -797,12 +790,10 @@ ASTContext::getTypeInfo(const Type *T) {
case Type::Typedef: {
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
- if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
- Align = std::max(Aligned->getMaxAlignment(),
- getTypeAlign(Typedef->getUnderlyingType().getTypePtr()));
- Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
- } else
- return getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ std::pair<uint64_t, unsigned> Info
+ = getTypeInfo(Typedef->getUnderlyingType().getTypePtr());
+ Align = std::max(Typedef->getMaxAlignment(), Info.second);
+ Width = Info.first;
break;
}
@@ -868,60 +859,37 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) {
return ABIAlign;
}
-static void CollectLocalObjCIvars(ASTContext *Ctx,
- const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<FieldDecl*> &Fields) {
- for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
- E = OI->ivar_end(); I != E; ++I) {
- ObjCIvarDecl *IVDecl = *I;
- if (!IVDecl->isInvalidDecl())
- Fields.push_back(cast<FieldDecl>(IVDecl));
- }
-}
-
-void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI,
- llvm::SmallVectorImpl<FieldDecl*> &Fields) {
- if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
- CollectObjCIvars(SuperClass, Fields);
- CollectLocalObjCIvars(this, OI, Fields);
-}
-
/// ShallowCollectObjCIvars -
/// Collect all ivars, including those synthesized, in the current class.
///
void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
- for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
- E = OI->ivar_end(); I != E; ++I) {
- Ivars.push_back(*I);
- }
-
- CollectNonClassIvars(OI, Ivars);
-}
-
-/// CollectNonClassIvars -
-/// This routine collects all other ivars which are not declared in the class.
-/// This includes synthesized ivars (via @synthesize) and those in
-// class's @implementation.
+ // FIXME. This need be removed but there are two many places which
+ // assume const-ness of ObjCInterfaceDecl
+ ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI);
+ for (ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
+ Iv= Iv->getNextIvar())
+ Ivars.push_back(Iv);
+}
+
+/// DeepCollectObjCIvars -
+/// This routine first collects all declared, but not synthesized, ivars in
+/// super class and then collects all ivars, including those synthesized for
+/// current class. This routine is used for implementation of current class
+/// when all ivars, declared and synthesized are known.
///
-void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
+void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
+ bool leafClass,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
- // Find ivars declared in class extension.
- for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
- CDecl = CDecl->getNextClassExtension()) {
- for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
- E = CDecl->ivar_end(); I != E; ++I) {
- Ivars.push_back(*I);
- }
- }
-
- // Also add any ivar defined in this class's implementation. This
- // includes synthesized ivars.
- if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) {
- for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
- E = ImplDecl->ivar_end(); I != E; ++I)
+ if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass())
+ DeepCollectObjCIvars(SuperClass, false, Ivars);
+ if (!leafClass) {
+ for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
+ E = OI->ivar_end(); I != E; ++I)
Ivars.push_back(*I);
}
+ else
+ ShallowCollectObjCIvars(OI, Ivars);
}
/// CollectInheritedProtocols - Collect all protocols in current class and
@@ -929,8 +897,10 @@ void ASTContext::CollectNonClassIvars(const ObjCInterfaceDecl *OI,
void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
- PE = OI->protocol_end(); P != PE; ++P) {
+ // We can use protocol_iterator here instead of
+ // all_referenced_protocol_iterator since we are walking all categories.
+ for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(),
+ PE = OI->all_referenced_protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
Protocols.insert(Proto);
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
@@ -950,7 +920,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
SD = SD->getSuperClass();
}
} else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
+ for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
PE = OC->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
Protocols.insert(Proto);
@@ -1154,6 +1124,15 @@ static QualType getExtFunctionType(ASTContext& Context, QualType T,
return T;
ResultType = Context.getBlockPointerType(ResultType);
+ } else if (const MemberPointerType *MemberPointer
+ = T->getAs<MemberPointerType>()) {
+ QualType Pointee = MemberPointer->getPointeeType();
+ ResultType = getExtFunctionType(Context, Pointee, Info);
+ if (ResultType == Pointee)
+ return T;
+
+ ResultType = Context.getMemberPointerType(ResultType,
+ MemberPointer->getClass());
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
if (F->getExtInfo() == Info)
return T;
@@ -1570,10 +1549,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
// If the element type isn't canonical, this won't be a canonical type either,
// so fill in the canonical type field.
QualType Canonical;
- if (!vecType.isCanonical() || (AltiVecSpec == VectorType::AltiVec)) {
- // pass VectorType::NotAltiVec for AltiVecSpec to make AltiVec canonical
- // vector type (except 'vector bool ...' and 'vector Pixel') the same as
- // the equivalent GCC vector types
+ if (!vecType.isCanonical()) {
Canonical = getVectorType(getCanonicalType(vecType), NumElts,
VectorType::NotAltiVec);
@@ -2567,21 +2543,31 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
return false;
}
-DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
+DeclarationNameInfo ASTContext::getNameForTemplate(TemplateName Name,
+ SourceLocation NameLoc) {
if (TemplateDecl *TD = Name.getAsTemplateDecl())
- return TD->getDeclName();
-
+ // DNInfo work in progress: CHECKME: what about DNLoc?
+ return DeclarationNameInfo(TD->getDeclName(), NameLoc);
+
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+ DeclarationName DName;
if (DTN->isIdentifier()) {
- return DeclarationNames.getIdentifier(DTN->getIdentifier());
+ DName = DeclarationNames.getIdentifier(DTN->getIdentifier());
+ return DeclarationNameInfo(DName, NameLoc);
} else {
- return DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ DName = DeclarationNames.getCXXOperatorName(DTN->getOperator());
+ // DNInfo work in progress: FIXME: source locations?
+ DeclarationNameLoc DNLoc;
+ DNLoc.CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
+ DNLoc.CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ return DeclarationNameInfo(DName, NameLoc, DNLoc);
}
}
OverloadedTemplateStorage *Storage = Name.getAsOverloadedTemplate();
assert(Storage);
- return (*Storage->begin())->getDeclName();
+ // DNInfo work in progress: CHECKME: what about DNLoc?
+ return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);
}
TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) {
@@ -3216,14 +3202,14 @@ bool ASTContext::BlockRequiresCopying(QualType Ty) {
return false;
}
-QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
+QualType ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) {
// type = struct __Block_byref_1_X {
// void *__isa;
// struct __Block_byref_1_X *__forwarding;
// unsigned int __flags;
// unsigned int __size;
- // void *__copy_helper; // as needed
- // void *__destroy_help // as needed
+ // void *__copy_helper; // as needed
+ // void *__destroy_help // as needed
// int X;
// } *
@@ -3249,7 +3235,7 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
Ty
};
- const char *FieldNames[] = {
+ llvm::StringRef FieldNames[] = {
"__isa",
"__forwarding",
"__flags",
@@ -3326,7 +3312,7 @@ QualType ASTContext::getBlockParmType(
const ValueDecl *D = BDRE->getDecl();
FieldName = D->getIdentifier();
if (BDRE->isByRef())
- FieldType = BuildByRefType(D->getNameAsCString(), FieldType);
+ FieldType = BuildByRefType(D->getName(), FieldType);
} else {
// Padding.
assert(isa<ConstantArrayType>(FieldType) &&
@@ -3885,15 +3871,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
const IdentifierInfo *II = OI->getIdentifier();
S += II->getName();
S += '=';
- llvm::SmallVector<FieldDecl*, 32> RecFields;
- CollectObjCIvars(OI, RecFields);
- for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
- if (RecFields[i]->isBitField())
- getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
- RecFields[i]);
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ DeepCollectObjCIvars(OI, true, Ivars);
+ for (unsigned i = 0, e = Ivars.size(); i != e; ++i) {
+ FieldDecl *Field = cast<FieldDecl>(Ivars[i]);
+ if (Field->isBitField())
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field);
else
- getObjCEncodingForTypeImpl(RecFields[i]->getType(), S, false, true,
- FD);
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD);
}
S += '}';
return;
@@ -4200,6 +4185,28 @@ static bool areCompatVectorTypes(const VectorType *LHS,
LHS->getNumElements() == RHS->getNumElements();
}
+bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
+ QualType SecondVec) {
+ assert(FirstVec->isVectorType() && "FirstVec should be a vector type");
+ assert(SecondVec->isVectorType() && "SecondVec should be a vector type");
+
+ if (hasSameUnqualifiedType(FirstVec, SecondVec))
+ return true;
+
+ // AltiVec vectors types are identical to equivalent GCC vector types
+ const VectorType *First = FirstVec->getAs<VectorType>();
+ const VectorType *Second = SecondVec->getAs<VectorType>();
+ if ((((First->getAltiVecSpecific() == VectorType::AltiVec) &&
+ (Second->getAltiVecSpecific() == VectorType::NotAltiVec)) ||
+ ((First->getAltiVecSpecific() == VectorType::NotAltiVec) &&
+ (Second->getAltiVecSpecific() == VectorType::AltiVec))) &&
+ hasSameType(First->getElementType(), Second->getElementType()) &&
+ (First->getNumElements() == Second->getNumElements()))
+ return true;
+
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
//===----------------------------------------------------------------------===//
@@ -4226,6 +4233,32 @@ bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
return false;
}
+/// ObjCQualifiedClassTypesAreCompatible - compare Class<p,...> and
+/// Class<p1, ...>.
+bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
+ QualType rhs) {
+ const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
+
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ bool match = false;
+ ObjCProtocolDecl *lhsProto = *I;
+ for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
+ E = rhsOPT->qual_end(); J != E; ++J) {
+ ObjCProtocolDecl *rhsProto = *J;
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false;
+ }
+ return true;
+}
+
/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
/// ObjCQualifiedIDType.
bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
@@ -4308,9 +4341,9 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
E = rhsQID->qual_end(); I != E; ++I) {
- // when comparing an id<P> on lhs with a static type on rhs,
- // see if static class implements all of id's protocols, directly or
- // through its super class and categories.
+ // when comparing an id<P> on rhs with a static type on lhs,
+ // static class must implement all of id's protocols directly or
+ // indirectly through its super class.
if (lhsID->ClassImplementsProtocol(*I, true)) {
match = true;
break;
@@ -4365,7 +4398,11 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
-
+
+ if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
+ return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0));
+
// If we have 2 user-defined types, fall into that path.
if (LHS->getInterface() && RHS->getInterface())
return canAssignObjCInterfaces(LHS, RHS);
@@ -4541,15 +4578,22 @@ bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) {
canAssignObjCInterfaces(RHSOPT, LHSOPT);
}
+bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
+ return canAssignObjCInterfaces(
+ getObjCObjectPointerType(To)->getAs<ObjCObjectPointerType>(),
+ getObjCObjectPointerType(From)->getAs<ObjCObjectPointerType>());
+}
+
/// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible,
/// both shall have the identically qualified version of a compatible type.
/// C99 6.2.7p1: Two types have compatible types if their types are the
/// same. See 6.7.[2,3,5] for additional rules.
-bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS) {
+bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
+ bool CompareUnqualified) {
if (getLangOptions().CPlusPlus)
return hasSameType(LHS, RHS);
- return !mergeTypes(LHS, RHS).isNull();
+ return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
}
bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
@@ -4557,7 +4601,8 @@ bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
}
QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
- bool OfBlockPointer) {
+ bool OfBlockPointer,
+ bool Unqualified) {
const FunctionType *lbase = lhs->getAs<FunctionType>();
const FunctionType *rbase = rhs->getAs<FunctionType>();
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
@@ -4568,13 +4613,26 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
// Check return type
QualType retType;
if (OfBlockPointer)
- retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true);
+ retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true,
+ Unqualified);
else
- retType = mergeTypes(lbase->getResultType(), rbase->getResultType());
+ retType = mergeTypes(lbase->getResultType(), rbase->getResultType(),
+ false, Unqualified);
if (retType.isNull()) return QualType();
- if (getCanonicalType(retType) != getCanonicalType(lbase->getResultType()))
+
+ if (Unqualified)
+ retType = retType.getUnqualifiedType();
+
+ CanQualType LRetType = getCanonicalType(lbase->getResultType());
+ CanQualType RRetType = getCanonicalType(rbase->getResultType());
+ if (Unqualified) {
+ LRetType = LRetType.getUnqualifiedType();
+ RRetType = RRetType.getUnqualifiedType();
+ }
+
+ if (getCanonicalType(retType) != LRetType)
allLTypes = false;
- if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
+ if (getCanonicalType(retType) != RRetType)
allRTypes = false;
// FIXME: double check this
// FIXME: should we error if lbase->getRegParmAttr() != 0 &&
@@ -4619,9 +4677,19 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
for (unsigned i = 0; i < lproto_nargs; i++) {
QualType largtype = lproto->getArgType(i).getUnqualifiedType();
QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
- QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer);
+ QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer,
+ Unqualified);
if (argtype.isNull()) return QualType();
+
+ if (Unqualified)
+ argtype = argtype.getUnqualifiedType();
+
types.push_back(argtype);
+ if (Unqualified) {
+ largtype = largtype.getUnqualifiedType();
+ rargtype = rargtype.getUnqualifiedType();
+ }
+
if (getCanonicalType(argtype) != getCanonicalType(largtype))
allLTypes = false;
if (getCanonicalType(argtype) != getCanonicalType(rargtype))
@@ -4677,7 +4745,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
}
QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
- bool OfBlockPointer) {
+ bool OfBlockPointer,
+ bool Unqualified) {
// C++ [expr]: If an expression initially has the type "reference to T", the
// type is adjusted to "T" prior to any further analysis, the expression
// designates the object or function denoted by the reference, and the
@@ -4685,6 +4754,11 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// the expression is a function call (possibly inside parentheses).
assert(!LHS->getAs<ReferenceType>() && "LHS is a reference type?");
assert(!RHS->getAs<ReferenceType>() && "RHS is a reference type?");
+
+ if (Unqualified) {
+ LHS = LHS.getUnqualifiedType();
+ RHS = RHS.getUnqualifiedType();
+ }
QualType LHSCan = getCanonicalType(LHS),
RHSCan = getCanonicalType(RHS);
@@ -4796,7 +4870,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// Merge two pointer types, while trying to preserve typedef info
QualType LHSPointee = LHS->getAs<PointerType>()->getPointeeType();
QualType RHSPointee = RHS->getAs<PointerType>()->getPointeeType();
- QualType ResultType = mergeTypes(LHSPointee, RHSPointee);
+ if (Unqualified) {
+ LHSPointee = LHSPointee.getUnqualifiedType();
+ RHSPointee = RHSPointee.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false,
+ Unqualified);
if (ResultType.isNull()) return QualType();
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
@@ -4809,7 +4888,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// Merge two block pointer types, while trying to preserve typedef info
QualType LHSPointee = LHS->getAs<BlockPointerType>()->getPointeeType();
QualType RHSPointee = RHS->getAs<BlockPointerType>()->getPointeeType();
- QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer);
+ if (Unqualified) {
+ LHSPointee = LHSPointee.getUnqualifiedType();
+ RHSPointee = RHSPointee.getUnqualifiedType();
+ }
+ QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
+ Unqualified);
if (ResultType.isNull()) return QualType();
if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
return LHS;
@@ -4826,7 +4910,12 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
QualType LHSElem = getAsArrayType(LHS)->getElementType();
QualType RHSElem = getAsArrayType(RHS)->getElementType();
- QualType ResultType = mergeTypes(LHSElem, RHSElem);
+ if (Unqualified) {
+ LHSElem = LHSElem.getUnqualifiedType();
+ RHSElem = RHSElem.getUnqualifiedType();
+ }
+
+ QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
if (ResultType.isNull()) return QualType();
if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
return LHS;
@@ -4860,7 +4949,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
ArrayType::ArraySizeModifier(), 0);
}
case Type::FunctionNoProto:
- return mergeFunctionTypes(LHS, RHS, OfBlockPointer);
+ return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified);
case Type::Record:
case Type::Enum:
return QualType();
@@ -5001,7 +5090,7 @@ unsigned ASTContext::getIntWidth(QualType T) {
}
QualType ASTContext::getCorrespondingUnsignedType(QualType T) {
- assert(T->isSignedIntegerType() && "Unexpected type");
+ assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
// Turn <4 x signed int> -> <4 x unsigned int>
if (const VectorType *VTy = T->getAs<VectorType>())
@@ -5381,8 +5470,8 @@ ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
// Finally, we have two differing integer types.
// The rules for this case are in C99 6.3.1.8
int compare = getIntegerTypeOrder(lhs, rhs);
- bool lhsSigned = lhs->isSignedIntegerType(),
- rhsSigned = rhs->isSignedIntegerType();
+ bool lhsSigned = lhs->hasSignedIntegerRepresentation(),
+ rhsSigned = rhs->hasSignedIntegerRepresentation();
QualType destType;
if (lhsSigned == rhsSigned) {
// Same signedness; use the higher-ranked type
@@ -5405,3 +5494,173 @@ ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
}
return destType;
}
+
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
+ GVALinkage External = GVA_StrongExternal;
+
+ Linkage L = FD->getLinkage();
+ if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
+ FD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return GVA_Internal;
+
+ case ExternalLinkage:
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ External = GVA_StrongExternal;
+ break;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ImplicitInstantiation:
+ External = GVA_TemplateInstantiation;
+ break;
+ }
+ }
+
+ if (!FD->isInlined())
+ return External;
+
+ if (!getLangOptions().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
+ // GNU or C99 inline semantics. Determine whether this symbol should be
+ // externally visible.
+ if (FD->isInlineDefinitionExternallyVisible())
+ return External;
+
+ // C99 inline semantics, where the symbol is not externally visible.
+ return GVA_C99Inline;
+ }
+
+ // C++0x [temp.explicit]p9:
+ // [ Note: The intent is that an inline function that is the subject of
+ // an explicit instantiation declaration will still be implicitly
+ // instantiated when used so that the body can be considered for
+ // inlining, but that no out-of-line copy of the inline function would be
+ // generated in the translation unit. -- end note ]
+ if (FD->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration)
+ return GVA_C99Inline;
+
+ return GVA_CXXInline;
+}
+
+GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ // If this is a static data member, compute the kind of template
+ // specialization. Otherwise, this variable is not part of a
+ // template.
+ TemplateSpecializationKind TSK = TSK_Undeclared;
+ if (VD->isStaticDataMember())
+ TSK = VD->getTemplateSpecializationKind();
+
+ Linkage L = VD->getLinkage();
+ if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
+ VD->getType()->getLinkage() == UniqueExternalLinkage)
+ L = UniqueExternalLinkage;
+
+ switch (L) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return GVA_Internal;
+
+ case ExternalLinkage:
+ switch (TSK) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return GVA_StrongExternal;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ llvm_unreachable("Variable should not be instantiated");
+ // Fall through to treat this like any other instantiation.
+
+ case TSK_ExplicitInstantiationDefinition:
+ return GVA_ExplicitTemplateInstantiation;
+
+ case TSK_ImplicitInstantiation:
+ return GVA_TemplateInstantiation;
+ }
+ }
+
+ return GVA_StrongExternal;
+}
+
+bool ASTContext::DeclMustBeEmitted(const Decl *D) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (!VD->isFileVarDecl())
+ return false;
+ } else if (!isa<FunctionDecl>(D))
+ return false;
+
+ // Weak references don't produce any output by themselves.
+ if (D->hasAttr<WeakRefAttr>())
+ return false;
+
+ // Aliases and used decls are required.
+ if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
+ return true;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // Forward declarations aren't required.
+ if (!FD->isThisDeclarationADefinition())
+ return false;
+
+ // Constructors and destructors are required.
+ if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+ return true;
+
+ // The key function for a class is required.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ const CXXRecordDecl *RD = MD->getParent();
+ if (MD->isOutOfLine() && RD->isDynamicClass()) {
+ const CXXMethodDecl *KeyFunc = getKeyFunction(RD);
+ if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
+ return true;
+ }
+ }
+
+ GVALinkage Linkage = GetGVALinkageForFunction(FD);
+
+ // static, static inline, always_inline, and extern inline functions can
+ // always be deferred. Normal inline functions can be deferred in C99/C++.
+ // Implicit template instantiations can also be deferred in C++.
+ if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
+ Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
+ return false;
+ return true;
+ }
+
+ const VarDecl *VD = cast<VarDecl>(D);
+ assert(VD->isFileVarDecl() && "Expected file scoped var");
+
+ if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly)
+ return false;
+
+ // Structs that have non-trivial constructors or destructors are required.
+
+ // FIXME: Handle references.
+ if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+ if (RD->hasDefinition() &&
+ (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
+ return true;
+ }
+ }
+
+ GVALinkage L = GetGVALinkageForVariable(VD);
+ if (L == GVA_Internal || L == GVA_TemplateInstantiation) {
+ if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this)))
+ return false;
+ }
+
+ return true;
+}
+
+CXXABI::~CXXABI() {}
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 0d609bfa6d39..23f323d0286a 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -151,10 +151,13 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
bool ShouldAKA = false;
QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
if (ShouldAKA) {
- S = "'"+S+"' (aka '";
- S += DesugaredTy.getAsString(Context.PrintingPolicy);
- S += "')";
- return S;
+ std::string D = DesugaredTy.getAsString(Context.PrintingPolicy);
+ if (D != S) {
+ S = "'" + S + "' (aka '";
+ S += D;
+ S += "')";
+ return S;
+ }
}
}
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 8d347d171665..2edd09c067e9 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -19,7 +19,6 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
@@ -82,6 +81,8 @@ namespace {
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
SourceLocation &Loc);
+ void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
+ DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC);
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord);
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
@@ -1385,6 +1386,40 @@ bool ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclContext *&DC,
return false;
}
+void
+ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
+ DeclarationNameInfo& To) {
+ // NOTE: To.Name and To.Loc are already imported.
+ // We only have to import To.LocInfo.
+ switch (To.getName().getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ return;
+
+ case DeclarationName::CXXOperatorName: {
+ SourceRange Range = From.getCXXOperatorNameRange();
+ To.setCXXOperatorNameRange(Importer.Import(Range));
+ return;
+ }
+ case DeclarationName::CXXLiteralOperatorName: {
+ SourceLocation Loc = From.getCXXLiteralOperatorNameLoc();
+ To.setCXXLiteralOperatorNameLoc(Importer.Import(Loc));
+ return;
+ }
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName: {
+ TypeSourceInfo *FromTInfo = From.getNamedTypeInfo();
+ To.setNamedTypeInfo(Importer.Import(FromTInfo));
+ return;
+ }
+ assert(0 && "Unknown name kind.");
+ }
+}
+
void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC) {
for (DeclContext::decl_iterator From = FromDC->decls_begin(),
FromEnd = FromDC->decls_end();
@@ -1752,7 +1787,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
Base1->isVirtual(),
Base1->isBaseOfClass(),
Base1->getAccessSpecifierAsWritten(),
- T));
+ Importer.Import(Base1->getTypeSourceInfo())));
}
if (!Bases.empty())
D2CXX->setBases(Bases.data(), Bases.size());
@@ -1822,7 +1857,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
SourceLocation Loc;
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
-
+
// Try to find a function in our own ("to") context with the same name, same
// type, and in the same context as the function we're importing.
if (!LexicalDC->isFunctionOrMethod()) {
@@ -1871,6 +1906,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
}
}
+ DeclarationNameInfo NameInfo(Name, Loc);
+ // Import additional name location/type info.
+ ImportDeclarationNameLoc(D->getNameInfo(), NameInfo);
+
// Import the type.
QualType T = Importer.Import(D->getType());
if (T.isNull())
@@ -1893,26 +1932,26 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) {
ToFunction = CXXConstructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- Loc, Name, T, TInfo,
+ NameInfo, T, TInfo,
FromConstructor->isExplicit(),
D->isInlineSpecified(),
D->isImplicit());
} else if (isa<CXXDestructorDecl>(D)) {
ToFunction = CXXDestructorDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- Loc, Name, T,
+ NameInfo, T,
D->isInlineSpecified(),
D->isImplicit());
} else if (CXXConversionDecl *FromConversion
= dyn_cast<CXXConversionDecl>(D)) {
ToFunction = CXXConversionDecl::Create(Importer.getToContext(),
cast<CXXRecordDecl>(DC),
- Loc, Name, T, TInfo,
+ NameInfo, T, TInfo,
D->isInlineSpecified(),
FromConversion->isExplicit());
} else {
- ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, Loc,
- Name, T, TInfo, D->getStorageClass(),
+ ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
+ NameInfo, T, TInfo, D->getStorageClass(),
D->getStorageClassAsWritten(),
D->isInlineSpecified(),
D->hasWrittenPrototype());
@@ -2026,7 +2065,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
cast<ObjCContainerDecl>(DC),
Loc, Name.getAsIdentifierInfo(),
T, TInfo, D->getAccessControl(),
- BitWidth);
+ BitWidth, D->getSynthesize());
ToIvar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIvar);
LexicalDC->addDecl(ToIvar);
@@ -2299,6 +2338,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
D->isInstanceMethod(),
D->isVariadic(),
D->isSynthesized(),
+ D->isDefined(),
D->getImplementationControl());
// FIXME: When we decide to merge method definitions, we'll need to
@@ -2513,6 +2553,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
ObjCInterfaceDecl::protocol_loc_iterator
FromProtoLoc = D->protocol_loc_begin();
+
+ // FIXME: Should we be usng all_referenced_protocol_begin() here?
for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
FromProtoEnd = D->protocol_end();
FromProto != FromProtoEnd;
@@ -2778,8 +2820,9 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) {
if (T.isNull())
return 0;
- return new (Importer.getToContext())
- IntegerLiteral(E->getValue(), T, Importer.Import(E->getLocation()));
+ return IntegerLiteral::Create(Importer.getToContext(),
+ E->getValue(), T,
+ Importer.Import(E->getLocation()));
}
Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) {
@@ -2886,6 +2929,13 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
Importer.Import(E->getOperatorLoc()));
}
+bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
+ if (E->path_empty()) return false;
+
+ // TODO: import cast paths
+ return true;
+}
+
Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
QualType T = Importer.Import(E->getType());
if (T.isNull())
@@ -2894,13 +2944,13 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
Expr *SubExpr = Importer.Import(E->getSubExpr());
if (!SubExpr)
return 0;
-
- // FIXME: Initialize the base path.
- assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
- CXXBaseSpecifierArray BasePath;
- return new (Importer.getToContext()) ImplicitCastExpr(T, E->getCastKind(),
- SubExpr, BasePath,
- E->isLvalueCast());
+
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, E->getValueKind());
}
Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
@@ -2916,13 +2966,14 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
if (!TInfo && E->getTypeInfoAsWritten())
return 0;
- // FIXME: Initialize the base path.
- assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
- CXXBaseSpecifierArray BasePath;
- return new (Importer.getToContext()) CStyleCastExpr(T, E->getCastKind(),
- SubExpr, BasePath, TInfo,
- Importer.Import(E->getLParenLoc()),
- Importer.Import(E->getRParenLoc()));
+ CXXCastPath BasePath;
+ if (ImportCastPath(E, BasePath))
+ return 0;
+
+ return CStyleCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+ SubExpr, &BasePath, TInfo,
+ Importer.Import(E->getLParenLoc()),
+ Importer.Import(E->getRParenLoc()));
}
ASTImporter::ASTImporter(Diagnostic &Diags,
@@ -2964,8 +3015,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
return FromTSI;
// FIXME: For now we just create a "trivial" type source info based
- // on the type and a seingle location. Implement a real version of
- // this.
+ // on the type and a single location. Implement a real version of this.
QualType T = Import(FromTSI->getType());
if (T.isNull())
return 0;
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index b09ba895c019..3ca7d4d01d1c 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -13,198 +13,10 @@
#include "clang/AST/Attr.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Expr.h"
using namespace clang;
-void Attr::Destroy(ASTContext &C) {
- if (Next) {
- Next->Destroy(C);
- Next = 0;
- }
- this->~Attr();
- C.Deallocate((void*)this);
-}
+Attr::~Attr() { }
-AttrWithString::AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s)
- : Attr(AK) {
- assert(!s.empty());
- StrLen = s.size();
- Str = new (C) char[StrLen];
- memcpy(const_cast<char*>(Str), s.data(), StrLen);
-}
-
-void AttrWithString::Destroy(ASTContext &C) {
- C.Deallocate(const_cast<char*>(Str));
- Attr::Destroy(C);
-}
-
-void AttrWithString::ReplaceString(ASTContext &C, llvm::StringRef newS) {
- if (newS.size() > StrLen) {
- C.Deallocate(const_cast<char*>(Str));
- Str = new (C) char[newS.size()];
- }
- StrLen = newS.size();
- memcpy(const_cast<char*>(Str), newS.data(), StrLen);
-}
-
-void FormatAttr::setType(ASTContext &C, llvm::StringRef type) {
- ReplaceString(C, type);
-}
-
-NonNullAttr::NonNullAttr(ASTContext &C, unsigned* arg_nums, unsigned size)
- : Attr(attr::NonNull), ArgNums(0), Size(0) {
- if (size == 0)
- return;
- assert(arg_nums);
- ArgNums = new (C) unsigned[size];
- Size = size;
- memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
-}
-
-void NonNullAttr::Destroy(ASTContext &C) {
- if (ArgNums)
- C.Deallocate(ArgNums);
- Attr::Destroy(C);
-}
-
-#define DEF_SIMPLE_ATTR_CLONE(ATTR) \
- Attr *ATTR##Attr::clone(ASTContext &C) const { \
- return ::new (C) ATTR##Attr; \
- }
-
-// FIXME: Can we use variadic macro to define DEF_SIMPLE_ATTR_CLONE for
-// "non-simple" classes?
-
-DEF_SIMPLE_ATTR_CLONE(AlignMac68k)
-DEF_SIMPLE_ATTR_CLONE(AlwaysInline)
-DEF_SIMPLE_ATTR_CLONE(AnalyzerNoReturn)
-DEF_SIMPLE_ATTR_CLONE(BaseCheck)
-DEF_SIMPLE_ATTR_CLONE(CDecl)
-DEF_SIMPLE_ATTR_CLONE(CFReturnsNotRetained)
-DEF_SIMPLE_ATTR_CLONE(CFReturnsRetained)
-DEF_SIMPLE_ATTR_CLONE(Const)
-DEF_SIMPLE_ATTR_CLONE(DLLExport)
-DEF_SIMPLE_ATTR_CLONE(DLLImport)
-DEF_SIMPLE_ATTR_CLONE(Deprecated)
-DEF_SIMPLE_ATTR_CLONE(FastCall)
-DEF_SIMPLE_ATTR_CLONE(Final)
-DEF_SIMPLE_ATTR_CLONE(Hiding)
-DEF_SIMPLE_ATTR_CLONE(Malloc)
-DEF_SIMPLE_ATTR_CLONE(NSReturnsNotRetained)
-DEF_SIMPLE_ATTR_CLONE(NSReturnsRetained)
-DEF_SIMPLE_ATTR_CLONE(NoDebug)
-DEF_SIMPLE_ATTR_CLONE(NoInline)
-DEF_SIMPLE_ATTR_CLONE(NoInstrumentFunction)
-DEF_SIMPLE_ATTR_CLONE(NoReturn)
-DEF_SIMPLE_ATTR_CLONE(NoThrow)
-DEF_SIMPLE_ATTR_CLONE(ObjCException)
-DEF_SIMPLE_ATTR_CLONE(ObjCNSObject)
-DEF_SIMPLE_ATTR_CLONE(Override)
-DEF_SIMPLE_ATTR_CLONE(Packed)
-DEF_SIMPLE_ATTR_CLONE(Pure)
-DEF_SIMPLE_ATTR_CLONE(StdCall)
-DEF_SIMPLE_ATTR_CLONE(ThisCall)
-DEF_SIMPLE_ATTR_CLONE(TransparentUnion)
-DEF_SIMPLE_ATTR_CLONE(Unavailable)
-DEF_SIMPLE_ATTR_CLONE(Unused)
-DEF_SIMPLE_ATTR_CLONE(Used)
-DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
-DEF_SIMPLE_ATTR_CLONE(Weak)
-DEF_SIMPLE_ATTR_CLONE(WeakImport)
-DEF_SIMPLE_ATTR_CLONE(WeakRef)
-DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer)
-
-Attr* MaxFieldAlignmentAttr::clone(ASTContext &C) const {
- return ::new (C) MaxFieldAlignmentAttr(Alignment);
-}
-
-Attr* AlignedAttr::clone(ASTContext &C) const {
- return ::new (C) AlignedAttr(Alignment);
-}
-
-Attr* AnnotateAttr::clone(ASTContext &C) const {
- return ::new (C) AnnotateAttr(C, getAnnotation());
-}
-
-Attr *AsmLabelAttr::clone(ASTContext &C) const {
- return ::new (C) AsmLabelAttr(C, getLabel());
-}
-
-Attr *AliasAttr::clone(ASTContext &C) const {
- return ::new (C) AliasAttr(C, getAliasee());
-}
-
-Attr *ConstructorAttr::clone(ASTContext &C) const {
- return ::new (C) ConstructorAttr(priority);
-}
-
-Attr *DestructorAttr::clone(ASTContext &C) const {
- return ::new (C) DestructorAttr(priority);
-}
-
-Attr *IBOutletAttr::clone(ASTContext &C) const {
- return ::new (C) IBOutletAttr;
-}
-
-Attr *IBOutletCollectionAttr::clone(ASTContext &C) const {
- return ::new (C) IBOutletCollectionAttr(D);
-}
-
-Attr *IBActionAttr::clone(ASTContext &C) const {
- return ::new (C) IBActionAttr;
-}
-
-Attr *GNUInlineAttr::clone(ASTContext &C) const {
- return ::new (C) GNUInlineAttr;
-}
-
-Attr *SectionAttr::clone(ASTContext &C) const {
- return ::new (C) SectionAttr(C, getName());
-}
-
-Attr *NonNullAttr::clone(ASTContext &C) const {
- return ::new (C) NonNullAttr(C, ArgNums, Size);
-}
-
-Attr *FormatAttr::clone(ASTContext &C) const {
- return ::new (C) FormatAttr(C, getType(), formatIdx, firstArg);
-}
-
-Attr *FormatArgAttr::clone(ASTContext &C) const {
- return ::new (C) FormatArgAttr(formatIdx);
-}
-
-Attr *SentinelAttr::clone(ASTContext &C) const {
- return ::new (C) SentinelAttr(sentinel, NullPos);
-}
-
-Attr *VisibilityAttr::clone(ASTContext &C) const {
- return ::new (C) VisibilityAttr(VisibilityType);
-}
-
-Attr *OverloadableAttr::clone(ASTContext &C) const {
- return ::new (C) OverloadableAttr;
-}
-
-Attr *BlocksAttr::clone(ASTContext &C) const {
- return ::new (C) BlocksAttr(BlocksAttrType);
-}
-
-Attr *CleanupAttr::clone(ASTContext &C) const {
- return ::new (C) CleanupAttr(FD);
-}
-
-Attr *RegparmAttr::clone(ASTContext &C) const {
- return ::new (C) RegparmAttr(NumParams);
-}
-
-Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const {
- return ::new (C) ReqdWorkGroupSizeAttr(X, Y, Z);
-}
-
-Attr *InitPriorityAttr::clone(ASTContext &C) const {
- return ::new (C) InitPriorityAttr(Priority);
-}
-
-Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
- return ::new (C) MSP430InterruptAttr(Number);
-}
+#include "clang/AST/AttrImpl.inc"
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 407ed95f3ee1..82a81ec42411 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -23,6 +23,8 @@ add_clang_library(clangAST
ExprCXX.cpp
FullExpr.cpp
InheritViz.cpp
+ ItaniumCXXABI.cpp
+ MicrosoftCXXABI.cpp
NestedNameSpecifier.cpp
ParentMap.cpp
RecordLayout.cpp
@@ -41,4 +43,4 @@ add_clang_library(clangAST
)
add_dependencies(clangAST ClangARMNeon ClangAttrClasses ClangAttrList
- ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
+ ClangAttrImpl ClangDiagnosticAST ClangDeclNodes ClangStmtNodes)
diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h
new file mode 100644
index 000000000000..4b38d7afb6a4
--- /dev/null
+++ b/lib/AST/CXXABI.h
@@ -0,0 +1,39 @@
+//===----- CXXABI.h - Interface to C++ ABIs ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for C++ AST support. Concrete
+// subclasses of this implement AST support for specific C++ ABIs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_CXXABI_H
+#define LLVM_CLANG_AST_CXXABI_H
+
+namespace clang {
+
+class ASTContext;
+class MemberPointerType;
+
+/// Implements C++ ABI-specific semantic analysis functions.
+class CXXABI {
+public:
+ virtual ~CXXABI();
+
+ /// Returns the size of a member pointer in multiples of the target
+ /// pointer size.
+ virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0;
+};
+
+/// Creates an instance of a C++ ABI class.
+CXXABI *CreateARMCXXABI(ASTContext &Ctx);
+CXXABI *CreateItaniumCXXABI(ASTContext &Ctx);
+CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx);
+}
+
+#endif
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 149938fc5c86..b7be02d74533 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -97,8 +97,14 @@ static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
return L;
}
+static Linkage
+getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) {
+ return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(),
+ TArgs.flat_size());
+}
+
static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
- assert(D->getDeclContext()->getLookupContext()->isFileContext() &&
+ assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@@ -110,7 +116,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// (This bullet corresponds to C99 6.2.2p3.)
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
- if (Var->getStorageClass() == VarDecl::Static)
+ if (Var->getStorageClass() == SC_Static)
return InternalLinkage;
// - an object or reference that is explicitly declared const
@@ -119,8 +125,8 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// (there is no equivalent in C99)
if (Context.getLangOptions().CPlusPlus &&
Var->getType().isConstant(Context) &&
- Var->getStorageClass() != VarDecl::Extern &&
- Var->getStorageClass() != VarDecl::PrivateExtern) {
+ Var->getStorageClass() != SC_Extern &&
+ Var->getStorageClass() != SC_PrivateExtern) {
bool FoundExtern = false;
for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
PrevVar && !FoundExtern;
@@ -143,7 +149,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
Function = cast<FunctionDecl>(D);
// Explicitly declared static.
- if (Function->getStorageClass() == FunctionDecl::Static)
+ if (Function->getStorageClass() == SC_Static)
return InternalLinkage;
} else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// - a data member of an anonymous union.
@@ -159,8 +165,8 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// - an object or reference, unless it has internal linkage; or
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (!Context.getLangOptions().CPlusPlus &&
- (Var->getStorageClass() == VarDecl::Extern ||
- Var->getStorageClass() == VarDecl::PrivateExtern)) {
+ (Var->getStorageClass() == SC_Extern ||
+ Var->getStorageClass() == SC_PrivateExtern)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
@@ -194,9 +200,9 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// as if it were declared with the storage-class specifier
// extern.
if (!Context.getLangOptions().CPlusPlus &&
- (Function->getStorageClass() == FunctionDecl::Extern ||
- Function->getStorageClass() == FunctionDecl::PrivateExtern ||
- Function->getStorageClass() == FunctionDecl::None)) {
+ (Function->getStorageClass() == SC_Extern ||
+ Function->getStorageClass() == SC_PrivateExtern ||
+ Function->getStorageClass() == SC_None)) {
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
@@ -219,10 +225,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
= Function->getTemplateSpecializationInfo()) {
Linkage L = SpecInfo->getTemplate()->getLinkage();
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
- L = minLinkage(L,
- getLinkageForTemplateArgumentList(
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size()));
+ L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs));
return L;
}
@@ -245,9 +248,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- Linkage L = getLinkageForTemplateArgumentList(
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size());
+ Linkage L = getLinkageForTemplateArgumentList(TemplateArgs);
return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
}
@@ -279,6 +280,47 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
return NoLinkage;
}
+static Linkage getLinkageForClassMember(const NamedDecl *D) {
+ if (!(isa<CXXMethodDecl>(D) ||
+ isa<VarDecl>(D) ||
+ (isa<TagDecl>(D) &&
+ (D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
+ return NoLinkage;
+
+ // Class members only have linkage if their class has external linkage.
+ Linkage L = cast<RecordDecl>(D->getDeclContext())->getLinkage();
+ if (!isExternalLinkage(L)) return NoLinkage;
+
+ // If the class already has unique-external linkage, we can't improve.
+ if (L == UniqueExternalLinkage) return UniqueExternalLinkage;
+
+ // If this is a method template specialization, use the linkage for
+ // the template parameters and arguments.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+ if (FunctionTemplateSpecializationInfo *SpecInfo
+ = MD->getTemplateSpecializationInfo()) {
+ Linkage ArgLinkage =
+ getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments);
+ Linkage ParamLinkage =
+ getLinkageForTemplateParameterList(
+ SpecInfo->getTemplate()->getTemplateParameters());
+ return minLinkage(ArgLinkage, ParamLinkage);
+ }
+
+ // Similarly for member class template specializations.
+ } else if (const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ Linkage ArgLinkage =
+ getLinkageForTemplateArgumentList(Spec->getTemplateArgs());
+ Linkage ParamLinkage =
+ getLinkageForTemplateParameterList(
+ Spec->getSpecializedTemplate()->getTemplateParameters());
+ return minLinkage(ArgLinkage, ParamLinkage);
+ }
+
+ return ExternalLinkage;
+}
+
Linkage NamedDecl::getLinkage() const {
// Objective-C: treat all Objective-C declarations as having external
@@ -303,7 +345,7 @@ Linkage NamedDecl::getLinkage() const {
}
// Handle linkage for namespace-scope names.
- if (getDeclContext()->getLookupContext()->isFileContext())
+ if (getDeclContext()->getRedeclContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
return L;
@@ -314,14 +356,8 @@ Linkage NamedDecl::getLinkage() const {
// that the class or enumeration has the typedef name for linkage
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
- if (getDeclContext()->isRecord() &&
- (isa<CXXMethodDecl>(this) || isa<VarDecl>(this) ||
- (isa<TagDecl>(this) &&
- (getDeclName() || cast<TagDecl>(this)->getTypedefForAnonDecl())))) {
- Linkage L = cast<RecordDecl>(getDeclContext())->getLinkage();
- if (isExternalLinkage(L))
- return L;
- }
+ if (getDeclContext()->isRecord())
+ return getLinkageForClassMember(this);
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
@@ -347,8 +383,8 @@ Linkage NamedDecl::getLinkage() const {
}
if (const VarDecl *Var = dyn_cast<VarDecl>(this))
- if (Var->getStorageClass() == VarDecl::Extern ||
- Var->getStorageClass() == VarDecl::PrivateExtern) {
+ if (Var->getStorageClass() == SC_Extern ||
+ Var->getStorageClass() == SC_PrivateExtern) {
if (Var->getPreviousDeclaration())
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
@@ -531,13 +567,6 @@ static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
return decl->getInnerLocStart();
}
-DeclaratorDecl::~DeclaratorDecl() {}
-void DeclaratorDecl::Destroy(ASTContext &C) {
- if (hasExtInfo())
- C.Deallocate(getExtInfo());
- ValueDecl::Destroy(C);
-}
-
SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
TypeSourceInfo *TSI = getTypeSourceInfo();
if (TSI) return TSI->getTypeLoc().getBeginLoc();
@@ -602,24 +631,18 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
}
}
-void QualifierInfo::Destroy(ASTContext &Context) {
- // FIXME: Deallocate template parameter lists themselves!
- if (TemplParamLists)
- Context.Deallocate(TemplParamLists);
-}
-
//===----------------------------------------------------------------------===//
// VarDecl Implementation
//===----------------------------------------------------------------------===//
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
switch (SC) {
- case VarDecl::None: break;
- case VarDecl::Auto: return "auto"; break;
- case VarDecl::Extern: return "extern"; break;
- case VarDecl::PrivateExtern: return "__private_extern__"; break;
- case VarDecl::Register: return "register"; break;
- case VarDecl::Static: return "static"; break;
+ case SC_None: break;
+ case SC_Auto: return "auto"; break;
+ case SC_Extern: return "extern"; break;
+ case SC_PrivateExtern: return "__private_extern__"; break;
+ case SC_Register: return "register"; break;
+ case SC_Static: return "static"; break;
}
assert(0 && "Invalid storage class");
@@ -632,22 +655,6 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);
}
-void VarDecl::Destroy(ASTContext& C) {
- Expr *Init = getInit();
- if (Init) {
- Init->Destroy(C);
- if (EvaluatedStmt *Eval = this->Init.dyn_cast<EvaluatedStmt *>()) {
- Eval->~EvaluatedStmt();
- C.Deallocate(Eval);
- }
- }
- this->~VarDecl();
- DeclaratorDecl::Destroy(C);
-}
-
-VarDecl::~VarDecl() {
-}
-
SourceLocation VarDecl::getInnerLocStart() const {
SourceLocation Start = getTypeSpecStartLoc();
if (Start.isInvalid())
@@ -665,14 +672,14 @@ bool VarDecl::isExternC() const {
ASTContext &Context = getASTContext();
if (!Context.getLangOptions().CPlusPlus)
return (getDeclContext()->isTranslationUnit() &&
- getStorageClass() != Static) ||
+ getStorageClass() != SC_Static) ||
(getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != Static;
+ return getStorageClass() != SC_Static;
break;
}
@@ -717,8 +724,8 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
if (hasExternalStorage())
return DeclarationOnly;
- if (getStorageClassAsWritten() == Extern ||
- getStorageClassAsWritten() == PrivateExtern) {
+ if (getStorageClassAsWritten() == SC_Extern ||
+ getStorageClassAsWritten() == SC_PrivateExtern) {
for (const VarDecl *PrevVar = getPreviousDeclaration();
PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) {
if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit())
@@ -912,28 +919,6 @@ SourceRange ParmVarDecl::getDefaultArgRange() const {
// FunctionDecl Implementation
//===----------------------------------------------------------------------===//
-void FunctionDecl::Destroy(ASTContext& C) {
- if (Body && Body.isOffset())
- Body.get(C.getExternalSource())->Destroy(C);
-
- for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
- (*I)->Destroy(C);
-
- FunctionTemplateSpecializationInfo *FTSInfo
- = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
- if (FTSInfo)
- C.Deallocate(FTSInfo);
-
- MemberSpecializationInfo *MSInfo
- = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>();
- if (MSInfo)
- C.Deallocate(MSInfo);
-
- C.Deallocate(ParamInfo);
-
- DeclaratorDecl::Destroy(C);
-}
-
void FunctionDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const {
@@ -984,7 +969,7 @@ void FunctionDecl::setBody(Stmt *B) {
bool FunctionDecl::isMain() const {
ASTContext &Context = getASTContext();
return !Context.getLangOptions().Freestanding &&
- getDeclContext()->getLookupContext()->isTranslationUnit() &&
+ getDeclContext()->getRedeclContext()->isTranslationUnit() &&
getIdentifier() && getIdentifier()->isStr("main");
}
@@ -993,17 +978,20 @@ bool FunctionDecl::isExternC() const {
// In C, any non-static, non-overloadable function has external
// linkage.
if (!Context.getLangOptions().CPlusPlus)
- return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+ return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit();
DC = DC->getParent()) {
if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != Static &&
+ return getStorageClass() != SC_Static &&
!getAttr<OverloadableAttr>();
break;
}
+
+ if (DC->isRecord())
+ break;
}
return false;
@@ -1013,7 +1001,7 @@ bool FunctionDecl::isGlobal() const {
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(this))
return Method->isStatic();
- if (getStorageClass() == Static)
+ if (getStorageClass() == SC_Static)
return false;
for (const DeclContext *DC = getDeclContext();
@@ -1072,7 +1060,7 @@ unsigned FunctionDecl::getBuiltinID() const {
// function or whether it just has the same name.
// If this is a static function, it's not a builtin.
- if (getStorageClass() == Static)
+ if (getStorageClass() == SC_Static)
return 0;
// If this function is at translation-unit scope and we're not in
@@ -1206,7 +1194,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
- if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != Extern)
+ if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern)
return true;
}
@@ -1225,7 +1213,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
continue;
- if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == Extern)
+ if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
return true; // Not an inline definition
}
@@ -1400,14 +1388,15 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
if (InsertPos)
Template->getSpecializations().InsertNode(Info, InsertPos);
else {
- // Try to insert the new node. If there is an existing node, remove it
- // first.
+ // Try to insert the new node. If there is an existing node, leave it, the
+ // set will contain the canonical decls while
+ // FunctionTemplateDecl::findSpecialization will return
+ // the most recent redeclarations.
FunctionTemplateSpecializationInfo *Existing
= Template->getSpecializations().GetOrInsertNode(Info);
- if (Existing) {
- Template->getSpecializations().RemoveNode(Existing);
- Template->getSpecializations().GetOrInsertNode(Info);
- }
+ (void)Existing;
+ assert((!Existing || Existing->Function->isCanonicalDecl()) &&
+ "Set is supposed to only contain canonical decls");
}
}
@@ -1564,12 +1553,6 @@ bool FieldDecl::isAnonymousStructOrUnion() const {
// TagDecl Implementation
//===----------------------------------------------------------------------===//
-void TagDecl::Destroy(ASTContext &C) {
- if (hasExtInfo())
- C.Deallocate(getExtInfo());
- TypeDecl::Destroy(C);
-}
-
SourceLocation TagDecl::getOuterLocStart() const {
return getTemplateOrInnerLocStart(this);
}
@@ -1590,14 +1573,7 @@ void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) {
}
void TagDecl::startDefinition() {
- if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
- TagT->decl.setPointer(this);
- TagT->decl.setInt(1);
- } else if (InjectedClassNameType *Injected
- = const_cast<InjectedClassNameType *>(
- TypeForDecl->getAs<InjectedClassNameType>())) {
- Injected->Decl = cast<CXXRecordDecl>(this);
- }
+ IsBeingDefined = true;
if (isa<CXXRecordDecl>(this)) {
CXXRecordDecl *D = cast<CXXRecordDecl>(this);
@@ -1614,17 +1590,7 @@ void TagDecl::completeDefinition() {
"definition completed but not started");
IsDefinition = true;
- if (TagType *TagT = const_cast<TagType *>(TypeForDecl->getAs<TagType>())) {
- assert(TagT->decl.getPointer() == this &&
- "Attempt to redefine a tag definition?");
- TagT->decl.setInt(0);
- } else if (InjectedClassNameType *Injected
- = const_cast<InjectedClassNameType *>(
- TypeForDecl->getAs<InjectedClassNameType>())) {
- assert(Injected->Decl == this &&
- "Attempt to redefine a class template definition?");
- (void)Injected;
- }
+ IsBeingDefined = false;
}
TagDecl* TagDecl::getDefinition() const {
@@ -1675,10 +1641,6 @@ EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) {
return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation());
}
-void EnumDecl::Destroy(ASTContext& C) {
- TagDecl::Destroy(C);
-}
-
void EnumDecl::completeDefinition(QualType NewType,
QualType NewPromotionType,
unsigned NumPositiveBits,
@@ -1719,13 +1681,6 @@ RecordDecl *RecordDecl::Create(ASTContext &C, EmptyShell Empty) {
SourceLocation());
}
-RecordDecl::~RecordDecl() {
-}
-
-void RecordDecl::Destroy(ASTContext& C) {
- TagDecl::Destroy(C);
-}
-
bool RecordDecl::isInjectedClassName() const {
return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
@@ -1753,20 +1708,6 @@ ValueDecl *RecordDecl::getAnonymousStructOrUnionObject() {
// BlockDecl Implementation
//===----------------------------------------------------------------------===//
-BlockDecl::~BlockDecl() {
-}
-
-void BlockDecl::Destroy(ASTContext& C) {
- if (Body)
- Body->Destroy(C);
-
- for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
- (*I)->Destroy(C);
-
- C.Deallocate(ParamInfo);
- Decl::Destroy(C);
-}
-
void BlockDecl::setParams(ParmVarDecl **NewParamInfo,
unsigned NParms) {
assert(ParamInfo == 0 && "Already has param info!");
@@ -1798,27 +1739,17 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) NamespaceDecl(DC, L, Id);
}
-void NamespaceDecl::Destroy(ASTContext& C) {
- // NamespaceDecl uses "NextDeclarator" to chain namespace declarations
- // together. They are all top-level Decls.
-
- this->~NamespaceDecl();
- Decl::Destroy(C);
-}
-
-
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, QualType T) {
return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T);
}
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- DeclarationName N, QualType T,
- TypeSourceInfo *TInfo,
+ const DeclarationNameInfo &NameInfo,
+ QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten,
bool isInline, bool hasWrittenPrototype) {
- FunctionDecl *New = new (C) FunctionDecl(Function, DC, L, N, T, TInfo,
+ FunctionDecl *New = new (C) FunctionDecl(Function, DC, NameInfo, T, TInfo,
S, SCAsWritten, isInline);
New->HasWrittenPrototype = hasWrittenPrototype;
return New;
@@ -1835,9 +1766,11 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
}
-void EnumConstantDecl::Destroy(ASTContext& C) {
- if (Init) Init->Destroy(C);
- ValueDecl::Destroy(C);
+SourceRange EnumConstantDecl::getSourceRange() const {
+ SourceLocation End = getLocation();
+ if (Init)
+ End = Init->getLocEnd();
+ return SourceRange(getLocation(), End);
}
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
@@ -1846,9 +1779,6 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TypedefDecl(DC, L, Id, TInfo);
}
-// Anchor TypedefDecl's vtable here.
-TypedefDecl::~TypedefDecl() {}
-
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
StringLiteral *Str) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index d4f997de7669..0b958fe82b09 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -157,9 +157,7 @@ void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
//===----------------------------------------------------------------------===//
// Out-of-line virtual method providing a home for Decl.
-Decl::~Decl() {
- assert(!HasAttrs && "attributes should have been freed by Destroy");
-}
+Decl::~Decl() { }
void Decl::setDeclContext(DeclContext *DC) {
if (isOutOfSemaDC())
@@ -314,35 +312,25 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
return 0;
}
-void Decl::initAttrs(Attr *attrs) {
+void Decl::setAttrs(const AttrVec &attrs) {
assert(!HasAttrs && "Decl already contains attrs.");
- Attr *&AttrBlank = getASTContext().getDeclAttrs(this);
- assert(AttrBlank == 0 && "HasAttrs was wrong?");
+ AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
+ assert(AttrBlank.empty() && "HasAttrs was wrong?");
AttrBlank = attrs;
HasAttrs = true;
}
-void Decl::addAttr(Attr *NewAttr) {
- Attr *&ExistingAttr = getASTContext().getDeclAttrs(this);
-
- assert(NewAttr->getNext() == 0 && "Chain of attributes will be truncated!");
- NewAttr->setNext(ExistingAttr);
- ExistingAttr = NewAttr;
-
- HasAttrs = true;
-}
-
-void Decl::invalidateAttrs() {
+void Decl::dropAttrs() {
if (!HasAttrs) return;
HasAttrs = false;
getASTContext().eraseDeclAttrs(this);
}
-const Attr *Decl::getAttrsImpl() const {
- assert(HasAttrs && "getAttrs() should verify this!");
+const AttrVec &Decl::getAttrs() const {
+ assert(HasAttrs && "No attrs to get!");
return getASTContext().getDeclAttrs(this);
}
@@ -372,40 +360,6 @@ void Decl::swapAttrs(Decl *RHS) {
RHS->HasAttrs = true;
}
-void Decl::Destroy(ASTContext &C) {
- // Free attributes for this decl.
- if (HasAttrs) {
- C.getDeclAttrs(this)->Destroy(C);
- invalidateAttrs();
- HasAttrs = false;
- }
-
-#if 0
- // FIXME: Once ownership is fully understood, we can enable this code
- if (DeclContext *DC = dyn_cast<DeclContext>(this))
- DC->decls_begin()->Destroy(C);
-
- // Observe the unrolled recursion. By setting N->NextDeclInContext = 0x0
- // within the loop, only the Destroy method for the first Decl
- // will deallocate all of the Decls in a chain.
-
- Decl* N = getNextDeclInContext();
-
- while (N) {
- Decl* Tmp = N->getNextDeclInContext();
- N->NextDeclInContext = 0;
- N->Destroy(C);
- N = Tmp;
- }
-
- if (isOutOfSemaDC())
- delete (C) getMultipleDC();
-
- this->~Decl();
- C.Deallocate((void *)this);
-#endif
-}
-
Decl *Decl::castFromDeclContext (const DeclContext *D) {
Decl::Kind DK = D->getDeclKind();
switch(DK) {
@@ -506,17 +460,7 @@ bool DeclContext::classof(const Decl *D) {
}
}
-DeclContext::~DeclContext() {
- // FIXME: Currently ~ASTContext will delete the StoredDeclsMaps because
- // ~DeclContext() is not guaranteed to be called when ASTContext uses
- // a BumpPtrAllocator.
- // delete LookupPtr;
-}
-
-void DeclContext::DestroyDecls(ASTContext &C) {
- for (decl_iterator D = decls_begin(); D != decls_end(); )
- (*D++)->Destroy(C);
-}
+DeclContext::~DeclContext() { }
/// \brief Find the parent context of this context that will be
/// used for unqualified name lookup.
@@ -527,13 +471,18 @@ void DeclContext::DestroyDecls(ASTContext &C) {
DeclContext *DeclContext::getLookupParent() {
// FIXME: Find a better way to identify friends
if (isa<FunctionDecl>(this))
- if (getParent()->getLookupContext()->isFileContext() &&
- getLexicalParent()->getLookupContext()->isRecord())
+ if (getParent()->getRedeclContext()->isFileContext() &&
+ getLexicalParent()->getRedeclContext()->isRecord())
return getLexicalParent();
return getParent();
}
+bool DeclContext::isInlineNamespace() const {
+ return isNamespace() &&
+ cast<NamespaceDecl>(this)->isInline();
+}
+
bool DeclContext::isDependentContext() const {
if (isFileContext())
return false;
@@ -565,13 +514,11 @@ bool DeclContext::isTransparentContext() const {
return true;
else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord)
return cast<RecordDecl>(this)->isAnonymousStructOrUnion();
- else if (DeclKind == Decl::Namespace)
- return false; // FIXME: Check for C++0x inline namespaces
return false;
}
-bool DeclContext::Encloses(DeclContext *DC) {
+bool DeclContext::Encloses(const DeclContext *DC) const {
if (getPrimaryContext() != this)
return getPrimaryContext()->Encloses(DC);
@@ -652,6 +599,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
ExternalASTSource *Source = getParentASTContext().getExternalSource();
assert(hasExternalLexicalStorage() && Source && "No external storage?");
+ // Notify that we have a DeclContext that is initializing.
+ ExternalASTSource::Deserializing ADeclContext(Source);
+
llvm::SmallVector<Decl*, 64> Decls;
if (Source->FindExternalLexicalDecls(this, Decls))
return;
@@ -701,19 +651,6 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclContext::lookup_result
ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
- const VisibleDeclaration &VD) {
- ASTContext &Context = DC->getParentASTContext();
- StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr))
- Map = DC->CreateStoredDeclsMap(Context);
-
- StoredDeclsList &List = (*Map)[VD.Name];
- List.setFromDeclIDs(VD.Declarations);
- return List.getLookupResult(Context);
-}
-
-DeclContext::lookup_result
-ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls) {
ASTContext &Context = DC->getParentASTContext();;
@@ -730,35 +667,34 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
List.AddSubsequentDecl(Decls[I]);
}
- return List.getLookupResult(Context);
+ return List.getLookupResult();
}
-void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
- // There is no longer any visible storage in this context.
- DC->ExternalVisibleStorage = false;
-
- assert(!DC->LookupPtr && "Have a lookup map before de-serialization?");
- StoredDeclsMap *Map = DC->CreateStoredDeclsMap(DC->getParentASTContext());
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations);
+void ExternalASTSource::MaterializeVisibleDeclsForName(const DeclContext *DC,
+ DeclarationName Name,
+ llvm::SmallVectorImpl<NamedDecl*> &Decls) {
+ assert(DC->LookupPtr);
+ StoredDeclsMap &Map = *DC->LookupPtr;
+
+ // If there's an entry in the table the visible decls for this name have
+ // already been deserialized.
+ if (Map.find(Name) == Map.end()) {
+ StoredDeclsList &List = Map[Name];
+ for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
+ if (List.isNull())
+ List.setOnlyValue(Decls[I]);
+ else
+ List.AddSubsequentDecl(Decls[I]);
+ }
}
}
-void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC,
- const llvm::SmallVectorImpl<NamedDecl*> &Decls) {
- // There is no longer any visible storage in this context.
- DC->ExternalVisibleStorage = false;
+DeclContext::decl_iterator DeclContext::noload_decls_begin() const {
+ return decl_iterator(FirstDecl);
+}
- assert(!DC->LookupPtr && "Have a lookup map before de-serialization?");
- StoredDeclsMap &Map = *DC->CreateStoredDeclsMap(DC->getParentASTContext());
- for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
- StoredDeclsList &List = Map[Decls[I]->getDeclName()];
- if (List.isNull())
- List.setOnlyValue(Decls[I]);
- else
- List.AddSubsequentDecl(Decls[I]);
- }
+DeclContext::decl_iterator DeclContext::noload_decls_end() const {
+ return decl_iterator();
}
DeclContext::decl_iterator DeclContext::decls_begin() const {
@@ -866,10 +802,10 @@ void DeclContext::buildLookup(DeclContext *DCtx) {
I != IEnd; ++I)
makeDeclVisibleInContextImpl(I->getInterface());
- // If this declaration is itself a transparent declaration context,
- // add its members (recursively).
+ // If this declaration is itself a transparent declaration context or
+ // inline namespace, add its members (recursively).
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
- if (InnerCtx->isTransparentContext())
+ if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
buildLookup(InnerCtx->getPrimaryContext());
}
}
@@ -886,7 +822,7 @@ DeclContext::lookup(DeclarationName Name) {
if (LookupPtr) {
StoredDeclsMap::iterator I = LookupPtr->find(Name);
if (I != LookupPtr->end())
- return I->second.getLookupResult(getParentASTContext());
+ return I->second.getLookupResult();
}
ExternalASTSource *Source = getParentASTContext().getExternalSource();
@@ -906,7 +842,7 @@ DeclContext::lookup(DeclarationName Name) {
StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
if (Pos == LookupPtr->end())
return lookup_result(lookup_iterator(0), lookup_iterator(0));
- return Pos->second.getLookupResult(getParentASTContext());
+ return Pos->second.getLookupResult();
}
DeclContext::lookup_const_result
@@ -914,7 +850,7 @@ DeclContext::lookup(DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Name);
}
-DeclContext *DeclContext::getLookupContext() {
+DeclContext *DeclContext::getRedeclContext() {
DeclContext *Ctx = this;
// Skip through transparent contexts.
while (Ctx->isTransparentContext())
@@ -925,11 +861,29 @@ DeclContext *DeclContext::getLookupContext() {
DeclContext *DeclContext::getEnclosingNamespaceContext() {
DeclContext *Ctx = this;
// Skip through non-namespace, non-translation-unit contexts.
- while (!Ctx->isFileContext() || Ctx->isTransparentContext())
+ while (!Ctx->isFileContext())
Ctx = Ctx->getParent();
return Ctx->getPrimaryContext();
}
+bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
+ // For non-file contexts, this is equivalent to Equals.
+ if (!isFileContext())
+ return O->Equals(this);
+
+ do {
+ if (O->Equals(this))
+ return true;
+
+ const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(O);
+ if (!NS || !NS->isInline())
+ break;
+ O = NS->getParent();
+ } while (O);
+
+ return false;
+}
+
void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
// FIXME: This feels like a hack. Should DeclarationName support
// template-ids, or is there a better way to keep specializations
@@ -953,9 +907,9 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
makeDeclVisibleInContextImpl(D);
- // If we are a transparent context, insert into our parent context,
- // too. This operation is recursive.
- if (isTransparentContext())
+ // If we are a transparent context or inline namespace, insert into our
+ // parent context, too. This operation is recursive.
+ if (isTransparentContext() || isInlineNamespace())
getParent()->makeDeclVisibleInContext(D, Recoverable);
}
@@ -970,18 +924,21 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
if (isa<ClassTemplateSpecializationDecl>(D))
return;
- // If there is an external AST source, load any declarations it knows about
- // with this declaration's name.
- if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
- if (hasExternalVisibleStorage())
- Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
-
ASTContext *C = 0;
if (!LookupPtr) {
C = &getParentASTContext();
CreateStoredDeclsMap(*C);
}
+ // If there is an external AST source, load any declarations it knows about
+ // with this declaration's name.
+ // If the lookup table contains an entry about this name it means that we
+ // have already checked the external source.
+ if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
+ if (hasExternalVisibleStorage() &&
+ LookupPtr->find(D->getDeclName()) == LookupPtr->end())
+ Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
+
// Insert this declaration into the map.
StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
if (DeclNameEntries.isNull()) {
@@ -992,16 +949,22 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
// If it is possible that this is a redeclaration, check to see if there is
// already a decl for which declarationReplaces returns true. If there is
// one, just replace it and return.
- if (!C)
- C = &getParentASTContext();
-
- if (DeclNameEntries.HandleRedeclaration(*C, D))
+ if (DeclNameEntries.HandleRedeclaration(D))
return;
// Put this declaration into the appropriate slot.
DeclNameEntries.AddSubsequentDecl(D);
}
+void DeclContext::MaterializeVisibleDeclsFromExternalStorage() {
+ ExternalASTSource *Source = getParentASTContext().getExternalSource();
+ assert(hasExternalVisibleStorage() && Source && "No external storage?");
+
+ if (!LookupPtr)
+ CreateStoredDeclsMap(getParentASTContext());
+ Source->MaterializeVisibleDecls(this);
+}
+
/// Returns iterator range [First, Last) of UsingDirectiveDecls stored within
/// this context.
DeclContext::udir_iterator_range
@@ -1011,43 +974,6 @@ DeclContext::getUsingDirectives() const {
reinterpret_cast<udir_iterator>(Result.second));
}
-void StoredDeclsList::materializeDecls(ASTContext &Context) {
- if (isNull())
- return;
-
- switch ((DataKind)(Data & 0x03)) {
- case DK_Decl:
- case DK_Decl_Vector:
- break;
-
- case DK_DeclID: {
- // Resolve this declaration ID to an actual declaration by
- // querying the external AST source.
- unsigned DeclID = Data >> 2;
-
- ExternalASTSource *Source = Context.getExternalSource();
- assert(Source && "No external AST source available!");
-
- Data = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(DeclID));
- break;
- }
-
- case DK_ID_Vector: {
- // We have a vector of declaration IDs. Resolve all of them to
- // actual declarations.
- VectorTy &Vector = *getAsVector();
- ExternalASTSource *Source = Context.getExternalSource();
- assert(Source && "No external AST source available!");
-
- for (unsigned I = 0, N = Vector.size(); I != N; ++I)
- Vector[I] = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(Vector[I]));
-
- Data = (Data & ~0x03) | DK_Decl_Vector;
- break;
- }
- }
-}
-
//===----------------------------------------------------------------------===//
// Creation and Destruction of StoredDeclsMaps. //
//===----------------------------------------------------------------------===//
@@ -1073,7 +999,6 @@ void ASTContext::ReleaseDeclContextMaps() {
// It's okay to delete DependentStoredDeclsMaps via a StoredDeclsMap
// pointer because the subclass doesn't add anything that needs to
// be deleted.
-
StoredDeclsMap::DestroyAll(LastSDM.getPointer(), LastSDM.getInt());
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index dd0fe08979f0..f2f0694826c6 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -65,18 +65,6 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, EmptyShell Empty) {
SourceLocation());
}
-CXXRecordDecl::~CXXRecordDecl() {
-}
-
-void CXXRecordDecl::Destroy(ASTContext &C) {
- if (data().Definition == this) {
- C.Deallocate(data().Bases);
- C.Deallocate(data().VBases);
- C.Deallocate(&data());
- }
- this->RecordDecl::Destroy(C);
-}
-
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
@@ -133,19 +121,19 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
data().NumVBases = VBases.size();
for (int I = 0, E = VBases.size(); I != E; ++I) {
- QualType VBaseType = VBases[I]->getType();
-
+ TypeSourceInfo *VBaseTypeInfo = VBases[I]->getTypeSourceInfo();
+
// Skip dependent types; we can't do any checking on them now.
- if (VBaseType->isDependentType())
+ if (VBaseTypeInfo->getType()->isDependentType())
continue;
- CXXRecordDecl *VBaseClassDecl
- = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl());
+ CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>(
+ VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl());
data().VBases[I] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == TTK_Class,
- VBases[I]->getAccessSpecifier(), VBaseType);
+ VBases[I]->getAccessSpecifier(), VBaseTypeInfo);
}
}
@@ -621,7 +609,8 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
DeclContext::lookup_const_iterator I, E;
llvm::tie(I, E) = lookup(Name);
- assert(I != E && "Did not find a destructor!");
+ if (I == E)
+ return 0;
CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I);
assert(++I == E && "Found more than one destructor!");
@@ -631,10 +620,10 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline) {
- return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, TInfo,
+ return new (C) CXXMethodDecl(CXXMethod, RD, NameInfo, T, TInfo,
isStatic, SCAsWritten, isInline);
}
@@ -796,13 +785,6 @@ CXXBaseOrMemberInitializer::Create(ASTContext &Context,
L, Init, R, Indices, NumIndices);
}
-void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) {
- if (Init)
- Init->Destroy(Context);
- // FIXME: Destroy indices
- this->~CXXBaseOrMemberInitializer();
-}
-
TypeLoc CXXBaseOrMemberInitializer::getBaseClassLoc() const {
if (isBaseInitializer())
return BaseOrMember.get<TypeSourceInfo*>()->getTypeLoc();
@@ -837,20 +819,21 @@ SourceRange CXXBaseOrMemberInitializer::getSourceRange() const {
CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationName(),
+ return new (C) CXXConstructorDecl(0, DeclarationNameInfo(),
QualType(), 0, false, false, false);
}
CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline,
bool isImplicitlyDeclared) {
- assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXConstructorName &&
"Name must refer to a constructor");
- return new (C) CXXConstructorDecl(RD, L, N, T, TInfo, isExplicit,
+ return new (C) CXXConstructorDecl(RD, NameInfo, T, TInfo, isExplicit,
isInline, isImplicitlyDeclared);
}
@@ -945,40 +928,38 @@ bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const {
CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationName(),
+ return new (C) CXXDestructorDecl(0, DeclarationNameInfo(),
QualType(), false, false);
}
CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, bool isInline,
bool isImplicitlyDeclared) {
- assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXDestructorName &&
"Name must refer to a destructor");
- return new (C) CXXDestructorDecl(RD, L, N, T, isInline, isImplicitlyDeclared);
-}
-
-void
-CXXConstructorDecl::Destroy(ASTContext& C) {
- C.Deallocate(BaseOrMemberInitializers);
- CXXMethodDecl::Destroy(C);
+ return new (C) CXXDestructorDecl(RD, NameInfo, T, isInline,
+ isImplicitlyDeclared);
}
CXXConversionDecl *
CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationName(),
+ return new (C) CXXConversionDecl(0, DeclarationNameInfo(),
QualType(), 0, false, false);
}
CXXConversionDecl *
CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
- SourceLocation L, DeclarationName N,
+ const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit) {
- assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+ assert(NameInfo.getName().getNameKind()
+ == DeclarationName::CXXConversionFunctionName &&
"Name must refer to a conversion function");
- return new (C) CXXConversionDecl(RD, L, N, T, TInfo, isInline, isExplicit);
+ return new (C) CXXConversionDecl(RD, NameInfo, T, TInfo,
+ isInline, isExplicit);
}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
@@ -1009,14 +990,8 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
-void UsingDirectiveDecl::setNominatedNamespace(NamedDecl* ND) {
- assert((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
- "expected a NamespaceDecl or NamespaceAliasDecl");
- NominatedNamespace = ND;
-}
-
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
+ SourceLocation UsingLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceRange QualifierRange,
@@ -1025,15 +1000,16 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
NamedDecl *Namespace) {
if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
- return new (C) NamespaceAliasDecl(DC, L, AliasLoc, Alias, QualifierRange,
+ return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange,
Qualifier, IdentLoc, Namespace);
}
UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, SourceRange NNR, SourceLocation UL,
- NestedNameSpecifier* TargetNNS, DeclarationName Name,
- bool IsTypeNameArg) {
- return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg);
+ SourceRange NNR, SourceLocation UL,
+ NestedNameSpecifier* TargetNNS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsTypeNameArg) {
+ return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg);
}
UnresolvedUsingValueDecl *
@@ -1041,11 +1017,9 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceRange TargetNNR,
NestedNameSpecifier *TargetNNS,
- SourceLocation TargetNameLoc,
- DeclarationName TargetName) {
+ const DeclarationNameInfo &NameInfo) {
return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
- TargetNNR, TargetNNS,
- TargetNameLoc, TargetName);
+ TargetNNR, TargetNNS, NameInfo);
}
UnresolvedUsingTypenameDecl *
@@ -1068,15 +1042,6 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) StaticAssertDecl(DC, L, AssertExpr, Message);
}
-void StaticAssertDecl::Destroy(ASTContext& C) {
- AssertExpr->Destroy(C);
- Message->Destroy(C);
- Decl::Destroy(C);
-}
-
-StaticAssertDecl::~StaticAssertDecl() {
-}
-
static const char *getAccessName(AccessSpecifier AS) {
switch (AS) {
default:
@@ -1096,5 +1061,3 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
AccessSpecifier AS) {
return DB << getAccessName(AS);
}
-
-
diff --git a/lib/AST/DeclGroup.cpp b/lib/AST/DeclGroup.cpp
index 434bf00d354e..036acc2d77a5 100644
--- a/lib/AST/DeclGroup.cpp
+++ b/lib/AST/DeclGroup.cpp
@@ -30,9 +30,3 @@ DeclGroup::DeclGroup(unsigned numdecls, Decl** decls) : NumDecls(numdecls) {
assert(decls);
memcpy(this+1, decls, numdecls * sizeof(*decls));
}
-
-void DeclGroup::Destroy(ASTContext& C) {
- // Decls are destroyed by the DeclContext.
- this->~DeclGroup();
- C.Deallocate((void*) this);
-}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index adb0e7d08345..d952cc36ef1d 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -21,14 +21,8 @@ using namespace clang;
// ObjCListBase
//===----------------------------------------------------------------------===//
-void ObjCListBase::Destroy(ASTContext &Ctx) {
- Ctx.Deallocate(List);
- NumElts = 0;
- List = 0;
-}
-
void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) {
- assert(List == 0 && "Elements already set!");
+ List = 0;
if (Elts == 0) return; // Setting to an empty list is a noop.
@@ -47,12 +41,6 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
set(InList, Elts, Ctx);
}
-void ObjCProtocolList::Destroy(ASTContext &Ctx) {
- Ctx.Deallocate(Locations);
- Locations = 0;
- ObjCList<ObjCProtocolDecl>::Destroy(Ctx);
-}
-
//===----------------------------------------------------------------------===//
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
@@ -132,8 +120,9 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
return P;
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator
- I = OID->protocol_begin(), E = OID->protocol_end(); I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
@@ -169,8 +158,9 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
return PD;
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator
- I = protocol_begin(), E = protocol_end(); I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = all_referenced_protocol_begin(),
+ E = all_referenced_protocol_end(); I != E; ++I)
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
return P;
@@ -179,23 +169,23 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
- const SourceLocation *Locs,
ASTContext &C)
{
- if (ReferencedProtocols.empty()) {
- ReferencedProtocols.set(ExtList, ExtNum, Locs, C);
+ if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
+ AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
+
// Check for duplicate protocol in class's protocol list.
- // This is (O)2. But it is extremely rare and number of protocols in
+ // This is O(n*m). But it is extremely rare and number of protocols in
// class or its extension are very few.
llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
- llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
for (unsigned i = 0; i < ExtNum; i++) {
bool protocolExists = false;
ObjCProtocolDecl *ProtoInExtension = ExtList[i];
- for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; p++) {
+ for (all_protocol_iterator
+ p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
ObjCProtocolDecl *Proto = (*p);
if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
protocolExists = true;
@@ -204,23 +194,20 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
}
// Do we want to warn on a protocol in extension class which
// already exist in the class? Probably not.
- if (!protocolExists) {
+ if (!protocolExists)
ProtocolRefs.push_back(ProtoInExtension);
- ProtocolLocs.push_back(Locs[i]);
- }
}
+
if (ProtocolRefs.empty())
return;
+
// Merge ProtocolRefs into class's protocol list;
- protocol_loc_iterator pl = protocol_loc_begin();
- for (protocol_iterator p = protocol_begin(), e = protocol_end();
- p != e; ++p, ++pl) {
+ for (all_protocol_iterator p = all_referenced_protocol_begin(),
+ e = all_referenced_protocol_end(); p != e; ++p) {
ProtocolRefs.push_back(*p);
- ProtocolLocs.push_back(*pl);
}
- ReferencedProtocols.Destroy(C);
- unsigned NumProtoRefs = ProtocolRefs.size();
- setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
+
+ AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
}
/// getFirstClassExtension - Find first class extension of the given class.
@@ -339,27 +326,17 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
bool isInstance,
bool isVariadic,
bool isSynthesized,
+ bool isDefined,
ImplementationControl impControl,
unsigned numSelectorArgs) {
return new (C) ObjCMethodDecl(beginLoc, endLoc,
SelInfo, T, ResultTInfo, contextDecl,
isInstance,
- isVariadic, isSynthesized, impControl,
+ isVariadic, isSynthesized, isDefined,
+ impControl,
numSelectorArgs);
}
-void ObjCMethodDecl::Destroy(ASTContext &C) {
- if (Body) Body->Destroy(C);
- if (SelfDecl) SelfDecl->Destroy(C);
-
- for (param_iterator I=param_begin(), E=param_end(); I!=E; ++I)
- if (*I) (*I)->Destroy(C);
-
- ParamInfo.Destroy(C);
-
- Decl::Destroy(C);
-}
-
/// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
@@ -465,22 +442,11 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal)
: ObjCContainerDecl(ObjCInterface, DC, atLoc, Id),
TypeForDecl(0), SuperClass(0),
- CategoryList(0), ForwardDecl(FD), InternalInterface(isInternal),
+ CategoryList(0), IvarList(0),
+ ForwardDecl(FD), InternalInterface(isInternal),
ClassLoc(CLoc) {
}
-void ObjCInterfaceDecl::Destroy(ASTContext &C) {
- for (ivar_iterator I = ivar_begin(), E = ivar_end(); I != E; ++I)
- if (*I) (*I)->Destroy(C);
-
- // FIXME: CategoryList?
-
- // FIXME: Because there is no clear ownership
- // role between ObjCInterfaceDecls and the ObjCPropertyDecls that they
- // reference, we destroy ObjCPropertyDecls in ~TranslationUnit.
- Decl::Destroy(C);
-}
-
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
return getASTContext().getObjCImplementation(
const_cast<ObjCInterfaceDecl*>(this));
@@ -490,6 +456,49 @@ void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
getASTContext().setObjCImplementation(this, ImplD);
}
+/// all_declared_ivar_begin - return first ivar declared in this class,
+/// its extensions and its implementation. Lazily build the list on first
+/// access.
+ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
+ if (IvarList)
+ return IvarList;
+
+ ObjCIvarDecl *curIvar = 0;
+ if (!ivar_empty()) {
+ ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end();
+ IvarList = (*I); ++I;
+ for (curIvar = IvarList; I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+
+ for (const ObjCCategoryDecl *CDecl = getFirstClassExtension(); CDecl;
+ CDecl = CDecl->getNextClassExtension()) {
+ if (!CDecl->ivar_empty()) {
+ ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
+ E = CDecl->ivar_end();
+ if (!IvarList) {
+ IvarList = (*I); ++I;
+ curIvar = IvarList;
+ }
+ for ( ;I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+ }
+
+ if (ObjCImplementationDecl *ImplDecl = getImplementation()) {
+ if (!ImplDecl->ivar_empty()) {
+ ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
+ E = ImplDecl->ivar_end();
+ if (!IvarList) {
+ IvarList = (*I); ++I;
+ curIvar = IvarList;
+ }
+ for ( ;I != E; curIvar = *I, ++I)
+ curIvar->setNextIvar(*I);
+ }
+ }
+ return IvarList;
+}
/// FindCategoryDeclaration - Finds category declaration in the list of
/// categories for this class and returns it. Name of the category is passed
@@ -575,7 +584,8 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
- AccessControl ac, Expr *BW) {
+ AccessControl ac, Expr *BW,
+ bool synthesized) {
if (DC) {
// Ivar's can only appear in interfaces, implementations (via synthesized
// properties), and class extensions (via direct declaration, or synthesized
@@ -590,9 +600,26 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
assert((isa<ObjCInterfaceDecl>(DC) || isa<ObjCImplementationDecl>(DC) ||
isa<ObjCCategoryDecl>(DC)) &&
"Invalid ivar decl context!");
+ // Once a new ivar is created in any of class/class-extension/implementation
+ // decl contexts, the previously built IvarList must be rebuilt.
+ ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(DC);
+ if (!ID) {
+ if (ObjCImplementationDecl *IM = dyn_cast<ObjCImplementationDecl>(DC)) {
+ ID = IM->getClassInterface();
+ if (BW)
+ IM->setHasSynthBitfield(true);
+ }
+ else {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(DC);
+ ID = CD->getClassInterface();
+ if (BW)
+ CD->setHasSynthBitfield(true);
+ }
+ }
+ ID->setIvarList(0);
}
- return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW);
+ return new (C) ObjCIvarDecl(DC, L, Id, T, TInfo, ac, BW, synthesized);
}
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
@@ -630,11 +657,6 @@ ObjCAtDefsFieldDecl
return new (C) ObjCAtDefsFieldDecl(DC, L, Id, T, BW);
}
-void ObjCAtDefsFieldDecl::Destroy(ASTContext& C) {
- this->~ObjCAtDefsFieldDecl();
- C.Deallocate((void *)this);
-}
-
//===----------------------------------------------------------------------===//
// ObjCProtocolDecl
//===----------------------------------------------------------------------===//
@@ -645,11 +667,6 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCProtocolDecl(DC, L, Id);
}
-void ObjCProtocolDecl::Destroy(ASTContext &C) {
- ReferencedProtocols.Destroy(C);
- ObjCContainerDecl::Destroy(C);
-}
-
ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
ObjCProtocolDecl *PDecl = this;
@@ -709,23 +726,6 @@ ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCClassDecl(DC, L, Elts, Locs, nElts, C);
}
-void ObjCClassDecl::Destroy(ASTContext &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);
@@ -754,11 +754,6 @@ ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
}
-void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
- ReferencedProtocols.Destroy(C);
- Decl::Destroy(C);
-}
-
//===----------------------------------------------------------------------===//
// ObjCCategoryDecl
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 765772dd13f9..f18d2f0215dd 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -198,6 +198,12 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
llvm::SmallVector<Decl*, 2> Decls;
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
D != DEnd; ++D) {
+
+ // Don't print ObjCIvarDecls, as they are printed when visiting the
+ // containing ObjCInterfaceDecl.
+ if (isa<ObjCIvarDecl>(*D))
+ continue;
+
if (!Policy.Dump) {
// Skip over implicit declarations in pretty-printing mode.
if (D->isImplicit()) continue;
@@ -329,10 +335,11 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!Policy.SuppressSpecifiers) {
switch (D->getStorageClass()) {
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: Out << "extern "; break;
- case FunctionDecl::Static: Out << "static "; break;
- case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
+ case SC_None: break;
+ case SC_Extern: Out << "extern "; break;
+ case SC_Static: Out << "static "; break;
+ case SC_PrivateExtern: Out << "__private_extern__ "; break;
+ case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
}
if (D->isInlineSpecified()) Out << "inline ";
@@ -341,7 +348,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
- std::string Proto = D->getNameAsString();
+ std::string Proto = D->getNameInfo().getAsString();
if (isa<FunctionType>(D->getType().getTypePtr())) {
const FunctionType *AFT = D->getType()->getAs<FunctionType>();
@@ -499,7 +506,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
}
void DeclPrinter::VisitVarDecl(VarDecl *D) {
- if (!Policy.SuppressSpecifiers && D->getStorageClass() != VarDecl::None)
+ if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None)
Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " ";
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 9e1d79d79d6b..e69338a7730d 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -84,10 +84,59 @@ unsigned TemplateParameterList::getDepth() const {
}
//===----------------------------------------------------------------------===//
-// TemplateDecl Implementation
+// RedeclarableTemplateDecl Implementation
//===----------------------------------------------------------------------===//
-TemplateDecl::~TemplateDecl() {
+RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
+ // Find the first declaration of this function template.
+ RedeclarableTemplateDecl *First = getCanonicalDecl();
+
+ if (First->CommonOrPrev.isNull()) {
+ CommonBase *CommonPtr = First->newCommon();
+ First->CommonOrPrev = CommonPtr;
+ CommonPtr->Latest = First;
+ }
+ return First->CommonOrPrev.get<CommonBase*>();
+}
+
+
+RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() {
+ RedeclarableTemplateDecl *Tmpl = this;
+ while (Tmpl->getPreviousDeclaration())
+ Tmpl = Tmpl->getPreviousDeclaration();
+ return Tmpl;
+}
+
+void RedeclarableTemplateDecl::setPreviousDeclarationImpl(
+ RedeclarableTemplateDecl *Prev) {
+ if (Prev) {
+ CommonBase *Common = Prev->getCommonPtr();
+ Prev = Common->Latest;
+ Common->Latest = this;
+ CommonOrPrev = Prev;
+ } else {
+ assert(CommonOrPrev.is<CommonBase*>() && "Cannot reset TemplateDecl Prev");
+ }
+}
+
+RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() {
+ if (CommonOrPrev.is<RedeclarableTemplateDecl*>())
+ return CommonOrPrev.get<RedeclarableTemplateDecl*>();
+ CommonBase *Common = CommonOrPrev.get<CommonBase*>();
+ return Common ? Common->Latest : this;
+}
+
+template <class EntryType>
+typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType*
+RedeclarableTemplateDecl::findSpecializationImpl(
+ llvm::FoldingSet<EntryType> &Specs,
+ const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos) {
+ typedef SpecEntryTraits<EntryType> SETraits;
+ llvm::FoldingSetNodeID ID;
+ EntryType::Profile(ID,Args,NumArgs, getASTContext());
+ EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
+ return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0;
}
//===----------------------------------------------------------------------===//
@@ -107,37 +156,16 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
}
-void FunctionTemplateDecl::Destroy(ASTContext &C) {
- if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
- for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
- Spec = CommonPtr->Specializations.begin(),
- SpecEnd = CommonPtr->Specializations.end();
- Spec != SpecEnd; ++Spec)
- C.Deallocate(&*Spec);
- }
-
- Decl::Destroy(C);
+RedeclarableTemplateDecl::CommonBase *FunctionTemplateDecl::newCommon() {
+ Common *CommonPtr = new (getASTContext()) Common;
+ getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
}
-FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
- FunctionTemplateDecl *FunTmpl = this;
- while (FunTmpl->getPreviousDeclaration())
- FunTmpl = FunTmpl->getPreviousDeclaration();
- return FunTmpl;
-}
-
-FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
- // Find the first declaration of this function template.
- FunctionTemplateDecl *First = this;
- while (First->getPreviousDeclaration())
- First = First->getPreviousDeclaration();
-
- if (First->CommonOrPrev.isNull()) {
- Common *CommonPtr = new (getASTContext()) Common;
- getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
- First->CommonOrPrev = CommonPtr;
- }
- return First->CommonOrPrev.get<Common*>();
+FunctionDecl *
+FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos) {
+ return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
}
//===----------------------------------------------------------------------===//
@@ -148,13 +176,6 @@ void ClassTemplateDecl::DeallocateCommon(void *Ptr) {
static_cast<Common *>(Ptr)->~Common();
}
-ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() {
- ClassTemplateDecl *Template = this;
- while (Template->getPreviousDeclaration())
- Template = Template->getPreviousDeclaration();
- return Template;
-}
-
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation L,
@@ -167,8 +188,24 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
return New;
}
-void ClassTemplateDecl::Destroy(ASTContext& C) {
- Decl::Destroy(C);
+RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() {
+ Common *CommonPtr = new (getASTContext()) Common;
+ getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
+}
+
+ClassTemplateSpecializationDecl *
+ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs, void *&InsertPos) {
+ return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos);
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
+ unsigned NumArgs,
+ void *&InsertPos) {
+ return findSpecializationImpl(getPartialSpecializations(), Args, NumArgs,
+ InsertPos);
}
void ClassTemplateDecl::getPartialSpecializations(
@@ -181,7 +218,7 @@ void ClassTemplateDecl::getPartialSpecializations(
P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
P != PEnd; ++P) {
assert(!PS[P->getSequenceNumber()]);
- PS[P->getSequenceNumber()] = &*P;
+ PS[P->getSequenceNumber()] = P->getMostRecentDeclaration();
}
}
@@ -194,7 +231,22 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
PEnd = getPartialSpecializations().end();
P != PEnd; ++P) {
if (Context.hasSameType(P->getInjectedSpecializationType(), T))
- return &*P;
+ return P->getMostRecentDeclaration();
+ }
+
+ return 0;
+}
+
+ClassTemplatePartialSpecializationDecl *
+ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
+ ClassTemplatePartialSpecializationDecl *D) {
+ Decl *DCanon = D->getCanonicalDecl();
+ for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
+ P = getPartialSpecializations().begin(),
+ PEnd = getPartialSpecializations().end();
+ P != PEnd; ++P) {
+ if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
+ return P->getMostRecentDeclaration();
}
return 0;
@@ -239,20 +291,6 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
return CommonPtr->InjectedClassNameType;
}
-ClassTemplateDecl::Common *ClassTemplateDecl::getCommonPtr() {
- // Find the first declaration of this function template.
- ClassTemplateDecl *First = this;
- while (First->getPreviousDeclaration())
- First = First->getPreviousDeclaration();
-
- if (First->CommonOrPrev.isNull()) {
- Common *CommonPtr = new (getASTContext()) Common;
- getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
- First->CommonOrPrev = CommonPtr;
- }
- return First->CommonOrPrev.get<Common*>();
-}
-
//===----------------------------------------------------------------------===//
// TemplateTypeParm Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
@@ -431,15 +469,6 @@ StructuredArguments.setPointer(NewArgs);
StructuredArguments.setInt(0); // Doesn't own the pointer.
}
-void TemplateArgumentList::Destroy(ASTContext &C) {
- if (FlatArguments.getInt())
- C.Deallocate((void*)FlatArguments.getPointer());
- if (StructuredArguments.getInt())
- C.Deallocate((void*)StructuredArguments.getPointer());
-}
-
-TemplateArgumentList::~TemplateArgumentList() {}
-
//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
@@ -487,16 +516,6 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) {
new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
}
-void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
- delete ExplicitInfo;
-
- if (SpecializedPartialSpecialization *PartialSpec
- = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
- C.Deallocate(PartialSpec);
-
- CXXRecordDecl::Destroy(C);
-}
-
void
ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
@@ -584,3 +603,8 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
= new (Context) FriendTemplateDecl(DC, L, NParams, Params, Friend, FLoc);
return Result;
}
+
+FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
+ EmptyShell Empty) {
+ return new (Context) FriendTemplateDecl(Empty);
+}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 343d403e76ad..860a0b276a79 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -15,6 +15,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/DenseMap.h"
@@ -404,26 +405,6 @@ DeclarationNameTable::~DeclarationNameTable() {
= static_cast<llvm::FoldingSet<CXXLiteralOperatorIdName>*>
(CXXLiteralOperatorNames);
- if (Ctx.FreeMemory) {
- llvm::FoldingSetIterator<CXXSpecialName>
- SI = SpecialNames->begin(), SE = SpecialNames->end();
-
- while (SI != SE) {
- CXXSpecialName *n = &*SI++;
- Ctx.Deallocate(n);
- }
-
- llvm::FoldingSetIterator<CXXLiteralOperatorIdName>
- LI = LiteralNames->begin(), LE = LiteralNames->end();
-
- while (LI != LE) {
- CXXLiteralOperatorIdName *n = &*LI++;
- Ctx.Deallocate(n);
- }
-
- Ctx.Deallocate(CXXOperatorNames);
- }
-
delete SpecialNames;
delete LiteralNames;
}
@@ -505,3 +486,98 @@ getHashValue(clang::DeclarationName N) {
return DenseMapInfo<void*>::getHashValue(N.getAsOpaquePtr());
}
+DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ NamedType.TInfo = 0;
+ break;
+ case DeclarationName::CXXOperatorName:
+ CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding();
+ CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding();
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ // FIXME: ?
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+}
+
+std::string DeclarationNameInfo::getAsString() const {
+ std::string Result;
+ llvm::raw_string_ostream OS(Result);
+ printName(OS);
+ return OS.str();
+}
+
+void DeclarationNameInfo::printName(llvm::raw_ostream &OS) const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ Name.printName(OS);
+ return;
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) {
+ if (Name.getNameKind() == DeclarationName::CXXDestructorName)
+ OS << '~';
+ else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
+ OS << "operator ";
+ OS << TInfo->getType().getAsString();
+ }
+ else
+ Name.printName(OS);
+ return;
+ }
+ assert(false && "Unexpected declaration name kind");
+}
+
+SourceLocation DeclarationNameInfo::getEndLoc() const {
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ return NameLoc;
+
+ case DeclarationName::CXXOperatorName: {
+ unsigned raw = LocInfo.CXXOperatorName.EndOpNameLoc;
+ return SourceLocation::getFromRawEncoding(raw);
+ }
+
+ case DeclarationName::CXXLiteralOperatorName: {
+ unsigned raw = LocInfo.CXXLiteralOperatorName.OpNameLoc;
+ return SourceLocation::getFromRawEncoding(raw);
+ }
+
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo)
+ return TInfo->getTypeLoc().getEndLoc();
+ else
+ return NameLoc;
+
+ // DNInfo work in progress: FIXME.
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXUsingDirective:
+ return NameLoc;
+ }
+ assert(false && "Unexpected declaration name kind");
+ return SourceLocation();
+}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 6524a312dc8b..5feef1c80332 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -44,8 +44,8 @@ bool Expr::isKnownToHaveBooleanValue() const {
if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(this)) {
switch (UO->getOpcode()) {
- case UnaryOperator::Plus:
- case UnaryOperator::Extension:
+ case UO_Plus:
+ case UO_Extension:
return UO->getSubExpr()->isKnownToHaveBooleanValue();
default:
return false;
@@ -60,25 +60,25 @@ bool Expr::isKnownToHaveBooleanValue() const {
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(this)) {
switch (BO->getOpcode()) {
default: return false;
- case BinaryOperator::LT: // Relational operators.
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ: // Equality operators.
- case BinaryOperator::NE:
- case BinaryOperator::LAnd: // AND operator.
- case BinaryOperator::LOr: // Logical OR operator.
+ case BO_LT: // Relational operators.
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ: // Equality operators.
+ case BO_NE:
+ case BO_LAnd: // AND operator.
+ case BO_LOr: // Logical OR operator.
return true;
- case BinaryOperator::And: // Bitwise AND operator.
- case BinaryOperator::Xor: // Bitwise XOR operator.
- case BinaryOperator::Or: // Bitwise OR operator.
+ case BO_And: // Bitwise AND operator.
+ case BO_Xor: // Bitwise XOR operator.
+ case BO_Or: // Bitwise OR operator.
// Handle things like (x==2)|(y==12).
return BO->getLHS()->isKnownToHaveBooleanValue() &&
BO->getRHS()->isKnownToHaveBooleanValue();
- case BinaryOperator::Comma:
- case BinaryOperator::Assign:
+ case BO_Comma:
+ case BO_Assign:
return BO->getRHS()->isKnownToHaveBooleanValue();
}
}
@@ -151,7 +151,7 @@ void DeclRefExpr::computeDependence() {
ValueDependent = true;
}
// (TD) - a template-id that is dependent,
- else if (hasExplicitTemplateArgumentList() &&
+ else if (hasExplicitTemplateArgs() &&
TemplateSpecializationType::anyDependentTemplateArguments(
getTemplateArgs(),
getNumTemplateArgs())) {
@@ -204,7 +204,29 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
}
if (TemplateArgs)
- getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
+
+ computeDependence();
+}
+
+DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ QualType T)
+ : Expr(DeclRefExprClass, T, false, false),
+ DecoratedD(D,
+ (Qualifier? HasQualifierFlag : 0) |
+ (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)),
+ Loc(NameInfo.getLoc()), DNLoc(NameInfo.getInfo()) {
+ if (Qualifier) {
+ NameQualifier *NQ = getNameQualifier();
+ NQ->NNS = Qualifier;
+ NQ->Range = QualifierRange;
+ }
+
+ if (TemplateArgs)
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
computeDependence();
}
@@ -216,6 +238,18 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
SourceLocation NameLoc,
QualType T,
const TemplateArgumentListInfo *TemplateArgs) {
+ return Create(Context, Qualifier, QualifierRange, D,
+ DeclarationNameInfo(D->getDeclName(), NameLoc),
+ T, TemplateArgs);
+}
+
+DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *D,
+ const DeclarationNameInfo &NameInfo,
+ QualType T,
+ const TemplateArgumentListInfo *TemplateArgs) {
std::size_t Size = sizeof(DeclRefExpr);
if (Qualifier != 0)
Size += sizeof(NameQualifier);
@@ -224,7 +258,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignof<DeclRefExpr>());
- return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameLoc,
+ return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameInfo,
TemplateArgs, T);
}
@@ -242,12 +276,10 @@ DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier,
}
SourceRange DeclRefExpr::getSourceRange() const {
- // FIXME: Does not handle multi-token names well, e.g., operator[].
- SourceRange R(Loc);
-
+ SourceRange R = getNameInfo().getSourceRange();
if (hasQualifier())
R.setBegin(getQualifierRange().getBegin());
- if (hasExplicitTemplateArgumentList())
+ if (hasExplicitTemplateArgs())
R.setEnd(getRAngleLoc());
return R;
}
@@ -342,6 +374,44 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
return "";
}
+void APNumericStorage::setIntValue(ASTContext &C, const llvm::APInt &Val) {
+ if (hasAllocation())
+ C.Deallocate(pVal);
+
+ BitWidth = Val.getBitWidth();
+ unsigned NumWords = Val.getNumWords();
+ const uint64_t* Words = Val.getRawData();
+ if (NumWords > 1) {
+ pVal = new (C) uint64_t[NumWords];
+ std::copy(Words, Words + NumWords, pVal);
+ } else if (NumWords == 1)
+ VAL = Words[0];
+ else
+ VAL = 0;
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, const llvm::APInt &V,
+ QualType type, SourceLocation l) {
+ return new (C) IntegerLiteral(C, V, type, l);
+}
+
+IntegerLiteral *
+IntegerLiteral::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) IntegerLiteral(Empty);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V,
+ bool isexact, QualType Type, SourceLocation L) {
+ return new (C) FloatingLiteral(C, V, isexact, Type, L);
+}
+
+FloatingLiteral *
+FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) {
+ return new (C) FloatingLiteral(Empty);
+}
+
/// getValueAsApproximateDouble - This returns the value as an inaccurate
/// double. Note that this may cause loss of precision, but is useful for
/// debugging dumps, etc.
@@ -390,15 +460,7 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
return SL;
}
-void StringLiteral::DoDestroy(ASTContext &C) {
- C.Deallocate(const_cast<char*>(StrData));
- Expr::DoDestroy(C);
-}
-
void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
- if (StrData)
- C.Deallocate(const_cast<char*>(StrData));
-
char *AStrData = new (C, 1) char[Str.size()];
memcpy(AStrData, Str.data(), Str.size());
StrData = AStrData;
@@ -410,48 +472,47 @@ void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) {
const char *UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
default: assert(0 && "Unknown unary operator");
- case PostInc: return "++";
- case PostDec: return "--";
- case PreInc: return "++";
- case PreDec: return "--";
- case AddrOf: return "&";
- case Deref: return "*";
- case Plus: return "+";
- case Minus: return "-";
- case Not: return "~";
- case LNot: return "!";
- case Real: return "__real";
- case Imag: return "__imag";
- case Extension: return "__extension__";
- case OffsetOf: return "__builtin_offsetof";
+ case UO_PostInc: return "++";
+ case UO_PostDec: return "--";
+ case UO_PreInc: return "++";
+ case UO_PreDec: return "--";
+ case UO_AddrOf: return "&";
+ case UO_Deref: return "*";
+ case UO_Plus: return "+";
+ case UO_Minus: return "-";
+ case UO_Not: return "~";
+ case UO_LNot: return "!";
+ case UO_Real: return "__real";
+ case UO_Imag: return "__imag";
+ case UO_Extension: return "__extension__";
}
}
-UnaryOperator::Opcode
+UnaryOperatorKind
UnaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix) {
switch (OO) {
default: assert(false && "No unary operator for overloaded function");
- case OO_PlusPlus: return Postfix ? PostInc : PreInc;
- case OO_MinusMinus: return Postfix ? PostDec : PreDec;
- case OO_Amp: return AddrOf;
- case OO_Star: return Deref;
- case OO_Plus: return Plus;
- case OO_Minus: return Minus;
- case OO_Tilde: return Not;
- case OO_Exclaim: return LNot;
+ case OO_PlusPlus: return Postfix ? UO_PostInc : UO_PreInc;
+ case OO_MinusMinus: return Postfix ? UO_PostDec : UO_PreDec;
+ case OO_Amp: return UO_AddrOf;
+ case OO_Star: return UO_Deref;
+ case OO_Plus: return UO_Plus;
+ case OO_Minus: return UO_Minus;
+ case OO_Tilde: return UO_Not;
+ case OO_Exclaim: return UO_LNot;
}
}
OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
switch (Opc) {
- case PostInc: case PreInc: return OO_PlusPlus;
- case PostDec: case PreDec: return OO_MinusMinus;
- case AddrOf: return OO_Amp;
- case Deref: return OO_Star;
- case Plus: return OO_Plus;
- case Minus: return OO_Minus;
- case Not: return OO_Tilde;
- case LNot: return OO_Exclaim;
+ case UO_PostInc: case UO_PreInc: return OO_PlusPlus;
+ case UO_PostDec: case UO_PreDec: return OO_MinusMinus;
+ case UO_AddrOf: return OO_Amp;
+ case UO_Deref: return OO_Star;
+ case UO_Plus: return OO_Plus;
+ case UO_Minus: return OO_Minus;
+ case UO_Not: return OO_Tilde;
+ case UO_LNot: return OO_Exclaim;
default: return OO_None;
}
}
@@ -496,13 +557,6 @@ CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty)
SubExprs = new (C) Stmt*[1];
}
-void CallExpr::DoDestroy(ASTContext& C) {
- DestroyChildren(C);
- if (SubExprs) C.Deallocate(SubExprs);
- this->~CallExpr();
- C.Deallocate(this);
-}
-
Decl *CallExpr::getCalleeDecl() {
Expr *CEE = getCallee()->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
@@ -526,8 +580,6 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
// If shrinking # arguments, just delete the extras and forgot them.
if (NumArgs < getNumArgs()) {
- for (unsigned i = NumArgs, e = getNumArgs(); i != e; ++i)
- getArg(i)->Destroy(C);
this->NumArgs = NumArgs;
return;
}
@@ -640,7 +692,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
SourceRange qualrange,
ValueDecl *memberdecl,
DeclAccessPair founddecl,
- SourceLocation l,
+ DeclarationNameInfo nameinfo,
const TemplateArgumentListInfo *targs,
QualType ty) {
std::size_t Size = sizeof(MemberExpr);
@@ -655,7 +707,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
Size += ExplicitTemplateArgumentList::sizeFor(*targs);
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
- MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty);
+ MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, ty);
if (hasQualOrFound) {
if (qual && qual->isDependent()) {
@@ -672,7 +724,7 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
if (targs) {
E->HasExplicitTemplateArgumentList = true;
- E->getExplicitTemplateArgumentList()->initializeFrom(*targs);
+ E->getExplicitTemplateArgs().initializeFrom(*targs);
}
return E;
@@ -680,72 +732,68 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
const char *CastExpr::getCastKindName() const {
switch (getCastKind()) {
- case CastExpr::CK_Unknown:
+ case CK_Unknown:
return "Unknown";
- case CastExpr::CK_BitCast:
+ case CK_BitCast:
return "BitCast";
- case CastExpr::CK_LValueBitCast:
+ case CK_LValueBitCast:
return "LValueBitCast";
- case CastExpr::CK_NoOp:
+ case CK_NoOp:
return "NoOp";
- case CastExpr::CK_BaseToDerived:
+ case CK_BaseToDerived:
return "BaseToDerived";
- case CastExpr::CK_DerivedToBase:
+ case CK_DerivedToBase:
return "DerivedToBase";
- case CastExpr::CK_UncheckedDerivedToBase:
+ case CK_UncheckedDerivedToBase:
return "UncheckedDerivedToBase";
- case CastExpr::CK_Dynamic:
+ case CK_Dynamic:
return "Dynamic";
- case CastExpr::CK_ToUnion:
+ case CK_ToUnion:
return "ToUnion";
- case CastExpr::CK_ArrayToPointerDecay:
+ case CK_ArrayToPointerDecay:
return "ArrayToPointerDecay";
- case CastExpr::CK_FunctionToPointerDecay:
+ case CK_FunctionToPointerDecay:
return "FunctionToPointerDecay";
- case CastExpr::CK_NullToMemberPointer:
+ case CK_NullToMemberPointer:
return "NullToMemberPointer";
- case CastExpr::CK_BaseToDerivedMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
return "BaseToDerivedMemberPointer";
- case CastExpr::CK_DerivedToBaseMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
return "DerivedToBaseMemberPointer";
- case CastExpr::CK_UserDefinedConversion:
+ case CK_UserDefinedConversion:
return "UserDefinedConversion";
- case CastExpr::CK_ConstructorConversion:
+ case CK_ConstructorConversion:
return "ConstructorConversion";
- case CastExpr::CK_IntegralToPointer:
+ case CK_IntegralToPointer:
return "IntegralToPointer";
- case CastExpr::CK_PointerToIntegral:
+ case CK_PointerToIntegral:
return "PointerToIntegral";
- case CastExpr::CK_ToVoid:
+ case CK_ToVoid:
return "ToVoid";
- case CastExpr::CK_VectorSplat:
+ case CK_VectorSplat:
return "VectorSplat";
- case CastExpr::CK_IntegralCast:
+ case CK_IntegralCast:
return "IntegralCast";
- case CastExpr::CK_IntegralToFloating:
+ case CK_IntegralToFloating:
return "IntegralToFloating";
- case CastExpr::CK_FloatingToIntegral:
+ case CK_FloatingToIntegral:
return "FloatingToIntegral";
- case CastExpr::CK_FloatingCast:
+ case CK_FloatingCast:
return "FloatingCast";
- case CastExpr::CK_MemberPointerToBoolean:
+ case CK_MemberPointerToBoolean:
return "MemberPointerToBoolean";
- case CastExpr::CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToObjCPointerCast:
return "AnyPointerToObjCPointerCast";
- case CastExpr::CK_AnyPointerToBlockPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
return "AnyPointerToBlockPointerCast";
+ case CK_ObjCObjectLValueCast:
+ return "ObjCObjectLValueCast";
}
assert(0 && "Unhandled cast kind!");
return 0;
}
-void CastExpr::DoDestroy(ASTContext &C)
-{
- BasePath.Destroy();
- Expr::DoDestroy(C);
-}
-
Expr *CastExpr::getSubExprAsWritten() {
Expr *SubExpr = 0;
CastExpr *E = this;
@@ -758,9 +806,9 @@ Expr *CastExpr::getSubExprAsWritten() {
// Conversions by constructor and conversion functions have a
// subexpression describing the call; strip it off.
- if (E->getCastKind() == CastExpr::CK_ConstructorConversion)
+ if (E->getCastKind() == CK_ConstructorConversion)
SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
- else if (E->getCastKind() == CastExpr::CK_UserDefinedConversion)
+ else if (E->getCastKind() == CK_UserDefinedConversion)
SubExpr = cast<CXXMemberCallExpr>(SubExpr)->getImplicitObjectArgument();
// If the subexpression we're left with is an implicit cast, look
@@ -770,82 +818,142 @@ Expr *CastExpr::getSubExprAsWritten() {
return SubExpr;
}
+CXXBaseSpecifier **CastExpr::path_buffer() {
+ switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+ case Stmt::Type##Class: \
+ return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+ default:
+ llvm_unreachable("non-cast expressions not possible here");
+ return 0;
+ }
+}
+
+void CastExpr::setCastPath(const CXXCastPath &Path) {
+ assert(Path.size() == path_size());
+ memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
+}
+
+ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T,
+ CastKind Kind, Expr *Operand,
+ const CXXCastPath *BasePath,
+ ExprValueKind VK) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ ImplicitCastExpr *E =
+ new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, VK);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
+}
+
+
+CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L, SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CStyleCastExpr *E =
+ new (Buffer) CStyleCastExpr(T, K, Op, PathSize, WrittenTy, L, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
+}
+
/// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
/// corresponds to, e.g. "<<=".
const char *BinaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
- case PtrMemD: return ".*";
- case PtrMemI: return "->*";
- case Mul: return "*";
- case Div: return "/";
- case Rem: return "%";
- case Add: return "+";
- case Sub: return "-";
- case Shl: return "<<";
- case Shr: return ">>";
- case LT: return "<";
- case GT: return ">";
- case LE: return "<=";
- case GE: return ">=";
- case EQ: return "==";
- case NE: return "!=";
- case And: return "&";
- case Xor: return "^";
- case Or: return "|";
- case LAnd: return "&&";
- case LOr: return "||";
- case Assign: return "=";
- case MulAssign: return "*=";
- case DivAssign: return "/=";
- case RemAssign: return "%=";
- case AddAssign: return "+=";
- case SubAssign: return "-=";
- case ShlAssign: return "<<=";
- case ShrAssign: return ">>=";
- case AndAssign: return "&=";
- case XorAssign: return "^=";
- case OrAssign: return "|=";
- case Comma: return ",";
+ case BO_PtrMemD: return ".*";
+ case BO_PtrMemI: return "->*";
+ case BO_Mul: return "*";
+ case BO_Div: return "/";
+ case BO_Rem: return "%";
+ case BO_Add: return "+";
+ case BO_Sub: return "-";
+ case BO_Shl: return "<<";
+ case BO_Shr: return ">>";
+ case BO_LT: return "<";
+ case BO_GT: return ">";
+ case BO_LE: return "<=";
+ case BO_GE: return ">=";
+ case BO_EQ: return "==";
+ case BO_NE: return "!=";
+ case BO_And: return "&";
+ case BO_Xor: return "^";
+ case BO_Or: return "|";
+ case BO_LAnd: return "&&";
+ case BO_LOr: return "||";
+ case BO_Assign: return "=";
+ case BO_MulAssign: return "*=";
+ case BO_DivAssign: return "/=";
+ case BO_RemAssign: return "%=";
+ case BO_AddAssign: return "+=";
+ case BO_SubAssign: return "-=";
+ case BO_ShlAssign: return "<<=";
+ case BO_ShrAssign: return ">>=";
+ case BO_AndAssign: return "&=";
+ case BO_XorAssign: return "^=";
+ case BO_OrAssign: return "|=";
+ case BO_Comma: return ",";
}
return "";
}
-BinaryOperator::Opcode
+BinaryOperatorKind
BinaryOperator::getOverloadedOpcode(OverloadedOperatorKind OO) {
switch (OO) {
default: assert(false && "Not an overloadable binary operator");
- case OO_Plus: return Add;
- case OO_Minus: return Sub;
- case OO_Star: return Mul;
- case OO_Slash: return Div;
- case OO_Percent: return Rem;
- case OO_Caret: return Xor;
- case OO_Amp: return And;
- case OO_Pipe: return Or;
- case OO_Equal: return Assign;
- case OO_Less: return LT;
- case OO_Greater: return GT;
- case OO_PlusEqual: return AddAssign;
- case OO_MinusEqual: return SubAssign;
- case OO_StarEqual: return MulAssign;
- case OO_SlashEqual: return DivAssign;
- case OO_PercentEqual: return RemAssign;
- case OO_CaretEqual: return XorAssign;
- case OO_AmpEqual: return AndAssign;
- case OO_PipeEqual: return OrAssign;
- case OO_LessLess: return Shl;
- case OO_GreaterGreater: return Shr;
- case OO_LessLessEqual: return ShlAssign;
- case OO_GreaterGreaterEqual: return ShrAssign;
- case OO_EqualEqual: return EQ;
- case OO_ExclaimEqual: return NE;
- case OO_LessEqual: return LE;
- case OO_GreaterEqual: return GE;
- case OO_AmpAmp: return LAnd;
- case OO_PipePipe: return LOr;
- case OO_Comma: return Comma;
- case OO_ArrowStar: return PtrMemI;
+ case OO_Plus: return BO_Add;
+ case OO_Minus: return BO_Sub;
+ case OO_Star: return BO_Mul;
+ case OO_Slash: return BO_Div;
+ case OO_Percent: return BO_Rem;
+ case OO_Caret: return BO_Xor;
+ case OO_Amp: return BO_And;
+ case OO_Pipe: return BO_Or;
+ case OO_Equal: return BO_Assign;
+ case OO_Less: return BO_LT;
+ case OO_Greater: return BO_GT;
+ case OO_PlusEqual: return BO_AddAssign;
+ case OO_MinusEqual: return BO_SubAssign;
+ case OO_StarEqual: return BO_MulAssign;
+ case OO_SlashEqual: return BO_DivAssign;
+ case OO_PercentEqual: return BO_RemAssign;
+ case OO_CaretEqual: return BO_XorAssign;
+ case OO_AmpEqual: return BO_AndAssign;
+ case OO_PipeEqual: return BO_OrAssign;
+ case OO_LessLess: return BO_Shl;
+ case OO_GreaterGreater: return BO_Shr;
+ case OO_LessLessEqual: return BO_ShlAssign;
+ case OO_GreaterGreaterEqual: return BO_ShrAssign;
+ case OO_EqualEqual: return BO_EQ;
+ case OO_ExclaimEqual: return BO_NE;
+ case OO_LessEqual: return BO_LE;
+ case OO_GreaterEqual: return BO_GE;
+ case OO_AmpAmp: return BO_LAnd;
+ case OO_PipePipe: return BO_LOr;
+ case OO_Comma: return BO_Comma;
+ case OO_ArrowStar: return BO_PtrMemI;
}
}
@@ -897,9 +1005,6 @@ void InitListExpr::reserveInits(ASTContext &C, unsigned NumInits) {
}
void InitListExpr::resizeInits(ASTContext &C, unsigned NumInits) {
- for (unsigned Idx = NumInits, LastIdx = InitExprs.size();
- Idx < LastIdx; ++Idx)
- InitExprs[Idx]->Destroy(C);
InitExprs.resize(C, NumInits, 0);
}
@@ -963,24 +1068,24 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
switch (UO->getOpcode()) {
default: break;
- case UnaryOperator::PostInc:
- case UnaryOperator::PostDec:
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec: // ++/--
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec: // ++/--
return false; // Not a warning.
- case UnaryOperator::Deref:
+ case UO_Deref:
// Dereferencing a volatile pointer is a side-effect.
if (Ctx.getCanonicalType(getType()).isVolatileQualified())
return false;
break;
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
+ case UO_Real:
+ case UO_Imag:
// accessing a piece of a volatile complex is a side-effect.
if (Ctx.getCanonicalType(UO->getSubExpr()->getType())
.isVolatileQualified())
return false;
break;
- case UnaryOperator::Extension:
+ case UO_Extension:
return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
}
Loc = UO->getOperatorLoc();
@@ -994,7 +1099,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
break;
// Consider the RHS of comma for side effects. LHS was checked by
// Sema::CheckCommaOperands.
- case BinaryOperator::Comma:
+ case BO_Comma:
// ((foo = <blah>), 0) is an idiom for hiding the result (and
// lvalue-ness) of an assignment written in a macro.
if (IntegerLiteral *IE =
@@ -1003,8 +1108,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
return false;
return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx);
// Consider '||', '&&' to have side effects if the LHS or RHS does.
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr:
+ case BO_LAnd:
+ case BO_LOr:
if (!BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx) ||
!BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Ctx))
return false;
@@ -1137,8 +1242,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// 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)
+ if (CE->getCastKind() == CK_ToVoid ||
+ CE->getCastKind() == CK_ConstructorConversion)
return (cast<CastExpr>(this)->getSubExpr()
->isUnusedResultAWarning(Loc, R1, R2, Ctx));
Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
@@ -1287,7 +1392,7 @@ bool Expr::isDefaultArgument() const {
/// expressions.
static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
else
break;
@@ -1297,7 +1402,7 @@ static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
E = BE->getSubExpr();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr();
else
break;
@@ -1314,8 +1419,8 @@ const Expr *Expr::getTemporaryObject() const {
if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) {
// Only user-defined and constructor conversions can produce
// temporary objects.
- if (Cast->getCastKind() != CastExpr::CK_ConstructorConversion &&
- Cast->getCastKind() != CastExpr::CK_UserDefinedConversion)
+ if (Cast->getCastKind() != CK_ConstructorConversion &&
+ Cast->getCastKind() != CK_UserDefinedConversion)
return 0;
// Strip off temporary bindings and no-op casts.
@@ -1323,12 +1428,12 @@ const Expr *Expr::getTemporaryObject() const {
// If this is a constructor conversion, see if we have an object
// construction.
- if (Cast->getCastKind() == CastExpr::CK_ConstructorConversion)
+ if (Cast->getCastKind() == CK_ConstructorConversion)
return dyn_cast<CXXConstructExpr>(Sub);
// If this is a user-defined conversion, see if we have a call to
// a function that itself returns a temporary object.
- if (Cast->getCastKind() == CastExpr::CK_UserDefinedConversion)
+ if (Cast->getCastKind() == CK_UserDefinedConversion)
if (const CallExpr *CE = dyn_cast<CallExpr>(Sub))
if (CE->getCallReturnType()->isRecordType())
return CE;
@@ -1368,15 +1473,20 @@ bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
return false;
}
-bool Expr::isConstantInitializer(ASTContext &Ctx) const {
+bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
// This function is attempting whether an expression is an initializer
// which can be evaluated at compile-time. isEvaluatable handles most
// of the cases, but it can't deal with some initializer-specific
// expressions, and it can't deal with aggregates; we deal with those here,
// and fall back to isEvaluatable for the other cases.
- // FIXME: This function assumes the variable being assigned to
- // isn't a reference type!
+ // If we ever capture reference-binding directly in the AST, we can
+ // kill the second parameter.
+
+ if (IsForRef) {
+ EvalResult Result;
+ return EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects;
+ }
switch (getStmtClass()) {
default: break;
@@ -1384,12 +1494,27 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
case ObjCStringLiteralClass:
case ObjCEncodeExprClass:
return true;
+ case CXXTemporaryObjectExprClass:
+ case CXXConstructExprClass: {
+ const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
+
+ // Only if it's
+ // 1) an application of the trivial default constructor or
+ if (!CE->getConstructor()->isTrivial()) return false;
+ if (!CE->getNumArgs()) return true;
+
+ // 2) an elidable trivial copy construction of an operand which is
+ // itself a constant initializer. Note that we consider the
+ // operand on its own, *not* as a reference binding.
+ return CE->isElidable() &&
+ CE->getArg(0)->isConstantInitializer(Ctx, false);
+ }
case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
- return Exp->isConstantInitializer(Ctx);
+ return Exp->isConstantInitializer(Ctx, false);
}
case InitListExprClass: {
// FIXME: This doesn't deal with fields with reference types correctly.
@@ -1398,7 +1523,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
const InitListExpr *Exp = cast<InitListExpr>(this);
unsigned numInits = Exp->getNumInits();
for (unsigned i = 0; i < numInits; i++) {
- if (!Exp->getInit(i)->isConstantInitializer(Ctx))
+ if (!Exp->getInit(i)->isConstantInitializer(Ctx, false))
return false;
}
return true;
@@ -1406,36 +1531,41 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const {
case ImplicitValueInitExprClass:
return true;
case ParenExprClass:
- return cast<ParenExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<ParenExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, IsForRef);
case UnaryOperatorClass: {
const UnaryOperator* Exp = cast<UnaryOperator>(this);
- if (Exp->getOpcode() == UnaryOperator::Extension)
- return Exp->getSubExpr()->isConstantInitializer(Ctx);
+ if (Exp->getOpcode() == UO_Extension)
+ return Exp->getSubExpr()->isConstantInitializer(Ctx, false);
break;
}
case BinaryOperatorClass: {
// Special case &&foo - &&bar. It would be nice to generalize this somehow
// but this handles the common case.
const BinaryOperator *Exp = cast<BinaryOperator>(this);
- if (Exp->getOpcode() == BinaryOperator::Sub &&
+ if (Exp->getOpcode() == BO_Sub &&
isa<AddrLabelExpr>(Exp->getLHS()->IgnoreParenNoopCasts(Ctx)) &&
isa<AddrLabelExpr>(Exp->getRHS()->IgnoreParenNoopCasts(Ctx)))
return true;
break;
}
+ case CXXFunctionalCastExprClass:
+ case CXXStaticCastExprClass:
case ImplicitCastExprClass:
case CStyleCastExprClass:
// Handle casts with a destination that's a struct or union; this
// deals with both the gcc no-op struct cast extension and the
// cast-to-union extension.
if (getType()->isRecordType())
- return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
// Integer->integer casts can be handled here, which is important for
// things like (int)(&&x-&&y). Scary but true.
if (getType()->isIntegerType() &&
cast<CastExpr>(this)->getSubExpr()->getType()->isIntegerType())
- return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
break;
}
@@ -1508,7 +1638,8 @@ FieldDecl *Expr::getBitField() {
Expr *E = this->IgnoreParens();
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getValueKind() != VK_RValue &&
+ ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr()->IgnoreParens();
else
break;
@@ -1530,7 +1661,8 @@ bool Expr::refersToVectorElement() const {
const Expr *E = this->IgnoreParens();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- if (ICE->isLvalueCast() && ICE->getCastKind() == CastExpr::CK_NoOp)
+ if (ICE->getValueKind() != VK_RValue &&
+ ICE->getCastKind() == CK_NoOp)
E = ICE->getSubExpr()->IgnoreParens();
else
break;
@@ -1773,27 +1905,6 @@ void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs,
memcpy(SubExprs, Exprs, sizeof(Expr *) * NumExprs);
}
-void ShuffleVectorExpr::DoDestroy(ASTContext& C) {
- DestroyChildren(C);
- if (SubExprs) C.Deallocate(SubExprs);
- this->~ShuffleVectorExpr();
- C.Deallocate(this);
-}
-
-void SizeOfAlignOfExpr::DoDestroy(ASTContext& C) {
- // Override default behavior of traversing children. If this has a type
- // operand and the type is a variable-length array, the child iteration
- // will iterate over the size expression. However, this expression belongs
- // to the type, not to this, so we don't want to delete it.
- // We still want to delete this expression.
- if (isArgumentType()) {
- this->~SizeOfAlignOfExpr();
- C.Deallocate(this);
- }
- else
- Expr::DoDestroy(C);
-}
-
//===----------------------------------------------------------------------===//
// DesignatedInitExpr
//===----------------------------------------------------------------------===//
@@ -1878,8 +1989,6 @@ DesignatedInitExpr *DesignatedInitExpr::CreateEmpty(ASTContext &C,
void DesignatedInitExpr::setDesignators(ASTContext &C,
const Designator *Desigs,
unsigned NumDesigs) {
- DestroyDesignators(C);
-
Designators = new (C) Designator[NumDesigs];
NumDesignators = NumDesigs;
for (unsigned I = 0; I != NumDesigs; ++I)
@@ -1950,23 +2059,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
std::copy(First, Last, NewDesignators + Idx);
std::copy(Designators + Idx + 1, Designators + NumDesignators,
NewDesignators + Idx + NumNewDesignators);
- DestroyDesignators(C);
Designators = NewDesignators;
NumDesignators = NumDesignators - 1 + NumNewDesignators;
}
-void DesignatedInitExpr::DoDestroy(ASTContext &C) {
- DestroyDesignators(C);
- Expr::DoDestroy(C);
-}
-
-void DesignatedInitExpr::DestroyDesignators(ASTContext &C) {
- for (unsigned I = 0; I != NumDesignators; ++I)
- Designators[I].~Designator();
- C.Deallocate(Designators);
- Designators = 0;
-}
-
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
SourceLocation rparenloc)
@@ -1980,13 +2076,6 @@ ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Exprs[i] = exprs[i];
}
-void ParenListExpr::DoDestroy(ASTContext& C) {
- DestroyChildren(C);
- if (Exprs) C.Deallocate(Exprs);
- this->~ParenListExpr();
- C.Deallocate(this);
-}
-
//===----------------------------------------------------------------------===//
// ExprIterator.
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index c2548eca659e..0a101300d8fa 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -118,14 +118,6 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray,
}
-void CXXNewExpr::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (SubExprs)
- C.Deallocate(SubExprs);
- this->~CXXNewExpr();
- C.Deallocate((void*)this);
-}
-
Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator CXXNewExpr::child_end() {
return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs();
@@ -167,8 +159,9 @@ UnresolvedLookupExpr *
UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange, DeclarationName Name,
- SourceLocation NameLoc, bool ADL,
+ SourceRange QualifierRange,
+ const DeclarationNameInfo &NameInfo,
+ bool ADL,
const TemplateArgumentListInfo &Args,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
@@ -179,8 +172,8 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
= new (Mem) UnresolvedLookupExpr(C,
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, NamingClass,
- Qualifier, QualifierRange,
- Name, NameLoc, ADL,
+ Qualifier, QualifierRange, NameInfo,
+ ADL,
/*Overload*/ true,
/*ExplicitTemplateArgs*/ true,
Begin, End);
@@ -204,14 +197,14 @@ UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) {
OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T,
bool Dependent, NestedNameSpecifier *Qualifier,
- SourceRange QRange, DeclarationName Name,
- SourceLocation NameLoc, bool HasTemplateArgs,
+ SourceRange QRange,
+ const DeclarationNameInfo &NameInfo,
+ bool HasTemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
: Expr(K, T, Dependent, Dependent),
- Results(0), NumResults(0), Name(Name), Qualifier(Qualifier),
- QualifierRange(QRange), NameLoc(NameLoc),
- HasExplicitTemplateArgs(HasTemplateArgs)
+ Results(0), NumResults(0), NameInfo(NameInfo), Qualifier(Qualifier),
+ QualifierRange(QRange), HasExplicitTemplateArgs(HasTemplateArgs)
{
initializeResults(C, Begin, End);
}
@@ -270,8 +263,7 @@ DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args);
@@ -280,8 +272,7 @@ DependentScopeDeclRefExpr::Create(ASTContext &C,
DependentScopeDeclRefExpr *DRE
= new (Mem) DependentScopeDeclRefExpr(C.DependentTy,
Qualifier, QualifierRange,
- Name, NameLoc,
- Args != 0);
+ NameInfo, Args != 0);
if (Args)
reinterpret_cast<ExplicitTemplateArgumentList*>(DRE+1)
@@ -299,7 +290,7 @@ DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
void *Mem = C.Allocate(size);
return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(),
- DeclarationName(),SourceLocation(),
+ DeclarationNameInfo(),
NumTemplateArgs != 0);
}
@@ -395,6 +386,118 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
C.getBaseElementType(QueriedType)->getAs<RecordType>())
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
return false;
+ // TODO: Propagate nothrowness for implicitly declared special members.
+ case UTT_HasNothrowAssign:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If type is const qualified or is a reference type then the
+ // trait is false. Otherwise if __has_trivial_assign (type)
+ // is true then the trait is true, else if type is a cv class
+ // or union type with copy assignment operators that are known
+ // not to throw an exception then the trait is true, else it is
+ // false.
+ if (C.getBaseElementType(QueriedType).isConstQualified())
+ return false;
+ if (QueriedType->isReferenceType())
+ return false;
+ if (QueriedType->isPODType())
+ return true;
+ if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyAssignment())
+ return true;
+
+ bool FoundAssign = false;
+ bool AllNoThrow = true;
+ DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = RD->lookup(Name);
+ Op != OpEnd; ++Op) {
+ CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+ if (Operator->isCopyAssignmentOperator()) {
+ FoundAssign = true;
+ const FunctionProtoType *CPT
+ = Operator->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+
+ return FoundAssign && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowCopy:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_copy (type) is true then the trait is true, else
+ // if type is a cv class or union type with copy constructors that are
+ // known not to throw an exception then the trait is true, else it is
+ // false.
+ if (QueriedType->isPODType() || QueriedType->isReferenceType())
+ return true;
+ if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyConstructor())
+ return true;
+
+ bool FoundConstructor = false;
+ bool AllNoThrow = true;
+ unsigned FoundTQs;
+ DeclarationName ConstructorName
+ = C.DeclarationNames.getCXXConstructorName(
+ C.getCanonicalType(QueriedType));
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = RD->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isCopyConstructor(FoundTQs)) {
+ FoundConstructor = true;
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+
+ return FoundConstructor && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowConstructor:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_constructor (type) is true then the trait is
+ // true, else if type is a cv class or union type (or array
+ // thereof) with a default constructor that is known not to
+ // throw an exception then the trait is true, else it is false.
+ if (QueriedType->isPODType())
+ return true;
+ if (const RecordType *RT =
+ C.getBaseElementType(QueriedType)->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialConstructor())
+ return true;
+
+ if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) {
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0)
+ return true;
+ }
+ }
+ return false;
+ case UTT_HasVirtualDestructor:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If type is a class type with a virtual destructor ([class.dtor])
+ // then the trait is true, else it is false.
+ if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (CXXDestructorDecl *Destructor = RD->getDestructor())
+ return Destructor->isVirtual();
+ }
+ return false;
}
}
@@ -468,6 +571,100 @@ const char *CXXNamedCastExpr::getCastName() const {
}
}
+CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXStaticCastExpr *E =
+ new (Buffer) CXXStaticCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T,
+ CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXDynamicCastExpr *E =
+ new (Buffer) CXXDynamicCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C,
+ unsigned PathSize) {
+ void *Buffer =
+ C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, CastKind K, Expr *Op,
+ const CXXCastPath *BasePath,
+ TypeSourceInfo *WrittenTy, SourceLocation L) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer =
+ C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXReinterpretCastExpr *E =
+ new (Buffer) CXXReinterpretCastExpr(T, K, Op, PathSize, WrittenTy, L);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, Expr *Op,
+ TypeSourceInfo *WrittenTy,
+ SourceLocation L) {
+ return new (C) CXXConstCastExpr(T, Op, WrittenTy, L);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
+ return new (C) CXXConstCastExpr(EmptyShell());
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::Create(ASTContext &C, QualType T,
+ TypeSourceInfo *Written, SourceLocation L,
+ CastKind K, Expr *Op, const CXXCastPath *BasePath,
+ SourceLocation R) {
+ unsigned PathSize = (BasePath ? BasePath->size() : 0);
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ CXXFunctionalCastExpr *E =
+ new (Buffer) CXXFunctionalCastExpr(T, Written, L, K, Op, PathSize, R);
+ if (PathSize) E->setCastPath(*BasePath);
+ return E;
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+ void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+ + PathSize * sizeof(CXXBaseSpecifier*));
+ return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+}
+
+
CXXDefaultArgExpr *
CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param, Expr *SubExpr) {
@@ -476,23 +673,11 @@ CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
SubExpr);
}
-void CXXDefaultArgExpr::DoDestroy(ASTContext &C) {
- if (Param.getInt())
- getExpr()->Destroy(C);
- this->~CXXDefaultArgExpr();
- C.Deallocate(this);
-}
-
CXXTemporary *CXXTemporary::Create(ASTContext &C,
const CXXDestructorDecl *Destructor) {
return new (C) CXXTemporary(Destructor);
}
-void CXXTemporary::Destroy(ASTContext &Ctx) {
- this->~CXXTemporary();
- Ctx.Deallocate(this);
-}
-
CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C,
CXXTemporary *Temp,
Expr* SubExpr) {
@@ -502,25 +687,6 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C,
return new (C) CXXBindTemporaryExpr(Temp, SubExpr);
}
-void CXXBindTemporaryExpr::DoDestroy(ASTContext &C) {
- Temp->Destroy(C);
- this->~CXXBindTemporaryExpr();
- C.Deallocate(this);
-}
-
-CXXBindReferenceExpr *CXXBindReferenceExpr::Create(ASTContext &C, Expr *SubExpr,
- bool ExtendsLifetime,
- bool RequiresTemporaryCopy) {
- return new (C) CXXBindReferenceExpr(SubExpr,
- ExtendsLifetime,
- RequiresTemporaryCopy);
-}
-
-void CXXBindReferenceExpr::DoDestroy(ASTContext &C) {
- this->~CXXBindReferenceExpr();
- C.Deallocate(this);
-}
-
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
CXXConstructorDecl *Cons,
QualType writtenTy,
@@ -569,14 +735,6 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
}
}
-void CXXConstructExpr::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (Args)
- C.Deallocate(Args);
- this->~CXXConstructExpr();
- C.Deallocate(this);
-}
-
CXXExprWithTemporaries::CXXExprWithTemporaries(ASTContext &C,
Expr *subexpr,
CXXTemporary **temps,
@@ -605,16 +763,6 @@ CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
return new (C) CXXExprWithTemporaries(C, SubExpr, Temps, NumTemps);
}
-void CXXExprWithTemporaries::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- if (Temps)
- C.Deallocate(Temps);
- this->~CXXExprWithTemporaries();
- C.Deallocate(this);
-}
-
-CXXExprWithTemporaries::~CXXExprWithTemporaries() {}
-
// CXXBindTemporaryExpr
Stmt::child_iterator CXXBindTemporaryExpr::child_begin() {
return &SubExpr;
@@ -624,15 +772,6 @@ Stmt::child_iterator CXXBindTemporaryExpr::child_end() {
return &SubExpr + 1;
}
-// CXXBindReferenceExpr
-Stmt::child_iterator CXXBindReferenceExpr::child_begin() {
- return &SubExpr;
-}
-
-Stmt::child_iterator CXXBindReferenceExpr::child_end() {
- return &SubExpr + 1;
-}
-
// CXXConstructExpr
Stmt::child_iterator CXXConstructExpr::child_begin() {
return &Args[0];
@@ -705,8 +844,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
@@ -714,9 +852,9 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope),
- Member(Member), MemberLoc(MemberLoc) {
+ MemberNameInfo(MemberNameInfo) {
if (TemplateArgs)
- getExplicitTemplateArgumentList()->initializeFrom(*TemplateArgs);
+ getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
}
CXXDependentScopeMemberExpr *
@@ -726,15 +864,14 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
if (!TemplateArgs)
return new (C) CXXDependentScopeMemberExpr(C, Base, BaseType,
IsArrow, OperatorLoc,
Qualifier, QualifierRange,
FirstQualifierFoundInScope,
- Member, MemberLoc);
+ MemberNameInfo);
std::size_t size = sizeof(CXXDependentScopeMemberExpr);
if (TemplateArgs)
@@ -745,7 +882,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C,
IsArrow, OperatorLoc,
Qualifier, QualifierRange,
FirstQualifierFoundInScope,
- Member, MemberLoc, TemplateArgs);
+ MemberNameInfo, TemplateArgs);
}
CXXDependentScopeMemberExpr *
@@ -755,8 +892,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(),
0, SourceLocation(), 0,
SourceRange(), 0,
- DeclarationName(),
- SourceLocation());
+ DeclarationNameInfo());
std::size_t size = sizeof(CXXDependentScopeMemberExpr) +
ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs);
@@ -765,8 +901,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C,
= new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(),
0, SourceLocation(), 0,
SourceRange(), 0,
- DeclarationName(),
- SourceLocation(), 0);
+ DeclarationNameInfo(), 0);
E->HasExplicitTemplateArgs = true;
return E;
}
@@ -789,13 +924,12 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, QualType T,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName MemberName,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End)
: OverloadExpr(UnresolvedMemberExprClass, C, T, Dependent,
- Qualifier, QualifierRange, MemberName, MemberLoc,
+ Qualifier, QualifierRange, MemberNameInfo,
TemplateArgs != 0, Begin, End),
IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
@@ -810,8 +944,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- DeclarationName Member,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
UnresolvedSetIterator End) {
@@ -824,7 +957,7 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, HasUnresolvedUsing, Base, BaseType,
IsArrow, OperatorLoc, Qualifier, QualifierRange,
- Member, MemberLoc, TemplateArgs, Begin, End);
+ MemberNameInfo, TemplateArgs, Begin, End);
}
UnresolvedMemberExpr *
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 60ac347c50fb..d7e38ebbf5c9 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -111,20 +111,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// C++ [expr.unary.op]p1: The unary * operator performs indirection:
// [...] the result is an lvalue referring to the object or function
// to which the expression points.
- case UnaryOperator::Deref:
+ case UO_Deref:
return Cl::CL_LValue;
// GNU extensions, simply look through them.
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
- case UnaryOperator::Extension:
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr());
// C++ [expr.pre.incr]p1: The result is the updated operand; it is an
// lvalue, [...]
// Not so in C.
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec:
+ case UO_PreInc:
+ case UO_PreDec:
return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue;
default:
@@ -134,10 +134,16 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// Implicit casts are lvalues if they're lvalue casts. Other than that, we
// only specifically record class temporaries.
case Expr::ImplicitCastExprClass:
- if (cast<ImplicitCastExpr>(E)->isLvalueCast())
+ switch (cast<ImplicitCastExpr>(E)->getValueKind()) {
+ case VK_RValue:
+ return Lang.CPlusPlus && E->getType()->isRecordType() ?
+ Cl::CL_ClassTemporary : Cl::CL_PRValue;
+ case VK_LValue:
return Cl::CL_LValue;
- return Lang.CPlusPlus && E->getType()->isRecordType() ?
- Cl::CL_ClassTemporary : Cl::CL_PRValue;
+ case VK_XValue:
+ return Cl::CL_XValue;
+ }
+ llvm_unreachable("Invalid value category of implicit cast.");
// C++ [expr.prim.general]p4: The presence of parentheses does not affect
// whether the expression is an lvalue.
@@ -223,6 +229,10 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
// In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
// lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
// special-case this.
+
+ if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+ return Cl::CL_MemberFunction;
+
bool islvalue;
if (const NonTypeTemplateParmDecl *NTTParm =
dyn_cast<NonTypeTemplateParmDecl>(D))
@@ -315,19 +325,19 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
// C++ [expr.comma]p1: the result is of the same value category as its right
// operand, [...].
- if (E->getOpcode() == BinaryOperator::Comma)
+ if (E->getOpcode() == BO_Comma)
return ClassifyInternal(Ctx, E->getRHS());
// C++ [expr.mptr.oper]p6: The result of a .* expression whose second operand
// is a pointer to a data member is of the same value category as its first
// operand.
- if (E->getOpcode() == BinaryOperator::PtrMemD)
+ if (E->getOpcode() == BO_PtrMemD)
return E->getType()->isFunctionType() ? Cl::CL_MemberFunction :
ClassifyInternal(Ctx, E->getLHS());
// C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
// second operand is a pointer to data member and a prvalue otherwise.
- if (E->getOpcode() == BinaryOperator::PtrMemI)
+ if (E->getOpcode() == BO_PtrMemI)
return E->getType()->isFunctionType() ?
Cl::CL_MemberFunction : Cl::CL_LValue;
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 3c9742033265..7347f5a43e17 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -337,7 +337,7 @@ public:
default:
return false;
- case CastExpr::CK_NoOp:
+ case CK_NoOp:
return Visit(E->getSubExpr());
}
}
@@ -481,8 +481,8 @@ static bool EvaluatePointer(const Expr* E, LValue& Result, EvalInfo &Info) {
}
bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() != BinaryOperator::Add &&
- E->getOpcode() != BinaryOperator::Sub)
+ if (E->getOpcode() != BO_Add &&
+ E->getOpcode() != BO_Sub)
return false;
const Expr *PExp = E->getLHS();
@@ -512,7 +512,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
else
SizeOfPointee = Info.Ctx.getTypeSizeInChars(PointeeType);
- if (E->getOpcode() == BinaryOperator::Add)
+ if (E->getOpcode() == BO_Add)
Result.Offset += AdditionalOffset * SizeOfPointee;
else
Result.Offset -= AdditionalOffset * SizeOfPointee;
@@ -532,7 +532,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
default:
break;
- case CastExpr::CK_Unknown: {
+ case CK_Unknown: {
// FIXME: The handling for CK_Unknown is ugly/shouldn't be necessary!
// Check for pointer->pointer cast
@@ -561,14 +561,14 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
break;
}
- case CastExpr::CK_NoOp:
- case CastExpr::CK_BitCast:
- case CastExpr::CK_LValueBitCast:
- case CastExpr::CK_AnyPointerToObjCPointerCast:
- case CastExpr::CK_AnyPointerToBlockPointerCast:
+ case CK_NoOp:
+ case CK_BitCast:
+ case CK_LValueBitCast:
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
return Visit(SubExpr);
- case CastExpr::CK_IntegralToPointer: {
+ case CK_IntegralToPointer: {
APValue Value;
if (!EvaluateIntegerOrLValue(SubExpr, Value, Info))
break;
@@ -585,8 +585,8 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
return true;
}
}
- case CastExpr::CK_ArrayToPointerDecay:
- case CastExpr::CK_FunctionToPointerDecay:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
return EvaluateLValue(SubExpr, Result, Info);
}
@@ -1008,8 +1008,11 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
VD->setEvaluatingValue();
- if (Visit(const_cast<Expr*>(Init))) {
+ Expr::EvalResult EResult;
+ if (Init->Evaluate(EResult, Info.Ctx) && !EResult.HasSideEffects &&
+ EResult.Val.isInt()) {
// Cache the evaluated value in the variable declaration.
+ Result = EResult.Val;
VD->setEvaluatedValue(Result);
return true;
}
@@ -1106,7 +1109,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(CallExpr *E) {
QualType T = GetObjectType(LVBase);
if (T.isNull() ||
T->isIncompleteType() ||
- !T->isObjectType() ||
+ T->isFunctionType() ||
T->isVariablyModifiedType() ||
T->isDependentType())
return false;
@@ -1161,7 +1164,7 @@ bool IntExprEvaluator::VisitCallExpr(CallExpr *E) {
}
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::Comma) {
+ if (E->getOpcode() == BO_Comma) {
if (!Visit(E->getRHS()))
return false;
@@ -1181,11 +1184,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (HandleConversionToBool(E->getLHS(), lhsResult, Info)) {
// We were able to evaluate the LHS, see if we can get away with not
// evaluating the RHS: 0 && X -> 0, 1 || X -> 1
- if (lhsResult == (E->getOpcode() == BinaryOperator::LOr))
+ if (lhsResult == (E->getOpcode() == BO_LOr))
return Success(lhsResult, E);
if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
- if (E->getOpcode() == BinaryOperator::LOr)
+ if (E->getOpcode() == BO_LOr)
return Success(lhsResult || rhsResult, E);
else
return Success(lhsResult && rhsResult, E);
@@ -1194,8 +1197,8 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
if (HandleConversionToBool(E->getRHS(), rhsResult, Info)) {
// We can't evaluate the LHS; however, sometimes the result
// is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
- if (rhsResult == (E->getOpcode() == BinaryOperator::LOr) ||
- !rhsResult == (E->getOpcode() == BinaryOperator::LAnd)) {
+ if (rhsResult == (E->getOpcode() == BO_LOr) ||
+ !rhsResult == (E->getOpcode() == BO_LAnd)) {
// Since we weren't able to evaluate the left hand side, it
// must have had side effects.
Info.EvalResult.HasSideEffects = true;
@@ -1227,11 +1230,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat::cmpResult CR_i =
LHS.getComplexFloatImag().compare(RHS.getComplexFloatImag());
- if (E->getOpcode() == BinaryOperator::EQ)
+ if (E->getOpcode() == BO_EQ)
return Success((CR_r == APFloat::cmpEqual &&
CR_i == APFloat::cmpEqual), E);
else {
- assert(E->getOpcode() == BinaryOperator::NE &&
+ assert(E->getOpcode() == BO_NE &&
"Invalid complex comparison.");
return Success(((CR_r == APFloat::cmpGreaterThan ||
CR_r == APFloat::cmpLessThan ||
@@ -1241,11 +1244,11 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
CR_i == APFloat::cmpUnordered)), E);
}
} else {
- if (E->getOpcode() == BinaryOperator::EQ)
+ if (E->getOpcode() == BO_EQ)
return Success((LHS.getComplexIntReal() == RHS.getComplexIntReal() &&
LHS.getComplexIntImag() == RHS.getComplexIntImag()), E);
else {
- assert(E->getOpcode() == BinaryOperator::NE &&
+ assert(E->getOpcode() == BO_NE &&
"Invalid compex comparison.");
return Success((LHS.getComplexIntReal() != RHS.getComplexIntReal() ||
LHS.getComplexIntImag() != RHS.getComplexIntImag()), E);
@@ -1268,18 +1271,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
assert(0 && "Invalid binary operator!");
- case BinaryOperator::LT:
+ case BO_LT:
return Success(CR == APFloat::cmpLessThan, E);
- case BinaryOperator::GT:
+ case BO_GT:
return Success(CR == APFloat::cmpGreaterThan, E);
- case BinaryOperator::LE:
+ case BO_LE:
return Success(CR == APFloat::cmpLessThan || CR == APFloat::cmpEqual, E);
- case BinaryOperator::GE:
+ case BO_GE:
return Success(CR == APFloat::cmpGreaterThan || CR == APFloat::cmpEqual,
E);
- case BinaryOperator::EQ:
+ case BO_EQ:
return Success(CR == APFloat::cmpEqual, E);
- case BinaryOperator::NE:
+ case BO_NE:
return Success(CR == APFloat::cmpGreaterThan
|| CR == APFloat::cmpLessThan
|| CR == APFloat::cmpUnordered, E);
@@ -1287,7 +1290,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
if (LHSTy->isPointerType() && RHSTy->isPointerType()) {
- if (E->getOpcode() == BinaryOperator::Sub || E->isEqualityOp()) {
+ if (E->getOpcode() == BO_Sub || E->isEqualityOp()) {
LValue LHSValue;
if (!EvaluatePointer(E->getLHS(), LHSValue, Info))
return false;
@@ -1306,7 +1309,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
bool bres;
if (!EvalPointerValueAsBool(LHSValue, bres))
return false;
- return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
+ return Success(bres ^ (E->getOpcode() == BO_EQ), E);
} else if (RHSValue.getLValueBase()) {
if (!E->isEqualityOp())
return false;
@@ -1315,10 +1318,10 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
bool bres;
if (!EvalPointerValueAsBool(RHSValue, bres))
return false;
- return Success(bres ^ (E->getOpcode() == BinaryOperator::EQ), E);
+ return Success(bres ^ (E->getOpcode() == BO_EQ), E);
}
- if (E->getOpcode() == BinaryOperator::Sub) {
+ if (E->getOpcode() == BO_Sub) {
QualType Type = E->getLHS()->getType();
QualType ElementType = Type->getAs<PointerType>()->getPointeeType();
@@ -1331,7 +1334,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
return Success(Diff / ElementSize, E);
}
bool Result;
- if (E->getOpcode() == BinaryOperator::EQ) {
+ if (E->getOpcode() == BO_EQ) {
Result = LHSValue.getLValueOffset() == RHSValue.getLValueOffset();
} else {
Result = LHSValue.getLValueOffset() != RHSValue.getLValueOffset();
@@ -1359,7 +1362,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
CharUnits Offset = Result.getLValueOffset();
CharUnits AdditionalOffset = CharUnits::fromQuantity(
RHSVal.getInt().getZExtValue());
- if (E->getOpcode() == BinaryOperator::Add)
+ if (E->getOpcode() == BO_Add)
Offset += AdditionalOffset;
else
Offset -= AdditionalOffset;
@@ -1368,7 +1371,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
// Handle cases like 4 + (unsigned long)&a
- if (E->getOpcode() == BinaryOperator::Add &&
+ if (E->getOpcode() == BO_Add &&
RHSVal.isLValue() && Result.isInt()) {
CharUnits Offset = RHSVal.getLValueOffset();
Offset += CharUnits::fromQuantity(Result.getInt().getZExtValue());
@@ -1385,38 +1388,38 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
- case BinaryOperator::Mul: return Success(Result.getInt() * RHS, E);
- case BinaryOperator::Add: return Success(Result.getInt() + RHS, E);
- case BinaryOperator::Sub: return Success(Result.getInt() - RHS, E);
- case BinaryOperator::And: return Success(Result.getInt() & RHS, E);
- case BinaryOperator::Xor: return Success(Result.getInt() ^ RHS, E);
- case BinaryOperator::Or: return Success(Result.getInt() | RHS, E);
- case BinaryOperator::Div:
+ case BO_Mul: return Success(Result.getInt() * RHS, E);
+ case BO_Add: return Success(Result.getInt() + RHS, E);
+ case BO_Sub: return Success(Result.getInt() - RHS, E);
+ case BO_And: return Success(Result.getInt() & RHS, E);
+ case BO_Xor: return Success(Result.getInt() ^ RHS, E);
+ case BO_Or: return Success(Result.getInt() | RHS, E);
+ case BO_Div:
if (RHS == 0)
return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
return Success(Result.getInt() / RHS, E);
- case BinaryOperator::Rem:
+ case BO_Rem:
if (RHS == 0)
return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E);
return Success(Result.getInt() % RHS, E);
- case BinaryOperator::Shl: {
+ case BO_Shl: {
// FIXME: Warn about out of range shift amounts!
unsigned SA =
(unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
return Success(Result.getInt() << SA, E);
}
- case BinaryOperator::Shr: {
+ case BO_Shr: {
unsigned SA =
(unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1);
return Success(Result.getInt() >> SA, E);
}
- case BinaryOperator::LT: return Success(Result.getInt() < RHS, E);
- case BinaryOperator::GT: return Success(Result.getInt() > RHS, E);
- case BinaryOperator::LE: return Success(Result.getInt() <= RHS, E);
- case BinaryOperator::GE: return Success(Result.getInt() >= RHS, E);
- case BinaryOperator::EQ: return Success(Result.getInt() == RHS, E);
- case BinaryOperator::NE: return Success(Result.getInt() != RHS, E);
+ case BO_LT: return Success(Result.getInt() < RHS, E);
+ case BO_GT: return Success(Result.getInt() > RHS, E);
+ case BO_LE: return Success(Result.getInt() <= RHS, E);
+ case BO_GE: return Success(Result.getInt() >= RHS, E);
+ case BO_EQ: return Success(Result.getInt() == RHS, E);
+ case BO_NE: return Success(Result.getInt() != RHS, E);
}
}
@@ -1573,20 +1576,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) {
}
bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
- // Special case unary operators that do not need their subexpression
- // evaluated. offsetof/sizeof/alignof are all special.
- if (E->isOffsetOfOp()) {
- // The AST for offsetof is defined in such a way that we can just
- // directly Evaluate it as an l-value.
- LValue LV;
- if (!EvaluateLValue(E->getSubExpr(), LV, Info))
- return false;
- if (LV.getLValueBase())
- return false;
- return Success(LV.getLValueOffset().getQuantity(), E);
- }
-
- if (E->getOpcode() == UnaryOperator::LNot) {
+ if (E->getOpcode() == UO_LNot) {
// LNot's operand isn't necessarily an integer, so we handle it specially.
bool bres;
if (!HandleConversionToBool(E->getSubExpr(), bres, Info))
@@ -1607,17 +1597,17 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
// Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
// See C99 6.6p3.
return Error(E->getOperatorLoc(), diag::note_invalid_subexpr_in_ice, E);
- case UnaryOperator::Extension:
+ case UO_Extension:
// FIXME: Should extension allow i-c-e extension expressions in its scope?
// If so, we could clear the diagnostic ID.
return true;
- case UnaryOperator::Plus:
+ case UO_Plus:
// The result is always just the subexpr.
return true;
- case UnaryOperator::Minus:
+ case UO_Minus:
if (!Result.isInt()) return false;
return Success(-Result.getInt(), E);
- case UnaryOperator::Not:
+ case UO_Not:
if (!Result.isInt()) return false;
return Success(~Result.getInt(), E);
}
@@ -1855,23 +1845,35 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) {
- ComplexValue CV;
- if (!EvaluateComplex(E->getSubExpr(), CV, Info))
- return false;
- Result = CV.FloatReal;
- return true;
+ if (E->getSubExpr()->getType()->isAnyComplexType()) {
+ ComplexValue CV;
+ if (!EvaluateComplex(E->getSubExpr(), CV, Info))
+ return false;
+ Result = CV.FloatReal;
+ return true;
+ }
+
+ return Visit(E->getSubExpr());
}
bool FloatExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
- ComplexValue CV;
- if (!EvaluateComplex(E->getSubExpr(), CV, Info))
- return false;
- Result = CV.FloatImag;
+ if (E->getSubExpr()->getType()->isAnyComplexType()) {
+ ComplexValue CV;
+ if (!EvaluateComplex(E->getSubExpr(), CV, Info))
+ return false;
+ Result = CV.FloatImag;
+ return true;
+ }
+
+ if (!E->getSubExpr()->isEvaluatable(Info.Ctx))
+ Info.EvalResult.HasSideEffects = true;
+ const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType());
+ Result = llvm::APFloat::getZero(Sem);
return true;
}
bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
- if (E->getOpcode() == UnaryOperator::Deref)
+ if (E->getOpcode() == UO_Deref)
return false;
if (!EvaluateFloat(E->getSubExpr(), Result, Info))
@@ -1879,16 +1881,16 @@ bool FloatExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
switch (E->getOpcode()) {
default: return false;
- case UnaryOperator::Plus:
+ case UO_Plus:
return true;
- case UnaryOperator::Minus:
+ case UO_Minus:
Result.changeSign();
return true;
}
}
bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::Comma) {
+ if (E->getOpcode() == BO_Comma) {
if (!EvaluateFloat(E->getRHS(), Result, Info))
return false;
@@ -1910,16 +1912,16 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default: return false;
- case BinaryOperator::Mul:
+ case BO_Mul:
Result.multiply(RHS, APFloat::rmNearestTiesToEven);
return true;
- case BinaryOperator::Add:
+ case BO_Add:
Result.add(RHS, APFloat::rmNearestTiesToEven);
return true;
- case BinaryOperator::Sub:
+ case BO_Sub:
Result.subtract(RHS, APFloat::rmNearestTiesToEven);
return true;
- case BinaryOperator::Div:
+ case BO_Div:
Result.divide(RHS, APFloat::rmNearestTiesToEven);
return true;
}
@@ -1990,138 +1992,142 @@ public:
bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
- bool VisitImaginaryLiteral(ImaginaryLiteral *E) {
- Expr* SubExpr = E->getSubExpr();
+ bool VisitImaginaryLiteral(ImaginaryLiteral *E);
- if (SubExpr->getType()->isRealFloatingType()) {
- Result.makeComplexFloat();
- APFloat &Imag = Result.FloatImag;
- if (!EvaluateFloat(SubExpr, Imag, Info))
- return false;
+ bool VisitCastExpr(CastExpr *E);
+
+ bool VisitBinaryOperator(const BinaryOperator *E);
+ bool VisitChooseExpr(const ChooseExpr *E)
+ { return Visit(E->getChosenSubExpr(Info.Ctx)); }
+ bool VisitUnaryExtension(const UnaryOperator *E)
+ { return Visit(E->getSubExpr()); }
+ // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr,
+ // conditional ?:, comma
+};
+} // end anonymous namespace
+
+static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
+ EvalInfo &Info) {
+ assert(E->getType()->isAnyComplexType());
+ return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+}
+
+bool ComplexExprEvaluator::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+ Expr* SubExpr = E->getSubExpr();
+
+ if (SubExpr->getType()->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ APFloat &Imag = Result.FloatImag;
+ if (!EvaluateFloat(SubExpr, Imag, Info))
+ return false;
- Result.FloatReal = APFloat(Imag.getSemantics());
+ Result.FloatReal = APFloat(Imag.getSemantics());
+ return true;
+ } else {
+ assert(SubExpr->getType()->isIntegerType() &&
+ "Unexpected imaginary literal.");
+
+ Result.makeComplexInt();
+ APSInt &Imag = Result.IntImag;
+ if (!EvaluateInteger(SubExpr, Imag, Info))
+ return false;
+
+ Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned());
+ return true;
+ }
+}
+
+bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) {
+ Expr* SubExpr = E->getSubExpr();
+ QualType EltType = E->getType()->getAs<ComplexType>()->getElementType();
+ QualType SubType = SubExpr->getType();
+
+ if (SubType->isRealFloatingType()) {
+ APFloat &Real = Result.FloatReal;
+ if (!EvaluateFloat(SubExpr, Real, Info))
+ return false;
+
+ if (EltType->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ Real = HandleFloatToFloatCast(EltType, SubType, Real, Info.Ctx);
+ Result.FloatImag = APFloat(Real.getSemantics());
return true;
} else {
- assert(SubExpr->getType()->isIntegerType() &&
- "Unexpected imaginary literal.");
-
Result.makeComplexInt();
- APSInt &Imag = Result.IntImag;
- if (!EvaluateInteger(SubExpr, Imag, Info))
- return false;
-
- Result.IntReal = APSInt(Imag.getBitWidth(), !Imag.isSigned());
+ Result.IntReal = HandleFloatToIntCast(EltType, SubType, Real, Info.Ctx);
+ Result.IntImag = APSInt(Result.IntReal.getBitWidth(),
+ !Result.IntReal.isSigned());
return true;
}
- }
+ } else if (SubType->isIntegerType()) {
+ APSInt &Real = Result.IntReal;
+ if (!EvaluateInteger(SubExpr, Real, Info))
+ return false;
- bool VisitCastExpr(CastExpr *E) {
- Expr* SubExpr = E->getSubExpr();
- QualType EltType = E->getType()->getAs<ComplexType>()->getElementType();
- QualType SubType = SubExpr->getType();
+ if (EltType->isRealFloatingType()) {
+ Result.makeComplexFloat();
+ Result.FloatReal
+ = HandleIntToFloatCast(EltType, SubType, Real, Info.Ctx);
+ Result.FloatImag = APFloat(Result.FloatReal.getSemantics());
+ return true;
+ } else {
+ Result.makeComplexInt();
+ Real = HandleIntToIntCast(EltType, SubType, Real, Info.Ctx);
+ Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned());
+ return true;
+ }
+ } else if (const ComplexType *CT = SubType->getAs<ComplexType>()) {
+ if (!Visit(SubExpr))
+ return false;
- if (SubType->isRealFloatingType()) {
- APFloat &Real = Result.FloatReal;
- if (!EvaluateFloat(SubExpr, Real, Info))
- return false;
+ QualType SrcType = CT->getElementType();
+ if (Result.isComplexFloat()) {
if (EltType->isRealFloatingType()) {
Result.makeComplexFloat();
- Real = HandleFloatToFloatCast(EltType, SubType, Real, Info.Ctx);
- Result.FloatImag = APFloat(Real.getSemantics());
+ Result.FloatReal = HandleFloatToFloatCast(EltType, SrcType,
+ Result.FloatReal,
+ Info.Ctx);
+ Result.FloatImag = HandleFloatToFloatCast(EltType, SrcType,
+ Result.FloatImag,
+ Info.Ctx);
return true;
} else {
Result.makeComplexInt();
- Result.IntReal = HandleFloatToIntCast(EltType, SubType, Real, Info.Ctx);
- Result.IntImag = APSInt(Result.IntReal.getBitWidth(),
- !Result.IntReal.isSigned());
+ Result.IntReal = HandleFloatToIntCast(EltType, SrcType,
+ Result.FloatReal,
+ Info.Ctx);
+ Result.IntImag = HandleFloatToIntCast(EltType, SrcType,
+ Result.FloatImag,
+ Info.Ctx);
return true;
}
- } else if (SubType->isIntegerType()) {
- APSInt &Real = Result.IntReal;
- if (!EvaluateInteger(SubExpr, Real, Info))
- return false;
-
+ } else {
+ assert(Result.isComplexInt() && "Invalid evaluate result.");
if (EltType->isRealFloatingType()) {
Result.makeComplexFloat();
- Result.FloatReal
- = HandleIntToFloatCast(EltType, SubType, Real, Info.Ctx);
- Result.FloatImag = APFloat(Result.FloatReal.getSemantics());
+ Result.FloatReal = HandleIntToFloatCast(EltType, SrcType,
+ Result.IntReal,
+ Info.Ctx);
+ Result.FloatImag = HandleIntToFloatCast(EltType, SrcType,
+ Result.IntImag,
+ Info.Ctx);
return true;
} else {
Result.makeComplexInt();
- Real = HandleIntToIntCast(EltType, SubType, Real, Info.Ctx);
- Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned());
+ Result.IntReal = HandleIntToIntCast(EltType, SrcType,
+ Result.IntReal,
+ Info.Ctx);
+ Result.IntImag = HandleIntToIntCast(EltType, SrcType,
+ Result.IntImag,
+ Info.Ctx);
return true;
}
- } else if (const ComplexType *CT = SubType->getAs<ComplexType>()) {
- if (!Visit(SubExpr))
- return false;
-
- QualType SrcType = CT->getElementType();
-
- if (Result.isComplexFloat()) {
- if (EltType->isRealFloatingType()) {
- Result.makeComplexFloat();
- Result.FloatReal = HandleFloatToFloatCast(EltType, SrcType,
- Result.FloatReal,
- Info.Ctx);
- Result.FloatImag = HandleFloatToFloatCast(EltType, SrcType,
- Result.FloatImag,
- Info.Ctx);
- return true;
- } else {
- Result.makeComplexInt();
- Result.IntReal = HandleFloatToIntCast(EltType, SrcType,
- Result.FloatReal,
- Info.Ctx);
- Result.IntImag = HandleFloatToIntCast(EltType, SrcType,
- Result.FloatImag,
- Info.Ctx);
- return true;
- }
- } else {
- assert(Result.isComplexInt() && "Invalid evaluate result.");
- if (EltType->isRealFloatingType()) {
- Result.makeComplexFloat();
- Result.FloatReal = HandleIntToFloatCast(EltType, SrcType,
- Result.IntReal,
- Info.Ctx);
- Result.FloatImag = HandleIntToFloatCast(EltType, SrcType,
- Result.IntImag,
- Info.Ctx);
- return true;
- } else {
- Result.makeComplexInt();
- Result.IntReal = HandleIntToIntCast(EltType, SrcType,
- Result.IntReal,
- Info.Ctx);
- Result.IntImag = HandleIntToIntCast(EltType, SrcType,
- Result.IntImag,
- Info.Ctx);
- return true;
- }
- }
}
-
- // FIXME: Handle more casts.
- return false;
}
- bool VisitBinaryOperator(const BinaryOperator *E);
- bool VisitChooseExpr(const ChooseExpr *E)
- { return Visit(E->getChosenSubExpr(Info.Ctx)); }
- bool VisitUnaryExtension(const UnaryOperator *E)
- { return Visit(E->getSubExpr()); }
- // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr,
- // conditional ?:, comma
-};
-} // end anonymous namespace
-
-static bool EvaluateComplex(const Expr *E, ComplexValue &Result,
- EvalInfo &Info) {
- assert(E->getType()->isAnyComplexType());
- return ComplexExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
+ // FIXME: Handle more casts.
+ return false;
}
bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
@@ -2136,7 +2142,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
"Invalid operands to binary operator.");
switch (E->getOpcode()) {
default: return false;
- case BinaryOperator::Add:
+ case BO_Add:
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().add(RHS.getComplexFloatReal(),
APFloat::rmNearestTiesToEven);
@@ -2147,7 +2153,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Result.getComplexIntImag() += RHS.getComplexIntImag();
}
break;
- case BinaryOperator::Sub:
+ case BO_Sub:
if (Result.isComplexFloat()) {
Result.getComplexFloatReal().subtract(RHS.getComplexFloatReal(),
APFloat::rmNearestTiesToEven);
@@ -2158,7 +2164,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Result.getComplexIntImag() -= RHS.getComplexIntImag();
}
break;
- case BinaryOperator::Mul:
+ case BO_Mul:
if (Result.isComplexFloat()) {
ComplexValue LHS = Result;
APFloat &LHS_r = LHS.getComplexFloatReal();
@@ -2321,6 +2327,8 @@ APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const {
// the comma operator in C99 mode.
// 2: This expression is not an ICE, and is not a legal subexpression for one.
+namespace {
+
struct ICEDiag {
unsigned Val;
SourceLocation Loc;
@@ -2330,7 +2338,9 @@ struct ICEDiag {
ICEDiag() : Val(0) {}
};
-ICEDiag NoDiag() { return ICEDiag(); }
+}
+
+static ICEDiag NoDiag() { return ICEDiag(); }
static ICEDiag CheckEvalInICE(const Expr* E, ASTContext &Ctx) {
Expr::EvalResult EVResult;
@@ -2380,7 +2390,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
case Expr::CXXBindTemporaryExprClass:
- case Expr::CXXBindReferenceExprClass:
case Expr::CXXExprWithTemporariesClass:
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXUnresolvedConstructExprClass:
@@ -2476,23 +2485,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(E);
switch (Exp->getOpcode()) {
- case UnaryOperator::PostInc:
- case UnaryOperator::PostDec:
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec:
- case UnaryOperator::AddrOf:
- case UnaryOperator::Deref:
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
+ case UO_AddrOf:
+ case UO_Deref:
return ICEDiag(2, E->getLocStart());
- case UnaryOperator::Extension:
- case UnaryOperator::LNot:
- case UnaryOperator::Plus:
- case UnaryOperator::Minus:
- case UnaryOperator::Not:
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
+ case UO_Extension:
+ case UO_LNot:
+ case UO_Plus:
+ case UO_Minus:
+ case UO_Not:
+ case UO_Real:
+ case UO_Imag:
return CheckICE(Exp->getSubExpr(), Ctx);
- case UnaryOperator::OffsetOf:
- break;
}
// OffsetOf falls through here.
@@ -2515,42 +2522,42 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::BinaryOperatorClass: {
const BinaryOperator *Exp = cast<BinaryOperator>(E);
switch (Exp->getOpcode()) {
- case BinaryOperator::PtrMemD:
- case BinaryOperator::PtrMemI:
- case BinaryOperator::Assign:
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::RemAssign:
- case BinaryOperator::AddAssign:
- case BinaryOperator::SubAssign:
- case BinaryOperator::ShlAssign:
- case BinaryOperator::ShrAssign:
- case BinaryOperator::AndAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::OrAssign:
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Assign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
return ICEDiag(2, E->getLocStart());
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
- case BinaryOperator::Rem:
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
- case BinaryOperator::And:
- case BinaryOperator::Xor:
- case BinaryOperator::Or:
- case BinaryOperator::Comma: {
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_Comma: {
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
- if (Exp->getOpcode() == BinaryOperator::Div ||
- Exp->getOpcode() == BinaryOperator::Rem) {
+ if (Exp->getOpcode() == BO_Div ||
+ Exp->getOpcode() == BO_Rem) {
// Evaluate gives an error for undefined Div/Rem, so make sure
// we don't evaluate one.
if (LHSResult.Val != 2 && RHSResult.Val != 2) {
@@ -2564,7 +2571,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
}
}
- if (Exp->getOpcode() == BinaryOperator::Comma) {
+ if (Exp->getOpcode() == BO_Comma) {
if (Ctx.getLangOptions().C99) {
// C99 6.6p3 introduces a strange edge case: comma can be in an ICE
// if it isn't evaluated.
@@ -2579,15 +2586,15 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
return LHSResult;
return RHSResult;
}
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr: {
+ case BO_LAnd:
+ case BO_LOr: {
ICEDiag LHSResult = CheckICE(Exp->getLHS(), Ctx);
ICEDiag RHSResult = CheckICE(Exp->getRHS(), Ctx);
if (LHSResult.Val == 0 && RHSResult.Val == 1) {
// Rare case where the RHS has a comma "side-effect"; we need
// to actually check the condition to see whether the side
// with the comma is evaluated.
- if ((Exp->getOpcode() == BinaryOperator::LAnd) !=
+ if ((Exp->getOpcode() == BO_LAnd) !=
(Exp->getLHS()->EvaluateAsInt(Ctx) == 0))
return RHSResult;
return NoDiag();
diff --git a/lib/AST/FullExpr.cpp b/lib/AST/FullExpr.cpp
index f47284f3d060..93ee8d136000 100644
--- a/lib/AST/FullExpr.cpp
+++ b/lib/AST/FullExpr.cpp
@@ -43,16 +43,3 @@ FullExpr FullExpr::Create(ASTContext &Context, Expr *SubExpr,
return E;
}
-void FullExpr::Destroy(ASTContext &Context) {
- if (Expr *E = SubExpr.dyn_cast<Expr *>()) {
- E->Destroy(Context);
- return;
- }
-
- ExprAndTemporaries *ET = SubExpr.get<ExprAndTemporaries *>();
- for (ExprAndTemporaries::temps_iterator i = ET->temps_begin(),
- e = ET->temps_end(); i != e; ++i)
- (*i)->Destroy(Context);
-
- Context.Deallocate(ET);
-}
diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp
new file mode 100644
index 000000000000..c3fa4666537b
--- /dev/null
+++ b/lib/AST/ItaniumCXXABI.cpp
@@ -0,0 +1,52 @@
+//===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ AST support targetting the Itanium C++ ABI, which is
+// documented at:
+// http://www.codesourcery.com/public/cxx-abi/abi.html
+// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+//
+// It also supports the closely-related ARM C++ ABI, documented at:
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXXABI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+
+using namespace clang;
+
+namespace {
+class ItaniumCXXABI : public CXXABI {
+protected:
+ ASTContext &Context;
+public:
+ ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
+
+ unsigned getMemberPointerSize(const MemberPointerType *MPT) const {
+ QualType Pointee = MPT->getPointeeType();
+ if (Pointee->isFunctionType()) return 2;
+ return 1;
+ }
+};
+
+class ARMCXXABI : public ItaniumCXXABI {
+public:
+ ARMCXXABI(ASTContext &Ctx) : ItaniumCXXABI(Ctx) { }
+};
+}
+
+CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
+ return new ItaniumCXXABI(Ctx);
+}
+
+CXXABI *clang::CreateARMCXXABI(ASTContext &Ctx) {
+ return new ARMCXXABI(Ctx);
+}
diff --git a/lib/AST/Makefile b/lib/AST/Makefile
index 7a1672b81728..65383c5552d4 100644
--- a/lib/AST/Makefile
+++ b/lib/AST/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangAST
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp
new file mode 100644
index 000000000000..87b77673925f
--- /dev/null
+++ b/lib/AST/MicrosoftCXXABI.cpp
@@ -0,0 +1,48 @@
+//===------- MicrosoftCXXABI.cpp - AST support for the Microsoft C++ ABI --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ AST support targetting the Microsoft Visual C++
+// ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXXABI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/DeclCXX.h"
+
+using namespace clang;
+
+namespace {
+class MicrosoftCXXABI : public CXXABI {
+ ASTContext &Context;
+public:
+ MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
+
+ unsigned getMemberPointerSize(const MemberPointerType *MPT) const;
+};
+}
+
+unsigned MicrosoftCXXABI::getMemberPointerSize(const MemberPointerType *MPT) const {
+ QualType Pointee = MPT->getPointeeType();
+ CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl();
+ if (RD->getNumVBases() > 0) {
+ if (Pointee->isFunctionType())
+ return 3;
+ else
+ return 2;
+ } else if (RD->getNumBases() > 1 && Pointee->isFunctionType())
+ return 2;
+ return 1;
+}
+
+CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) {
+ return new MicrosoftCXXABI(Ctx);
+}
+
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index d6594cdfd02f..212def8565ea 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -176,11 +176,6 @@ NestedNameSpecifier::print(llvm::raw_ostream &OS,
OS << "::";
}
-void NestedNameSpecifier::Destroy(ASTContext &Context) {
- this->~NestedNameSpecifier();
- Context.Deallocate((void *)this);
-}
-
void NestedNameSpecifier::dump(const LangOptions &LO) {
print(llvm::errs(), PrintingPolicy(LO));
}
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index 48251d52fd2a..5fe873acf7ac 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -73,7 +73,7 @@ bool ParentMap::isConsumedExpr(Expr* E) const {
BinaryOperator *BE = cast<BinaryOperator>(P);
// If it is a comma, only the right side is consumed.
// If it isn't a comma, both sides are consumed.
- return BE->getOpcode()!=BinaryOperator::Comma ||DirectChild==BE->getRHS();
+ return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
}
case Stmt::ForStmtClass:
return DirectChild == cast<ForStmt>(P)->getCond();
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index 262c4597f846..4d9c51633626 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -19,8 +19,10 @@ using namespace clang;
void ASTRecordLayout::Destroy(ASTContext &Ctx) {
if (FieldOffsets)
Ctx.Deallocate(FieldOffsets);
- if (CXXInfo)
+ if (CXXInfo) {
Ctx.Deallocate(CXXInfo);
+ CXXInfo->~CXXRecordLayoutInfo();
+ }
this->~ASTRecordLayout();
Ctx.Deallocate(this);
}
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 88d71ce04287..13fae299d877 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -73,22 +73,11 @@ class EmptySubobjectMap {
/// member subobject that is empty.
void ComputeEmptySubobjectSizes();
- bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
- uint64_t Offset) const;
-
void AddSubobjectAtOffset(const CXXRecordDecl *RD, uint64_t Offset);
- bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
- uint64_t Offset);
void UpdateEmptyBaseSubobjects(const BaseSubobjectInfo *Info,
uint64_t Offset, bool PlacingEmptyBase);
- bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
- const CXXRecordDecl *Class,
- uint64_t Offset) const;
- bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
- uint64_t Offset) const;
-
void UpdateEmptyFieldSubobjects(const CXXRecordDecl *RD,
const CXXRecordDecl *Class,
uint64_t Offset);
@@ -100,6 +89,19 @@ class EmptySubobjectMap {
return Offset <= MaxEmptyClassOffset;
}
+protected:
+ bool CanPlaceSubobjectAtOffset(const CXXRecordDecl *RD,
+ uint64_t Offset) const;
+
+ bool CanPlaceBaseSubobjectAtOffset(const BaseSubobjectInfo *Info,
+ uint64_t Offset);
+
+ bool CanPlaceFieldSubobjectAtOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *Class,
+ uint64_t Offset) const;
+ bool CanPlaceFieldSubobjectAtOffset(const FieldDecl *FD,
+ uint64_t Offset) const;
+
public:
/// This holds the size of the largest empty subobject (either a base
/// or a member). Will be zero if the record being built doesn't contain
@@ -513,6 +515,7 @@ void EmptySubobjectMap::UpdateEmptyFieldSubobjects(const FieldDecl *FD,
}
class RecordLayoutBuilder {
+protected:
// FIXME: Remove this and make the appropriate fields public.
friend class clang::ASTContext;
@@ -623,12 +626,14 @@ class RecordLayoutBuilder {
void SelectPrimaryVBase(const CXXRecordDecl *RD);
+ virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+
/// IdentifyPrimaryBases - Identify all virtual base classes, direct or
/// indirect, that are primary base classes for some other direct or indirect
/// base class.
void IdentifyPrimaryBases(const CXXRecordDecl *RD);
- bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
+ virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
/// LayoutNonVirtualBases - Determines the primary base class (if any) and
/// lays it out. Will then proceed to lay out all non-virtual base clasess.
@@ -638,7 +643,7 @@ class RecordLayoutBuilder {
void LayoutNonVirtualBase(const BaseSubobjectInfo *Base);
void AddPrimaryVirtualBaseOffsets(const BaseSubobjectInfo *Info,
- uint64_t Offset);
+ uint64_t Offset);
/// LayoutVirtualBases - Lays out all the virtual bases.
void LayoutVirtualBases(const CXXRecordDecl *RD,
@@ -664,6 +669,8 @@ class RecordLayoutBuilder {
void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT
public:
static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD);
+
+ virtual ~RecordLayoutBuilder() { }
};
} // end anonymous namespace
@@ -734,6 +741,11 @@ RecordLayoutBuilder::SelectPrimaryVBase(const CXXRecordDecl *RD) {
}
}
+uint64_t
+RecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
+ return Context.Target.getPointerWidth(0);
+}
+
/// DeterminePrimaryBase - Determine the primary base of the given class.
void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
// If the class isn't dynamic, it won't have a primary base.
@@ -794,7 +806,7 @@ void RecordLayoutBuilder::DeterminePrimaryBase(const CXXRecordDecl *RD) {
assert(DataSize == 0 && "Vtable pointer must be at offset zero!");
// Update the size.
- Size += Context.Target.getPointerWidth(0);
+ Size += GetVirtualPointersSize(RD);
DataSize = Size;
// Update the alignment.
@@ -1123,8 +1135,8 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) {
if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
MaxFieldAlignment = MFAA->getAlignment();
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- UpdateAlignment(AA->getMaxAlignment());
+ if (unsigned MaxAlign = D->getMaxAlignment())
+ UpdateAlignment(MaxAlign);
}
}
@@ -1287,8 +1299,7 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
if (FieldPacked || !Context.Target.useBitFieldTypeAlignment())
FieldAlign = 1;
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+ FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
@@ -1357,8 +1368,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) {
if (FieldPacked)
FieldAlign = 8;
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
- FieldAlign = std::max(FieldAlign, AA->getMaxAlignment());
+ FieldAlign = std::max(FieldAlign, D->getMaxAlignment());
// The maximum field alignment overrides the aligned attribute.
if (MaxFieldAlignment)
@@ -1453,6 +1463,37 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
return 0;
}
+// This class implements layout specific to the Microsoft ABI.
+class MSRecordLayoutBuilder: public RecordLayoutBuilder {
+public:
+ MSRecordLayoutBuilder(ASTContext& Ctx, EmptySubobjectMap *EmptySubobjects):
+ RecordLayoutBuilder(Ctx, EmptySubobjects) {}
+
+ virtual bool IsNearlyEmpty(const CXXRecordDecl *RD) const;
+ virtual uint64_t GetVirtualPointersSize(const CXXRecordDecl *RD) const;
+};
+
+bool MSRecordLayoutBuilder::IsNearlyEmpty(const CXXRecordDecl *RD) const {
+ // FIXME: Audit the corners
+ if (!RD->isDynamicClass())
+ return false;
+ const ASTRecordLayout &BaseInfo = Context.getASTRecordLayout(RD);
+ // In the Microsoft ABI, classes can have one or two vtable pointers.
+ if (BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0) ||
+ BaseInfo.getNonVirtualSize() == Context.Target.getPointerWidth(0) * 2)
+ return true;
+ return false;
+}
+
+uint64_t
+MSRecordLayoutBuilder::GetVirtualPointersSize(const CXXRecordDecl *RD) const {
+ // We should reserve space for two pointers if the class has both
+ // virtual functions and virtual bases.
+ if (RD->isPolymorphic() && RD->getNumVBases() > 0)
+ return 2 * Context.Target.getPointerWidth(0);
+ return Context.Target.getPointerWidth(0);
+}
+
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
@@ -1471,8 +1512,16 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
EmptySubobjectMap EmptySubobjects(*this, RD);
- RecordLayoutBuilder Builder(*this, &EmptySubobjects);
- Builder.Layout(RD);
+ // When compiling for Microsoft, use the special MS builder.
+ llvm::OwningPtr<RecordLayoutBuilder> Builder;
+ switch (Target.getCXXABI()) {
+ default:
+ Builder.reset(new RecordLayoutBuilder(*this, &EmptySubobjects));
+ break;
+ case CXXABI_Microsoft:
+ Builder.reset(new MSRecordLayoutBuilder(*this, &EmptySubobjects));
+ }
+ Builder->Layout(RD);
// FIXME: This is not always correct. See the part about bitfields at
// http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
@@ -1481,20 +1530,20 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) {
// FIXME: This should be done in FinalizeLayout.
uint64_t DataSize =
- IsPODForThePurposeOfLayout ? Builder.Size : Builder.DataSize;
+ IsPODForThePurposeOfLayout ? Builder->Size : Builder->DataSize;
uint64_t NonVirtualSize =
- IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
+ IsPODForThePurposeOfLayout ? DataSize : Builder->NonVirtualSize;
NewEntry =
- new (*this) ASTRecordLayout(*this, Builder.Size, Builder.Alignment,
- DataSize, Builder.FieldOffsets.data(),
- Builder.FieldOffsets.size(),
+ new (*this) ASTRecordLayout(*this, Builder->Size, Builder->Alignment,
+ DataSize, Builder->FieldOffsets.data(),
+ Builder->FieldOffsets.size(),
NonVirtualSize,
- Builder.NonVirtualAlignment,
+ Builder->NonVirtualAlignment,
EmptySubobjects.SizeOfLargestEmptySubobject,
- Builder.PrimaryBase,
- Builder.PrimaryBaseIsVirtual,
- Builder.Bases, Builder.VBases);
+ Builder->PrimaryBase,
+ Builder->PrimaryBaseIsVirtual,
+ Builder->Bases, Builder->VBases);
} else {
RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
Builder.Layout(D);
@@ -1630,7 +1679,7 @@ static void DumpCXXRecordLayout(llvm::raw_ostream &OS,
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel,
- Field->getNameAsCString(),
+ Field->getName().data(),
/*IncludeVirtualBases=*/true);
continue;
}
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 6dbe8f4d18c1..fc8898173f3e 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -119,7 +119,7 @@ bool Stmt::hasImplicitControlFlow() const {
case Stmt::BinaryOperatorClass: {
const BinaryOperator* B = cast<BinaryOperator>(this);
- if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
+ if (B->isLogicalOp() || B->getOpcode() == BO_Comma)
return true;
else
return false;
@@ -215,8 +215,9 @@ int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const {
/// true, otherwise return false.
unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
ASTContext &C, unsigned &DiagOffs) const {
- const char *StrStart = getAsmString()->getStrData();
- const char *StrEnd = StrStart + getAsmString()->getByteLength();
+ llvm::StringRef Str = getAsmString()->getString();
+ const char *StrStart = Str.begin();
+ const char *StrEnd = Str.end();
const char *CurPtr = StrStart;
// "Simple" inline asms have no constraints or operands, just convert the asm
@@ -451,6 +452,15 @@ CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc,
return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers);
}
+CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty,
+ unsigned numHandlers) {
+ std::size_t Size = sizeof(CXXTryStmt);
+ Size += ((numHandlers + 1) * sizeof(Stmt));
+
+ void *Mem = C.Allocate(Size, llvm::alignof<CXXTryStmt>());
+ return new (Mem) CXXTryStmt(Empty, numHandlers);
+}
+
CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
Stmt **handlers, unsigned numHandlers)
: Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) {
@@ -459,46 +469,6 @@ CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
std::copy(handlers, handlers + NumHandlers, Stmts + 1);
}
-//===----------------------------------------------------------------------===//
-// AST Destruction.
-//===----------------------------------------------------------------------===//
-
-void Stmt::DestroyChildren(ASTContext &C) {
- for (child_iterator I = child_begin(), E = child_end(); I !=E; )
- if (Stmt* Child = *I++) Child->Destroy(C);
-}
-
-static void BranchDestroy(ASTContext &C, Stmt *S, Stmt **SubExprs,
- unsigned NumExprs) {
- // We do not use child_iterator here because that will include
- // the expressions referenced by the condition variable.
- for (Stmt **I = SubExprs, **E = SubExprs + NumExprs; I != E; ++I)
- if (Stmt *Child = *I) Child->Destroy(C);
-
- S->~Stmt();
- C.Deallocate((void *) S);
-}
-
-void Stmt::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
- this->~Stmt();
- C.Deallocate((void *)this);
-}
-
-void CXXCatchStmt::DoDestroy(ASTContext& C) {
- if (ExceptionDecl)
- ExceptionDecl->Destroy(C);
- Stmt::DoDestroy(C);
-}
-
-void DeclStmt::DoDestroy(ASTContext &C) {
- // Don't use StmtIterator to iterate over the Decls, as that can recurse
- // into VLA size expressions (which are owned by the VLA). Further, Decls
- // are owned by the DeclContext, and will be destroyed with them.
- if (DG.isDeclGroup())
- DG.getDeclGroup().Destroy(C);
-}
-
IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
Stmt *then, SourceLocation EL, Stmt *elsev)
: Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL)
@@ -528,10 +498,6 @@ void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void IfStmt::DoDestroy(ASTContext &C) {
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
SourceLocation RP)
@@ -563,10 +529,6 @@ void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void ForStmt::DoDestroy(ASTContext &C) {
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond)
: Stmt(SwitchStmtClass), FirstCase(0)
{
@@ -594,20 +556,6 @@ void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void SwitchStmt::DoDestroy(ASTContext &C) {
- // Destroy the SwitchCase statements in this switch. In the normal
- // case, this loop will merely decrement the reference counts from
- // the Retain() calls in addSwitchCase();
- SwitchCase *SC = FirstCase;
- while (SC) {
- SwitchCase *Next = SC->getNextSwitchCase();
- SC->Destroy(C);
- SC = Next;
- }
-
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
SourceLocation WL)
: Stmt(WhileStmtClass)
@@ -637,22 +585,6 @@ void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
V->getSourceRange().getEnd());
}
-void WhileStmt::DoDestroy(ASTContext &C) {
- BranchDestroy(C, this, SubExprs, END_EXPR);
-}
-
-void AsmStmt::DoDestroy(ASTContext &C) {
- DestroyChildren(C);
-
- C.Deallocate(Names);
- C.Deallocate(Constraints);
- C.Deallocate(Exprs);
- C.Deallocate(Clobbers);
-
- this->~AsmStmt();
- C.Deallocate((void *)this);
-}
-
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index b388a3b18ffa..5c236a45a690 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -65,6 +65,13 @@ namespace {
OS << '\n';
DumpSubTree(*CI++);
}
+ if (const ConditionalOperator *CO =
+ dyn_cast<ConditionalOperator>(S)) {
+ if (CO->getSAVE()) {
+ OS << '\n';
+ DumpSubTree(CO->getSAVE());
+ }
+ }
}
}
OS << ')';
@@ -225,7 +232,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {
OS << "\"";
// Emit storage class for vardecls.
if (VarDecl *V = dyn_cast<VarDecl>(VD)) {
- if (V->getStorageClass() != VarDecl::None)
+ if (V->getStorageClass() != SC_None)
OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass())
<< " ";
}
@@ -308,13 +315,13 @@ void StmtDumper::VisitExpr(Expr *Node) {
}
static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) {
- if (Node->getBasePath().empty())
+ if (Node->path_empty())
return;
OS << " (";
bool First = true;
- for (CXXBaseSpecifierArray::iterator I = Node->getBasePath().begin(),
- E = Node->getBasePath().end(); I != E; ++I) {
+ for (CastExpr::path_iterator
+ I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
const CXXBaseSpecifier *Base = *I;
if (!First)
OS << " -> ";
@@ -340,8 +347,16 @@ void StmtDumper::VisitCastExpr(CastExpr *Node) {
void StmtDumper::VisitImplicitCastExpr(ImplicitCastExpr *Node) {
VisitCastExpr(Node);
- if (Node->isLvalueCast())
+ switch (Node->getValueKind()) {
+ case VK_LValue:
OS << " lvalue";
+ break;
+ case VK_XValue:
+ OS << " xvalue";
+ break;
+ case VK_RValue:
+ break;
+ }
}
void StmtDumper::VisitDeclRefExpr(DeclRefExpr *Node) {
@@ -421,8 +436,7 @@ void StmtDumper::VisitStringLiteral(StringLiteral *Str) {
if (Str->isWide())
OS << "L";
OS << '"';
- OS.write_escaped(llvm::StringRef(Str->getStrData(),
- Str->getByteLength()));
+ OS.write_escaped(Str->getString());
OS << '"';
}
@@ -511,6 +525,8 @@ void StmtDumper::VisitCXXConstructExpr(CXXConstructExpr *Node) {
DumpType(Ctor->getType());
if (Node->isElidable())
OS << " elidable";
+ if (Node->requiresZeroInitialization())
+ OS << " zeroing";
}
void StmtDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
@@ -623,9 +639,13 @@ void StmtDumper::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
/// specified node and a few nodes underneath it, but not the whole subtree.
/// This is useful in a debugger.
void Stmt::dump(SourceManager &SM) const {
- StmtDumper P(&SM, llvm::errs(), 4);
+ dump(llvm::errs(), SM);
+}
+
+void Stmt::dump(llvm::raw_ostream &OS, SourceManager &SM) const {
+ StmtDumper P(&SM, OS, 4);
P.DumpSubTree(const_cast<Stmt*>(this));
- llvm::errs() << "\n";
+ OS << "\n";
}
/// dump - This does a local dump of the specified AST fragment. It dumps the
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 7043c3551628..5236a6672622 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -77,16 +77,21 @@ namespace {
return OS;
}
- bool PrintOffsetOfDesignator(Expr *E);
- void VisitUnaryOffsetOf(UnaryOperator *Node);
-
void Visit(Stmt* S) {
if (Helper && Helper->handledStmt(S,OS))
return;
else StmtVisitor<StmtPrinter>::Visit(S);
}
+
+ void VisitStmt(Stmt *Node) ATTRIBUTE_UNUSED {
+ Indent() << "<<unknown stmt type>>\n";
+ }
+ void VisitExpr(Expr *Node) ATTRIBUTE_UNUSED {
+ OS << "<<unknown expr type>>";
+ }
+ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
- void VisitStmt(Stmt *Node);
+#define ABSTRACT_STMT(CLASS)
#define STMT(CLASS, PARENT) \
void Visit##CLASS(CLASS *Node);
#include "clang/AST/StmtNodes.inc"
@@ -97,10 +102,6 @@ namespace {
// Stmt printing methods.
//===----------------------------------------------------------------------===//
-void StmtPrinter::VisitStmt(Stmt *Node) {
- Indent() << "<<unknown stmt type>>\n";
-}
-
/// PrintRawCompoundStmt - Print a compound stmt without indenting the {, and
/// with no newline after the }.
void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) {
@@ -465,15 +466,11 @@ void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
// Expr printing methods.
//===----------------------------------------------------------------------===//
-void StmtPrinter::VisitExpr(Expr *Node) {
- OS << "<<unknown expr type>>";
-}
-
void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
- OS << Node->getDecl();
- if (Node->hasExplicitTemplateArgumentList())
+ OS << Node->getNameInfo();
+ if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
@@ -483,7 +480,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
void StmtPrinter::VisitDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *Node) {
Node->getQualifier()->print(OS, Policy);
- OS << Node->getDeclName().getAsString();
+ OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
@@ -494,7 +491,7 @@ void StmtPrinter::VisitDependentScopeDeclRefExpr(
void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) {
if (Node->getQualifier())
Node->getQualifier()->print(OS, Policy);
- OS << Node->getName().getAsString();
+ OS << Node->getNameInfo();
if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
@@ -515,7 +512,7 @@ void StmtPrinter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
PrintExpr(Node->getBase());
OS << ".";
}
- OS << Node->getProperty()->getNameAsCString();
+ OS << Node->getProperty()->getName();
}
void StmtPrinter::VisitObjCImplicitSetterGetterRefExpr(
@@ -624,8 +621,10 @@ void StmtPrinter::VisitStringLiteral(StringLiteral *Str) {
OS << '"';
// FIXME: this doesn't print wstrings right.
- for (unsigned i = 0, e = Str->getByteLength(); i != e; ++i) {
- unsigned char Char = Str->getStrData()[i];
+ llvm::StringRef StrData = Str->getString();
+ for (llvm::StringRef::iterator I = StrData.begin(), E = StrData.end();
+ I != E; ++I) {
+ unsigned char Char = *I;
switch (Char) {
default:
@@ -661,13 +660,13 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
// it might be concatenated incorrectly like '+'.
switch (Node->getOpcode()) {
default: break;
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
- case UnaryOperator::Extension:
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
OS << ' ';
break;
- case UnaryOperator::Plus:
- case UnaryOperator::Minus:
+ case UO_Plus:
+ case UO_Minus:
if (isa<UnaryOperator>(Node->getSubExpr()))
OS << ' ';
break;
@@ -679,31 +678,6 @@ void StmtPrinter::VisitUnaryOperator(UnaryOperator *Node) {
OS << UnaryOperator::getOpcodeStr(Node->getOpcode());
}
-bool StmtPrinter::PrintOffsetOfDesignator(Expr *E) {
- if (isa<UnaryOperator>(E)) {
- // Base case, print the type and comma.
- OS << E->getType().getAsString(Policy) << ", ";
- return true;
- } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
- PrintOffsetOfDesignator(ASE->getLHS());
- OS << "[";
- PrintExpr(ASE->getRHS());
- OS << "]";
- return false;
- } else {
- MemberExpr *ME = cast<MemberExpr>(E);
- bool IsFirst = PrintOffsetOfDesignator(ME->getBase());
- OS << (IsFirst ? "" : ".") << ME->getMemberDecl();
- return false;
- }
-}
-
-void StmtPrinter::VisitUnaryOffsetOf(UnaryOperator *Node) {
- OS << "__builtin_offsetof(";
- PrintOffsetOfDesignator(Node->getSubExpr());
- OS << ")";
-}
-
void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
OS << "__builtin_offsetof(";
OS << Node->getTypeSourceInfo()->getType().getAsString(Policy) << ", ";
@@ -777,9 +751,9 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) {
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
- OS << Node->getMemberDecl();
+ OS << Node->getMemberNameInfo();
- if (Node->hasExplicitTemplateArgumentList())
+ if (Node->hasExplicitTemplateArgs())
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
@@ -795,12 +769,6 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
OS << ".";
OS << Node->getAccessor().getName();
}
-void StmtPrinter::VisitCastExpr(CastExpr *) {
- assert(0 && "CastExpr is an abstract class");
-}
-void StmtPrinter::VisitExplicitCastExpr(ExplicitCastExpr *) {
- assert(0 && "ExplicitCastExpr is an abstract class");
-}
void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) {
OS << "(" << Node->getType().getAsString(Policy) << ")";
PrintExpr(Node->getSubExpr());
@@ -1069,10 +1037,6 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) {
PrintExpr(Node->getSubExpr());
}
-void StmtPrinter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *Node) {
- PrintExpr(Node->getSubExpr());
-}
-
void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
OS << Node->getType().getAsString(Policy);
OS << "(";
@@ -1201,7 +1165,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
// FIXME: Track use of "template" keyword explicitly?
OS << "template ";
- OS << Node->getMember().getAsString();
+ OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs()) {
OS << TemplateSpecializationType::PrintTemplateArgumentList(
@@ -1221,7 +1185,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
// FIXME: this might originally have been written with 'template'
- OS << Node->getMemberName().getAsString();
+ OS << Node->getMemberNameInfo();
if (Node->hasExplicitTemplateArgs()) {
OS << TemplateSpecializationType::PrintTemplateArgumentList(
@@ -1368,7 +1332,7 @@ void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,
}
if (Policy.Dump && &Context) {
- dump(Context.getSourceManager());
+ dump(OS, Context.getSourceManager());
return;
}
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index cff86a4e1cec..78a336d2bfbe 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -325,7 +325,7 @@ void StmtProfiler::VisitCastExpr(CastExpr *S) {
void StmtProfiler::VisitImplicitCastExpr(ImplicitCastExpr *S) {
VisitCastExpr(S);
- ID.AddBoolean(S->isLvalueCast());
+ ID.AddInteger(S->getValueKind());
}
void StmtProfiler::VisitExplicitCastExpr(ExplicitCastExpr *S) {
@@ -436,8 +436,8 @@ void StmtProfiler::VisitBlockDeclRefExpr(BlockDeclRefExpr *S) {
}
static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
- UnaryOperator::Opcode &UnaryOp,
- BinaryOperator::Opcode &BinaryOp) {
+ UnaryOperatorKind &UnaryOp,
+ BinaryOperatorKind &BinaryOp) {
switch (S->getOperator()) {
case OO_None:
case OO_New:
@@ -453,165 +453,165 @@ static Stmt::StmtClass DecodeOperatorCall(CXXOperatorCallExpr *S,
case OO_Plus:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::Plus;
+ UnaryOp = UO_Plus;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::Add;
+ BinaryOp = BO_Add;
return Stmt::BinaryOperatorClass;
case OO_Minus:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::Minus;
+ UnaryOp = UO_Minus;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::Sub;
+ BinaryOp = BO_Sub;
return Stmt::BinaryOperatorClass;
case OO_Star:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::Minus;
+ UnaryOp = UO_Minus;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::Sub;
+ BinaryOp = BO_Sub;
return Stmt::BinaryOperatorClass;
case OO_Slash:
- BinaryOp = BinaryOperator::Div;
+ BinaryOp = BO_Div;
return Stmt::BinaryOperatorClass;
case OO_Percent:
- BinaryOp = BinaryOperator::Rem;
+ BinaryOp = BO_Rem;
return Stmt::BinaryOperatorClass;
case OO_Caret:
- BinaryOp = BinaryOperator::Xor;
+ BinaryOp = BO_Xor;
return Stmt::BinaryOperatorClass;
case OO_Amp:
if (S->getNumArgs() == 1) {
- UnaryOp = UnaryOperator::AddrOf;
+ UnaryOp = UO_AddrOf;
return Stmt::UnaryOperatorClass;
}
- BinaryOp = BinaryOperator::And;
+ BinaryOp = BO_And;
return Stmt::BinaryOperatorClass;
case OO_Pipe:
- BinaryOp = BinaryOperator::Or;
+ BinaryOp = BO_Or;
return Stmt::BinaryOperatorClass;
case OO_Tilde:
- UnaryOp = UnaryOperator::Not;
+ UnaryOp = UO_Not;
return Stmt::UnaryOperatorClass;
case OO_Exclaim:
- UnaryOp = UnaryOperator::LNot;
+ UnaryOp = UO_LNot;
return Stmt::UnaryOperatorClass;
case OO_Equal:
- BinaryOp = BinaryOperator::Assign;
+ BinaryOp = BO_Assign;
return Stmt::BinaryOperatorClass;
case OO_Less:
- BinaryOp = BinaryOperator::LT;
+ BinaryOp = BO_LT;
return Stmt::BinaryOperatorClass;
case OO_Greater:
- BinaryOp = BinaryOperator::GT;
+ BinaryOp = BO_GT;
return Stmt::BinaryOperatorClass;
case OO_PlusEqual:
- BinaryOp = BinaryOperator::AddAssign;
+ BinaryOp = BO_AddAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_MinusEqual:
- BinaryOp = BinaryOperator::SubAssign;
+ BinaryOp = BO_SubAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_StarEqual:
- BinaryOp = BinaryOperator::MulAssign;
+ BinaryOp = BO_MulAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_SlashEqual:
- BinaryOp = BinaryOperator::DivAssign;
+ BinaryOp = BO_DivAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_PercentEqual:
- BinaryOp = BinaryOperator::RemAssign;
+ BinaryOp = BO_RemAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_CaretEqual:
- BinaryOp = BinaryOperator::XorAssign;
+ BinaryOp = BO_XorAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_AmpEqual:
- BinaryOp = BinaryOperator::AndAssign;
+ BinaryOp = BO_AndAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_PipeEqual:
- BinaryOp = BinaryOperator::OrAssign;
+ BinaryOp = BO_OrAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_LessLess:
- BinaryOp = BinaryOperator::Shl;
+ BinaryOp = BO_Shl;
return Stmt::BinaryOperatorClass;
case OO_GreaterGreater:
- BinaryOp = BinaryOperator::Shr;
+ BinaryOp = BO_Shr;
return Stmt::BinaryOperatorClass;
case OO_LessLessEqual:
- BinaryOp = BinaryOperator::ShlAssign;
+ BinaryOp = BO_ShlAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_GreaterGreaterEqual:
- BinaryOp = BinaryOperator::ShrAssign;
+ BinaryOp = BO_ShrAssign;
return Stmt::CompoundAssignOperatorClass;
case OO_EqualEqual:
- BinaryOp = BinaryOperator::EQ;
+ BinaryOp = BO_EQ;
return Stmt::BinaryOperatorClass;
case OO_ExclaimEqual:
- BinaryOp = BinaryOperator::NE;
+ BinaryOp = BO_NE;
return Stmt::BinaryOperatorClass;
case OO_LessEqual:
- BinaryOp = BinaryOperator::LE;
+ BinaryOp = BO_LE;
return Stmt::BinaryOperatorClass;
case OO_GreaterEqual:
- BinaryOp = BinaryOperator::GE;
+ BinaryOp = BO_GE;
return Stmt::BinaryOperatorClass;
case OO_AmpAmp:
- BinaryOp = BinaryOperator::LAnd;
+ BinaryOp = BO_LAnd;
return Stmt::BinaryOperatorClass;
case OO_PipePipe:
- BinaryOp = BinaryOperator::LOr;
+ BinaryOp = BO_LOr;
return Stmt::BinaryOperatorClass;
case OO_PlusPlus:
- UnaryOp = S->getNumArgs() == 1? UnaryOperator::PreInc
- : UnaryOperator::PostInc;
+ UnaryOp = S->getNumArgs() == 1? UO_PreInc
+ : UO_PostInc;
return Stmt::UnaryOperatorClass;
case OO_MinusMinus:
- UnaryOp = S->getNumArgs() == 1? UnaryOperator::PreDec
- : UnaryOperator::PostDec;
+ UnaryOp = S->getNumArgs() == 1? UO_PreDec
+ : UO_PostDec;
return Stmt::UnaryOperatorClass;
case OO_Comma:
- BinaryOp = BinaryOperator::Comma;
+ BinaryOp = BO_Comma;
return Stmt::BinaryOperatorClass;
case OO_ArrowStar:
- BinaryOp = BinaryOperator::PtrMemI;
+ BinaryOp = BO_PtrMemI;
return Stmt::BinaryOperatorClass;
case OO_Subscript:
@@ -626,8 +626,8 @@ void StmtProfiler::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *S) {
if (S->isTypeDependent()) {
// Type-dependent operator calls are profiled like their underlying
// syntactic operator.
- UnaryOperator::Opcode UnaryOp = UnaryOperator::Extension;
- BinaryOperator::Opcode BinaryOp = BinaryOperator::Comma;
+ UnaryOperatorKind UnaryOp = UO_Extension;
+ BinaryOperatorKind BinaryOp = BO_Comma;
Stmt::StmtClass SC = DecodeOperatorCall(S, UnaryOp, BinaryOp);
ID.AddInteger(SC);
@@ -706,10 +706,6 @@ void StmtProfiler::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *S) {
const_cast<CXXDestructorDecl *>(S->getTemporary()->getDestructor()));
}
-void StmtProfiler::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *S) {
- VisitExpr(S);
-}
-
void StmtProfiler::VisitCXXConstructExpr(CXXConstructExpr *S) {
VisitExpr(S);
VisitDecl(S->getConstructor());
@@ -757,14 +753,19 @@ void StmtProfiler::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *S) {
VisitType(S->getDestroyedType());
}
-void
-StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
+void StmtProfiler::VisitOverloadExpr(OverloadExpr *S) {
VisitExpr(S);
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
- VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
+ VisitTemplateArguments(S->getExplicitTemplateArgs().getTemplateArgs(),
+ S->getExplicitTemplateArgs().NumTemplateArgs);
+}
+
+void
+StmtProfiler::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *S) {
+ VisitOverloadExpr(S);
}
void StmtProfiler::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *S) {
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 02e648879ad7..a3bf1459c283 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -125,19 +125,22 @@ SourceRange TemplateArgumentLoc::getSourceRange() const {
switch (Argument.getKind()) {
case TemplateArgument::Expression:
return getSourceExpression()->getSourceRange();
-
+
case TemplateArgument::Declaration:
return getSourceDeclExpression()->getSourceRange();
-
+
case TemplateArgument::Type:
- return getTypeSourceInfo()->getTypeLoc().getSourceRange();
-
+ if (TypeSourceInfo *TSI = getTypeSourceInfo())
+ return TSI->getTypeLoc().getSourceRange();
+ else
+ return SourceRange();
+
case TemplateArgument::Template:
if (getTemplateQualifierRange().isValid())
return SourceRange(getTemplateQualifierRange().getBegin(),
getTemplateNameLoc());
return SourceRange(getTemplateNameLoc());
-
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
@@ -152,7 +155,9 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
const TemplateArgument &Arg) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
- return DB;
+ // This is bad, but not as bad as crashing because of argument
+ // count mismatches.
+ return DB << "(null template argument)";
case TemplateArgument::Type:
return DB << Arg.getAsType();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d7929304233f..ca10532e729e 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
@@ -21,6 +22,7 @@
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
using namespace clang;
bool QualType::isConstant(QualType T, ASTContext &Ctx) {
@@ -33,24 +35,32 @@ bool QualType::isConstant(QualType T, ASTContext &Ctx) {
return false;
}
-void Type::Destroy(ASTContext& C) {
- this->~Type();
- C.Deallocate(this);
-}
+Type::~Type() { }
+
+unsigned ConstantArrayType::getNumAddressingBits(ASTContext &Context,
+ QualType ElementType,
+ const llvm::APInt &NumElements) {
+ llvm::APSInt SizeExtended(NumElements, true);
+ unsigned SizeTypeBits = Context.getTypeSize(Context.getSizeType());
+ SizeExtended.extend(std::max(SizeTypeBits, SizeExtended.getBitWidth()) * 2);
-void VariableArrayType::Destroy(ASTContext& C) {
- if (SizeExpr)
- SizeExpr->Destroy(C);
- this->~VariableArrayType();
- C.Deallocate(this);
+ uint64_t ElementSize
+ = Context.getTypeSizeInChars(ElementType).getQuantity();
+ llvm::APSInt TotalSize(llvm::APInt(SizeExtended.getBitWidth(), ElementSize));
+ TotalSize *= SizeExtended;
+
+ return TotalSize.getActiveBits();
}
-void DependentSizedArrayType::Destroy(ASTContext& C) {
- // FIXME: Resource contention like in ConstantArrayWithExprType ?
- // May crash, depending on platform or a particular build.
- // SizeExpr->Destroy(C);
- this->~DependentSizedArrayType();
- C.Deallocate(this);
+unsigned ConstantArrayType::getMaxSizeBits(ASTContext &Context) {
+ unsigned Bits = Context.getTypeSize(Context.getSizeType());
+
+ // GCC appears to only allow 63 bits worth of address space when compiling
+ // for 64-bit, so we do the same.
+ if (Bits == 64)
+ --Bits;
+
+ return Bits;
}
void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
@@ -73,14 +83,6 @@ DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
SizeExpr->Profile(ID, Context, true);
}
-void DependentSizedExtVectorType::Destroy(ASTContext& C) {
- // FIXME: Deallocate size expression, once we're cloning properly.
-// if (SizeExpr)
-// SizeExpr->Destroy(C);
- this->~DependentSizedExtVectorType();
- C.Deallocate(this);
-}
-
/// getArrayElementTypeNoTypeQual - If this is an array type, return the
/// element type of the array, potentially with type qualifiers missing.
/// This method should never be used when type qualifiers are meaningful.
@@ -192,13 +194,6 @@ bool Type::isVoidType() const {
return false;
}
-bool Type::isObjectType() const {
- if (isa<FunctionType>(CanonicalType) || isa<ReferenceType>(CanonicalType) ||
- isa<IncompleteArrayType>(CanonicalType) || isVoidType())
- return false;
- return true;
-}
-
bool Type::isDerivedType() const {
switch (CanonicalType->getTypeClass()) {
case Pointer:
@@ -348,11 +343,6 @@ const RecordType *Type::getAsUnionType() const {
return 0;
}
-void ObjCInterfaceType::Destroy(ASTContext& C) {
- this->~ObjCInterfaceType();
- C.Deallocate(this);
-}
-
ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols)
@@ -366,11 +356,6 @@ ObjCObjectType::ObjCObjectType(QualType Canonical, QualType Base,
NumProtocols * sizeof(ObjCProtocolDecl*));
}
-void ObjCObjectTypeImpl::Destroy(ASTContext& C) {
- this->~ObjCObjectTypeImpl();
- C.Deallocate(this);
-}
-
const ObjCObjectType *Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCObjectType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to
@@ -385,11 +370,6 @@ bool Type::isObjCQualifiedInterfaceType() const {
return getAsObjCQualifiedInterfaceType() != 0;
}
-void ObjCObjectPointerType::Destroy(ASTContext& C) {
- this->~ObjCObjectPointerType();
- C.Deallocate(this);
-}
-
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class.
@@ -434,9 +414,14 @@ bool Type::isIntegerType() const {
// FIXME: In C++, enum types are never integer types.
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true;
+ return false;
+}
+
+bool Type::hasIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
- return false;
+ else
+ return isIntegerType();
}
/// \brief Determine whether this type is an integral type.
@@ -475,10 +460,13 @@ bool Type::isIntegralOrEnumerationType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::Int128;
-
- if (isa<EnumType>(CanonicalType))
- return true;
-
+
+ // Check for a complete enum type; incomplete enum types are not properly an
+ // enumeration type in the sense required here.
+ if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
+ if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
+ return true;
+
return false;
}
@@ -523,8 +511,7 @@ bool Type::isAnyCharacterType() const {
/// isSignedIntegerType - Return true if this is an integer type that is
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
-/// an enum decl which has a signed representation, or a vector of signed
-/// integer element type.
+/// an enum decl which has a signed representation
bool Type::isSignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
@@ -534,15 +521,19 @@ bool Type::isSignedIntegerType() const {
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
+ return false;
+}
+
+bool Type::hasSignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
- return false;
+ else
+ return isSignedIntegerType();
}
/// isUnsignedIntegerType - Return true if this is an integer type that is
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
-/// decl which has an unsigned representation, or a vector of unsigned integer
-/// element type.
+/// decl which has an unsigned representation
bool Type::isUnsignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Bool &&
@@ -552,9 +543,14 @@ bool Type::isUnsignedIntegerType() const {
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
+ return false;
+}
+
+bool Type::hasUnsignedIntegerRepresentation() const {
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
- return false;
+ else
+ return isUnsignedIntegerType();
}
bool Type::isFloatingType() const {
@@ -671,10 +667,11 @@ bool Type::isIncompleteType() const {
// An array of unknown size is an incomplete type (C99 6.2.5p22).
return true;
case ObjCObject:
- return cast<ObjCObjectType>(this)->getBaseType()->isIncompleteType();
+ return cast<ObjCObjectType>(CanonicalType)->getBaseType()
+ ->isIncompleteType();
case ObjCInterface:
// ObjC interfaces are incomplete if they are @class, not @interface.
- return cast<ObjCInterfaceType>(this)->getDecl()->isForwardDecl();
+ return cast<ObjCInterfaceType>(CanonicalType)->getDecl()->isForwardDecl();
}
}
@@ -894,15 +891,6 @@ ElaboratedType::~ElaboratedType() {}
DependentNameType::~DependentNameType() {}
DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {}
-void DependentTemplateSpecializationType::Destroy(ASTContext &C) {
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- // FIXME: Not all expressions get cloned, so we can't yet perform
- // this destruction.
- // if (Expr *E = getArg(Arg).getAsExpr())
- // E->Destroy(C);
- }
-}
-
DependentTemplateSpecializationType::DependentTemplateSpecializationType(
ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS, const IdentifierInfo *Name,
@@ -1017,6 +1005,7 @@ llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) {
case CC_X86StdCall: return "stdcall";
case CC_X86FastCall: return "fastcall";
case CC_X86ThisCall: return "thiscall";
+ case CC_X86Pascal: return "pascal";
}
}
@@ -1108,7 +1097,30 @@ void DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
TagType::TagType(TypeClass TC, const TagDecl *D, QualType can)
: Type(TC, can, D->isDependentType()),
- decl(const_cast<TagDecl*>(D), 0) {}
+ decl(const_cast<TagDecl*>(D)) {}
+
+static TagDecl *getInterestingTagDecl(TagDecl *decl) {
+ for (TagDecl::redecl_iterator I = decl->redecls_begin(),
+ E = decl->redecls_end();
+ I != E; ++I) {
+ if (I->isDefinition() || I->isBeingDefined())
+ return *I;
+ }
+ // If there's no definition (not even in progress), return what we have.
+ return decl;
+}
+
+TagDecl *TagType::getDecl() const {
+ return getInterestingTagDecl(decl);
+}
+
+bool TagType::isBeingDefined() const {
+ return getDecl()->isBeingDefined();
+}
+
+CXXRecordDecl *InjectedClassNameType::getDecl() const {
+ return cast<CXXRecordDecl>(getInterestingTagDecl(Decl));
+}
bool RecordType::classof(const TagType *TT) {
return isa<RecordDecl>(TT->getDecl());
@@ -1196,15 +1208,6 @@ TemplateSpecializationType(TemplateName T,
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
}
-void TemplateSpecializationType::Destroy(ASTContext& C) {
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- // FIXME: Not all expressions get cloned, so we can't yet perform
- // this destruction.
- // if (Expr *E = getArg(Arg).getAsExpr())
- // E->Destroy(C);
- }
-}
-
void
TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
TemplateName T,
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 4893b384dd10..66578fb3dc49 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -74,20 +74,6 @@ TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
return NextLoc().Visit(TL);
}
-namespace {
- struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> {
- SourceLocation Loc;
- TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {}
-
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- TyLoc.initializeLocal(Loc); \
- }
-#include "clang/AST/TypeLocNodes.def"
- };
-}
-
/// \brief Initializes a type location, and all of its children
/// recursively, as if the entire tree had been written in the
/// given location.
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index a08ee1ae695d..d3a6b645537c 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -299,6 +299,9 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T,
case CC_X86ThisCall:
S += " __attribute__((thiscall))";
break;
+ case CC_X86Pascal:
+ S += " __attribute__((pascal))";
+ break;
}
if (Info.getNoReturn())
S += " __attribute__((noreturn))";
@@ -430,9 +433,10 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
Buffer += ' ';
}
+ // Compute the full nested-name-specifier for this type.
+ // In C, this will always be empty except when the type
+ // being printed is anonymous within other Record.
if (!Policy.SuppressScope)
- // Compute the full nested-name-specifier for this type. In C,
- // this will always be empty.
AppendScope(D->getDeclContext(), Buffer);
if (const IdentifierInfo *II = D->getIdentifier())
@@ -463,7 +467,6 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) {
}
OS << '>';
- OS.flush();
}
// If this is a class template specialization, print the template
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 06d8aec3910e..bf9f96719001 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/Support/BumpVector.h"
@@ -54,8 +55,11 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
}
CFG *AnalysisContext::getCFG() {
+ if (UseUnoptimizedCFG)
+ return getUnoptimizedCFG();
+
if (!builtCFG) {
- cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), AddEHEdges);
+ cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), true, AddEHEdges);
// Even when the cfg is not successfully built, we don't
// want to try building it again.
builtCFG = true;
@@ -63,12 +67,29 @@ CFG *AnalysisContext::getCFG() {
return cfg;
}
+CFG *AnalysisContext::getUnoptimizedCFG() {
+ if (!builtCompleteCFG) {
+ completeCFG = CFG::buildCFG(D, getBody(), &D->getASTContext(),
+ false, AddEHEdges);
+ // Even when the cfg is not successfully built, we don't
+ // want to try building it again.
+ builtCompleteCFG = true;
+ }
+ return completeCFG;
+}
+
ParentMap &AnalysisContext::getParentMap() {
if (!PM)
PM = new ParentMap(getBody());
return *PM;
}
+PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() {
+ if (!PCA)
+ PCA = new PseudoConstantAnalysis(getBody());
+ return PCA;
+}
+
LiveVariables *AnalysisContext::getLiveVariables() {
if (!liveness) {
CFG *c = getCFG();
@@ -83,10 +104,25 @@ LiveVariables *AnalysisContext::getLiveVariables() {
return liveness;
}
-AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
+LiveVariables *AnalysisContext::getRelaxedLiveVariables() {
+ if (!relaxedLiveness) {
+ CFG *c = getCFG();
+ if (!c)
+ return 0;
+
+ relaxedLiveness = new LiveVariables(*this, false);
+ relaxedLiveness->runOnCFG(*c);
+ relaxedLiveness->runOnAllBlocks(*c, 0, true);
+ }
+
+ return relaxedLiveness;
+}
+
+AnalysisContext *AnalysisContextManager::getContext(const Decl *D,
+ idx::TranslationUnit *TU) {
AnalysisContext *&AC = Contexts[D];
if (!AC)
- AC = new AnalysisContext(D);
+ AC = new AnalysisContext(D, TU, UseUnoptimizedCFG);
return AC;
}
@@ -296,8 +332,11 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
AnalysisContext::~AnalysisContext() {
delete cfg;
+ delete completeCFG;
delete liveness;
+ delete relaxedLiveness;
delete PM;
+ delete PCA;
delete ReferencedBlockVars;
}
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 08543aacba5c..c97b9165bca2 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -35,7 +35,7 @@ static SourceLocation GetEndLoc(Decl* D) {
return D->getLocation();
}
-
+
class AddStmtChoice {
public:
enum Kind { NotAlwaysAdd = 0,
@@ -99,7 +99,8 @@ public:
TryTerminatedBlock(NULL) {}
// buildCFG - Used by external clients to construct the CFG.
- CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, bool AddEHEdges,
+ CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C,
+ bool pruneTriviallyFalseEdges, bool AddEHEdges,
bool AddScopes);
private:
@@ -174,12 +175,12 @@ private:
CFGBlock *addStmt(Stmt *S) {
return Visit(S, AddStmtChoice::AlwaysAdd);
}
-
+
void AppendStmt(CFGBlock *B, Stmt *S,
AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue());
}
-
+
void AddSuccessor(CFGBlock *B, CFGBlock *S) {
B->addSuccessor(S, cfg->getBumpVectorContext());
}
@@ -206,6 +207,9 @@ private:
/// TryEvaluateBool - Try and evaluate the Stmt and return 0 or 1
/// if we can evaluate to a known value, otherwise return -1.
TryResult TryEvaluateBool(Expr *S) {
+ if (!PruneTriviallyFalseEdges)
+ return TryResult();
+
Expr::EvalResult Result;
if (!S->isTypeDependent() && !S->isValueDependent() &&
S->Evaluate(Result, *Context) && Result.Val.isInt())
@@ -216,6 +220,9 @@ private:
bool badCFG;
+ // True iff trivially false edges should be pruned from the CFG.
+ bool PruneTriviallyFalseEdges;
+
// True iff EH edges on CallExprs should be added to the CFG.
bool AddEHEdges;
@@ -243,8 +250,12 @@ static VariableArrayType* FindVA(Type* t) {
/// transferred to the caller. If CFG construction fails, this method returns
/// NULL.
CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
+ bool pruneTriviallyFalseEdges,
bool addehedges, bool AddScopes) {
+
AddEHEdges = addehedges;
+ PruneTriviallyFalseEdges = pruneTriviallyFalseEdges;
+
Context = C;
assert(cfg.get());
if (!Statement)
@@ -359,6 +370,7 @@ tryAgain:
return VisitBreakStmt(cast<BreakStmt>(S));
case Stmt::CallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
return VisitCallExpr(cast<CallExpr>(S), asc);
case Stmt::CaseStmtClass:
@@ -379,15 +391,21 @@ tryAgain:
case Stmt::CXXCatchStmtClass:
return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
+ case Stmt::CXXExprWithTemporariesClass: {
+ // FIXME: Handle temporaries. For now, just visit the subexpression
+ // so we don't artificially create extra blocks.
+ return Visit(cast<CXXExprWithTemporaries>(S)->getSubExpr(), asc);
+ }
+
case Stmt::CXXMemberCallExprClass:
return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc);
case Stmt::CXXThrowExprClass:
return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
-
+
case Stmt::CXXTryStmtClass:
return VisitCXXTryStmt(cast<CXXTryStmt>(S));
-
+
case Stmt::DeclStmtClass:
return VisitDeclStmt(cast<DeclStmt>(S));
@@ -515,15 +533,15 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
// See if this is a known constant.
TryResult KnownVal = TryEvaluateBool(B->getLHS());
- if (KnownVal.isKnown() && (B->getOpcode() == BinaryOperator::LOr))
+ if (KnownVal.isKnown() && (B->getOpcode() == BO_LOr))
KnownVal.negate();
// Now link the LHSBlock with RHSBlock.
- if (B->getOpcode() == BinaryOperator::LOr) {
+ if (B->getOpcode() == BO_LOr) {
AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
} else {
- assert(B->getOpcode() == BinaryOperator::LAnd);
+ assert(B->getOpcode() == BO_LAnd);
AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
}
@@ -532,7 +550,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
Block = LHSBlock;
return addStmt(B->getLHS());
}
- else if (B->getOpcode() == BinaryOperator::Comma) { // ,
+ else if (B->getOpcode() == BO_Comma) { // ,
autoCreateBlock();
AppendStmt(Block, B, asc);
addStmt(B->getRHS());
@@ -543,7 +561,7 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
autoCreateBlock();
AppendStmt(Block, B, asc);
}
-
+
Visit(B->getRHS());
return Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd);
}
@@ -586,7 +604,7 @@ static bool CanThrow(Expr *E) {
Ty = Ty->getAs<PointerType>()->getPointeeType();
else if (Ty->isBlockPointerType())
Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
-
+
const FunctionType *FT = Ty->getAs<FunctionType>();
if (FT) {
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
@@ -691,7 +709,10 @@ CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
I != E; ++I ) {
- LastBlock = addStmt(*I);
+ // If we hit a segment of code just containing ';' (NullStmts), we can
+ // get a null block back. In such cases, just use the LastBlock
+ if (CFGBlock *newBlock = addStmt(*I))
+ LastBlock = newBlock;
if (badCFG)
return NULL;
@@ -901,7 +922,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
// new blocks as the condition may contain control-flow. Any newly created
// blocks will be pointed to be "Block".
Block = addStmt(I->getCond());
-
+
// Finally, if the IfStmt contains a condition variable, add both the IfStmt
// and the condition variable initialization to the CFG.
if (VarDecl *VD = I->getConditionVariable()) {
@@ -911,7 +932,7 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
addStmt(Init);
}
}
-
+
return Block;
}
@@ -1029,7 +1050,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
assert(Block == EntryConditionBlock);
}
}
-
+
if (Block) {
if (!FinishBlock(EntryConditionBlock))
return 0;
@@ -1277,7 +1298,7 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
assert(Block == EntryConditionBlock);
-
+
// If this block contains a condition variable, add both the condition
// variable and initializer to the CFG.
if (VarDecl *VD = W->getConditionVariable()) {
@@ -1389,7 +1410,7 @@ CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
if (TryTerminatedBlock)
// The current try statement is the only successor.
AddSuccessor(Block, TryTerminatedBlock);
- else
+ else
// otherwise the Exit block is the only successor.
AddSuccessor(Block, &cfg->getExit());
@@ -1465,18 +1486,22 @@ CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) {
return 0;
}
- // Add an intermediate block between the BodyBlock and the
- // ExitConditionBlock to represent the "loop back" transition. Create an
- // empty block to represent the transition block for looping back to the
- // head of the loop.
- // FIXME: Can we do this more efficiently without adding another block?
- Block = NULL;
- Succ = BodyBlock;
- CFGBlock *LoopBackBlock = createBlock();
- LoopBackBlock->setLoopTarget(D);
-
- // Add the loop body entry as a successor to the condition.
- AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : LoopBackBlock);
+ if (!KnownVal.isFalse()) {
+ // Add an intermediate block between the BodyBlock and the
+ // ExitConditionBlock to represent the "loop back" transition. Create an
+ // empty block to represent the transition block for looping back to the
+ // head of the loop.
+ // FIXME: Can we do this more efficiently without adding another block?
+ Block = NULL;
+ Succ = BodyBlock;
+ CFGBlock *LoopBackBlock = createBlock();
+ LoopBackBlock->setLoopTarget(D);
+
+ // Add the loop body entry as a successor to the condition.
+ AddSuccessor(ExitConditionBlock, LoopBackBlock);
+ }
+ else
+ AddSuccessor(ExitConditionBlock, NULL);
}
// Link up the condition block with the code that follows the loop.
@@ -1589,7 +1614,7 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
assert(Terminator->getCond() && "switch condition must be non-NULL");
Block = SwitchTerminatedBlock;
Block = addStmt(Terminator->getCond());
-
+
// Finally, if the SwitchStmt contains a condition variable, add both the
// SwitchStmt and the condition variable initialization to the CFG.
if (VarDecl *VD = Terminator->getConditionVariable()) {
@@ -1599,16 +1624,37 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
addStmt(Init);
}
}
-
+
return Block;
}
CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
// CaseStmts are essentially labels, so they are the first statement in a
// block.
+ CFGBlock *TopBlock = 0, *LastBlock = 0;
+
+ if (Stmt *Sub = CS->getSubStmt()) {
+ // For deeply nested chains of CaseStmts, instead of doing a recursion
+ // (which can blow out the stack), manually unroll and create blocks
+ // along the way.
+ while (isa<CaseStmt>(Sub)) {
+ CFGBlock *CurrentBlock = createBlock(false);
+ CurrentBlock->setLabel(CS);
+
+ if (TopBlock)
+ AddSuccessor(LastBlock, CurrentBlock);
+ else
+ TopBlock = CurrentBlock;
+
+ AddSuccessor(SwitchTerminatedBlock, CurrentBlock);
+ LastBlock = CurrentBlock;
+
+ CS = cast<CaseStmt>(Sub);
+ Sub = CS->getSubStmt();
+ }
- if (CS->getSubStmt())
- addStmt(CS->getSubStmt());
+ addStmt(Sub);
+ }
CFGBlock* CaseBlock = Block;
if (!CaseBlock)
@@ -1629,10 +1675,16 @@ CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
// We set Block to NULL to allow lazy creation of a new block (if necessary)
Block = NULL;
- // This block is now the implicit successor of other blocks.
- Succ = CaseBlock;
+ if (TopBlock) {
+ AddSuccessor(LastBlock, CaseBlock);
+ Succ = TopBlock;
+ }
+ else {
+ // This block is now the implicit successor of other blocks.
+ Succ = CaseBlock;
+ }
- return CaseBlock;
+ return Succ;
}
CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) {
@@ -1742,9 +1794,9 @@ CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) {
return CatchBlock;
}
-CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
+CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
AddStmtChoice asc) {
- AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
+ AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
: AddStmtChoice::AlwaysAdd;
autoCreateBlock();
AppendStmt(Block, C, AddStmtChoice(K));
@@ -1795,9 +1847,11 @@ CFGBlock* CFG::createBlock() {
/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
/// CFG is returned to the caller.
CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
+ bool PruneTriviallyFalse,
bool AddEHEdges, bool AddScopes) {
CFGBuilder Builder;
- return Builder.buildCFG(D, Statement, C, AddEHEdges, AddScopes);
+ return Builder.buildCFG(D, Statement, C, PruneTriviallyFalse,
+ AddEHEdges, AddScopes);
}
//===----------------------------------------------------------------------===//
@@ -1814,10 +1868,10 @@ static void FindSubExprAssignments(Stmt *S,
return;
for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) {
- Stmt *child = *I;
+ Stmt *child = *I;
if (!child)
continue;
-
+
if (BinaryOperator* B = dyn_cast<BinaryOperator>(child))
if (B->isAssignmentOp()) Set.insert(B);
@@ -2037,10 +2091,10 @@ public:
B->getLHS()->printPretty(OS, Helper, Policy);
switch (B->getOpcode()) {
- case BinaryOperator::LOr:
+ case BO_LOr:
OS << " || ...";
return;
- case BinaryOperator::LAnd:
+ case BO_LAnd:
OS << " && ...";
return;
default:
@@ -2057,7 +2111,6 @@ public:
static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
const CFGElement &E) {
- Stmt *Terminator = E;
if (E.asStartScope()) {
OS << "start scope\n";
@@ -2068,9 +2121,11 @@ static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
return;
}
+ Stmt *S = E;
+
if (Helper) {
// special printing for statement-expressions.
- if (StmtExpr* SE = dyn_cast<StmtExpr>(Terminator)) {
+ if (StmtExpr* SE = dyn_cast<StmtExpr>(S)) {
CompoundStmt* Sub = SE->getSubStmt();
if (Sub->child_begin() != Sub->child_end()) {
@@ -2082,8 +2137,8 @@ static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
}
// special printing for comma expressions.
- if (BinaryOperator* B = dyn_cast<BinaryOperator>(Terminator)) {
- if (B->getOpcode() == BinaryOperator::Comma) {
+ if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
+ if (B->getOpcode() == BO_Comma) {
OS << "... , ";
Helper->handledStmt(B->getRHS(),OS);
OS << '\n';
@@ -2092,10 +2147,19 @@ static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
}
}
- Terminator->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
+ S->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
+
+ if (isa<CXXOperatorCallExpr>(S)) {
+ OS << " (OperatorCall)";
+ }
+ else if (isa<CXXBindTemporaryExpr>(S)) {
+ OS << " (BindTemporary)";
+ }
+
// Expressions need a newline.
- if (isa<Expr>(Terminator)) OS << '\n';
+ if (isa<Expr>(S))
+ OS << '\n';
}
static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
diff --git a/lib/Analysis/CFGStmtMap.cpp b/lib/Analysis/CFGStmtMap.cpp
new file mode 100644
index 000000000000..965eca1b3c90
--- /dev/null
+++ b/lib/Analysis/CFGStmtMap.cpp
@@ -0,0 +1,88 @@
+//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- 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 CFGStmtMap class, which defines a mapping from
+// Stmt* to CFGBlock*
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CFGStmtMap.h"
+
+using namespace clang;
+
+typedef llvm::DenseMap<Stmt*,CFGBlock*> SMap;
+static SMap *AsMap(void *m) { return (SMap*) m; }
+
+CFGStmtMap::~CFGStmtMap() { delete AsMap(M); }
+
+CFGBlock *CFGStmtMap::getBlock(Stmt *S) {
+ SMap *SM = AsMap(M);
+ Stmt *X = S;
+
+ // If 'S' isn't in the map, walk the ParentMap to see if one of its ancestors
+ // is in the map.
+ while (X) {
+ SMap::iterator I = SM->find(X);
+ if (I != SM->end()) {
+ CFGBlock *B = I->second;
+ // Memoize this lookup.
+ if (X != S)
+ (*SM)[X] = B;
+ return B;
+ }
+
+ X = PM->getParentIgnoreParens(X);
+ }
+
+ return 0;
+}
+
+static void Accumulate(SMap &SM, CFGBlock *B) {
+ // First walk the block-level expressions.
+ for (CFGBlock::iterator I = B->begin(), E = B->end(); I != E; ++I) {
+ const CFGElement &CE = *I;
+ if (Stmt *S = CE.getStmt()) {
+ CFGBlock *&Entry = SM[S];
+ // If 'Entry' is already initialized (e.g., a terminator was already),
+ // skip.
+ if (Entry)
+ continue;
+
+ Entry = B;
+ }
+ }
+
+ // Look at the label of the block.
+ if (Stmt *Label = B->getLabel())
+ SM[Label] = B;
+
+ // Finally, look at the terminator. If the terminator was already added
+ // because it is a block-level expression in another block, overwrite
+ // that mapping.
+ if (Stmt *Term = B->getTerminator())
+ SM[Term] = B;
+}
+
+CFGStmtMap *CFGStmtMap::Build(CFG *C, ParentMap *PM) {
+ if (!C || !PM)
+ return 0;
+
+ SMap *SM = new SMap();
+
+ // Walk all blocks, accumulating the block-level expressions, labels,
+ // and terminators.
+ for (CFG::iterator I = C->begin(), E = C->end(); I != E; ++I)
+ Accumulate(*SM, *I);
+
+ return new CFGStmtMap(PM, SM);
+}
+
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index f2916c2068e1..850e9b468100 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -3,9 +3,13 @@ set(LLVM_NO_RTTI 1)
add_clang_library(clangAnalysis
AnalysisContext.cpp
CFG.cpp
+ CFGStmtMap.cpp
+ FormatString.cpp
LiveVariables.cpp
PrintfFormatString.cpp
+ PseudoConstantAnalysis.cpp
ReachableCode.cpp
+ ScanfFormatString.cpp
UninitializedValues.cpp
)
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
new file mode 100644
index 000000000000..388b9d34a238
--- /dev/null
+++ b/lib/Analysis/FormatString.cpp
@@ -0,0 +1,474 @@
+// FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared details for processing format strings of printf and scanf
+// (and friends).
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatStringParsing.h"
+
+using clang::analyze_format_string::ArgTypeResult;
+using clang::analyze_format_string::FormatStringHandler;
+using clang::analyze_format_string::FormatSpecifier;
+using clang::analyze_format_string::LengthModifier;
+using clang::analyze_format_string::OptionalAmount;
+using clang::analyze_format_string::PositionContext;
+using clang::analyze_format_string::ConversionSpecifier;
+using namespace clang;
+
+// Key function to FormatStringHandler.
+FormatStringHandler::~FormatStringHandler() {}
+
+//===----------------------------------------------------------------------===//
+// Functions for parsing format strings components in both printf and
+// scanf format strings.
+//===----------------------------------------------------------------------===//
+
+OptionalAmount
+clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
+ const char *I = Beg;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ unsigned accumulator = 0;
+ bool hasDigits = false;
+
+ for ( ; I != E; ++I) {
+ char c = *I;
+ if (c >= '0' && c <= '9') {
+ hasDigits = true;
+ accumulator = (accumulator * 10) + (c - '0');
+ continue;
+ }
+
+ if (hasDigits)
+ return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
+ false);
+
+ break;
+ }
+
+ return OptionalAmount();
+}
+
+OptionalAmount
+clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
+ const char *E,
+ unsigned &argIndex) {
+ if (*Beg == '*') {
+ ++Beg;
+ return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
+ }
+
+ return ParseAmount(Beg, E);
+}
+
+OptionalAmount
+clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
+ const char *Start,
+ const char *&Beg,
+ const char *E,
+ PositionContext p) {
+ if (*Beg == '*') {
+ const char *I = Beg + 1;
+ const OptionalAmount &Amt = ParseAmount(I, E);
+
+ if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
+ H.HandleInvalidPosition(Beg, I - Beg, p);
+ return OptionalAmount(false);
+ }
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return OptionalAmount(false);
+ }
+
+ assert(Amt.getHowSpecified() == OptionalAmount::Constant);
+
+ if (*I == '$') {
+ // Handle positional arguments
+
+ // Special case: '*0$', since this is an easy mistake.
+ if (Amt.getConstantAmount() == 0) {
+ H.HandleZeroPosition(Beg, I - Beg + 1);
+ return OptionalAmount(false);
+ }
+
+ const char *Tmp = Beg;
+ Beg = ++I;
+
+ return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
+ Tmp, 0, true);
+ }
+
+ H.HandleInvalidPosition(Beg, I - Beg, p);
+ return OptionalAmount(false);
+ }
+
+ return ParseAmount(Beg, E);
+}
+
+
+bool
+clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
+ FormatSpecifier &CS,
+ const char *Start,
+ const char *&Beg, const char *E,
+ unsigned *argIndex) {
+ // FIXME: Support negative field widths.
+ if (argIndex) {
+ CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
+ }
+ else {
+ const OptionalAmount Amt =
+ ParsePositionAmount(H, Start, Beg, E,
+ analyze_format_string::FieldWidthPos);
+
+ if (Amt.isInvalid())
+ return true;
+ CS.setFieldWidth(Amt);
+ }
+ return false;
+}
+
+bool
+clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
+ FormatSpecifier &FS,
+ const char *Start,
+ const char *&Beg,
+ const char *E) {
+ const char *I = Beg;
+
+ const OptionalAmount &Amt = ParseAmount(I, E);
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
+ // Special case: '%0$', since this is an easy mistake.
+ if (Amt.getConstantAmount() == 0) {
+ H.HandleZeroPosition(Start, I - Start);
+ return true;
+ }
+
+ FS.setArgIndex(Amt.getConstantAmount() - 1);
+ FS.setUsesPositionalArg();
+ // Update the caller's pointer if we decided to consume
+ // these characters.
+ Beg = I;
+ return false;
+ }
+
+ return false;
+}
+
+bool
+clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
+ const char *&I,
+ const char *E) {
+ LengthModifier::Kind lmKind = LengthModifier::None;
+ const char *lmPosition = I;
+ switch (*I) {
+ default:
+ return false;
+ case 'h':
+ ++I;
+ lmKind = (I != E && *I == 'h') ?
+ ++I, LengthModifier::AsChar : LengthModifier::AsShort;
+ break;
+ case 'l':
+ ++I;
+ lmKind = (I != E && *I == 'l') ?
+ ++I, LengthModifier::AsLongLong : LengthModifier::AsLong;
+ break;
+ case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
+ case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
+ case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
+ case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
+ case 'q': lmKind = LengthModifier::AsLongLong; ++I; break;
+ }
+ LengthModifier lm(lmPosition, lmKind);
+ FS.setLengthModifier(lm);
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on ArgTypeResult.
+//===----------------------------------------------------------------------===//
+
+bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
+ switch (K) {
+ case InvalidTy:
+ assert(false && "ArgTypeResult must be valid");
+ return true;
+
+ case UnknownTy:
+ return true;
+
+ case SpecificTy: {
+ argTy = C.getCanonicalType(argTy).getUnqualifiedType();
+ if (T == argTy)
+ return true;
+ if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ default:
+ break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return T == C.UnsignedCharTy;
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ return T == C.SignedCharTy;
+ case BuiltinType::Short:
+ return T == C.UnsignedShortTy;
+ case BuiltinType::UShort:
+ return T == C.ShortTy;
+ case BuiltinType::Int:
+ return T == C.UnsignedIntTy;
+ case BuiltinType::UInt:
+ return T == C.IntTy;
+ case BuiltinType::Long:
+ return T == C.UnsignedLongTy;
+ case BuiltinType::ULong:
+ return T == C.LongTy;
+ case BuiltinType::LongLong:
+ return T == C.UnsignedLongLongTy;
+ case BuiltinType::ULongLong:
+ return T == C.LongLongTy;
+ }
+ return false;
+ }
+
+ case CStrTy: {
+ const PointerType *PT = argTy->getAs<PointerType>();
+ if (!PT)
+ return false;
+ QualType pointeeTy = PT->getPointeeType();
+ if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
+ switch (BT->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ case WCStrTy: {
+ const PointerType *PT = argTy->getAs<PointerType>();
+ if (!PT)
+ return false;
+ QualType pointeeTy =
+ C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
+ return pointeeTy == C.getWCharType();
+ }
+
+ case WIntTy: {
+ // Instead of doing a lookup for the definition of 'wint_t' (which
+ // is defined by the system headers) instead see if wchar_t and
+ // the argument type promote to the same type.
+ QualType PromoWChar =
+ C.getWCharType()->isPromotableIntegerType()
+ ? C.getPromotedIntegerType(C.getWCharType()) : C.getWCharType();
+ QualType PromoArg =
+ argTy->isPromotableIntegerType()
+ ? C.getPromotedIntegerType(argTy) : argTy;
+
+ PromoWChar = C.getCanonicalType(PromoWChar).getUnqualifiedType();
+ PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
+
+ return PromoWChar == PromoArg;
+ }
+
+ case CPointerTy:
+ return argTy->getAs<PointerType>() != NULL ||
+ argTy->getAs<ObjCObjectPointerType>() != NULL;
+
+ case ObjCPointerTy:
+ return argTy->getAs<ObjCObjectPointerType>() != NULL;
+ }
+
+ // FIXME: Should be unreachable, but Clang is currently emitting
+ // a warning.
+ return false;
+}
+
+QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
+ switch (K) {
+ case InvalidTy:
+ assert(false && "No representative type for Invalid ArgTypeResult");
+ // Fall-through.
+ case UnknownTy:
+ return QualType();
+ case SpecificTy:
+ return T;
+ case CStrTy:
+ return C.getPointerType(C.CharTy);
+ case WCStrTy:
+ return C.getPointerType(C.getWCharType());
+ case ObjCPointerTy:
+ return C.ObjCBuiltinIdTy;
+ case CPointerTy:
+ return C.VoidPtrTy;
+ case WIntTy: {
+ QualType WC = C.getWCharType();
+ return WC->isPromotableIntegerType() ? C.getPromotedIntegerType(WC) : WC;
+ }
+ }
+
+ // FIXME: Should be unreachable, but Clang is currently emitting
+ // a warning.
+ return QualType();
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on OptionalAmount.
+//===----------------------------------------------------------------------===//
+
+ArgTypeResult
+analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
+ return Ctx.IntTy;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on LengthModifier.
+//===----------------------------------------------------------------------===//
+
+const char *
+analyze_format_string::LengthModifier::toString() const {
+ switch (kind) {
+ case AsChar:
+ return "hh";
+ case AsShort:
+ return "h";
+ case AsLong: // or AsWideChar
+ return "l";
+ case AsLongLong:
+ return "ll";
+ case AsIntMax:
+ return "j";
+ case AsSizeT:
+ return "z";
+ case AsPtrDiff:
+ return "t";
+ case AsLongDouble:
+ return "L";
+ case None:
+ return "";
+ }
+ return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on OptionalAmount.
+//===----------------------------------------------------------------------===//
+
+void OptionalAmount::toString(llvm::raw_ostream &os) const {
+ switch (hs) {
+ case Invalid:
+ case NotSpecified:
+ return;
+ case Arg:
+ if (UsesDotPrefix)
+ os << ".";
+ if (usesPositionalArg())
+ os << "*" << getPositionalArgIndex() << "$";
+ else
+ os << "*";
+ break;
+ case Constant:
+ if (UsesDotPrefix)
+ os << ".";
+ os << amt;
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Methods on ConversionSpecifier.
+//===----------------------------------------------------------------------===//
+
+bool FormatSpecifier::hasValidLengthModifier() const {
+ switch (LM.getKind()) {
+ case LengthModifier::None:
+ return true;
+
+ // Handle most integer flags
+ case LengthModifier::AsChar:
+ case LengthModifier::AsShort:
+ case LengthModifier::AsLongLong:
+ case LengthModifier::AsIntMax:
+ case LengthModifier::AsSizeT:
+ case LengthModifier::AsPtrDiff:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::nArg:
+ return true;
+ default:
+ return false;
+ }
+
+ // Handle 'l' flag
+ case LengthModifier::AsLong:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::dArg:
+ case ConversionSpecifier::iArg:
+ case ConversionSpecifier::oArg:
+ case ConversionSpecifier::uArg:
+ case ConversionSpecifier::xArg:
+ case ConversionSpecifier::XArg:
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ case ConversionSpecifier::nArg:
+ case ConversionSpecifier::cArg:
+ case ConversionSpecifier::sArg:
+ return true;
+ default:
+ return false;
+ }
+
+ case LengthModifier::AsLongDouble:
+ switch (CS.getKind()) {
+ case ConversionSpecifier::aArg:
+ case ConversionSpecifier::AArg:
+ case ConversionSpecifier::fArg:
+ case ConversionSpecifier::FArg:
+ case ConversionSpecifier::eArg:
+ case ConversionSpecifier::EArg:
+ case ConversionSpecifier::gArg:
+ case ConversionSpecifier::GArg:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
+
+
diff --git a/lib/Analysis/FormatStringParsing.h b/lib/Analysis/FormatStringParsing.h
new file mode 100644
index 000000000000..607e99ccd076
--- /dev/null
+++ b/lib/Analysis/FormatStringParsing.h
@@ -0,0 +1,72 @@
+#ifndef LLVM_CLANG_FORMAT_PARSING_H
+#define LLVM_CLANG_FORMAT_PARSING_H
+
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+template <typename T>
+class UpdateOnReturn {
+ T &ValueToUpdate;
+ const T &ValueToCopy;
+public:
+ UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
+ : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
+
+ ~UpdateOnReturn() {
+ ValueToUpdate = ValueToCopy;
+ }
+};
+
+namespace analyze_format_string {
+
+OptionalAmount ParseAmount(const char *&Beg, const char *E);
+OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
+ unsigned &argIndex);
+
+OptionalAmount ParsePositionAmount(FormatStringHandler &H,
+ const char *Start, const char *&Beg,
+ const char *E, PositionContext p);
+
+bool ParseFieldWidth(FormatStringHandler &H,
+ FormatSpecifier &CS,
+ const char *Start, const char *&Beg, const char *E,
+ unsigned *argIndex);
+
+bool ParseArgPosition(FormatStringHandler &H,
+ FormatSpecifier &CS, const char *Start,
+ const char *&Beg, const char *E);
+
+/// Returns true if a LengthModifier was parsed and installed in the
+/// FormatSpecifier& argument, and false otherwise.
+bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E);
+
+template <typename T> class SpecifierResult {
+ T FS;
+ const char *Start;
+ bool Stop;
+public:
+ SpecifierResult(bool stop = false)
+ : Start(0), Stop(stop) {}
+ SpecifierResult(const char *start,
+ const T &fs)
+ : FS(fs), Start(start), Stop(false) {}
+
+ const char *getStart() const { return Start; }
+ bool shouldStop() const { return Stop; }
+ bool hasValue() const { return Start != 0; }
+ const T &getValue() const {
+ assert(hasValue());
+ return FS;
+ }
+ const T &getValue() { return FS; }
+};
+
+} // end analyze_format_string namespace
+} // end clang namespace
+
+#endif
+
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 4efe25ea1e0e..47b2e3d6040f 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -77,12 +77,13 @@ public:
};
} // end anonymous namespace
-LiveVariables::LiveVariables(AnalysisContext &AC) {
+LiveVariables::LiveVariables(AnalysisContext &AC, bool killAtAssign) {
// Register all referenced VarDecls.
CFG &cfg = *AC.getCFG();
getAnalysisData().setCFG(cfg);
getAnalysisData().setContext(AC.getASTContext());
getAnalysisData().AC = &AC;
+ getAnalysisData().killAtAssign = killAtAssign;
RegisterDecls R(getAnalysisData());
cfg.VisitBlockStmts(R);
@@ -229,10 +230,10 @@ void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
Expr *E = U->getSubExpr();
switch (U->getOpcode()) {
- case UnaryOperator::PostInc:
- case UnaryOperator::PostDec:
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec:
+ case UO_PostInc:
+ case UO_PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
// Walk through the subexpressions, blasting through ParenExprs
// until we either find a DeclRefExpr or some non-DeclRefExpr
// expression.
@@ -260,15 +261,16 @@ void TransferFuncs::VisitAssign(BinaryOperator* B) {
if (DR->getDecl()->getType()->isReferenceType()) {
VisitDeclRefExpr(DR);
} else {
- // Update liveness inforamtion.
- unsigned bit = AD.getIdx(DR->getDecl());
- LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
-
- if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+ if (AD.killAtAssign) {
+ // Update liveness inforamtion.
+ unsigned bit = AD.getIdx(DR->getDecl());
+ LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
+ if (AD.Observer) { AD.Observer->ObserverKill(DR); }
+ }
// Handle things like +=, etc., which also generate "uses"
// of a variable. Do this just by visiting the subexpression.
- if (B->getOpcode() != BinaryOperator::Assign)
+ if (B->getOpcode() != BO_Assign)
VisitDeclRefExpr(DR);
}
}
diff --git a/lib/Analysis/Makefile b/lib/Analysis/Makefile
index 03bf7a6712f3..fbbb83d71003 100644
--- a/lib/Analysis/Makefile
+++ b/lib/Analysis/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangAnalysis
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index 558d38af0c6e..b8c327cdeba6 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -1,4 +1,4 @@
-//= PrintfFormatStrings.cpp - Analysis of printf format strings --*- C++ -*-==//
+//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -12,141 +12,28 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Analysis/Analyses/PrintfFormatString.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Type.h"
-#include "llvm/Support/raw_ostream.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "FormatStringParsing.h"
-using clang::analyze_printf::ArgTypeResult;
-using clang::analyze_printf::FormatSpecifier;
-using clang::analyze_printf::FormatStringHandler;
-using clang::analyze_printf::OptionalAmount;
-using clang::analyze_printf::PositionContext;
-using clang::analyze_printf::ConversionSpecifier;
-using clang::analyze_printf::LengthModifier;
+using clang::analyze_format_string::ArgTypeResult;
+using clang::analyze_format_string::FormatStringHandler;
+using clang::analyze_format_string::LengthModifier;
+using clang::analyze_format_string::OptionalAmount;
+using clang::analyze_format_string::ConversionSpecifier;
+using clang::analyze_printf::PrintfSpecifier;
using namespace clang;
-namespace {
-class FormatSpecifierResult {
- FormatSpecifier FS;
- const char *Start;
- bool Stop;
-public:
- FormatSpecifierResult(bool stop = false)
- : Start(0), Stop(stop) {}
- FormatSpecifierResult(const char *start,
- const FormatSpecifier &fs)
- : FS(fs), Start(start), Stop(false) {}
-
- const char *getStart() const { return Start; }
- bool shouldStop() const { return Stop; }
- bool hasValue() const { return Start != 0; }
- const FormatSpecifier &getValue() const {
- assert(hasValue());
- return FS;
- }
- const FormatSpecifier &getValue() { return FS; }
-};
-} // end anonymous namespace
-
-template <typename T>
-class UpdateOnReturn {
- T &ValueToUpdate;
- const T &ValueToCopy;
-public:
- UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
- : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
-
- ~UpdateOnReturn() {
- ValueToUpdate = ValueToCopy;
- }
-};
+typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
+ PrintfSpecifierResult;
//===----------------------------------------------------------------------===//
// Methods for parsing format strings.
//===----------------------------------------------------------------------===//
-static OptionalAmount ParseAmount(const char *&Beg, const char *E) {
- const char *I = Beg;
- UpdateOnReturn <const char*> UpdateBeg(Beg, I);
-
- unsigned accumulator = 0;
- bool hasDigits = false;
-
- for ( ; I != E; ++I) {
- char c = *I;
- if (c >= '0' && c <= '9') {
- hasDigits = true;
- accumulator = (accumulator * 10) + (c - '0');
- continue;
- }
-
- if (hasDigits)
- return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
- false);
-
- break;
- }
-
- return OptionalAmount();
-}
-
-static OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
- unsigned &argIndex) {
- if (*Beg == '*') {
- ++Beg;
- return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
- }
-
- return ParseAmount(Beg, E);
-}
-
-static OptionalAmount ParsePositionAmount(FormatStringHandler &H,
- const char *Start,
- const char *&Beg, const char *E,
- PositionContext p) {
- if (*Beg == '*') {
- const char *I = Beg + 1;
- const OptionalAmount &Amt = ParseAmount(I, E);
-
- if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
- H.HandleInvalidPosition(Beg, I - Beg, p);
- return OptionalAmount(false);
- }
-
- if (I== E) {
- // No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
- return OptionalAmount(false);
- }
-
- assert(Amt.getHowSpecified() == OptionalAmount::Constant);
-
- if (*I == '$') {
- // Handle positional arguments
-
- // Special case: '*0$', since this is an easy mistake.
- if (Amt.getConstantAmount() == 0) {
- H.HandleZeroPosition(Beg, I - Beg + 1);
- return OptionalAmount(false);
- }
-
- const char *Tmp = Beg;
- Beg = ++I;
-
- return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
- Tmp, 0, true);
- }
-
- H.HandleInvalidPosition(Beg, I - Beg, p);
- return OptionalAmount(false);
- }
-
- return ParseAmount(Beg, E);
-}
+using analyze_format_string::ParseNonPositionAmount;
-static bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS,
+static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
const char *Start, const char *&Beg, const char *E,
unsigned *argIndex) {
if (argIndex) {
@@ -154,7 +41,7 @@ static bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS,
}
else {
const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
- analyze_printf::PrecisionPos);
+ analyze_format_string::PrecisionPos);
if (Amt.isInvalid())
return true;
FS.setPrecision(Amt);
@@ -162,61 +49,12 @@ static bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS,
return false;
}
-static bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &FS,
- const char *Start, const char *&Beg, const char *E,
- unsigned *argIndex) {
- // FIXME: Support negative field widths.
- if (argIndex) {
- FS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
- }
- else {
- const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
- analyze_printf::FieldWidthPos);
- if (Amt.isInvalid())
- return true;
- FS.setFieldWidth(Amt);
- }
- return false;
-}
-
-static bool ParseArgPosition(FormatStringHandler &H,
- FormatSpecifier &FS, const char *Start,
- const char *&Beg, const char *E) {
-
- using namespace clang::analyze_printf;
- const char *I = Beg;
-
- const OptionalAmount &Amt = ParseAmount(I, E);
-
- if (I == E) {
- // No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
- return true;
- }
-
- if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
- // Special case: '%0$', since this is an easy mistake.
- if (Amt.getConstantAmount() == 0) {
- H.HandleZeroPosition(Start, I - Start);
- return true;
- }
-
- FS.setArgIndex(Amt.getConstantAmount() - 1);
- FS.setUsesPositionalArg();
- // Update the caller's pointer if we decided to consume
- // these characters.
- Beg = I;
- return false;
- }
-
- return false;
-}
-
-static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
+static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
const char *&Beg,
const char *E,
unsigned &argIndex) {
+ using namespace clang::analyze_format_string;
using namespace clang::analyze_printf;
const char *I = Beg;
@@ -243,17 +81,17 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
if (I == E) {
// No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
- FormatSpecifier FS;
+ PrintfSpecifier FS;
if (ParseArgPosition(H, FS, Start, I, E))
return true;
if (I == E) {
// No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
@@ -274,7 +112,7 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
if (I == E) {
// No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
@@ -285,7 +123,7 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
if (I == E) {
// No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
@@ -293,7 +131,7 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
if (*I == '.') {
++I;
if (I == E) {
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
@@ -303,39 +141,15 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
if (I == E) {
// No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
}
// Look for the length modifier.
- LengthModifier::Kind lmKind = LengthModifier::None;
- const char *lmPosition = I;
- switch (*I) {
- default:
- break;
- case 'h':
- ++I;
- lmKind = (I != E && *I == 'h') ?
- ++I, LengthModifier::AsChar : LengthModifier::AsShort;
- break;
- case 'l':
- ++I;
- lmKind = (I != E && *I == 'l') ?
- ++I, LengthModifier::AsLongLong : LengthModifier::AsLong;
- break;
- case 'j': lmKind = LengthModifier::AsIntMax; ++I; break;
- case 'z': lmKind = LengthModifier::AsSizeT; ++I; break;
- case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break;
- case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
- case 'q': lmKind = LengthModifier::AsLongLong; ++I; break;
- }
- LengthModifier lm(lmPosition, lmKind);
- FS.setLengthModifier(lm);
-
- if (I == E) {
+ if (ParseLengthModifier(FS, I, E) && I == E) {
// No more characters left?
- H.HandleIncompleteFormatSpecifier(Start, E - Start);
+ H.HandleIncompleteSpecifier(Start, E - Start);
return true;
}
@@ -359,46 +173,47 @@ static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
case 'G': k = ConversionSpecifier::GArg; break;
case 'X': k = ConversionSpecifier::XArg; break;
case 'a': k = ConversionSpecifier::aArg; break;
- case 'c': k = ConversionSpecifier::IntAsCharArg; break;
+ case 'c': k = ConversionSpecifier::cArg; break;
case 'd': k = ConversionSpecifier::dArg; break;
case 'e': k = ConversionSpecifier::eArg; break;
case 'f': k = ConversionSpecifier::fArg; break;
case 'g': k = ConversionSpecifier::gArg; break;
case 'i': k = ConversionSpecifier::iArg; break;
- case 'n': k = ConversionSpecifier::OutIntPtrArg; break;
+ case 'n': k = ConversionSpecifier::nArg; break;
case 'o': k = ConversionSpecifier::oArg; break;
- case 'p': k = ConversionSpecifier::VoidPtrArg; break;
- case 's': k = ConversionSpecifier::CStrArg; break;
+ case 'p': k = ConversionSpecifier::pArg; break;
+ case 's': k = ConversionSpecifier::sArg; break;
case 'u': k = ConversionSpecifier::uArg; break;
case 'x': k = ConversionSpecifier::xArg; break;
// Mac OS X (unicode) specific
case 'C': k = ConversionSpecifier::CArg; break;
- case 'S': k = ConversionSpecifier::UnicodeStrArg; break;
+ case 'S': k = ConversionSpecifier::SArg; break;
// Objective-C.
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
case 'm': k = ConversionSpecifier::PrintErrno; break;
}
- ConversionSpecifier CS(conversionPosition, k);
+ PrintfConversionSpecifier CS(conversionPosition, k);
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
FS.setArgIndex(argIndex++);
if (k == ConversionSpecifier::InvalidSpecifier) {
// Assume the conversion takes one argument.
- return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg);
+ return !H.HandleInvalidPrintfConversionSpecifier(FS, Beg, I - Beg);
}
- return FormatSpecifierResult(Start, FS);
+ return PrintfSpecifierResult(Start, FS);
}
-bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
- const char *I, const char *E) {
+bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
+ const char *I,
+ const char *E) {
unsigned argIndex = 0;
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
- const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex);
+ const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex);
// Did a fail-stop error of any kind occur when parsing the specifier?
// If so, don't do any more processing.
if (FSR.shouldStop())
@@ -408,7 +223,7 @@ bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
if (!FSR.hasValue())
continue;
// We have a format specifier. Pass it to the callback.
- if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(),
+ if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
I - FSR.getStart()))
return true;
}
@@ -416,129 +231,6 @@ bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
return false;
}
-FormatStringHandler::~FormatStringHandler() {}
-
-//===----------------------------------------------------------------------===//
-// Methods on ArgTypeResult.
-//===----------------------------------------------------------------------===//
-
-bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
- switch (K) {
- case InvalidTy:
- assert(false && "ArgTypeResult must be valid");
- return true;
-
- case UnknownTy:
- return true;
-
- case SpecificTy: {
- argTy = C.getCanonicalType(argTy).getUnqualifiedType();
- if (T == argTy)
- return true;
- if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
- switch (BT->getKind()) {
- default:
- break;
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- return T == C.UnsignedCharTy;
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- return T == C.SignedCharTy;
- case BuiltinType::Short:
- return T == C.UnsignedShortTy;
- case BuiltinType::UShort:
- return T == C.ShortTy;
- case BuiltinType::Int:
- return T == C.UnsignedIntTy;
- case BuiltinType::UInt:
- return T == C.IntTy;
- case BuiltinType::Long:
- return T == C.UnsignedLongTy;
- case BuiltinType::ULong:
- return T == C.LongTy;
- case BuiltinType::LongLong:
- return T == C.UnsignedLongLongTy;
- case BuiltinType::ULongLong:
- return T == C.LongLongTy;
- }
- return false;
- }
-
- case CStrTy: {
- const PointerType *PT = argTy->getAs<PointerType>();
- if (!PT)
- return false;
- QualType pointeeTy = PT->getPointeeType();
- if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
- switch (BT->getKind()) {
- case BuiltinType::Void:
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- return true;
- default:
- break;
- }
-
- return false;
- }
-
- case WCStrTy: {
- const PointerType *PT = argTy->getAs<PointerType>();
- if (!PT)
- return false;
- QualType pointeeTy =
- C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
- return pointeeTy == C.getWCharType();
- }
-
- case CPointerTy:
- return argTy->getAs<PointerType>() != NULL ||
- argTy->getAs<ObjCObjectPointerType>() != NULL;
-
- case ObjCPointerTy:
- return argTy->getAs<ObjCObjectPointerType>() != NULL;
- }
-
- // FIXME: Should be unreachable, but Clang is currently emitting
- // a warning.
- return false;
-}
-
-QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
- switch (K) {
- case InvalidTy:
- assert(false && "No representative type for Invalid ArgTypeResult");
- // Fall-through.
- case UnknownTy:
- return QualType();
- case SpecificTy:
- return T;
- case CStrTy:
- return C.getPointerType(C.CharTy);
- case WCStrTy:
- return C.getPointerType(C.getWCharType());
- case ObjCPointerTy:
- return C.ObjCBuiltinIdTy;
- case CPointerTy:
- return C.VoidPtrTy;
- }
-
- // FIXME: Should be unreachable, but Clang is currently emitting
- // a warning.
- return QualType();
-}
-
-//===----------------------------------------------------------------------===//
-// Methods on OptionalAmount.
-//===----------------------------------------------------------------------===//
-
-ArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const {
- return Ctx.IntTy;
-}
-
//===----------------------------------------------------------------------===//
// Methods on ConversionSpecifier.
//===----------------------------------------------------------------------===//
@@ -558,16 +250,17 @@ const char *ConversionSpecifier::toString() const {
case GArg: return "G";
case aArg: return "a";
case AArg: return "A";
- case IntAsCharArg: return "c";
- case CStrArg: return "s";
- case VoidPtrArg: return "p";
- case OutIntPtrArg: return "n";
- case PercentArg: return "%";
+ case cArg: return "c";
+ case sArg: return "s";
+ case pArg: return "p";
+ case nArg: return "n";
+ case PercentArg: return "%";
+ case ScanListArg: return "[";
case InvalidSpecifier: return NULL;
// MacOS X unicode extensions.
- case CArg: return "C";
- case UnicodeStrArg: return "S";
+ case CArg: return "C";
+ case SArg: return "S";
// Objective-C specific specifiers.
case ObjCObjArg: return "@";
@@ -579,66 +272,23 @@ const char *ConversionSpecifier::toString() const {
}
//===----------------------------------------------------------------------===//
-// Methods on LengthModifier.
-//===----------------------------------------------------------------------===//
-
-const char *LengthModifier::toString() const {
- switch (kind) {
- case AsChar:
- return "hh";
- case AsShort:
- return "h";
- case AsLong: // or AsWideChar
- return "l";
- case AsLongLong:
- return "ll";
- case AsIntMax:
- return "j";
- case AsSizeT:
- return "z";
- case AsPtrDiff:
- return "t";
- case AsLongDouble:
- return "L";
- case None:
- return "";
- }
- return NULL;
-}
-
-//===----------------------------------------------------------------------===//
-// Methods on OptionalAmount.
+// Methods on PrintfSpecifier.
//===----------------------------------------------------------------------===//
-void OptionalAmount::toString(llvm::raw_ostream &os) const {
- switch (hs) {
- case Invalid:
- case NotSpecified:
- return;
- case Arg:
- if (UsesDotPrefix)
- os << ".";
- if (usesPositionalArg())
- os << "*" << getPositionalArgIndex() << "$";
- else
- os << "*";
- break;
- case Constant:
- if (UsesDotPrefix)
- os << ".";
- os << amt;
- break;
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Methods on FormatSpecifier.
-//===----------------------------------------------------------------------===//
-
-ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
+ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
+ const PrintfConversionSpecifier &CS = getConversionSpecifier();
+
if (!CS.consumesDataArgument())
return ArgTypeResult::Invalid();
+ if (CS.getKind() == ConversionSpecifier::cArg)
+ switch (LM.getKind()) {
+ case LengthModifier::None: return Ctx.IntTy;
+ case LengthModifier::AsLong: return ArgTypeResult::WIntTy;
+ default:
+ return ArgTypeResult::Invalid();
+ }
+
if (CS.isIntArg())
switch (LM.getKind()) {
case LengthModifier::AsLongDouble:
@@ -684,15 +334,15 @@ ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
}
switch (CS.getKind()) {
- case ConversionSpecifier::CStrArg:
+ case ConversionSpecifier::sArg:
return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ?
ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
- case ConversionSpecifier::UnicodeStrArg:
+ case ConversionSpecifier::SArg:
// FIXME: This appears to be Mac OS X specific.
return ArgTypeResult::WCStrTy;
case ConversionSpecifier::CArg:
return Ctx.WCharTy;
- case ConversionSpecifier::VoidPtrArg:
+ case ConversionSpecifier::pArg:
return ArgTypeResult::CPointerTy;
default:
break;
@@ -702,10 +352,10 @@ ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
return ArgTypeResult();
}
-bool FormatSpecifier::fixType(QualType QT) {
+bool PrintfSpecifier::fixType(QualType QT) {
// Handle strings first (char *, wchar_t *)
if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
- CS.setKind(ConversionSpecifier::CStrArg);
+ CS.setKind(ConversionSpecifier::sArg);
// Disable irrelevant flags
HasAlternativeForm = 0;
@@ -750,7 +400,7 @@ bool FormatSpecifier::fixType(QualType QT) {
// Set conversion specifier and disable any flags which do not apply to it.
if (QT->isAnyCharacterType()) {
- CS.setKind(ConversionSpecifier::IntAsCharArg);
+ CS.setKind(ConversionSpecifier::cArg);
Precision.setHowSpecified(OptionalAmount::NotSpecified);
HasAlternativeForm = 0;
HasLeadingZeroes = 0;
@@ -761,7 +411,7 @@ bool FormatSpecifier::fixType(QualType QT) {
CS.setKind(ConversionSpecifier::fArg);
}
else if (QT->isPointerType()) {
- CS.setKind(ConversionSpecifier::VoidPtrArg);
+ CS.setKind(ConversionSpecifier::pArg);
Precision.setHowSpecified(OptionalAmount::NotSpecified);
HasAlternativeForm = 0;
HasLeadingZeroes = 0;
@@ -783,9 +433,9 @@ bool FormatSpecifier::fixType(QualType QT) {
return true;
}
-void FormatSpecifier::toString(llvm::raw_ostream &os) const {
+void PrintfSpecifier::toString(llvm::raw_ostream &os) const {
// Whilst some features have no defined order, we are using the order
- // appearing in the C99 standard (ISO/IEC 9899:1999 (E) ¤7.19.6.1)
+ // appearing in the C99 standard (ISO/IEC 9899:1999 (E) ¤7.19.6.1)
os << "%";
// Positional args
@@ -810,7 +460,7 @@ void FormatSpecifier::toString(llvm::raw_ostream &os) const {
os << CS.toString();
}
-bool FormatSpecifier::hasValidPlusPrefix() const {
+bool PrintfSpecifier::hasValidPlusPrefix() const {
if (!HasPlusPrefix)
return true;
@@ -833,7 +483,7 @@ bool FormatSpecifier::hasValidPlusPrefix() const {
}
}
-bool FormatSpecifier::hasValidAlternativeForm() const {
+bool PrintfSpecifier::hasValidAlternativeForm() const {
if (!HasAlternativeForm)
return true;
@@ -856,7 +506,7 @@ bool FormatSpecifier::hasValidAlternativeForm() const {
}
}
-bool FormatSpecifier::hasValidLeadingZeros() const {
+bool PrintfSpecifier::hasValidLeadingZeros() const {
if (!HasLeadingZeroes)
return true;
@@ -883,7 +533,7 @@ bool FormatSpecifier::hasValidLeadingZeros() const {
}
}
-bool FormatSpecifier::hasValidSpacePrefix() const {
+bool PrintfSpecifier::hasValidSpacePrefix() const {
if (!HasSpacePrefix)
return true;
@@ -906,13 +556,13 @@ bool FormatSpecifier::hasValidSpacePrefix() const {
}
}
-bool FormatSpecifier::hasValidLeftJustified() const {
+bool PrintfSpecifier::hasValidLeftJustified() const {
if (!IsLeftJustified)
return true;
// The left justified flag is valid for all conversions except n
switch (CS.getKind()) {
- case ConversionSpecifier::OutIntPtrArg:
+ case ConversionSpecifier::nArg:
return false;
default:
@@ -920,75 +570,7 @@ bool FormatSpecifier::hasValidLeftJustified() const {
}
}
-bool FormatSpecifier::hasValidLengthModifier() const {
- switch (LM.getKind()) {
- case LengthModifier::None:
- return true;
-
- // Handle most integer flags
- case LengthModifier::AsChar:
- case LengthModifier::AsShort:
- case LengthModifier::AsLongLong:
- case LengthModifier::AsIntMax:
- case LengthModifier::AsSizeT:
- case LengthModifier::AsPtrDiff:
- switch (CS.getKind()) {
- case ConversionSpecifier::dArg:
- case ConversionSpecifier::iArg:
- case ConversionSpecifier::oArg:
- case ConversionSpecifier::uArg:
- case ConversionSpecifier::xArg:
- case ConversionSpecifier::XArg:
- case ConversionSpecifier::OutIntPtrArg:
- return true;
- default:
- return false;
- }
-
- // Handle 'l' flag
- case LengthModifier::AsLong:
- switch (CS.getKind()) {
- case ConversionSpecifier::dArg:
- case ConversionSpecifier::iArg:
- case ConversionSpecifier::oArg:
- case ConversionSpecifier::uArg:
- case ConversionSpecifier::xArg:
- case ConversionSpecifier::XArg:
- case ConversionSpecifier::aArg:
- case ConversionSpecifier::AArg:
- case ConversionSpecifier::fArg:
- case ConversionSpecifier::FArg:
- case ConversionSpecifier::eArg:
- case ConversionSpecifier::EArg:
- case ConversionSpecifier::gArg:
- case ConversionSpecifier::GArg:
- case ConversionSpecifier::OutIntPtrArg:
- case ConversionSpecifier::IntAsCharArg:
- case ConversionSpecifier::CStrArg:
- return true;
- default:
- return false;
- }
-
- case LengthModifier::AsLongDouble:
- switch (CS.getKind()) {
- case ConversionSpecifier::aArg:
- case ConversionSpecifier::AArg:
- case ConversionSpecifier::fArg:
- case ConversionSpecifier::FArg:
- case ConversionSpecifier::eArg:
- case ConversionSpecifier::EArg:
- case ConversionSpecifier::gArg:
- case ConversionSpecifier::GArg:
- return true;
- default:
- return false;
- }
- }
- return false;
-}
-
-bool FormatSpecifier::hasValidPrecision() const {
+bool PrintfSpecifier::hasValidPrecision() const {
if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
return true;
@@ -1008,20 +590,20 @@ bool FormatSpecifier::hasValidPrecision() const {
case ConversionSpecifier::FArg:
case ConversionSpecifier::gArg:
case ConversionSpecifier::GArg:
- case ConversionSpecifier::CStrArg:
+ case ConversionSpecifier::sArg:
return true;
default:
return false;
}
}
-bool FormatSpecifier::hasValidFieldWidth() const {
+bool PrintfSpecifier::hasValidFieldWidth() const {
if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
return true;
// The field width is valid for all conversions except n
switch (CS.getKind()) {
- case ConversionSpecifier::OutIntPtrArg:
+ case ConversionSpecifier::nArg:
return false;
default:
diff --git a/lib/Analysis/PseudoConstantAnalysis.cpp b/lib/Analysis/PseudoConstantAnalysis.cpp
new file mode 100644
index 000000000000..ff43fc252aa3
--- /dev/null
+++ b/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -0,0 +1,238 @@
+//== PseudoConstantAnalysis.cpp - Find Pseudoconstants in the AST-*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tracks the usage of variables in a Decl body to see if they are
+// never written to, implying that they constant. This is useful in static
+// analysis to see if a developer might have intended a variable to be const.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include <deque>
+
+using namespace clang;
+
+// The number of ValueDecls we want to keep track of by default (per-function)
+#define VARDECL_SET_SIZE 256
+typedef llvm::SmallPtrSet<const VarDecl*, VARDECL_SET_SIZE> VarDeclSet;
+
+PseudoConstantAnalysis::PseudoConstantAnalysis(const Stmt *DeclBody) :
+ DeclBody(DeclBody), Analyzed(false) {
+ NonConstantsImpl = new VarDeclSet;
+ UsedVarsImpl = new VarDeclSet;
+}
+
+PseudoConstantAnalysis::~PseudoConstantAnalysis() {
+ delete (VarDeclSet*)NonConstantsImpl;
+ delete (VarDeclSet*)UsedVarsImpl;
+}
+
+// Returns true if the given ValueDecl is never written to in the given DeclBody
+bool PseudoConstantAnalysis::isPseudoConstant(const VarDecl *VD) {
+ // Only local and static variables can be pseudoconstants
+ if (!VD->hasLocalStorage() && !VD->isStaticLocal())
+ return false;
+
+ if (!Analyzed) {
+ RunAnalysis();
+ Analyzed = true;
+ }
+
+ VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
+
+ return !NonConstants->count(VD);
+}
+
+// Returns true if the variable was used (self assignments don't count)
+bool PseudoConstantAnalysis::wasReferenced(const VarDecl *VD) {
+ if (!Analyzed) {
+ RunAnalysis();
+ Analyzed = true;
+ }
+
+ VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
+
+ return UsedVars->count(VD);
+}
+
+// Returns a Decl from a (Block)DeclRefExpr (if any)
+const Decl *PseudoConstantAnalysis::getDecl(const Expr *E) {
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
+ return DR->getDecl();
+ else if (const BlockDeclRefExpr *BDR = dyn_cast<BlockDeclRefExpr>(E))
+ return BDR->getDecl();
+ else
+ return 0;
+}
+
+void PseudoConstantAnalysis::RunAnalysis() {
+ std::deque<const Stmt *> WorkList;
+ VarDeclSet *NonConstants = (VarDeclSet*)NonConstantsImpl;
+ VarDeclSet *UsedVars = (VarDeclSet*)UsedVarsImpl;
+
+ // Start with the top level statement of the function
+ WorkList.push_back(DeclBody);
+
+ while (!WorkList.empty()) {
+ const Stmt* Head = WorkList.front();
+ WorkList.pop_front();
+
+ switch (Head->getStmtClass()) {
+ // Case 1: Assignment operators modifying VarDecls
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(Head);
+ // Look for a Decl on the LHS
+ const Decl *LHSDecl = getDecl(BO->getLHS()->IgnoreParenCasts());
+ if (!LHSDecl)
+ break;
+
+ // We found a binary operator with a DeclRefExpr on the LHS. We now check
+ // for any of the assignment operators, implying that this Decl is being
+ // written to.
+ switch (BO->getOpcode()) {
+ // Self-assignments don't count as use of a variable
+ case BO_Assign: {
+ // Look for a DeclRef on the RHS
+ const Decl *RHSDecl = getDecl(BO->getRHS()->IgnoreParenCasts());
+
+ // If the Decls match, we have self-assignment
+ if (LHSDecl == RHSDecl)
+ // Do not visit the children
+ continue;
+
+ }
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign: {
+ const VarDecl *VD = dyn_cast<VarDecl>(LHSDecl);
+ // The DeclRefExpr is being assigned to - mark it as non-constant
+ if (VD)
+ NonConstants->insert(VD);
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ // Case 2: Pre/post increment/decrement and address of
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(Head);
+
+ // Look for a DeclRef in the subexpression
+ const Decl *D = getDecl(UO->getSubExpr()->IgnoreParenCasts());
+ if (!D)
+ break;
+
+ // We found a unary operator with a DeclRef as a subexpression. We now
+ // check for any of the increment/decrement operators, as well as
+ // addressOf.
+ switch (UO->getOpcode()) {
+ case UO_PostDec:
+ case UO_PostInc:
+ case UO_PreDec:
+ case UO_PreInc:
+ // The DeclRef is being changed - mark it as non-constant
+ case UO_AddrOf: {
+ // If we are taking the address of the DeclRefExpr, assume it is
+ // non-constant.
+ const VarDecl *VD = dyn_cast<VarDecl>(D);
+ if (VD)
+ NonConstants->insert(VD);
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ // Case 3: Reference Declarations
+ case Stmt::DeclStmtClass: {
+ const DeclStmt *DS = cast<DeclStmt>(Head);
+ // Iterate over each decl and see if any of them contain reference decls
+ for (DeclStmt::const_decl_iterator I = DS->decl_begin(),
+ E = DS->decl_end(); I != E; ++I) {
+ // We only care about VarDecls
+ const VarDecl *VD = dyn_cast<VarDecl>(*I);
+ if (!VD)
+ continue;
+
+ // We found a VarDecl; make sure it is a reference type
+ if (!VD->getType().getTypePtr()->isReferenceType())
+ continue;
+
+ // Try to find a Decl in the initializer
+ const Decl *D = getDecl(VD->getInit()->IgnoreParenCasts());
+ if (!D)
+ break;
+
+ // If the reference is to another var, add the var to the non-constant
+ // list
+ if (const VarDecl *RefVD = dyn_cast<VarDecl>(D)) {
+ NonConstants->insert(RefVD);
+ continue;
+ }
+ }
+ break;
+ }
+
+ // Case 4: Block variable references
+ case Stmt::BlockDeclRefExprClass: {
+ const BlockDeclRefExpr *BDR = cast<BlockDeclRefExpr>(Head);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(BDR->getDecl())) {
+ // Add the Decl to the used list
+ UsedVars->insert(VD);
+ continue;
+ }
+ break;
+ }
+
+ // Case 5: Variable references
+ case Stmt::DeclRefExprClass: {
+ const DeclRefExpr *DR = cast<DeclRefExpr>(Head);
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ // Add the Decl to the used list
+ UsedVars->insert(VD);
+ continue;
+ }
+ break;
+ }
+
+ // Case 6: Block expressions
+ case Stmt::BlockExprClass: {
+ const BlockExpr *B = cast<BlockExpr>(Head);
+ // Add the body of the block to the list
+ WorkList.push_back(B->getBody());
+ continue;
+ }
+
+ default:
+ break;
+ } // switch (head->getStmtClass())
+
+ // Add all substatements to the worklist
+ for (Stmt::const_child_iterator I = Head->child_begin(),
+ E = Head->child_end(); I != E; ++I)
+ if (*I)
+ WorkList.push_back(*I);
+ } // while (!WorkList.empty())
+}
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index f959e5cd43e1..05439392f916 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -41,7 +41,7 @@ top:
switch (S->getStmtClass()) {
case Expr::BinaryOperatorClass: {
const BinaryOperator *BO = cast<BinaryOperator>(S);
- if (BO->getOpcode() == BinaryOperator::Comma) {
+ if (BO->getOpcode() == BO_Comma) {
if (sn+1 < b.size())
return b[sn+1].getStmt()->getLocStart();
const CFGBlock *n = &b;
diff --git a/lib/Analysis/ScanfFormatString.cpp b/lib/Analysis/ScanfFormatString.cpp
new file mode 100644
index 000000000000..6a8673ab55ca
--- /dev/null
+++ b/lib/Analysis/ScanfFormatString.cpp
@@ -0,0 +1,221 @@
+//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Handling of format string in scanf and friends. The structure of format
+// strings for fscanf() are described in C99 7.19.6.2.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "FormatStringParsing.h"
+
+using clang::analyze_format_string::ArgTypeResult;
+using clang::analyze_format_string::FormatStringHandler;
+using clang::analyze_format_string::LengthModifier;
+using clang::analyze_format_string::OptionalAmount;
+using clang::analyze_format_string::ConversionSpecifier;
+using clang::analyze_scanf::ScanfConversionSpecifier;
+using clang::analyze_scanf::ScanfSpecifier;
+using clang::UpdateOnReturn;
+
+typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
+ ScanfSpecifierResult;
+
+static bool ParseScanList(FormatStringHandler &H,
+ ScanfConversionSpecifier &CS,
+ const char *&Beg, const char *E) {
+ const char *I = Beg;
+ const char *start = I - 1;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ // No more characters?
+ if (I == E) {
+ H.HandleIncompleteScanList(start, I);
+ return true;
+ }
+
+ // Special case: ']' is the first character.
+ if (*I == ']') {
+ if (++I == E) {
+ H.HandleIncompleteScanList(start, I - 1);
+ return true;
+ }
+ }
+
+ // Look for a ']' character which denotes the end of the scan list.
+ while (*I != ']') {
+ if (++I == E) {
+ H.HandleIncompleteScanList(start, I - 1);
+ return true;
+ }
+ }
+
+ CS.setEndScanList(I);
+ return false;
+}
+
+// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
+// We can possibly refactor.
+static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
+ const char *&Beg,
+ const char *E,
+ unsigned &argIndex) {
+
+ using namespace clang::analyze_scanf;
+ const char *I = Beg;
+ const char *Start = 0;
+ UpdateOnReturn <const char*> UpdateBeg(Beg, I);
+
+ // Look for a '%' character that indicates the start of a format specifier.
+ for ( ; I != E ; ++I) {
+ char c = *I;
+ if (c == '\0') {
+ // Detect spurious null characters, which are likely errors.
+ H.HandleNullChar(I);
+ return true;
+ }
+ if (c == '%') {
+ Start = I++; // Record the start of the format specifier.
+ break;
+ }
+ }
+
+ // No format specifier found?
+ if (!Start)
+ return false;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ ScanfSpecifier FS;
+ if (ParseArgPosition(H, FS, Start, I, E))
+ return true;
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Look for '*' flag if it is present.
+ if (*I == '*') {
+ FS.setSuppressAssignment(I);
+ if (++I == E) {
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ }
+
+ // Look for the field width (if any). Unlike printf, this is either
+ // a fixed integer or isn't present.
+ const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
+ if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
+ assert(Amt.getHowSpecified() == OptionalAmount::Constant);
+ FS.setFieldWidth(Amt);
+
+ if (I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+ }
+
+ // Look for the length modifier.
+ if (ParseLengthModifier(FS, I, E) && I == E) {
+ // No more characters left?
+ H.HandleIncompleteSpecifier(Start, E - Start);
+ return true;
+ }
+
+ // Detect spurious null characters, which are likely errors.
+ if (*I == '\0') {
+ H.HandleNullChar(I);
+ return true;
+ }
+
+ // Finally, look for the conversion specifier.
+ const char *conversionPosition = I++;
+ ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
+ switch (*conversionPosition) {
+ default:
+ break;
+ case '%': k = ConversionSpecifier::PercentArg; break;
+ case 'A': k = ConversionSpecifier::AArg; break;
+ case 'E': k = ConversionSpecifier::EArg; break;
+ case 'F': k = ConversionSpecifier::FArg; break;
+ case 'G': k = ConversionSpecifier::GArg; break;
+ case 'X': k = ConversionSpecifier::XArg; break;
+ case 'a': k = ConversionSpecifier::aArg; break;
+ case 'd': k = ConversionSpecifier::dArg; break;
+ case 'e': k = ConversionSpecifier::eArg; break;
+ case 'f': k = ConversionSpecifier::fArg; break;
+ case 'g': k = ConversionSpecifier::gArg; break;
+ case 'i': k = ConversionSpecifier::iArg; break;
+ case 'n': k = ConversionSpecifier::nArg; break;
+ case 'c': k = ConversionSpecifier::cArg; break;
+ case 'C': k = ConversionSpecifier::CArg; break;
+ case 'S': k = ConversionSpecifier::SArg; break;
+ case '[': k = ConversionSpecifier::ScanListArg; break;
+ case 'u': k = ConversionSpecifier::uArg; break;
+ case 'x': k = ConversionSpecifier::xArg; break;
+ case 'o': k = ConversionSpecifier::oArg; break;
+ case 's': k = ConversionSpecifier::sArg; break;
+ case 'p': k = ConversionSpecifier::pArg; break;
+ }
+ ScanfConversionSpecifier CS(conversionPosition, k);
+ if (k == ScanfConversionSpecifier::ScanListArg) {
+ if (!ParseScanList(H, CS, I, E))
+ return true;
+ }
+ FS.setConversionSpecifier(CS);
+ if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
+ && !FS.usesPositionalArg())
+ FS.setArgIndex(argIndex++);
+
+ // FIXME: '%' and '*' doesn't make sense. Issue a warning.
+ // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
+
+ if (k == ScanfConversionSpecifier::InvalidSpecifier) {
+ // Assume the conversion takes one argument.
+ return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg);
+ }
+ return ScanfSpecifierResult(Start, FS);
+}
+
+bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
+ const char *I,
+ const char *E) {
+
+ unsigned argIndex = 0;
+
+ // Keep looking for a format specifier until we have exhausted the string.
+ while (I != E) {
+ const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex);
+ // Did a fail-stop error of any kind occur when parsing the specifier?
+ // If so, don't do any more processing.
+ if (FSR.shouldStop())
+ return true;;
+ // Did we exhaust the string or encounter an error that
+ // we can recover from?
+ if (!FSR.hasValue())
+ continue;
+ // We have a format specifier. Pass it to the callback.
+ if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
+ I - FSR.getStart())) {
+ return true;
+ }
+ }
+ assert(I == E && "Format string not exhausted");
+ return false;
+}
+
+
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 7a628642dc99..0f43efa58cc0 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -121,7 +121,7 @@ bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
if (VarDecl* VD = FindBlockVarDecl(B->getLHS()))
if (B->isAssignmentOp()) {
- if (B->getOpcode() == BinaryOperator::Assign)
+ if (B->getOpcode() == BO_Assign)
return V(VD,AD) = Visit(B->getRHS());
else // Handle +=, -=, *=, etc. We do want '&', not '&&'.
return V(VD,AD) = Visit(B->getLHS()) & Visit(B->getRHS());
@@ -168,7 +168,7 @@ bool TransferFuncs::VisitCallExpr(CallExpr* C) {
bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
switch (U->getOpcode()) {
- case UnaryOperator::AddrOf: {
+ case UO_AddrOf: {
VarDecl* VD = FindBlockVarDecl(U->getSubExpr());
if (VD && VD->isBlockVarDecl())
return V(VD,AD) = Initialized;
diff --git a/lib/Basic/Builtins.cpp b/lib/Basic/Builtins.cpp
index 1a3293775ed6..040cdb5d55f3 100644
--- a/lib/Basic/Builtins.cpp
+++ b/lib/Basic/Builtins.cpp
@@ -93,3 +93,23 @@ Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx,
return true;
}
+// FIXME: Refactor with isPrintfLike.
+bool
+Builtin::Context::isScanfLike(unsigned ID, unsigned &FormatIdx,
+ bool &HasVAListArg) {
+ const char *Scanf = strpbrk(GetRecord(ID).Attributes, "sS");
+ if (!Scanf)
+ return false;
+
+ HasVAListArg = (*Scanf == 'S');
+
+ ++Scanf;
+ assert(*Scanf == ':' && "s or S specifier must have be followed by a ':'");
+ ++Scanf;
+
+ assert(strchr(Scanf, ':') && "printf specifier must end with a ':'");
+ FormatIdx = strtol(Scanf, 0, 10);
+ return true;
+}
+
+
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 641d87bb9afa..d8095f4f6d54 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -38,6 +38,8 @@ using namespace clang;
// Builtin Diagnostic information
//===----------------------------------------------------------------------===//
+namespace {
+
// Diagnostic classes.
enum {
CLASS_NOTE = 0x01,
@@ -59,11 +61,10 @@ struct StaticDiagInfoRec {
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
- bool operator>(const StaticDiagInfoRec &RHS) const {
- return DiagID > RHS.DiagID;
- }
};
+}
+
static const StaticDiagInfoRec StaticDiagInfo[] = {
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE, CATEGORY) \
{ diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, CATEGORY, DESC, GROUP },
@@ -244,6 +245,9 @@ static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
+ ArgToStringFn = DummyArgToStringFn;
+ ArgToStringCookie = 0;
+
AllExtensionsSilenced = 0;
IgnoreAllWarnings = false;
WarningsAsErrors = false;
@@ -253,26 +257,15 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
ShowOverloads = Ovl_All;
ExtBehavior = Ext_Ignore;
- ErrorOccurred = false;
- FatalErrorOccurred = false;
ErrorLimit = 0;
TemplateBacktraceLimit = 0;
-
- NumWarnings = 0;
- NumErrors = 0;
- NumErrorsSuppressed = 0;
CustomDiagInfo = 0;
- CurDiagID = ~0U;
- LastDiagLevel = Ignored;
-
- ArgToStringFn = DummyArgToStringFn;
- ArgToStringCookie = 0;
-
- DelayedDiagID = 0;
// Set all mappings to 'unset'.
- DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0);
- DiagMappingsStack.push_back(BlankDiags);
+ DiagMappingsStack.clear();
+ DiagMappingsStack.push_back(DiagMappings());
+
+ Reset();
}
Diagnostic::~Diagnostic() {
@@ -331,10 +324,21 @@ bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID,
getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
return false;
- EnabledByDefault = StaticDiagInfo[DiagID].Mapping != diag::MAP_IGNORE;
+ EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
return true;
}
+void Diagnostic::Reset() {
+ ErrorOccurred = false;
+ FatalErrorOccurred = false;
+
+ NumWarnings = 0;
+ NumErrors = 0;
+ NumErrorsSuppressed = 0;
+ CurDiagID = ~0U;
+ LastDiagLevel = Ignored;
+ DelayedDiagID = 0;
+}
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
@@ -572,11 +576,11 @@ bool Diagnostic::ProcessDiag() {
// If a fatal error has already been emitted, silence all subsequent
// diagnostics.
if (FatalErrorOccurred) {
- if (DiagLevel >= Diagnostic::Error) {
+ if (DiagLevel >= Diagnostic::Error && Client->IncludeInDiagnosticCounts()) {
++NumErrors;
++NumErrorsSuppressed;
}
-
+
return false;
}
@@ -597,9 +601,11 @@ bool Diagnostic::ProcessDiag() {
}
if (DiagLevel >= Diagnostic::Error) {
- ErrorOccurred = true;
- ++NumErrors;
-
+ if (Client->IncludeInDiagnosticCounts()) {
+ ErrorOccurred = true;
+ ++NumErrors;
+ }
+
// If we've emitted a lot of errors, emit a fatal error after it to stop a
// flood of bogus errors.
if (ErrorLimit && NumErrors >= ErrorLimit &&
@@ -1146,11 +1152,6 @@ void StoredDiagnostic::Serialize(llvm::raw_ostream &OS) const {
break;
}
- if (F->InsertionLoc.isValid() && F->InsertionLoc.isMacroID()) {
- NumFixIts = 0;
- break;
- }
-
++NumFixIts;
}
@@ -1160,7 +1161,6 @@ void StoredDiagnostic::Serialize(llvm::raw_ostream &OS) const {
WriteSourceLocation(OS, SM, F->RemoveRange.getBegin());
WriteSourceLocation(OS, SM, F->RemoveRange.getEnd());
WriteUnsigned(OS, F->RemoveRange.isTokenRange());
- WriteSourceLocation(OS, SM, F->InsertionLoc);
WriteString(OS, F->CodeToInsert);
}
}
@@ -1288,12 +1288,11 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
if (ReadUnsigned(Memory, MemoryEnd, NumFixIts))
return Diag;
for (unsigned I = 0; I != NumFixIts; ++I) {
- SourceLocation RemoveBegin, RemoveEnd, InsertionLoc;
+ SourceLocation RemoveBegin, RemoveEnd;
unsigned InsertLen = 0, RemoveIsTokenRange;
if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveBegin) ||
ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveEnd) ||
ReadUnsigned(Memory, MemoryEnd, RemoveIsTokenRange) ||
- ReadSourceLocation(FM, SM, Memory, MemoryEnd, InsertionLoc) ||
ReadUnsigned(Memory, MemoryEnd, InsertLen) ||
Memory + InsertLen > MemoryEnd) {
Diag.FixIts.clear();
@@ -1303,7 +1302,6 @@ StoredDiagnostic::Deserialize(FileManager &FM, SourceManager &SM,
FixItHint Hint;
Hint.RemoveRange = CharSourceRange(SourceRange(RemoveBegin, RemoveEnd),
RemoveIsTokenRange);
- Hint.InsertionLoc = InsertionLoc;
Hint.CodeToInsert.assign(Memory, Memory + InsertLen);
Memory += InsertLen;
Diag.FixIts.push_back(Hint);
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 3c91a0f875cc..565f8a61dee6 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/Config/config.h"
@@ -83,6 +84,9 @@ class FileManager::UniqueFileContainer {
public:
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
std::string FullPath(GetFullPath(Name));
+
+ // LowercaseString because Windows filesystem is case insensitive.
+ FullPath = llvm::LowercaseString(FullPath);
return UniqueFiles.GetOrCreateValue(
FullPath.c_str(),
FullPath.c_str() + FullPath.size()
@@ -365,6 +369,18 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
UFE->ModTime = ModificationTime;
UFE->Dir = DirInfo;
UFE->UID = NextFileUID++;
+
+ // If this virtual file resolves to a file, also map that file to the
+ // newly-created file entry.
+ const char *InterndFileName = NamedFileEnt.getKeyData();
+ struct stat StatBuf;
+ if (!stat_cached(InterndFileName, &StatBuf) &&
+ !S_ISDIR(StatBuf.st_mode)) {
+ llvm::sys::Path FilePath(InterndFileName);
+ FilePath.makeAbsolute();
+ FileEntries[FilePath.str()] = UFE;
+ }
+
return UFE;
}
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 8993e6713fbe..6b673e39d365 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -34,6 +34,8 @@ IdentifierInfo::IdentifierInfo() {
IsPoisoned = false;
IsCPPOperatorKeyword = false;
NeedsHandleIdentifier = false;
+ IsFromAST = false;
+ RevertedTokenID = false;
FETokenInfo = 0;
Entry = 0;
}
@@ -71,7 +73,8 @@ namespace {
KEYMS = 32,
BOOLSUPPORT = 64,
KEYALTIVEC = 128,
- KEYNOMS = 256
+ KEYNOMS = 256,
+ KEYBORLAND = 512
};
}
@@ -93,6 +96,7 @@ static void AddKeyword(llvm::StringRef Keyword,
else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2;
else if (LangOpts.GNUKeywords && (Flags & KEYGNU)) AddResult = 1;
else if (LangOpts.Microsoft && (Flags & KEYMS)) AddResult = 1;
+ else if (LangOpts.Borland && (Flags & KEYBORLAND)) AddResult = 1;
else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2;
else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2;
else if (!LangOpts.Microsoft && (Flags & KEYNOMS)) AddResult = 2;
@@ -100,8 +104,7 @@ static void AddKeyword(llvm::StringRef Keyword,
// Don't add this keyword if disabled in this language.
if (AddResult == 0) return;
- IdentifierInfo &Info = Table.get(Keyword);
- Info.setTokenID(TokenCode);
+ IdentifierInfo &Info = Table.get(Keyword, TokenCode);
Info.setIsExtensionToken(AddResult == 1);
}
@@ -110,8 +113,7 @@ static void AddKeyword(llvm::StringRef Keyword,
static void AddCXXOperatorKeyword(llvm::StringRef Keyword,
tok::TokenKind TokenCode,
IdentifierTable &Table) {
- IdentifierInfo &Info = Table.get(Keyword);
- Info.setTokenID(TokenCode);
+ IdentifierInfo &Info = Table.get(Keyword, TokenCode);
Info.setIsCPlusPlusOperatorKeyword();
}
diff --git a/lib/Basic/Makefile b/lib/Basic/Makefile
index 51b8ac1b4569..c15630459567 100644
--- a/lib/Basic/Makefile
+++ b/lib/Basic/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangBasic
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index e6d9785e1505..633d86c1eb8a 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -32,7 +32,8 @@ using llvm::MemoryBuffer;
//===----------------------------------------------------------------------===//
ContentCache::~ContentCache() {
- delete Buffer.getPointer();
+ if (shouldFreeBuffer())
+ delete Buffer.getPointer();
}
/// getSizeBytesMapped - Returns the number of bytes actually mapped for
@@ -51,12 +52,14 @@ unsigned ContentCache::getSize() const {
: (unsigned) Entry->getSize();
}
-void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B) {
+void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B,
+ bool DoNotFree) {
assert(B != Buffer.getPointer());
- delete Buffer.getPointer();
+ if (shouldFreeBuffer())
+ delete Buffer.getPointer();
Buffer.setPointer(B);
- Buffer.setInt(false);
+ Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
}
const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
@@ -72,7 +75,6 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
struct stat FileInfo;
Buffer.setPointer(MemoryBuffer::getFile(Entry->getName(), &ErrorStr,
Entry->getSize(), &FileInfo));
- Buffer.setInt(false);
// If we were unable to open the file, then we are in an inconsistent
// situation where the content cache referenced a file which no longer
@@ -99,7 +101,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
Diag.Report(FullSourceLoc(Loc, SM), diag::err_cannot_open_file)
<< Entry->getName() << ErrorStr;
- Buffer.setInt(true);
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
// FIXME: This conditionalization is horrible, but we see spurious failures
// in the test suite due to this warning and no one has had time to hunt it
@@ -119,14 +121,14 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
Diag.Report(FullSourceLoc(Loc, SM), diag::err_file_modified)
<< Entry->getName();
- Buffer.setInt(true);
+ Buffer.setInt(Buffer.getInt() | InvalidFlag);
#endif
}
// If the buffer is valid, check to see if it has a UTF Byte Order Mark
// (BOM). We only support UTF-8 without a BOM right now. See
// http://en.wikipedia.org/wiki/Byte_order_mark for more information.
- if (!Buffer.getInt()) {
+ if (!isBufferInvalid()) {
llvm::StringRef BufStr = Buffer.getPointer()->getBuffer();
const char *BOM = 0;
if (BufStr.startswith("\xFE\xBB\xBF"))
@@ -161,7 +163,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
}
if (Invalid)
- *Invalid = Buffer.getInt();
+ *Invalid = isBufferInvalid();
return Buffer.getPointer();
}
@@ -422,9 +424,12 @@ void SourceManager::PreallocateSLocEntries(ExternalSLocEntrySource *Source,
unsigned NextOffset) {
ExternalSLocEntries = Source;
this->NextOffset = NextOffset;
+ unsigned CurPrealloc = SLocEntryLoaded.size();
+ // If we've ever preallocated, we must not count the dummy entry.
+ if (CurPrealloc) --CurPrealloc;
SLocEntryLoaded.resize(NumSLocEntries + 1);
SLocEntryLoaded[0] = true;
- SLocEntryTable.resize(SLocEntryTable.size() + NumSLocEntries);
+ SLocEntryTable.resize(SLocEntryTable.size() + NumSLocEntries - CurPrealloc);
}
void SourceManager::ClearPreallocatedSLocEntries() {
@@ -448,7 +453,7 @@ void SourceManager::ClearPreallocatedSLocEntries() {
// Methods to create new FileID's and instantiations.
//===----------------------------------------------------------------------===//
-/// createFileID - Create a new fileID for the specified ContentCache and
+/// createFileID - Create a new FileID for the specified ContentCache and
/// include position. This works regardless of whether the ContentCache
/// corresponds to a file or some other input source.
FileID SourceManager::createFileID(const ContentCache *File,
@@ -521,12 +526,13 @@ SourceManager::getMemoryBufferForFile(const FileEntry *File,
}
bool SourceManager::overrideFileContents(const FileEntry *SourceFile,
- const llvm::MemoryBuffer *Buffer) {
+ const llvm::MemoryBuffer *Buffer,
+ bool DoNotFree) {
const SrcMgr::ContentCache *IR = getOrCreateContentCache(SourceFile);
if (IR == 0)
return true;
- const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer);
+ const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree);
return false;
}
@@ -1241,7 +1247,7 @@ bool SourceManager::isBeforeInTranslationUnit(SourceLocation LHS,
}
// There is no common ancestor, most probably because one location is in the
- // predefines buffer or a PCH file.
+ // predefines buffer or an AST file.
// FIXME: We should rearrange the external interface so this simply never
// happens; it can't conceptually happen. Also see PR5662.
IsBeforeInTUCache.setQueryFIDs(FileID(), FileID()); // Don't try caching.
diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp
index 7fcf372a368c..6d42883cd13c 100644
--- a/lib/Basic/TargetInfo.cpp
+++ b/lib/Basic/TargetInfo.cpp
@@ -58,6 +58,9 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {
// Default to no types using fpret.
RealTypeUsesObjCFPRet = 0;
+
+ // Default to using the Itanium ABI.
+ CXXABI = CXXABI_Itanium;
}
// Out of line virtual dtor for TargetInfo.
@@ -287,8 +290,15 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
Info.setAllowsRegister();
Info.setAllowsMemory();
break;
- case ',': // FIXME: Until we handle multiple alternative constraints,
- return true; // ignore everything after the first comma.
+ case ',': // multiple alternative constraint. Pass it.
+ Name++;
+ // Handle additional optional '=' or '+' modifiers.
+ if (*Name == '=' || *Name == '+')
+ Name++;
+ break;
+ case '?': // Disparage slightly code.
+ case '!': // Disparage severly.
+ break; // Pass them.
}
Name++;
@@ -352,6 +362,7 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
if (!resolveSymbolicName(Name, OutputConstraints, NumOutputs, Index))
return false;
+ Info.setTiedOperand(Index, OutputConstraints[Index]);
break;
}
case '%': // commutative
@@ -382,8 +393,11 @@ bool TargetInfo::validateInputConstraint(ConstraintInfo *OutputConstraints,
Info.setAllowsRegister();
Info.setAllowsMemory();
break;
- case ',': // FIXME: Until we handle multiple alternative constraints,
- return true; // ignore everything after the first comma.
+ case ',': // multiple alternative constraint. Ignore comma.
+ break;
+ case '?': // Disparage slightly code.
+ case '!': // Disparage severly.
+ break; // Pass them.
}
Name++;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index fdf63e738b53..df20defa0fc0 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -502,7 +502,7 @@ public:
// is therefore only safe to use `m' in an asm statement
// if that asm statement accesses the operand exactly once.
// The asm statement must also use `%U<opno>' as a
- // placeholder for the “update” flag in the corresponding
+ // placeholder for the "update" flag in the corresponding
// load or store instruction. For example:
// asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));
// is correct but:
@@ -512,7 +512,7 @@ public:
case 'e':
if (Name[1] != 's')
return false;
- // es: A “stable” memory operand; that is, one which does not
+ // es: A "stable" memory operand; that is, one which does not
// include any automodification of the base register. Unlike
// `m', this constraint can be used in asm statements that
// might access the operand several times, or that might not
@@ -912,11 +912,12 @@ class X86TargetInfo : public TargetInfo {
} AMD3DNowLevel;
bool HasAES;
-
+ bool HasAVX;
+
public:
X86TargetInfo(const std::string& triple)
: TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow),
- HasAES(false) {
+ HasAES(false), HasAVX(false) {
LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
}
virtual void getTargetBuiltins(const Builtin::Info *&Records,
@@ -963,6 +964,7 @@ void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
Features["sse41"] = false;
Features["sse42"] = false;
Features["aes"] = false;
+ Features["avx"] = false;
// LLVM does not currently recognize this.
// Features["sse4a"] = false;
@@ -1046,6 +1048,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["3dnow"] = Features["3dnowa"] = true;
else if (Name == "aes")
Features["aes"] = true;
+ else if (Name == "avx")
+ Features["avx"] = true;
} else {
if (Name == "mmx")
Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
@@ -1073,6 +1077,8 @@ bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
Features["3dnowa"] = false;
else if (Name == "aes")
Features["aes"] = false;
+ else if (Name == "avx")
+ Features["avx"] = false;
}
return true;
@@ -1092,6 +1098,13 @@ void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
continue;
}
+ // FIXME: Not sure yet how to treat AVX in regard to SSE levels.
+ // For now let it be enabled together with other SSE levels.
+ if (Features[i].substr(1) == "avx") {
+ HasAVX = true;
+ continue;
+ }
+
assert(Features[i][0] == '+' && "Invalid target feature!");
X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Features[i].substr(1))
.Case("sse42", SSE42)
@@ -1133,6 +1146,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasAES)
Builder.defineMacro("__AES__");
+ if (HasAVX)
+ Builder.defineMacro("__AVX__");
+
// Target properties.
Builder.defineMacro("__LITTLE_ENDIAN__");
@@ -1186,6 +1202,15 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
default: return false;
+ case 'Y': // first letter of a pair:
+ switch (*(Name+1)) {
+ default: return false;
+ case '0': // First SSE register.
+ case 't': // Any SSE register, when SSE2 is enabled.
+ case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+ case 'm': // any MMX register, when inter-unit moves enabled.
+ break; // falls through to setAllowsRegister.
+ }
case 'a': // eax.
case 'b': // ebx.
case 'c': // ecx.
@@ -1193,22 +1218,27 @@ X86TargetInfo::validateAsmConstraint(const char *&Name,
case 'S': // esi.
case 'D': // edi.
case 'A': // edx:eax.
+ case 'f': // any x87 floating point stack register.
case 't': // top of floating point stack.
case 'u': // second from top of floating point stack.
case 'q': // Any register accessible as [r]l: a, b, c, and d.
case 'y': // Any MMX register.
case 'x': // Any SSE register.
case 'Q': // Any register accessible as [r]h: a, b, c, and d.
+ case 'R': // "Legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
+ case 'l': // "Index" registers: any general register that can be used as an
+ // index in a base+index memory access.
+ Info.setAllowsRegister();
+ return true;
+ case 'C': // SSE floating point constant.
+ case 'G': // x87 floating point constant.
case 'e': // 32-bit signed integer constant for use with zero-extending
// x86_64 instructions.
case 'Z': // 32-bit unsigned integer constant for use with zero-extending
// x86_64 instructions.
- case 'N': // unsigned 8-bit integer constant for use with in and out
- // instructions.
- case 'R': // "legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
- Info.setAllowsRegister();
return true;
}
+ return false;
}
std::string
@@ -1333,6 +1363,8 @@ public:
// 300=386, 400=486, 500=Pentium, 600=Blend (default)
// We lost the original triple, so we use the default.
Builder.defineMacro("_M_IX86", "600");
+ Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
+ Builder.defineMacro("_STDCALL_SUPPORTED");
}
};
} // end anonymous namespace
@@ -1388,7 +1420,7 @@ public:
SizeType = UnsignedLong;
IntPtrType = SignedLong;
PtrDiffType = SignedLong;
- }
+ }
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
X86_32TargetInfo::getTargetDefines(Opts, Builder);
@@ -1447,7 +1479,10 @@ public:
TLSSupported = false;
WCharType = UnsignedShort;
LongWidth = LongAlign = 32;
- DoubleAlign = LongLongAlign = 64;
+ DoubleAlign = LongLongAlign = 64;
+ IntMaxType = SignedLongLong;
+ UIntMaxType = UnsignedLongLong;
+ Int64Type = SignedLongLong;
}
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
@@ -1469,9 +1504,10 @@ public:
MacroBuilder &Builder) const {
WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
Builder.defineMacro("_M_X64");
+ Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
}
virtual const char *getVAListDeclaration() const {
- return "typedef char* va_list;";
+ return "typedef char* __builtin_va_list;";
}
};
} // end anonymous namespace
@@ -1566,6 +1602,9 @@ public:
"i64:64:64-f32:32:32-f64:64:64-"
"v64:64:64-v128:128:128-a0:0:64-n32");
}
+
+ // ARM targets default to using the ARM C++ ABI.
+ CXXABI = CXXABI_ARM;
}
virtual const char *getABI() const { return ABI.c_str(); }
virtual bool setABI(const std::string &Name) {
@@ -1769,18 +1808,27 @@ public:
};
const char * const ARMTargetInfo::GCCRegNames[] = {
+ // Integer registers
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
+
+ // Float registers
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"
+
+ // FIXME: Need double and NEON registers, but we need support for aliasing
+ // multiple registers for that.
};
void ARMTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
+ unsigned &NumNames) const {
Names = GCCRegNames;
NumNames = llvm::array_lengthof(GCCRegNames);
}
const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
-
{ { "a1" }, "r0" },
{ { "a2" }, "r1" },
{ { "a3" }, "r2" },
@@ -1794,9 +1842,9 @@ const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
{ { "sl" }, "r10" },
{ { "fp" }, "r11" },
{ { "ip" }, "r12" },
- { { "sp" }, "r13" },
- { { "lr" }, "r14" },
- { { "pc" }, "r15" },
+ { { "r13" }, "sp" },
+ { { "r14" }, "lr" },
+ { { "r15" }, "pc" },
};
void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
@@ -2603,7 +2651,7 @@ TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags,
}
// Set the target C++ ABI.
- if (!Target->setCXXABI(Opts.CXXABI)) {
+ if (!Opts.CXXABI.empty() && !Target->setCXXABI(Opts.CXXABI)) {
Diags.Report(diag::err_target_unknown_cxxabi) << Opts.CXXABI;
return 0;
}
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index e0c23362b930..3e6d222b621f 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -21,7 +21,7 @@ using namespace std;
namespace clang {
llvm::StringRef getClangRepositoryPath() {
- static const char URL[] = "$URL: http://llvm.org/svn/llvm-project/cfe/trunk/lib/Basic/Version.cpp $";
+ static const char URL[] = "$URL: http://llvm.org/svn/llvm-project/cfe/branches/release_28/lib/Basic/Version.cpp $";
const char *URLEnd = URL + strlen(URL);
const char *End = strstr(URL, "/lib/Basic");
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index bc2cd460d92b..bd5e342e028f 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -8,6 +8,8 @@ add_subdirectory(CodeGen)
add_subdirectory(Analysis)
add_subdirectory(Rewrite)
add_subdirectory(Driver)
+add_subdirectory(Serialization)
add_subdirectory(Frontend)
+add_subdirectory(FrontendTool)
add_subdirectory(Index)
add_subdirectory(Checker)
diff --git a/lib/Checker/AdjustedReturnValueChecker.cpp b/lib/Checker/AdjustedReturnValueChecker.cpp
index b92f2e705625..0ed04fb14aba 100644
--- a/lib/Checker/AdjustedReturnValueChecker.cpp
+++ b/lib/Checker/AdjustedReturnValueChecker.cpp
@@ -70,8 +70,7 @@ void AdjustedReturnValueChecker::PostVisitCallExpr(CheckerContext &C,
}
else if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(callee)) {
const BlockTextRegion *BR = BD->getCodeRegion();
- const BlockPointerType *BT =
- BR->getLocationType(C.getASTContext())->getAs<BlockPointerType>();
+ const BlockPointerType *BT=BR->getLocationType()->getAs<BlockPointerType>();
const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
actualResultTy = FT->getResultType();
}
diff --git a/lib/Checker/AggExprVisitor.cpp b/lib/Checker/AggExprVisitor.cpp
index 343afec18d21..6d472f46b45a 100644
--- a/lib/Checker/AggExprVisitor.cpp
+++ b/lib/Checker/AggExprVisitor.cpp
@@ -18,6 +18,13 @@
using namespace clang;
namespace {
+/// AggExprVisitor is designed after AggExprEmitter of the CodeGen module. It
+/// is used for evaluating exprs of C++ object type. Evaluating such exprs
+/// requires a destination pointer pointing to the object being evaluated
+/// into. Passing such a pointer around would pollute the Visit* interface of
+/// GRExprEngine. AggExprVisitor encapsulates code that goes through various
+/// cast and construct exprs (and others), and at the final point, dispatches
+/// back to the GRExprEngine to let the real evaluation logic happen.
class AggExprVisitor : public StmtVisitor<AggExprVisitor> {
SVal DestPtr;
ExplodedNode *Pred;
@@ -38,8 +45,8 @@ void AggExprVisitor::VisitCastExpr(CastExpr *E) {
switch (E->getCastKind()) {
default:
assert(0 && "Unhandled cast kind");
- case CastExpr::CK_NoOp:
- case CastExpr::CK_ConstructorConversion:
+ case CK_NoOp:
+ case CK_ConstructorConversion:
Visit(E->getSubExpr());
break;
}
diff --git a/lib/Checker/AnalysisConsumer.cpp b/lib/Checker/AnalysisConsumer.cpp
index 524f37e39662..ad5ccb503b24 100644
--- a/lib/Checker/AnalysisConsumer.cpp
+++ b/lib/Checker/AnalysisConsumer.cpp
@@ -29,6 +29,7 @@
#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
#include "clang/Checker/PathDiagnosticClients.h"
#include "GRExprEngineExperimentalChecks.h"
+#include "GRExprEngineInternalChecks.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/AnalyzerOptions.h"
@@ -173,10 +174,12 @@ public:
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
+ /* Indexer */ 0,
Opts.MaxNodes, Opts.MaxLoop,
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
Opts.PurgeDead, Opts.EagerlyAssume,
- Opts.TrimGraph, Opts.InlineCall));
+ Opts.TrimGraph, Opts.InlineCall,
+ Opts.UnoptimizedCFG));
}
virtual void HandleTranslationUnit(ASTContext &C);
@@ -341,7 +344,10 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
if (C.Opts.EnableExperimentalChecks)
RegisterExperimentalChecks(Eng);
- if (C.Opts.EnableIdempotentOperationChecker)
+ // Enable idempotent operation checking if it was explicitly turned on, or if
+ // we are running experimental checks (i.e. everything)
+ if (C.Opts.IdempotentOps || C.Opts.EnableExperimentalChecks
+ || C.Opts.EnableExperimentalInternalChecks)
RegisterIdempotentOperationChecker(Eng);
// Set the graph auditor.
@@ -352,7 +358,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
}
// Execute the worklist algorithm.
- Eng.ExecuteWorkList(mgr.getStackFrame(D), mgr.getMaxNodes());
+ Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
diff --git a/lib/Checker/AnalysisManager.cpp b/lib/Checker/AnalysisManager.cpp
new file mode 100644
index 000000000000..339cdab80bdb
--- /dev/null
+++ b/lib/Checker/AnalysisManager.cpp
@@ -0,0 +1,31 @@
+//===-- AnalysisManager.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/Indexer.h"
+
+using namespace clang;
+
+const AnalysisContext *
+AnalysisManager::getAnalysisContextInAnotherTU(const Decl *D) {
+ idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D),
+ Idxer->getProgram());
+ FunctionDecl *FuncDef;
+ idx::TranslationUnit *TU;
+ llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent);
+
+ if (FuncDef == 0)
+ return 0;
+
+ // This AnalysisContext wraps function definition in another translation unit.
+ // But it is still owned by the AnalysisManager associated with the current
+ // translation unit.
+ return AnaCtxMgr.getContext(FuncDef, TU);
+}
diff --git a/lib/Checker/ArrayBoundChecker.cpp b/lib/Checker/ArrayBoundChecker.cpp
index 746b3f95d41e..98345bd70375 100644
--- a/lib/Checker/ArrayBoundChecker.cpp
+++ b/lib/Checker/ArrayBoundChecker.cpp
@@ -58,7 +58,7 @@ void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
// Get the size of the array.
DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
- ER->getValueType(C.getASTContext()));
+ ER->getValueType());
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
diff --git a/lib/Checker/BasicObjCFoundationChecks.cpp b/lib/Checker/BasicObjCFoundationChecks.cpp
index ecb2d1c4e34b..3c1a6d1c8282 100644
--- a/lib/Checker/BasicObjCFoundationChecks.cpp
+++ b/lib/Checker/BasicObjCFoundationChecks.cpp
@@ -73,9 +73,6 @@ class BasicObjCFoundationChecks : public GRSimpleAPICheck {
bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);
bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);
- void Warn(ExplodedNode* N, const Expr* E, const std::string& s);
- void WarnNilArg(ExplodedNode* N, const Expr* E);
-
bool CheckNilArg(ExplodedNode* N, unsigned Arg);
public:
@@ -358,7 +355,7 @@ bool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){
if (!R)
return false;
- QualType T = Ctx.getCanonicalType(R->getValueType(Ctx));
+ QualType T = Ctx.getCanonicalType(R->getValueType());
// FIXME: If the pointee isn't an integer type, should we flag a warning?
// People can do weird stuff with pointers.
diff --git a/lib/Checker/BasicStore.cpp b/lib/Checker/BasicStore.cpp
index 62c8d9c248ae..f82e1b20be9b 100644
--- a/lib/Checker/BasicStore.cpp
+++ b/lib/Checker/BasicStore.cpp
@@ -52,7 +52,7 @@ public:
Store InvalidateRegions(Store store, const MemRegion * const *Begin,
const MemRegion * const *End, const Expr *E,
unsigned Count, InvalidatedSymbols *IS,
- bool invalidateGlobals);
+ bool invalidateGlobals, InvalidatedRegions *Regions);
Store scanForIvars(Stmt *B, const Decl* SelfDecl,
const MemRegion *SelfRegion, Store St);
@@ -61,11 +61,6 @@ public:
Store Remove(Store St, Loc loc);
Store getInitialStore(const LocationContext *InitLoc);
- // FIXME: Investigate what is using this. This method should be removed.
- virtual Loc getLoc(const VarDecl* VD, const LocationContext *LC) {
- return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC));
- }
-
Store BindCompoundLiteral(Store store, const CompoundLiteralExpr*,
const LocationContext*, SVal val) {
return store;
@@ -77,9 +72,8 @@ public:
/// RemoveDeadBindings - Scans a BasicStore of 'state' for dead values.
/// It updatees the GRState object in place with the values removed.
- const GRState *RemoveDeadBindings(GRState &state,
- const StackFrameContext *LCtx,
- SymbolReaper& SymReaper,
+ Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
void iterBindings(Store store, BindingsHandler& f);
@@ -103,8 +97,6 @@ public:
private:
SVal LazyRetrieve(Store store, const TypedRegion *R);
-
- ASTContext& getContext() { return StateMgr.getContext(); }
};
} // end anonymous namespace
@@ -228,17 +220,15 @@ Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
return VBFactory.Add(B, R, V).getRoot();
}
- ASTContext &C = StateMgr.getContext();
-
// Special case: handle store of pointer values (Loc) to pointers via
// a cast to intXX_t*, void*, etc. This is needed to handle
// OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
// FIXME: Should check for index 0.
- QualType T = ER->getLocationType(C);
+ QualType T = ER->getLocationType();
- if (isHigherOrderRawPtr(T, C))
+ if (isHigherOrderRawPtr(T, Ctx))
R = ER->getSuperRegion();
}
@@ -249,7 +239,7 @@ Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
// Do not bind to arrays. We need to explicitly check for this so that
// we do not encounter any weirdness of trying to load/store from arrays.
- if (TyR->isBoundable() && TyR->getValueType(C)->isArrayType())
+ if (TyR->isBoundable() && TyR->getValueType()->isArrayType())
return store;
if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
@@ -259,7 +249,7 @@ Store BasicStoreManager::Bind(Store store, Loc loc, SVal V) {
// a pointer. We may wish to flag a type error here if the types
// are incompatible. This may also cause lots of breakage
// elsewhere. Food for thought.
- if (TyR->isBoundable() && Loc::IsLocType(TyR->getValueType(C)))
+ if (TyR->isBoundable() && Loc::IsLocType(TyR->getValueType()))
V = X->getLoc();
}
@@ -285,12 +275,11 @@ Store BasicStoreManager::Remove(Store store, Loc loc) {
}
}
-const GRState *BasicStoreManager::RemoveDeadBindings(GRState &state,
+Store BasicStoreManager::RemoveDeadBindings(Store store,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
- Store store = state.getStore();
BindingsTy B = GetBindings(store);
typedef SVal::symbol_iterator symbol_iterator;
@@ -365,8 +354,7 @@ const GRState *BasicStoreManager::RemoveDeadBindings(GRState &state,
}
}
- state.setStore(store);
- return StateMgr.getPersistentState(state);
+ return store;
}
Store BasicStoreManager::scanForIvars(Stmt *B, const Decl* SelfDecl,
@@ -406,10 +394,10 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
Store St = VBFactory.GetEmptyMap().getRoot();
for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
- NamedDecl* ND = const_cast<NamedDecl*>(I->first);
+ const NamedDecl* ND = I->first;
// Handle implicit parameters.
- if (ImplicitParamDecl* PD = dyn_cast<ImplicitParamDecl>(ND)) {
+ if (const ImplicitParamDecl* PD = dyn_cast<ImplicitParamDecl>(ND)) {
const Decl& CD = *InitLoc->getDecl();
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CD)) {
if (MD->getSelfDecl() == PD) {
@@ -449,11 +437,11 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
// will not be called more than once.
// Static global variables should not be visited here.
- assert(!(VD->getStorageClass() == VarDecl::Static &&
+ assert(!(VD->getStorageClass() == SC_Static &&
VD->isFileVarDecl()));
// Process static variables.
- if (VD->getStorageClass() == VarDecl::Static) {
+ if (VD->getStorageClass() == SC_Static) {
// C99: 6.7.8 Initialization
// If an object that has static storage duration is not initialized
// explicitly, then:
@@ -465,12 +453,9 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
if (Loc::IsLocType(T))
store = Bind(store, loc::MemRegionVal(VR),
loc::ConcreteInt(BasicVals.getValue(0, T)));
- else if (T->isIntegerType())
+ else if (T->isIntegerType() && T->isScalarType())
store = Bind(store, loc::MemRegionVal(VR),
nonloc::ConcreteInt(BasicVals.getValue(0, T)));
- else {
- // assert(0 && "ignore other types of variables");
- }
} else {
store = Bind(store, loc::MemRegionVal(VR), *InitVal);
}
@@ -478,7 +463,8 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarRegion* VR,
} else {
// Process local scalar variables.
QualType T = VD->getType();
- if (ValMgr.getSymbolManager().canSymbolicate(T)) {
+ // BasicStore only supports scalars.
+ if (T->isScalarType() && ValMgr.getSymbolManager().canSymbolicate(T)) {
SVal V = InitVal ? *InitVal : UndefinedVal();
store = Bind(store, loc::MemRegionVal(VR), V);
}
@@ -523,11 +509,12 @@ StoreManager::BindingsHandler::~BindingsHandler() {}
Store BasicStoreManager::InvalidateRegions(Store store,
- const MemRegion * const *I,
- const MemRegion * const *End,
- const Expr *E, unsigned Count,
- InvalidatedSymbols *IS,
- bool invalidateGlobals) {
+ const MemRegion * const *I,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
if (invalidateGlobals) {
BindingsTy B = GetBindings(store);
for (BindingsTy::iterator I=B.begin(), End=B.end(); I != End; ++I) {
@@ -545,6 +532,8 @@ Store BasicStoreManager::InvalidateRegions(Store store,
continue;
}
store = InvalidateRegion(store, *I, E, Count, IS);
+ if (Regions)
+ Regions->push_back(R);
}
// FIXME: This is copy-and-paste from RegionStore.cpp.
@@ -558,6 +547,8 @@ Store BasicStoreManager::InvalidateRegions(Store store,
Count);
store = Bind(store, loc::MemRegionVal(GS), V);
+ if (Regions)
+ Regions->push_back(GS);
}
return store;
@@ -582,7 +573,7 @@ Store BasicStoreManager::InvalidateRegion(Store store,
}
}
- QualType T = cast<TypedRegion>(R)->getValueType(R->getContext());
+ QualType T = cast<TypedRegion>(R)->getValueType();
SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count);
return Bind(store, loc::MemRegionVal(R), V);
}
diff --git a/lib/Checker/BasicValueFactory.cpp b/lib/Checker/BasicValueFactory.cpp
index 246beead1208..4c9b109c8823 100644
--- a/lib/Checker/BasicValueFactory.cpp
+++ b/lib/Checker/BasicValueFactory.cpp
@@ -149,22 +149,22 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
default:
assert (false && "Invalid Opcode.");
- case BinaryOperator::Mul:
+ case BO_Mul:
return &getValue( V1 * V2 );
- case BinaryOperator::Div:
+ case BO_Div:
return &getValue( V1 / V2 );
- case BinaryOperator::Rem:
+ case BO_Rem:
return &getValue( V1 % V2 );
- case BinaryOperator::Add:
+ case BO_Add:
return &getValue( V1 + V2 );
- case BinaryOperator::Sub:
+ case BO_Sub:
return &getValue( V1 - V2 );
- case BinaryOperator::Shl: {
+ case BO_Shl: {
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
@@ -182,7 +182,7 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
return &getValue( V1.operator<<( (unsigned) Amt ));
}
- case BinaryOperator::Shr: {
+ case BO_Shr: {
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
@@ -200,33 +200,33 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
return &getValue( V1.operator>>( (unsigned) Amt ));
}
- case BinaryOperator::LT:
+ case BO_LT:
return &getTruthValue( V1 < V2 );
- case BinaryOperator::GT:
+ case BO_GT:
return &getTruthValue( V1 > V2 );
- case BinaryOperator::LE:
+ case BO_LE:
return &getTruthValue( V1 <= V2 );
- case BinaryOperator::GE:
+ case BO_GE:
return &getTruthValue( V1 >= V2 );
- case BinaryOperator::EQ:
+ case BO_EQ:
return &getTruthValue( V1 == V2 );
- case BinaryOperator::NE:
+ case BO_NE:
return &getTruthValue( V1 != V2 );
// Note: LAnd, LOr, Comma are handled specially by higher-level logic.
- case BinaryOperator::And:
+ case BO_And:
return &getValue( V1 & V2 );
- case BinaryOperator::Or:
+ case BO_Or:
return &getValue( V1 | V2 );
- case BinaryOperator::Xor:
+ case BO_Xor:
return &getValue( V1 ^ V2 );
}
}
diff --git a/lib/Checker/BugReporter.cpp b/lib/Checker/BugReporter.cpp
index 0422d80ae26d..bffbd52b7d88 100644
--- a/lib/Checker/BugReporter.cpp
+++ b/lib/Checker/BugReporter.cpp
@@ -94,8 +94,8 @@ static const Stmt* GetNextStmt(const ExplodedNode* N) {
case Stmt::ChooseExprClass:
case Stmt::ConditionalOperatorClass: continue;
case Stmt::BinaryOperatorClass: {
- BinaryOperator::Opcode Op = cast<BinaryOperator>(S)->getOpcode();
- if (Op == BinaryOperator::LAnd || Op == BinaryOperator::LOr)
+ BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
+ if (Op == BO_LAnd || Op == BO_LOr)
continue;
break;
}
@@ -177,18 +177,9 @@ public:
}
virtual NodeMapClosure& getNodeResolver() { return NMC; }
- BugReport& getReport() { return *R; }
PathDiagnosticLocation getEnclosingStmtLocation(const Stmt *S);
- PathDiagnosticLocation
- getEnclosingStmtLocation(const PathDiagnosticLocation &L) {
- if (const Stmt *S = L.asStmt())
- return getEnclosingStmtLocation(S);
-
- return L;
- }
-
PathDiagnosticClient::PathGenerationScheme getGenerationScheme() const {
return PDC ? PDC->getGenerationScheme() : PathDiagnosticClient::Extensive;
}
@@ -541,9 +532,9 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
ProgramPoint P = N->getLocation();
if (const BlockEdge* BE = dyn_cast<BlockEdge>(&P)) {
- CFGBlock* Src = BE->getSrc();
- CFGBlock* Dst = BE->getDst();
- Stmt* T = Src->getTerminator();
+ const CFGBlock* Src = BE->getSrc();
+ const CFGBlock* Dst = BE->getDst();
+ const Stmt* T = Src->getTerminator();
if (!T)
continue;
@@ -577,7 +568,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
- if (Stmt* S = Dst->getLabel()) {
+ if (const Stmt* S = Dst->getLabel()) {
PathDiagnosticLocation End(S, SMgr);
switch (S->getStmtClass()) {
@@ -593,17 +584,17 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
case Stmt::CaseStmtClass: {
os << "Control jumps to 'case ";
- CaseStmt* Case = cast<CaseStmt>(S);
- Expr* LHS = Case->getLHS()->IgnoreParenCasts();
+ const CaseStmt* Case = cast<CaseStmt>(S);
+ const Expr* LHS = Case->getLHS()->IgnoreParenCasts();
// Determine if it is an enum.
bool GetRawInt = true;
- if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
+ if (const DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) {
// FIXME: Maybe this should be an assertion. Are there cases
// were it is not an EnumConstantDecl?
- EnumConstantDecl* D =
- dyn_cast<EnumConstantDecl>(DR->getDecl());
+ const EnumConstantDecl* D =
+ dyn_cast<EnumConstantDecl>(DR->getDecl());
if (D) {
GetRawInt = false;
@@ -668,12 +659,12 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
if (!PDB.supportsLogicalOpControlFlow())
break;
- BinaryOperator *B = cast<BinaryOperator>(T);
+ const BinaryOperator *B = cast<BinaryOperator>(T);
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
os << "Left side of '";
- if (B->getOpcode() == BinaryOperator::LAnd) {
+ if (B->getOpcode() == BO_LAnd) {
os << "&&" << "' is ";
if (*(Src->succ_begin()+1) == Dst) {
@@ -692,7 +683,7 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD,
}
}
else {
- assert(B->getOpcode() == BinaryOperator::LOr);
+ assert(B->getOpcode() == BO_LOr);
os << "||" << "' is ";
if (*(Src->succ_begin()+1) == Dst) {
@@ -902,8 +893,6 @@ class EdgeBuilder {
CLocs.pop_back();
}
- PathDiagnosticLocation IgnoreParens(const PathDiagnosticLocation &L);
-
public:
EdgeBuilder(PathDiagnostic &pd, PathDiagnosticBuilder &pdb)
: PD(pd), PDB(pdb) {
@@ -935,10 +924,6 @@ public:
void addEdge(PathDiagnosticLocation NewLoc, bool alwaysAdd = false);
- void addEdge(const Stmt *S, bool alwaysAdd = false) {
- addEdge(PathDiagnosticLocation(S, PDB.getSourceManager()), alwaysAdd);
- }
-
void rawAddEdge(PathDiagnosticLocation NewLoc);
void addContext(const Stmt *S);
@@ -1006,14 +991,6 @@ bool EdgeBuilder::containsLocation(const PathDiagnosticLocation &Container,
SM.getInstantiationColumnNumber(ContainerREnd)));
}
-PathDiagnosticLocation
-EdgeBuilder::IgnoreParens(const PathDiagnosticLocation &L) {
- if (const Expr* E = dyn_cast_or_null<Expr>(L.asStmt()))
- return PathDiagnosticLocation(E->IgnoreParenCasts(),
- PDB.getSourceManager());
- return L;
-}
-
void EdgeBuilder::rawAddEdge(PathDiagnosticLocation NewLoc) {
if (!PrevLoc.isValid()) {
PrevLoc = NewLoc;
diff --git a/lib/Checker/BugReporterVisitors.cpp b/lib/Checker/BugReporterVisitors.cpp
index 776e12bd2ae4..91cf349107ca 100644
--- a/lib/Checker/BugReporterVisitors.cpp
+++ b/lib/Checker/BugReporterVisitors.cpp
@@ -31,7 +31,7 @@ const Stmt *clang::bugreporter::GetDerefExpr(const ExplodedNode *N) {
const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
if (const UnaryOperator *U = dyn_cast<UnaryOperator>(S)) {
- if (U->getOpcode() == UnaryOperator::Deref)
+ if (U->getOpcode() == UO_Deref)
return U->getSubExpr()->IgnoreParenCasts();
}
else if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) {
@@ -143,10 +143,9 @@ public:
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
- ASTContext &C = BRC.getASTContext();
if (R->isBoundable()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
- if (TR->getValueType(C)->isObjCObjectPointerType()) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
os << "initialized to nil";
b = true;
}
@@ -174,10 +173,9 @@ public:
if (os.str().empty()) {
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
- ASTContext &C = BRC.getASTContext();
if (R->isBoundable()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
- if (TR->getValueType(C)->isObjCObjectPointerType()) {
+ if (TR->getValueType()->isObjCObjectPointerType()) {
os << "nil object reference stored to ";
b = true;
}
@@ -209,7 +207,7 @@ public:
ProgramPoint P = N->getLocation();
if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
- CFGBlock *BSrc = BE->getSrc();
+ const CFGBlock *BSrc = BE->getSrc();
S = BSrc->getTerminatorCondition();
}
else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
@@ -282,7 +280,7 @@ public:
ProgramPoint P = N->getLocation();
if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
- CFGBlock *BSrc = BE->getSrc();
+ const CFGBlock *BSrc = BE->getSrc();
S = BSrc->getTerminatorCondition();
}
else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
@@ -421,3 +419,40 @@ public:
void clang::bugreporter::registerNilReceiverVisitor(BugReporterContext &BRC) {
BRC.addVisitor(new NilReceiverVisitor());
}
+
+// Registers every VarDecl inside a Stmt with a last store vistor.
+void clang::bugreporter::registerVarDeclsLastStore(BugReporterContext &BRC,
+ const void *stmt,
+ const ExplodedNode *N) {
+ const Stmt *S = static_cast<const Stmt *>(stmt);
+
+ std::deque<const Stmt *> WorkList;
+
+ WorkList.push_back(S);
+
+ while (!WorkList.empty()) {
+ const Stmt *Head = WorkList.front();
+ WorkList.pop_front();
+
+ GRStateManager &StateMgr = BRC.getStateManager();
+ const GRState *state = N->getState();
+
+ if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
+ const VarRegion *R =
+ StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
+
+ // What did we load?
+ SVal V = state->getSVal(S);
+
+ if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
+ ::registerFindLastStore(BRC, R, V);
+ }
+ }
+ }
+
+ for (Stmt::const_child_iterator I = Head->child_begin();
+ I != Head->child_end(); ++I)
+ WorkList.push_back(*I);
+ }
+}
diff --git a/lib/Checker/CFRefCount.cpp b/lib/Checker/CFRefCount.cpp
index 3c74cd8f9b27..6fa48b2923fe 100644
--- a/lib/Checker/CFRefCount.cpp
+++ b/lib/Checker/CFRefCount.cpp
@@ -82,8 +82,7 @@ public:
static const ObjCMethodDecl*
ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
- ObjCInterfaceDecl *ID =
- const_cast<ObjCInterfaceDecl*>(MD->getClassInterface());
+ const ObjCInterfaceDecl *ID = MD->getClassInterface();
return MD->isInstanceMethod()
? ID->lookupInstanceMethod(MD->getSelector())
@@ -93,11 +92,11 @@ ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
namespace {
class GenericNodeBuilder {
GRStmtNodeBuilder *SNB;
- Stmt *S;
+ const Stmt *S;
const void *tag;
GREndPathNodeBuilder *ENB;
public:
- GenericNodeBuilder(GRStmtNodeBuilder &snb, Stmt *s,
+ GenericNodeBuilder(GRStmtNodeBuilder &snb, const Stmt *s,
const void *t)
: SNB(&snb), S(s), tag(t), ENB(0) {}
@@ -195,12 +194,6 @@ public:
static RetEffect MakeNoRet() {
return RetEffect(NoRet);
}
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.AddInteger((unsigned)K);
- ID.AddInteger((unsigned)O);
- ID.AddInteger(index);
- }
};
//===----------------------------------------------------------------------===//
@@ -239,9 +232,6 @@ private:
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; }
@@ -256,12 +246,6 @@ public:
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;
}
@@ -278,11 +262,6 @@ public:
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);
@@ -474,11 +453,6 @@ public:
DefaultArgEffect = E;
}
- /// setArg - Set the argument effect on the argument specified by idx.
- void setArgEffect(ArgEffects::Factory& AF, unsigned idx, ArgEffect E) {
- Args = AF.Add(Args, idx, E);
- }
-
/// getRetEffect - Returns the effect on the return value of the call.
RetEffect getRetEffect() const { return Ret; }
@@ -492,28 +466,6 @@ public:
/// getReceiverEffect - Returns the effect on the receiver of the call.
/// This is only meaningful if the summary applies to an ObjCMessageExpr*.
ArgEffect getReceiverEffect() const { return Receiver; }
-
- /// setReceiverEffect - Set the effect on the receiver of the call.
- void setReceiverEffect(ArgEffect E) { Receiver = E; }
-
- typedef ArgEffects::iterator ExprIterator;
-
- ExprIterator begin_args() const { return Args.begin(); }
- ExprIterator end_args() const { return Args.end(); }
-
- static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects A,
- RetEffect RetEff, ArgEffect DefaultEff,
- ArgEffect ReceiverEff, bool EndPath) {
- ID.Add(A);
- ID.Add(RetEff);
- ID.AddInteger((unsigned) DefaultEff);
- ID.AddInteger((unsigned) ReceiverEff);
- ID.AddInteger((unsigned) EndPath);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- Profile(ID, Args, Ret, DefaultArgEffect, Receiver, EndPath);
- }
};
} // end anonymous namespace
@@ -618,11 +570,6 @@ public:
return Summ;
}
-
- RetainSummary* find(Expr* Receiver, Selector S) {
- return find(getReceiverDecl(Receiver), S);
- }
-
RetainSummary* find(IdentifierInfo* II, Selector S) {
// FIXME: Class method lookup. Right now we dont' have a good way
// of going between IdentifierInfo* and the class hierarchy.
@@ -634,47 +581,6 @@ public:
return I == M.end() ? NULL : I->second;
}
- const ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
- if (const ObjCObjectPointerType* PT =
- E->getType()->getAs<ObjCObjectPointerType>())
- return PT->getInterfaceDecl();
-
- return NULL;
- }
-
- RetainSummary*& operator[](ObjCMessageExpr* ME) {
-
- Selector S = ME->getSelector();
-
- const ObjCInterfaceDecl* OD = 0;
- bool IsInstanceMessage = false;
- switch (ME->getReceiverKind()) {
- case ObjCMessageExpr::Instance:
- OD = getReceiverDecl(ME->getInstanceReceiver());
- IsInstanceMessage = true;
- break;
-
- case ObjCMessageExpr::SuperInstance:
- IsInstanceMessage = true;
- OD = ME->getSuperType()->getAs<ObjCObjectPointerType>()
- ->getInterfaceDecl();
- break;
-
- case ObjCMessageExpr::Class:
- OD = ME->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
- break;
-
- case ObjCMessageExpr::SuperClass:
- OD = ME->getSuperType()->getAs<ObjCObjectType>()->getInterface();
- break;
- }
-
- if (IsInstanceMessage)
- return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
-
- return M[ObjCSummaryKey(OD->getIdentifier(), S)];
- }
-
RetainSummary*& operator[](ObjCSummaryKey K) {
return M[K];
}
@@ -696,7 +602,7 @@ class RetainSummaryManager {
// Typedefs.
//==-----------------------------------------------------------------==//
- typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
+ typedef llvm::DenseMap<const FunctionDecl*, RetainSummary*>
FuncSummariesTy;
typedef ObjCSummaryCache ObjCMethodSummariesTy;
@@ -766,9 +672,10 @@ public:
RetainSummary* getUnarySummary(const FunctionType* FT, UnaryFuncKind func);
- RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
- RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
- RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, StringRef FName);
+ RetainSummary* getCFSummaryCreateRule(const FunctionDecl* FD);
+ RetainSummary* getCFSummaryGetRule(const FunctionDecl* FD);
+ RetainSummary* getCFCreateGetRuleSummary(const FunctionDecl* FD,
+ StringRef FName);
RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
ArgEffect ReceiverEff = DoNothing,
@@ -796,12 +703,6 @@ public:
void InitializeClassMethodSummaries();
void InitializeMethodSummaries();
private:
-
- void addClsMethSummary(IdentifierInfo* ClsII, Selector S,
- RetainSummary* Summ) {
- ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
- }
-
void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
ObjCClassMethodSummaries[S] = Summ;
}
@@ -892,7 +793,7 @@ public:
~RetainSummaryManager();
- RetainSummary* getSummary(FunctionDecl* FD);
+ RetainSummary* getSummary(const FunctionDecl* FD);
RetainSummary *getInstanceMethodSummary(const ObjCMessageExpr *ME,
const GRState *state,
@@ -999,15 +900,15 @@ RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
// Summary creation for functions (largely uses of Core Foundation).
//===----------------------------------------------------------------------===//
-static bool isRetain(FunctionDecl* FD, StringRef FName) {
+static bool isRetain(const FunctionDecl* FD, StringRef FName) {
return FName.endswith("Retain");
}
-static bool isRelease(FunctionDecl* FD, StringRef FName) {
+static bool isRelease(const FunctionDecl* FD, StringRef FName) {
return FName.endswith("Release");
}
-RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
+RetainSummary* RetainSummaryManager::getSummary(const FunctionDecl* FD) {
// Look up a summary in our cache of FunctionDecls -> Summaries.
FuncSummariesTy::iterator I = FuncSummaries.find(FD);
if (I != FuncSummaries.end())
@@ -1201,7 +1102,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
}
RetainSummary*
-RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl* FD,
StringRef FName) {
if (FName.find("Create") != StringRef::npos ||
@@ -1250,7 +1151,8 @@ RetainSummaryManager::getUnarySummary(const FunctionType* FT,
}
}
-RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
+RetainSummary*
+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl* FD) {
assert (ScratchArgs.isEmpty());
if (FD->getIdentifier() == CFDictionaryCreateII) {
@@ -1261,7 +1163,8 @@ RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
}
-RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
+RetainSummary*
+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl* FD) {
assert (ScratchArgs.isEmpty());
return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
DoNothing, DoNothing);
@@ -1767,7 +1670,7 @@ private:
void ProcessNonLeakError(ExplodedNodeSet& Dst,
GRStmtNodeBuilder& Builder,
- Expr* NodeExpr, SourceRange ErrorRange,
+ const Expr* NodeExpr, SourceRange ErrorRange,
ExplodedNode* Pred,
const GRState* St,
RefVal::Kind hasErr, SymbolRef Sym);
@@ -1810,33 +1713,26 @@ public:
void EvalSummary(ExplodedNodeSet& Dst,
GRExprEngine& Eng,
GRStmtNodeBuilder& Builder,
- Expr* Ex,
+ const Expr* Ex,
InstanceReceiver Receiver,
const RetainSummary& Summ,
const MemRegion *Callee,
- ExprIterator arg_beg, ExprIterator arg_end,
+ ConstExprIterator arg_beg, ConstExprIterator arg_end,
ExplodedNode* Pred, const GRState *state);
virtual void EvalCall(ExplodedNodeSet& Dst,
GRExprEngine& Eng,
GRStmtNodeBuilder& Builder,
- CallExpr* CE, SVal L,
+ const CallExpr* CE, SVal L,
ExplodedNode* Pred);
virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- ObjCMessageExpr* ME,
+ const ObjCMessageExpr* ME,
ExplodedNode* Pred,
const GRState *state);
-
- bool EvalObjCMessageExprAux(ExplodedNodeSet& Dst,
- GRExprEngine& Engine,
- GRStmtNodeBuilder& Builder,
- ObjCMessageExpr* ME,
- ExplodedNode* Pred);
-
// Stores.
virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val);
@@ -1861,7 +1757,7 @@ public:
virtual void EvalReturn(ExplodedNodeSet& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder& Builder,
- ReturnStmt* S,
+ const ReturnStmt* S,
ExplodedNode* Pred);
// Assumptions.
@@ -1934,7 +1830,6 @@ namespace {
public:
CFRefCount& getTF() { return TF; }
- const CFRefCount& getTF() const { return TF; }
// FIXME: Eventually remove.
virtual const char* getDescription() const = 0;
@@ -2049,9 +1944,6 @@ namespace {
CFRefBug& getBugType() {
return (CFRefBug&) RangedBugReport::getBugType();
}
- const CFRefBug& getBugType() const {
- return (const CFRefBug&) RangedBugReport::getBugType();
- }
virtual void getRanges(const SourceRange*& beg, const SourceRange*& end) {
if (!getBugType().isLeak())
@@ -2605,11 +2497,12 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
GRExprEngine& Eng,
GRStmtNodeBuilder& Builder,
- Expr* Ex,
+ const Expr* Ex,
InstanceReceiver Receiver,
const RetainSummary& Summ,
const MemRegion *Callee,
- ExprIterator arg_beg, ExprIterator arg_end,
+ ConstExprIterator arg_beg,
+ ConstExprIterator arg_end,
ExplodedNode* Pred, const GRState *state) {
// Evaluate the effect of the arguments.
@@ -2620,19 +2513,25 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
- for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
+ // HACK: Symbols that have ref-count state that are referenced directly
+ // (not as structure or array elements, or via bindings) by an argument
+ // should not have their ref-count state stripped after we have
+ // done an invalidation pass.
+ llvm::DenseSet<SymbolRef> WhitelistedSymbols;
+
+ for (ConstExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
SVal V = state->getSValAsScalarOrLoc(*I);
SymbolRef Sym = V.getAsLocSymbol();
if (Sym)
if (RefBindings::data_type* T = state->get<RefBindings>(Sym)) {
+ WhitelistedSymbols.insert(Sym);
state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
if (hasErr) {
ErrorRange = (*I)->getSourceRange();
ErrorSym = Sym;
break;
}
- continue;
}
tryAgain:
@@ -2703,22 +2602,22 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
// expression (the context) and the expression itself. This should
// disambiguate conjured symbols.
unsigned Count = Builder.getCurrentBlockCount();
- StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
StoreManager::InvalidatedSymbols IS;
- Store store = state->getStore();
// NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
// global variables.
- store = StoreMgr.InvalidateRegions(store, RegionsToInvalidate.data(),
- RegionsToInvalidate.data() +
- RegionsToInvalidate.size(),
- Ex, Count, &IS,
- /* invalidateGlobals = */ true);
+ state = state->InvalidateRegions(RegionsToInvalidate.data(),
+ RegionsToInvalidate.data() +
+ RegionsToInvalidate.size(),
+ Ex, Count, &IS,
+ /* invalidateGlobals = */ true);
- state = state->makeWithStore(store);
for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
E = IS.end(); I!=E; ++I) {
- // Remove any existing reference-count binding.
+ SymbolRef sym = *I;
+ if (WhitelistedSymbols.count(sym))
+ continue;
+ // Remove any existing reference-count binding.
state = state->remove<RefBindings>(*I);
}
@@ -2860,7 +2759,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,
void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
GRExprEngine& Eng,
GRStmtNodeBuilder& Builder,
- CallExpr* CE, SVal L,
+ const CallExpr* CE, SVal L,
ExplodedNode* Pred) {
RetainSummary *Summ = 0;
@@ -2874,7 +2773,7 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
else {
const FunctionDecl* FD = L.getAsFunctionDecl();
Summ = !FD ? Summaries.getDefaultSummary() :
- Summaries.getSummary(const_cast<FunctionDecl*>(FD));
+ Summaries.getSummary(FD);
}
assert(Summ);
@@ -2885,7 +2784,7 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst,
GRExprEngine& Eng,
GRStmtNodeBuilder& Builder,
- ObjCMessageExpr* ME,
+ const ObjCMessageExpr* ME,
ExplodedNode* Pred,
const GRState *state) {
RetainSummary *Summ =
@@ -2956,10 +2855,10 @@ void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) {
void CFRefCount::EvalReturn(ExplodedNodeSet& Dst,
GRExprEngine& Eng,
GRStmtNodeBuilder& Builder,
- ReturnStmt* S,
+ const ReturnStmt* S,
ExplodedNode* Pred) {
- Expr* RetE = S->getRetValue();
+ const Expr* RetE = S->getRetValue();
if (!RetE)
return;
@@ -3404,7 +3303,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst,
ExplodedNode* Pred,
const GRState* state,
SymbolReaper& SymReaper) {
- Stmt *S = Builder.getStmt();
+ const Stmt *S = Builder.getStmt();
RefBindings B = state->get<RefBindings>();
// Update counts from autorelease pools
@@ -3454,7 +3353,8 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst,
void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst,
GRStmtNodeBuilder& Builder,
- Expr* NodeExpr, SourceRange ErrorRange,
+ const Expr* NodeExpr,
+ SourceRange ErrorRange,
ExplodedNode* Pred,
const GRState* St,
RefVal::Kind hasErr, SymbolRef Sym) {
diff --git a/lib/Checker/CMakeLists.txt b/lib/Checker/CMakeLists.txt
index 259346a97068..5b54f0d12d5d 100644
--- a/lib/Checker/CMakeLists.txt
+++ b/lib/Checker/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangChecker
AdjustedReturnValueChecker.cpp
AggExprVisitor.cpp
AnalysisConsumer.cpp
+ AnalysisManager.cpp
ArrayBoundChecker.cpp
AttrNonNullChecker.cpp
BasicConstraintManager.cpp
@@ -15,7 +16,6 @@ add_clang_library(clangChecker
BuiltinFunctionChecker.cpp
CFRefCount.cpp
CallAndMessageChecker.cpp
- CallInliner.cpp
CastSizeChecker.cpp
CastToStructChecker.cpp
CheckDeadStores.cpp
@@ -24,6 +24,7 @@ add_clang_library(clangChecker
CheckSecuritySyntaxOnly.cpp
CheckSizeofPointer.cpp
Checker.cpp
+ CheckerHelpers.cpp
CocoaConventions.cpp
CStringChecker.cpp
DereferenceChecker.cpp
@@ -74,6 +75,7 @@ add_clang_library(clangChecker
UndefinedArraySubscriptChecker.cpp
UndefinedAssignmentChecker.cpp
UnixAPIChecker.cpp
+ UnreachableCodeChecker.cpp
VLASizeChecker.cpp
ValueManager.cpp
)
diff --git a/lib/Checker/CStringChecker.cpp b/lib/Checker/CStringChecker.cpp
index a92d409703a3..9ea572f90dfb 100644
--- a/lib/Checker/CStringChecker.cpp
+++ b/lib/Checker/CStringChecker.cpp
@@ -15,19 +15,30 @@
#include "GRExprEngineExperimentalChecks.h"
#include "clang/Checker/BugReporter/BugType.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/GRStateTrait.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
namespace {
class CStringChecker : public CheckerVisitor<CStringChecker> {
- BugType *BT_Null, *BT_Bounds, *BT_Overlap;
+ BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString;
public:
CStringChecker()
- : BT_Null(0), BT_Bounds(0), BT_Overlap(0) {}
+ : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0)
+ {}
static void *getTag() { static int tag; return &tag; }
bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+ void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
+ void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
+ void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
+ bool WantsRegionChangeUpdate(const GRState *state);
+
+ const GRState *EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool*);
typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
@@ -40,26 +51,61 @@ public:
void EvalMemcmp(CheckerContext &C, const CallExpr *CE);
+ void EvalStrlen(CheckerContext &C, const CallExpr *CE);
+
+ void EvalStrcpy(CheckerContext &C, const CallExpr *CE);
+ void EvalStpcpy(CheckerContext &C, const CallExpr *CE);
+ void EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool ReturnEnd);
+
// Utility methods
std::pair<const GRState*, const GRState*>
AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
+ const GRState *SetCStringLength(const GRState *state, const MemRegion *MR,
+ SVal StrLen);
+ SVal GetCStringLengthForRegion(CheckerContext &C, const GRState *&state,
+ const Expr *Ex, const MemRegion *MR);
+ SVal GetCStringLength(CheckerContext &C, const GRState *&state,
+ const Expr *Ex, SVal Buf);
+
+ const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state,
+ const Expr *Ex, SVal V);
+
+ bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+ const MemRegion *MR);
+
+ // Re-usable checks
const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
const Expr *S, SVal l);
const GRState *CheckLocation(CheckerContext &C, const GRState *state,
- const Expr *S, SVal l);
+ const Expr *S, SVal l,
+ bool IsDestination = false);
const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
const Expr *Size,
const Expr *FirstBuf,
- const Expr *SecondBuf = NULL);
+ const Expr *SecondBuf = NULL,
+ bool FirstIsDestination = false);
const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
const Expr *Size, const Expr *First,
const Expr *Second);
void EmitOverlapBug(CheckerContext &C, const GRState *state,
const Stmt *First, const Stmt *Second);
};
+
+class CStringLength {
+public:
+ typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap;
+};
} //end anonymous namespace
+namespace clang {
+ template <>
+ struct GRStateTrait<CStringLength>
+ : public GRStatePartialTrait<CStringLength::EntryMap> {
+ static void *GDMIndex() { return CStringChecker::getTag(); }
+ };
+}
+
void clang::RegisterCStringChecker(GRExprEngine &Eng) {
Eng.registerCheck(new CStringChecker());
}
@@ -122,7 +168,8 @@ const GRState *CStringChecker::CheckNonNull(CheckerContext &C,
// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
const GRState *CStringChecker::CheckLocation(CheckerContext &C,
const GRState *state,
- const Expr *S, SVal l) {
+ const Expr *S, SVal l,
+ bool IsDestination) {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -136,7 +183,7 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
if (!ER)
return state;
- assert(ER->getValueType(C.getASTContext()) == C.getASTContext().CharTy &&
+ assert(ER->getValueType() == C.getASTContext().CharTy &&
"CheckLocation should only be called with char* ElementRegions");
// Get the size of the array.
@@ -155,17 +202,26 @@ const GRState *CStringChecker::CheckLocation(CheckerContext &C,
if (!N)
return NULL;
- if (!BT_Bounds)
- BT_Bounds = new BuiltinBug("Out-of-bound array access",
- "Byte string function accesses out-of-bound array element "
- "(buffer overflow)");
+ BuiltinBug *BT;
+ if (IsDestination) {
+ if (!BT_BoundsWrite) {
+ BT_BoundsWrite = new BuiltinBug("Out-of-bound array access",
+ "Byte string function overflows destination buffer");
+ }
+ BT = static_cast<BuiltinBug*>(BT_BoundsWrite);
+ } else {
+ if (!BT_Bounds) {
+ BT_Bounds = new BuiltinBug("Out-of-bound array access",
+ "Byte string function accesses out-of-bound array element");
+ }
+ BT = static_cast<BuiltinBug*>(BT_Bounds);
+ }
// 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.
- BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
report->addRange(S->getSourceRange());
@@ -182,7 +238,8 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
const GRState *state,
const Expr *Size,
const Expr *FirstBuf,
- const Expr *SecondBuf) {
+ const Expr *SecondBuf,
+ bool FirstIsDestination) {
// If a previous check has failed, propagate the failure.
if (!state)
return NULL;
@@ -191,7 +248,7 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
SValuator &SV = VM.getSValuator();
ASTContext &Ctx = C.getASTContext();
- QualType SizeTy = Ctx.getSizeType();
+ QualType SizeTy = Size->getType();
QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
// Check that the first buffer is non-null.
@@ -208,18 +265,20 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
// Compute the offset of the last element to be accessed: size-1.
NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
- NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub,
+ NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BO_Sub,
*Length, One, SizeTy));
// Check that the first buffer is sufficently long.
- Loc BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, FirstBuf->getType()));
- SVal BufEnd
- = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
- state = CheckLocation(C, state, FirstBuf, BufEnd);
+ SVal BufStart = SV.EvalCast(BufVal, PtrTy, FirstBuf->getType());
+ if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+ SVal BufEnd = SV.EvalBinOpLN(state, BO_Add, *BufLoc,
+ LastOffset, PtrTy);
+ state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination);
- // If the buffer isn't large enough, abort.
- if (!state)
- return NULL;
+ // If the buffer isn't large enough, abort.
+ if (!state)
+ return NULL;
+ }
// If there's a second buffer, check it as well.
if (SecondBuf) {
@@ -228,10 +287,12 @@ const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
if (!state)
return NULL;
- BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, SecondBuf->getType()));
- BufEnd
- = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
- state = CheckLocation(C, state, SecondBuf, BufEnd);
+ BufStart = SV.EvalCast(BufVal, PtrTy, SecondBuf->getType());
+ if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
+ SVal BufEnd = SV.EvalBinOpLN(state, BO_Add, *BufLoc,
+ LastOffset, PtrTy);
+ state = CheckLocation(C, state, SecondBuf, BufEnd);
+ }
}
// Large enough or not, return this state!
@@ -284,7 +345,7 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
// Which value comes first?
QualType CmpTy = Ctx.IntTy;
- SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT,
+ SVal Reverse = SV.EvalBinOpLL(state, BO_GT,
*FirstLoc, *SecondLoc, CmpTy);
DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
if (!ReverseTest)
@@ -324,14 +385,14 @@ const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
return state;
// Compute the end of the first buffer. Bail out if THAT fails.
- SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add,
+ SVal FirstEnd = SV.EvalBinOpLN(state, BO_Add,
*FirstStartLoc, *Length, CharPtrTy);
Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
if (!FirstEndLoc)
return state;
// Is the end of the first buffer past the start of the second buffer?
- SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT,
+ SVal Overlap = SV.EvalBinOpLL(state, BO_GT,
*FirstEndLoc, *SecondLoc, CmpTy);
DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
if (!OverlapTest)
@@ -369,6 +430,222 @@ void CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state,
C.EmitReport(report);
}
+const GRState *CStringChecker::SetCStringLength(const GRState *state,
+ const MemRegion *MR,
+ SVal StrLen) {
+ assert(!StrLen.isUndef() && "Attempt to set an undefined string length");
+ if (StrLen.isUnknown())
+ return state;
+
+ MR = MR->StripCasts();
+
+ switch (MR->getKind()) {
+ case MemRegion::StringRegionKind:
+ // FIXME: This can happen if we strcpy() into a string region. This is
+ // undefined [C99 6.4.5p6], but we should still warn about it.
+ return state;
+
+ case MemRegion::SymbolicRegionKind:
+ case MemRegion::AllocaRegionKind:
+ case MemRegion::VarRegionKind:
+ case MemRegion::FieldRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
+ return state->set<CStringLength>(MR, StrLen);
+
+ case MemRegion::ElementRegionKind:
+ // FIXME: Handle element regions by upper-bounding the parent region's
+ // string length.
+ return state;
+
+ default:
+ // Other regions (mostly non-data) can't have a reliable C string length.
+ // For now, just ignore the change.
+ // FIXME: These are rare but not impossible. We should output some kind of
+ // warning for things like strcpy((char[]){'a', 0}, "b");
+ return state;
+ }
+}
+
+SVal CStringChecker::GetCStringLengthForRegion(CheckerContext &C,
+ const GRState *&state,
+ const Expr *Ex,
+ const MemRegion *MR) {
+ // If there's a recorded length, go ahead and return it.
+ const SVal *Recorded = state->get<CStringLength>(MR);
+ if (Recorded)
+ return *Recorded;
+
+ // Otherwise, get a new symbol and update the state.
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ ValueManager &ValMgr = C.getValueManager();
+ QualType SizeTy = ValMgr.getContext().getSizeType();
+ SVal Strlen = ValMgr.getMetadataSymbolVal(getTag(), MR, Ex, SizeTy, Count);
+
+ state = state->set<CStringLength>(MR, Strlen);
+ return Strlen;
+}
+
+SVal CStringChecker::GetCStringLength(CheckerContext &C, const GRState *&state,
+ const Expr *Ex, SVal Buf) {
+ const MemRegion *MR = Buf.getAsRegion();
+ if (!MR) {
+ // If we can't get a region, see if it's something we /know/ isn't a
+ // C string. In the context of locations, the only time we can issue such
+ // a warning is for labels.
+ if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
+ if (ExplodedNode *N = C.GenerateNode(state)) {
+ if (!BT_NotCString)
+ BT_NotCString = new BuiltinBug("API",
+ "Argument is not a null-terminated string.");
+
+ llvm::SmallString<120> buf;
+ llvm::raw_svector_ostream os(buf);
+ os << "Argument to byte string function is the address of the label '"
+ << Label->getLabel()->getID()->getName()
+ << "', which is not a null-terminated string";
+
+ // Generate a report for this bug.
+ EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
+ os.str(), N);
+
+ report->addRange(Ex->getSourceRange());
+ C.EmitReport(report);
+ }
+
+ return UndefinedVal();
+ }
+
+ // If it's not a region and not a label, give up.
+ return UnknownVal();
+ }
+
+ // If we have a region, strip casts from it and see if we can figure out
+ // its length. For anything we can't figure out, just return UnknownVal.
+ MR = MR->StripCasts();
+
+ switch (MR->getKind()) {
+ case MemRegion::StringRegionKind: {
+ // Modifying the contents of string regions is undefined [C99 6.4.5p6],
+ // so we can assume that the byte length is the correct C string length.
+ ValueManager &ValMgr = C.getValueManager();
+ QualType SizeTy = ValMgr.getContext().getSizeType();
+ const StringLiteral *Str = cast<StringRegion>(MR)->getStringLiteral();
+ return ValMgr.makeIntVal(Str->getByteLength(), SizeTy);
+ }
+ case MemRegion::SymbolicRegionKind:
+ case MemRegion::AllocaRegionKind:
+ case MemRegion::VarRegionKind:
+ case MemRegion::FieldRegionKind:
+ case MemRegion::ObjCIvarRegionKind:
+ return GetCStringLengthForRegion(C, state, Ex, MR);
+ case MemRegion::CompoundLiteralRegionKind:
+ // FIXME: Can we track this? Is it necessary?
+ return UnknownVal();
+ case MemRegion::ElementRegionKind:
+ // FIXME: How can we handle this? It's not good enough to subtract the
+ // offset from the base string length; consider "123\x00567" and &a[5].
+ return UnknownVal();
+ default:
+ // Other regions (mostly non-data) can't have a reliable C string length.
+ // In this case, an error is emitted and UndefinedVal is returned.
+ // The caller should always be prepared to handle this case.
+ if (ExplodedNode *N = C.GenerateNode(state)) {
+ if (!BT_NotCString)
+ BT_NotCString = new BuiltinBug("API",
+ "Argument is not a null-terminated string.");
+
+ llvm::SmallString<120> buf;
+ llvm::raw_svector_ostream os(buf);
+
+ os << "Argument to byte string function is ";
+
+ if (SummarizeRegion(os, C.getASTContext(), MR))
+ os << ", which is not a null-terminated string";
+ else
+ os << "not a null-terminated string";
+
+ // Generate a report for this bug.
+ EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
+ os.str(), N);
+
+ report->addRange(Ex->getSourceRange());
+ C.EmitReport(report);
+ }
+
+ return UndefinedVal();
+ }
+}
+
+const GRState *CStringChecker::InvalidateBuffer(CheckerContext &C,
+ const GRState *state,
+ const Expr *E, SVal V) {
+ Loc *L = dyn_cast<Loc>(&V);
+ if (!L)
+ return state;
+
+ // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes
+ // some assumptions about the value that CFRefCount can't. Even so, it should
+ // probably be refactored.
+ if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) {
+ const MemRegion *R = MR->getRegion()->StripCasts();
+
+ // Are we dealing with an ElementRegion? If so, we should be invalidating
+ // the super-region.
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ R = ER->getSuperRegion();
+ // FIXME: What about layers of ElementRegions?
+ }
+
+ // Invalidate this region.
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ return state->InvalidateRegion(R, E, Count, NULL);
+ }
+
+ // If we have a non-region value by chance, just remove the binding.
+ // FIXME: is this necessary or correct? This handles the non-Region
+ // cases. Is it ever valid to store to these?
+ return state->unbindLoc(*L);
+}
+
+bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
+ const MemRegion *MR) {
+ const TypedRegion *TR = dyn_cast<TypedRegion>(MR);
+ if (!TR)
+ return false;
+
+ switch (TR->getKind()) {
+ case MemRegion::FunctionTextRegionKind: {
+ const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl();
+ if (FD)
+ os << "the address of the function '" << FD << "'";
+ else
+ os << "the address of a function";
+ return true;
+ }
+ case MemRegion::BlockTextRegionKind:
+ os << "block text";
+ return true;
+ case MemRegion::BlockDataRegionKind:
+ os << "a block";
+ return true;
+ case MemRegion::CXXThisRegionKind:
+ case MemRegion::CXXObjectRegionKind:
+ os << "a C++ object of type " << TR->getValueType().getAsString();
+ return true;
+ case MemRegion::VarRegionKind:
+ os << "a variable of type" << TR->getValueType().getAsString();
+ return true;
+ case MemRegion::FieldRegionKind:
+ os << "a field of type " << TR->getValueType().getAsString();
+ return true;
+ case MemRegion::ObjCIvarRegionKind:
+ os << "an instance variable of type " << TR->getValueType().getAsString();
+ return true;
+ default:
+ return false;
+ }
+}
+
//===----------------------------------------------------------------------===//
// Evaluation of individual function calls.
//===----------------------------------------------------------------------===//
@@ -390,11 +667,20 @@ void CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
// If the size can be nonzero, we have to check the other arguments.
if (StNonZeroSize) {
state = StNonZeroSize;
- state = CheckBufferAccess(C, state, Size, Dest, Source);
+ state = CheckBufferAccess(C, state, Size, Dest, Source,
+ /* FirstIsDst = */ true);
if (Restricted)
state = CheckOverlap(C, state, Size, Dest, Source);
- if (state)
+
+ if (state) {
+ // Invalidate the destination.
+ // FIXME: Even if we can't perfectly model the copy, we should see if we
+ // can use LazyCompoundVals to copy the source values into the destination.
+ // This would probably remove any existing bindings past the end of the
+ // copied region, but that's still an improvement over blank invalidation.
+ state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest));
C.addTransition(state);
+ }
}
}
@@ -481,7 +767,7 @@ void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
if (state) {
// The return value is the comparison result, which we don't know.
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
- SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
+ SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, Count);
state = state->BindExpr(CE, CmpV);
C.addTransition(state);
}
@@ -489,8 +775,123 @@ void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
}
}
+void CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) {
+ // size_t strlen(const char *s);
+ const GRState *state = C.getState();
+ const Expr *Arg = CE->getArg(0);
+ SVal ArgVal = state->getSVal(Arg);
+
+ // Check that the argument is non-null.
+ state = CheckNonNull(C, state, Arg, ArgVal);
+
+ if (state) {
+ SVal StrLen = GetCStringLength(C, state, Arg, ArgVal);
+
+ // If the argument isn't a valid C string, there's no valid state to
+ // transition to.
+ if (StrLen.isUndef())
+ return;
+
+ // If GetCStringLength couldn't figure out the length, conjure a return
+ // value, so it can be used in constraints, at least.
+ if (StrLen.isUnknown()) {
+ ValueManager &ValMgr = C.getValueManager();
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ StrLen = ValMgr.getConjuredSymbolVal(NULL, CE, Count);
+ }
+
+ // Bind the return value.
+ state = state->BindExpr(CE, StrLen);
+ C.addTransition(state);
+ }
+}
+
+void CStringChecker::EvalStrcpy(CheckerContext &C, const CallExpr *CE) {
+ // char *strcpy(char *restrict dst, const char *restrict src);
+ EvalStrcpyCommon(C, CE, /* ReturnEnd = */ false);
+}
+
+void CStringChecker::EvalStpcpy(CheckerContext &C, const CallExpr *CE) {
+ // char *stpcpy(char *restrict dst, const char *restrict src);
+ EvalStrcpyCommon(C, CE, /* ReturnEnd = */ true);
+}
+
+void CStringChecker::EvalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
+ bool ReturnEnd) {
+ const GRState *state = C.getState();
+
+ // Check that the destination is non-null
+ const Expr *Dst = CE->getArg(0);
+ SVal DstVal = state->getSVal(Dst);
+
+ state = CheckNonNull(C, state, Dst, DstVal);
+ if (!state)
+ return;
+
+ // Check that the source is non-null.
+ const Expr *Src = CE->getArg(1);
+ SVal SrcVal = state->getSVal(Src);
+
+ state = CheckNonNull(C, state, Src, SrcVal);
+ if (!state)
+ return;
+
+ // Get the string length of the source.
+ SVal StrLen = GetCStringLength(C, state, Src, SrcVal);
+
+ // If the source isn't a valid C string, give up.
+ if (StrLen.isUndef())
+ return;
+
+ SVal Result = (ReturnEnd ? UnknownVal() : DstVal);
+
+ // If the destination is a MemRegion, try to check for a buffer overflow and
+ // record the new string length.
+ if (loc::MemRegionVal *DstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) {
+ // If the length is known, we can check for an overflow.
+ if (NonLoc *KnownStrLen = dyn_cast<NonLoc>(&StrLen)) {
+ SValuator &SV = C.getSValuator();
+
+ SVal LastElement = SV.EvalBinOpLN(state, BO_Add,
+ *DstRegVal, *KnownStrLen,
+ Dst->getType());
+
+ state = CheckLocation(C, state, Dst, LastElement, /* IsDst = */ true);
+ if (!state)
+ return;
+
+ // If this is a stpcpy-style copy, the last element is the return value.
+ if (ReturnEnd)
+ Result = LastElement;
+ }
+
+ // Invalidate the destination. This must happen before we set the C string
+ // length because invalidation will clear the length.
+ // FIXME: Even if we can't perfectly model the copy, we should see if we
+ // can use LazyCompoundVals to copy the source values into the destination.
+ // This would probably remove any existing bindings past the end of the
+ // string, but that's still an improvement over blank invalidation.
+ state = InvalidateBuffer(C, state, Dst, *DstRegVal);
+
+ // Set the C string length of the destination.
+ state = SetCStringLength(state, DstRegVal->getRegion(), StrLen);
+ }
+
+ // If this is a stpcpy-style copy, but we were unable to check for a buffer
+ // overflow, we still need a result. Conjure a return value.
+ if (ReturnEnd && Result.isUnknown()) {
+ ValueManager &ValMgr = C.getValueManager();
+ unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+ StrLen = ValMgr.getConjuredSymbolVal(NULL, CE, Count);
+ }
+
+ // Set the return value.
+ state = state->BindExpr(CE, Result);
+ C.addTransition(state);
+}
+
//===----------------------------------------------------------------------===//
-// The driver method.
+// The driver method, and other Checker callbacks.
//===----------------------------------------------------------------------===//
bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
@@ -512,6 +913,9 @@ bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
.Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
.Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp)
.Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
+ .Cases("strcpy", "__strcpy_chk", &CStringChecker::EvalStrcpy)
+ .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::EvalStpcpy)
+ .Case("strlen", &CStringChecker::EvalStrlen)
.Case("bcopy", &CStringChecker::EvalBcopy)
.Default(NULL);
@@ -523,3 +927,129 @@ bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
(this->*EvalFunction)(C, CE);
return true;
}
+
+void CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
+ // Record string length for char a[] = "abc";
+ const GRState *state = C.getState();
+
+ for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
+ I != E; ++I) {
+ const VarDecl *D = dyn_cast<VarDecl>(*I);
+ if (!D)
+ continue;
+
+ // FIXME: Handle array fields of structs.
+ if (!D->getType()->isArrayType())
+ continue;
+
+ const Expr *Init = D->getInit();
+ if (!Init)
+ continue;
+ if (!isa<StringLiteral>(Init))
+ continue;
+
+ Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext());
+ const MemRegion *MR = VarLoc.getAsRegion();
+ if (!MR)
+ continue;
+
+ SVal StrVal = state->getSVal(Init);
+ assert(StrVal.isValid() && "Initializer string is unknown or undefined");
+ DefinedOrUnknownSVal StrLen
+ = cast<DefinedOrUnknownSVal>(GetCStringLength(C, state, Init, StrVal));
+
+ state = state->set<CStringLength>(MR, StrLen);
+ }
+
+ C.addTransition(state);
+}
+
+bool CStringChecker::WantsRegionChangeUpdate(const GRState *state) {
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+ return !Entries.isEmpty();
+}
+
+const GRState *CStringChecker::EvalRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ bool *) {
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+ if (Entries.isEmpty())
+ return state;
+
+ llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
+ llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
+
+ // First build sets for the changed regions and their super-regions.
+ for ( ; Begin != End; ++Begin) {
+ const MemRegion *MR = *Begin;
+ Invalidated.insert(MR);
+
+ SuperRegions.insert(MR);
+ while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
+ MR = SR->getSuperRegion();
+ SuperRegions.insert(MR);
+ }
+ }
+
+ CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+
+ // Then loop over the entries in the current state.
+ for (CStringLength::EntryMap::iterator I = Entries.begin(),
+ E = Entries.end(); I != E; ++I) {
+ const MemRegion *MR = I.getKey();
+
+ // Is this entry for a super-region of a changed region?
+ if (SuperRegions.count(MR)) {
+ Entries = F.Remove(Entries, MR);
+ continue;
+ }
+
+ // Is this entry for a sub-region of a changed region?
+ const MemRegion *Super = MR;
+ while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
+ Super = SR->getSuperRegion();
+ if (Invalidated.count(Super)) {
+ Entries = F.Remove(Entries, MR);
+ break;
+ }
+ }
+ }
+
+ return state->set<CStringLength>(Entries);
+}
+
+void CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
+ // Mark all symbols in our string length map as valid.
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+
+ for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ SVal Len = I.getData();
+ if (SymbolRef Sym = Len.getAsSymbol())
+ SR.markInUse(Sym);
+ }
+}
+
+void CStringChecker::EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
+ if (!SR.hasDeadSymbols())
+ return;
+
+ const GRState *state = C.getState();
+ CStringLength::EntryMap Entries = state->get<CStringLength>();
+ if (Entries.isEmpty())
+ return;
+
+ CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
+ for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
+ I != E; ++I) {
+ SVal Len = I.getData();
+ if (SymbolRef Sym = Len.getAsSymbol()) {
+ if (SR.isDead(Sym))
+ Entries = F.Remove(Entries, I.getKey());
+ }
+ }
+
+ state = state->set<CStringLength>(Entries);
+ C.GenerateNode(state);
+}
diff --git a/lib/Checker/CallAndMessageChecker.cpp b/lib/Checker/CallAndMessageChecker.cpp
index c619d75479ed..3c9ddce9f664 100644
--- a/lib/Checker/CallAndMessageChecker.cpp
+++ b/lib/Checker/CallAndMessageChecker.cpp
@@ -114,7 +114,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
: C(c), StoreMgr(storeMgr), MrMgr(mrMgr), store(s) {}
bool Find(const TypedRegion *R) {
- QualType T = R->getValueType(C);
+ QualType T = R->getValueType();
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl()->getDefinition();
assert(RD && "Referred record has no definition");
diff --git a/lib/Checker/CallInliner.cpp b/lib/Checker/CallInliner.cpp
deleted file mode 100644
index c47e06c78fb2..000000000000
--- a/lib/Checker/CallInliner.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===--- CallInliner.cpp - Transfer function that inlines callee ----------===//
-//
-// 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 callee inlining transfer function.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Checker/PathSensitive/CheckerVisitor.h"
-#include "clang/Checker/PathSensitive/GRState.h"
-#include "clang/Checker/Checkers/LocalCheckers.h"
-
-using namespace clang;
-
-namespace {
-class CallInliner : public Checker {
-public:
- static void *getTag() {
- static int x;
- return &x;
- }
-
- virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
-};
-}
-
-void clang::RegisterCallInliner(GRExprEngine &Eng) {
- Eng.registerCheck(new CallInliner());
-}
-
-bool CallInliner::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
- const GRState *state = C.getState();
- const Expr *Callee = CE->getCallee();
- SVal L = state->getSVal(Callee);
-
- const FunctionDecl *FD = L.getAsFunctionDecl();
- if (!FD)
- return false;
-
- if (!FD->hasBody(FD))
- return false;
-
- // Now we have the definition of the callee, create a CallEnter node.
- CallEnter Loc(CE, FD, C.getPredecessor()->getLocationContext());
- C.addTransition(state, Loc);
-
- return true;
-}
-
diff --git a/lib/Checker/CastSizeChecker.cpp b/lib/Checker/CastSizeChecker.cpp
index a502c10cac16..6676fe5e7a36 100644
--- a/lib/Checker/CastSizeChecker.cpp
+++ b/lib/Checker/CastSizeChecker.cpp
@@ -44,6 +44,10 @@ void CastSizeChecker::PreVisitCastExpr(CheckerContext &C, const CastExpr *CE) {
QualType ToPointeeTy = ToPTy->getPointeeType();
+ // Only perform the check if 'ToPointeeTy' is a complete type.
+ if (ToPointeeTy->isIncompleteType())
+ return;
+
const GRState *state = C.getState();
const MemRegion *R = state->getSVal(E).getAsRegion();
if (R == 0)
diff --git a/lib/Checker/CheckDeadStores.cpp b/lib/Checker/CheckDeadStores.cpp
index d6ea187957ce..38961000d3fd 100644
--- a/lib/Checker/CheckDeadStores.cpp
+++ b/lib/Checker/CheckDeadStores.cpp
@@ -217,7 +217,7 @@ public:
// If x is EVER assigned a new value later, don't issue
// a warning. This is because such initialization can be
// due to defensive programming.
- if (E->isConstantInitializer(Ctx))
+ if (E->isConstantInitializer(Ctx, false))
return;
if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
@@ -268,7 +268,7 @@ public:
// Check for '&'. Any VarDecl whose value has its address-taken we
// treat as escaped.
Expr* E = U->getSubExpr()->IgnoreParenCasts();
- if (U->getOpcode() == UnaryOperator::AddrOf)
+ if (U->getOpcode() == UO_AddrOf)
if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
Escaped.insert(VD);
diff --git a/lib/Checker/CheckSecuritySyntaxOnly.cpp b/lib/Checker/CheckSecuritySyntaxOnly.cpp
index af85c2faee3a..9a2ac45fa2e1 100644
--- a/lib/Checker/CheckSecuritySyntaxOnly.cpp
+++ b/lib/Checker/CheckSecuritySyntaxOnly.cpp
@@ -41,8 +41,8 @@ class WalkAST : public StmtVisitor<WalkAST> {
public:
WalkAST(BugReporter &br) : BR(br),
- II_gets(0), II_getpw(0), II_mktemp(0),
- II_rand(), II_random(0), II_setid(),
+ II_gets(0), II_getpw(0), II_mktemp(0),
+ II_rand(), II_random(0), II_setid(),
CheckRand(isArc4RandomAvailable(BR.getContext())) {}
// Statement visitor methods.
@@ -131,7 +131,7 @@ GetIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
- B->getOpcode() == BinaryOperator::Comma))
+ B->getOpcode() == BO_Comma))
return NULL;
if (const DeclRefExpr *lhs = GetIncrementedVar(B->getLHS(), x, y))
@@ -217,7 +217,7 @@ void WalkAST::CheckLoopConditionForFloat(const ForStmt *FS) {
llvm::SmallString<256> sbuf;
llvm::raw_svector_ostream os(sbuf);
- os << "Variable '" << drCond->getDecl()->getNameAsCString()
+ os << "Variable '" << drCond->getDecl()->getName()
<< "' with floating point type '" << drCond->getType().getAsString()
<< "' should not be used as a loop counter";
@@ -332,10 +332,10 @@ void WalkAST::CheckCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
// Issue a waring.
SourceRange R = CE->getCallee()->getSourceRange();
BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'",
- "Security",
- "Call to function 'mktemp' is insecure as it always "
- "creates or uses insecure temporary file. Use 'mkstemp' instead",
- CE->getLocStart(), &R, 1);
+ "Security",
+ "Call to function 'mktemp' is insecure as it always "
+ "creates or uses insecure temporary file. Use 'mkstemp' instead",
+ CE->getLocStart(), &R, 1);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Checker/CheckerHelpers.cpp b/lib/Checker/CheckerHelpers.cpp
new file mode 100644
index 000000000000..ece69435cac7
--- /dev/null
+++ b/lib/Checker/CheckerHelpers.cpp
@@ -0,0 +1,80 @@
+//===---- CheckerHelpers.cpp - Helper functions for checkers ----*- 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 several static functions for use in checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Checker/PathSensitive/CheckerHelpers.h"
+#include "clang/AST/Expr.h"
+
+// Recursively find any substatements containing macros
+bool clang::containsMacro(const Stmt *S) {
+ if (S->getLocStart().isMacroID())
+ return true;
+
+ if (S->getLocEnd().isMacroID())
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsMacro(child))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing enum constants
+bool clang::containsEnum(const Stmt *S) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+ if (DR && isa<EnumConstantDecl>(DR->getDecl()))
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsEnum(child))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing static vars
+bool clang::containsStaticLocal(const Stmt *S) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+
+ if (DR)
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (VD->isStaticLocal())
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsStaticLocal(child))
+ return true;
+
+ return false;
+}
+
+// Recursively find any substatements containing __builtin_offsetof
+bool clang::containsBuiltinOffsetOf(const Stmt *S) {
+ if (isa<OffsetOfExpr>(S))
+ return true;
+
+ for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
+ ++I)
+ if (const Stmt *child = *I)
+ if (containsBuiltinOffsetOf(child))
+ return true;
+
+ return false;
+}
diff --git a/lib/Checker/CocoaConventions.cpp b/lib/Checker/CocoaConventions.cpp
index 3ba887ccc7e3..b446a048d488 100644
--- a/lib/Checker/CocoaConventions.cpp
+++ b/lib/Checker/CocoaConventions.cpp
@@ -173,9 +173,10 @@ bool cocoa::isCocoaObjectRef(QualType Ty) {
if (!PT)
return true;
- // We assume that id<..>, id, and "Class" all represent tracked objects.
+ // We assume that id<..>, id, Class, and Class<..> all represent tracked
+ // objects.
if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
- PT->isObjCClassType())
+ PT->isObjCClassType() || PT->isObjCQualifiedClassType())
return true;
// Does the interface subclass NSObject?
diff --git a/lib/Checker/DivZeroChecker.cpp b/lib/Checker/DivZeroChecker.cpp
index e09a87149f5c..32e2a1782d10 100644
--- a/lib/Checker/DivZeroChecker.cpp
+++ b/lib/Checker/DivZeroChecker.cpp
@@ -40,10 +40,10 @@ void *DivZeroChecker::getTag() {
void DivZeroChecker::PreVisitBinaryOperator(CheckerContext &C,
const BinaryOperator *B) {
BinaryOperator::Opcode Op = B->getOpcode();
- if (Op != BinaryOperator::Div &&
- Op != BinaryOperator::Rem &&
- Op != BinaryOperator::DivAssign &&
- Op != BinaryOperator::RemAssign)
+ if (Op != BO_Div &&
+ Op != BO_Rem &&
+ Op != BO_DivAssign &&
+ Op != BO_RemAssign)
return;
if (!B->getRHS()->getType()->isIntegerType() ||
diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp
index 48152ceb46f0..02291f43500c 100644
--- a/lib/Checker/Environment.cpp
+++ b/lib/Checker/Environment.cpp
@@ -80,7 +80,7 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
return LookupExpr(E);
}
-Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S,
+Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S,
SVal V, bool Invalidate) {
assert(S);
@@ -94,6 +94,16 @@ Environment EnvironmentManager::BindExpr(Environment Env, const Stmt *S,
return Environment(F.Add(Env.ExprBindings, S, V));
}
+static inline const Stmt *MakeLocation(const Stmt *S) {
+ return (const Stmt*) (((uintptr_t) S) | 0x1);
+}
+
+Environment EnvironmentManager::bindExprAndLocation(Environment Env,
+ const Stmt *S,
+ SVal location, SVal V) {
+ return Environment(F.Add(F.Add(Env.ExprBindings, MakeLocation(S), V), S, V));
+}
+
namespace {
class MarkLiveCallback : public SymbolVisitor {
SymbolReaper &SymReaper;
@@ -115,6 +125,12 @@ static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) {
return false;
}
+// In addition to mapping from Stmt * - > SVals in the Environment, we also
+// maintain a mapping from Stmt * -> SVals (locations) that were used during
+// a load and store.
+static inline bool IsLocation(const Stmt *S) {
+ return (bool) (((uintptr_t) S) & 0x1);
+}
// RemoveDeadBindings:
// - Remove subexpression bindings.
@@ -123,7 +139,6 @@ static bool isBlockExprInCallers(const Stmt *E, const LocationContext *LC) {
// - Mark their reachable symbols live in SymbolReaper,
// see ScanReachableSymbols.
// - Mark the region in DRoots if the binding is a loc::MemRegionVal.
-
Environment
EnvironmentManager::RemoveDeadBindings(Environment Env,
SymbolReaper &SymReaper,
@@ -136,12 +151,25 @@ EnvironmentManager::RemoveDeadBindings(Environment Env,
// individually removing all the subexpression bindings (which will greatly
// outnumber block-level expression bindings).
Environment NewEnv = getInitialEnvironment();
+
+ llvm::SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations;
// Iterate over the block-expr bindings.
for (Environment::iterator I = Env.begin(), E = Env.end();
I != E; ++I) {
const Stmt *BlkExpr = I.getKey();
+
+ // For recorded locations (used when evaluating loads and stores), we
+ // consider them live only when their associated normal expression is
+ // also live.
+ // NOTE: This assumes that loads/stores that evaluated to UnknownVal
+ // still have an entry in the map.
+ if (IsLocation(BlkExpr)) {
+ deferredLocations.push_back(std::make_pair(BlkExpr, I.getData()));
+ continue;
+ }
+
const SVal &X = I.getData();
// Block-level expressions in callers are assumed always live.
@@ -186,6 +214,15 @@ EnvironmentManager::RemoveDeadBindings(Environment Env,
if (X.isUndef() && cast<UndefinedVal>(X).getData())
NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X);
}
+
+ // Go through he deferred locations and add them to the new environment if
+ // the correspond Stmt* is in the map as well.
+ for (llvm::SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator
+ I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) {
+ const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1);
+ if (NewEnv.ExprBindings.lookup(S))
+ NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, I->first, I->second);
+ }
return NewEnv;
}
diff --git a/lib/Checker/FixedAddressChecker.cpp b/lib/Checker/FixedAddressChecker.cpp
index 4fce45bd35e8..29a3c3ae3533 100644
--- a/lib/Checker/FixedAddressChecker.cpp
+++ b/lib/Checker/FixedAddressChecker.cpp
@@ -40,7 +40,7 @@ void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
// 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)
+ if (B->getOpcode() != BO_Assign)
return;
QualType T = B->getType();
diff --git a/lib/Checker/FlatStore.cpp b/lib/Checker/FlatStore.cpp
index 64575b3c9783..21fa422166f0 100644
--- a/lib/Checker/FlatStore.cpp
+++ b/lib/Checker/FlatStore.cpp
@@ -44,11 +44,10 @@ public:
}
SVal ArrayToPointer(Loc Array);
- const GRState *RemoveDeadBindings(GRState &state,
- const StackFrameContext *LCtx,
+ Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots){
- return StateMgr.getPersistentState(state);
+ return store;
}
Store BindDecl(Store store, const VarRegion *VR, SVal initVal);
@@ -57,13 +56,10 @@ public:
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
- Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
- unsigned Count, InvalidatedSymbols *IS);
-
Store InvalidateRegions(Store store, const MemRegion * const *I,
const MemRegion * const *E, const Expr *Ex,
unsigned Count, InvalidatedSymbols *IS,
- bool invalidateGlobals);
+ bool invalidateGlobals, InvalidatedRegions *Regions);
void print(Store store, llvm::raw_ostream& Out, const char* nl,
const char *sep);
@@ -74,7 +70,14 @@ private:
return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
}
- Interval RegionToInterval(const MemRegion *R);
+ class RegionInterval {
+ public:
+ const MemRegion *R;
+ Interval I;
+ RegionInterval(const MemRegion *r, int64_t s, int64_t e) : R(r), I(s, e){}
+ };
+
+ RegionInterval RegionToInterval(const MemRegion *R);
SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T);
};
@@ -86,11 +89,15 @@ StoreManager *clang::CreateFlatStoreManager(GRStateManager &StMgr) {
SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) {
const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
- Interval I = RegionToInterval(R);
+ RegionInterval RI = RegionToInterval(R);
+ // FIXME: FlatStore should handle regions with unknown intervals.
+ if (!RI.R)
+ return UnknownVal();
+
RegionBindings B = getRegionBindings(store);
- const BindingVal *BV = B.lookup(R);
+ const BindingVal *BV = B.lookup(RI.R);
if (BV) {
- const SVal *V = BVFactory.Lookup(*BV, I);
+ const SVal *V = BVFactory.Lookup(*BV, RI.I);
if (V)
return *V;
else
@@ -116,9 +123,12 @@ Store FlatStoreManager::Bind(Store store, Loc L, SVal val) {
if (V)
BV = *V;
- Interval I = RegionToInterval(R);
- BV = BVFactory.Add(BV, I, val);
- B = RBFactory.Add(B, R, BV);
+ RegionInterval RI = RegionToInterval(R);
+ // FIXME: FlatStore should handle regions with unknown intervals.
+ if (!RI.R)
+ return B.getRoot();
+ BV = BVFactory.Add(BV, RI.I, val);
+ B = RBFactory.Add(B, RI.R, BV);
return B.getRoot();
}
@@ -139,7 +149,7 @@ SVal FlatStoreManager::ArrayToPointer(Loc Array) {
Store FlatStoreManager::BindDecl(Store store, const VarRegion *VR,
SVal initVal) {
- return store;
+ return Bind(store, ValMgr.makeLoc(VR), initVal);
}
Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
@@ -147,18 +157,12 @@ Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
}
Store FlatStoreManager::InvalidateRegions(Store store,
- const MemRegion * const *I,
- const MemRegion * const *E,
- const Expr *Ex, unsigned Count,
- InvalidatedSymbols *IS,
- bool invalidateGlobals) {
- assert(false && "Not implemented");
- return store;
-}
-
-Store FlatStoreManager::InvalidateRegion(Store store, const MemRegion *R,
- const Expr *E, unsigned Count,
- InvalidatedSymbols *IS) {
+ const MemRegion * const *I,
+ const MemRegion * const *E,
+ const Expr *Ex, unsigned Count,
+ InvalidatedSymbols *IS,
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
assert(false && "Not implemented");
return store;
}
@@ -170,15 +174,29 @@ void FlatStoreManager::print(Store store, llvm::raw_ostream& Out,
void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) {
}
-Interval FlatStoreManager::RegionToInterval(const MemRegion *R) {
+FlatStoreManager::RegionInterval
+FlatStoreManager::RegionToInterval(const MemRegion *R) {
switch (R->getKind()) {
case MemRegion::VarRegionKind: {
- QualType T = cast<VarRegion>(R)->getValueType(Ctx);
- uint64_t Size = Ctx.getTypeSize(T);
- return Interval(0, Size-1);
+ QualType T = cast<VarRegion>(R)->getValueType();
+ int64_t Size = Ctx.getTypeSize(T);
+ return RegionInterval(R, 0, Size-1);
}
+
+ case MemRegion::ElementRegionKind:
+ case MemRegion::FieldRegionKind: {
+ RegionOffset Offset = R->getAsOffset();
+ // We cannot compute offset for all regions, for example, elements
+ // with symbolic offsets.
+ if (!Offset.getRegion())
+ return RegionInterval(0, 0, 0);
+ int64_t Start = Offset.getOffset();
+ int64_t Size = Ctx.getTypeSize(cast<TypedRegion>(R)->getValueType());
+ return RegionInterval(Offset.getRegion(), Start, Start+Size);
+ }
+
default:
llvm_unreachable("Region kind unhandled.");
- return Interval(0, 0);
+ return RegionInterval(0, 0, 0);
}
}
diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp
index 18e112cc8d36..a49989b5fda5 100644
--- a/lib/Checker/GRCXXExprEngine.cpp
+++ b/lib/Checker/GRCXXExprEngine.cpp
@@ -17,7 +17,7 @@
using namespace clang;
-void GRExprEngine::EvalArguments(ExprIterator AI, ExprIterator AE,
+void GRExprEngine::EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
const FunctionProtoType *FnType,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
llvm::SmallVector<CallExprWLItem, 20> WorkList;
@@ -55,7 +55,7 @@ const CXXThisRegion *GRExprEngine::getCXXThisRegion(const CXXMethodDecl *D,
return ValMgr.getRegionManager().getCXXThisRegion(PT, SFC);
}
-void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ExplodedNodeSet Tmp;
Visit(Ex, Pred, Tmp);
@@ -94,9 +94,7 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
// Evaluate other arguments.
ExplodedNodeSet ArgsEvaluated;
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
- EvalArguments(const_cast<CXXConstructExpr*>(E)->arg_begin(),
- const_cast<CXXConstructExpr*>(E)->arg_end(),
- FnType, Pred, ArgsEvaluated);
+ EvalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, ArgsEvaluated);
// The callee stack frame context used to create the 'this' parameter region.
const StackFrameContext *SFC = AMgr.getStackFrame(CD,
Pred->getLocationContext(),
@@ -104,11 +102,12 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
const CXXThisRegion *ThisR = getCXXThisRegion(E->getConstructor(), SFC);
- CallEnter Loc(E, CD, Pred->getLocationContext());
+ CallEnter Loc(E, SFC->getAnalysisContext(), Pred->getLocationContext());
for (ExplodedNodeSet::iterator NI = ArgsEvaluated.begin(),
NE = ArgsEvaluated.end(); NI != NE; ++NI) {
const GRState *state = GetState(*NI);
- // Setup 'this' region.
+ // Setup 'this' region, so that the ctor is evaluated on the object pointed
+ // by 'Dest'.
state = state->bindLoc(loc::MemRegionVal(ThisR), Dest);
ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
if (N)
@@ -126,9 +125,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
// Evaluate explicit arguments with a worklist.
ExplodedNodeSet ArgsEvaluated;
- EvalArguments(const_cast<CXXMemberCallExpr*>(MCE)->arg_begin(),
- const_cast<CXXMemberCallExpr*>(MCE)->arg_end(),
- FnType, Pred, ArgsEvaluated);
+ EvalArguments(MCE->arg_begin(), MCE->arg_end(), FnType, Pred, ArgsEvaluated);
// Evaluate the implicit object argument.
ExplodedNodeSet AllArgsEvaluated;
@@ -157,7 +154,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
Builder->getBlock(),
Builder->getIndex());
const CXXThisRegion *ThisR = getCXXThisRegion(MD, SFC);
- CallEnter Loc(MCE, MD, Pred->getLocationContext());
+ CallEnter Loc(MCE, SFC->getAnalysisContext(), Pred->getLocationContext());
for (ExplodedNodeSet::iterator I = AllArgsEvaluated.begin(),
E = AllArgsEvaluated.end(); I != E; ++I) {
// Set up 'this' region.
@@ -169,7 +166,7 @@ void GRExprEngine::VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE,
}
}
-void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
+void GRExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
if (CNE->isArray()) {
// FIXME: allocating an array has not been handled.
@@ -177,7 +174,7 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
}
unsigned Count = Builder->getCurrentBlockCount();
- DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
+ DefinedOrUnknownSVal SymVal = getValueManager().getConjuredSymbolVal(NULL,CNE,
CNE->getType(), Count);
const MemRegion *NewReg = cast<loc::MemRegionVal>(SymVal).getRegion();
@@ -201,10 +198,7 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
const GRState *state = GetState(*I);
if (ObjTy->isRecordType()) {
- Store store = state->getStore();
- StoreManager::InvalidatedSymbols IS;
- store = getStoreManager().InvalidateRegion(store, EleReg, CNE, Count, &IS);
- state = state->makeWithStore(store);
+ state = state->InvalidateRegion(EleReg, CNE, Count);
} else {
if (CNE->hasInitializer()) {
SVal V = state->getSVal(*CNE->constructor_arg_begin());
@@ -220,8 +214,8 @@ void GRExprEngine::VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
}
}
-void GRExprEngine::VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
+void GRExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,
+ ExplodedNode *Pred,ExplodedNodeSet &Dst) {
// Should do more checking.
ExplodedNodeSet ArgEvaluated;
Visit(CDE->getArgument(), Pred, ArgEvaluated);
@@ -232,7 +226,7 @@ void GRExprEngine::VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
}
}
-void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
+void GRExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
// Get the this object region from StoreManager.
const MemRegion *R =
diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp
index a816186a307d..5125f366de2a 100644
--- a/lib/Checker/GRCoreEngine.cpp
+++ b/lib/Checker/GRCoreEngine.cpp
@@ -12,8 +12,10 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Checker/PathSensitive/AnalysisManager.h"
#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/GRExprEngine.h"
+#include "clang/Index/TranslationUnit.h"
#include "clang/AST/Expr.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/DenseMap.h"
@@ -24,6 +26,12 @@ using llvm::cast;
using llvm::isa;
using namespace clang;
+// This should be removed in the future.
+namespace clang {
+GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
+ const LangOptions& lopts);
+}
+
//===----------------------------------------------------------------------===//
// Worklist classes for exploration of reachable states.
//===----------------------------------------------------------------------===//
@@ -118,47 +126,15 @@ GRWorkList* GRWorkList::MakeBFSBlockDFSContents() {
//===----------------------------------------------------------------------===//
// Core analysis engine.
//===----------------------------------------------------------------------===//
-void GRCoreEngine::ProcessEndPath(GREndPathNodeBuilder& Builder) {
- SubEngine.ProcessEndPath(Builder);
-}
-
-void GRCoreEngine::ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder) {
- SubEngine.ProcessStmt(E, Builder);
-}
-
-bool GRCoreEngine::ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,
- GRBlockCounter BC) {
- return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
-}
-
-void GRCoreEngine::ProcessBranch(Stmt* Condition, Stmt* Terminator,
- GRBranchNodeBuilder& Builder) {
- SubEngine.ProcessBranch(Condition, Terminator, Builder);
-}
-
-void GRCoreEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
- SubEngine.ProcessIndirectGoto(Builder);
-}
-
-void GRCoreEngine::ProcessSwitch(GRSwitchNodeBuilder& Builder) {
- SubEngine.ProcessSwitch(Builder);
-}
-
-void GRCoreEngine::ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
- SubEngine.ProcessCallEnter(Builder);
-}
-
-void GRCoreEngine::ProcessCallExit(GRCallExitNodeBuilder &Builder) {
- SubEngine.ProcessCallExit(Builder);
-}
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
-bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
+bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
+ const GRState *InitState) {
if (G->num_roots() == 0) { // Initialize the analysis by constructing
// the root if none exists.
- CFGBlock* Entry = &(L->getCFG()->getEntry());
+ const CFGBlock* Entry = &(L->getCFG()->getEntry());
assert (Entry->empty() &&
"Entry block must be empty.");
@@ -167,7 +143,7 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
"Entry block must have 1 successor.");
// Get the solitary successor.
- CFGBlock* Succ = *(Entry->succ_begin());
+ const CFGBlock* Succ = *(Entry->succ_begin());
// Construct an edge representing the
// starting location in the function.
@@ -176,8 +152,11 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
// Set the current block counter to being empty.
WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
- // Generate the root.
- GenerateNode(StartLoc, getInitialState(L), 0);
+ if (!InitState)
+ // Generate the root.
+ GenerateNode(StartLoc, getInitialState(L), 0);
+ else
+ GenerateNode(StartLoc, InitState, 0);
}
while (Steps && WList->hasWork()) {
@@ -221,14 +200,25 @@ bool GRCoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps) {
}
}
- SubEngine.ProcessEndWorklist(WList->hasWork() || BlockAborted);
+ SubEngine.ProcessEndWorklist(hasWorkRemaining());
return WList->hasWork();
}
+void GRCoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
+ unsigned Steps,
+ const GRState *InitState,
+ ExplodedNodeSet &Dst) {
+ ExecuteWorkList(L, Steps, InitState);
+ for (llvm::SmallVectorImpl<ExplodedNode*>::iterator I = G->EndNodes.begin(),
+ E = G->EndNodes.end(); I != E; ++I) {
+ Dst.Add(*I);
+ }
+}
+
void GRCoreEngine::HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred) {
- GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(), L.getCallee(),
- Block, Index);
+ GRCallEnterNodeBuilder Builder(*this, Pred, L.getCallExpr(),
+ L.getCalleeContext(), Block, Index);
ProcessCallEnter(Builder);
}
@@ -239,7 +229,7 @@ void GRCoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
- CFGBlock* Blk = L.getDst();
+ const CFGBlock* Blk = L.getDst();
// Check if we are entering the EXIT block.
if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
@@ -260,8 +250,9 @@ void GRCoreEngine::HandleBlockEdge(const BlockEdge& L, ExplodedNode* Pred) {
if (ProcessBlockEntrance(Blk, Pred, WList->getBlockCounter()))
GenerateNode(BlockEntrance(Blk, Pred->getLocationContext()),
Pred->State, Pred);
- else
- BlockAborted = true;
+ else {
+ blocksAborted.push_back(std::make_pair(L, Pred));
+ }
}
void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
@@ -284,9 +275,9 @@ void GRCoreEngine::HandleBlockEntrance(const BlockEntrance& L,
HandleBlockExit(L.getBlock(), Pred);
}
-void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
+void GRCoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode* Pred) {
- if (Stmt* Term = B->getTerminator()) {
+ if (const Stmt* Term = B->getTerminator()) {
switch (Term->getStmtClass()) {
default:
assert(false && "Analysis for this terminator not implemented.");
@@ -372,8 +363,8 @@ void GRCoreEngine::HandleBlockExit(CFGBlock * B, ExplodedNode* Pred) {
Pred->State, Pred);
}
-void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
- ExplodedNode* Pred) {
+void GRCoreEngine::HandleBranch(const Stmt* Cond, const Stmt* Term,
+ const CFGBlock * B, ExplodedNode* Pred) {
assert (B->succ_size() == 2);
GRBranchNodeBuilder Builder(B, *(B->succ_begin()), *(B->succ_begin()+1),
@@ -382,7 +373,7 @@ void GRCoreEngine::HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock * B,
ProcessBranch(Cond, Term, Builder);
}
-void GRCoreEngine::HandlePostStmt(const PostStmt& L, CFGBlock* B,
+void GRCoreEngine::HandlePostStmt(const PostStmt& L, const CFGBlock* B,
unsigned StmtIdx, ExplodedNode* Pred) {
assert (!B->empty());
@@ -415,7 +406,7 @@ void GRCoreEngine::GenerateNode(const ProgramPoint& Loc,
if (IsNew) WList->Enqueue(Node);
}
-GRStmtNodeBuilder::GRStmtNodeBuilder(CFGBlock* b, unsigned idx,
+GRStmtNodeBuilder::GRStmtNodeBuilder(const CFGBlock* b, unsigned idx,
ExplodedNode* N, GRCoreEngine* e,
GRStateManager &mgr)
: Eng(*e), B(*b), Idx(idx), Pred(N), Mgr(mgr), Auditor(0),
@@ -438,7 +429,7 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
if (isa<CallEnter>(N->getLocation())) {
// Still use the index of the CallExpr. It's needed to create the callee
// StackFrameContext.
- Eng.WList->Enqueue(N, B, Idx);
+ Eng.WList->Enqueue(N, &B, Idx);
return;
}
@@ -447,7 +438,7 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
if (Loc == N->getLocation()) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be
// a member of Deferred.
- Eng.WList->Enqueue(N, B, Idx+1);
+ Eng.WList->Enqueue(N, &B, Idx+1);
return;
}
@@ -456,10 +447,10 @@ void GRStmtNodeBuilder::GenerateAutoTransition(ExplodedNode* N) {
Succ->addPredecessor(N, *Eng.G);
if (IsNew)
- Eng.WList->Enqueue(Succ, B, Idx+1);
+ Eng.WList->Enqueue(Succ, &B, Idx+1);
}
-ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, Stmt* S,
+ExplodedNode* GRStmtNodeBuilder::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K) {
const GRState* PredState = GetState(Pred);
@@ -692,6 +683,59 @@ void GREndPathNodeBuilder::GenerateCallExitNode(const GRState *state) {
void GRCallEnterNodeBuilder::GenerateNode(const GRState *state,
const LocationContext *LocCtx) {
+ // Check if the callee is in the same translation unit.
+ if (CalleeCtx->getTranslationUnit() !=
+ Pred->getLocationContext()->getTranslationUnit()) {
+ // Create a new engine. We must be careful that the new engine should not
+ // reference data structures owned by the old engine.
+
+ AnalysisManager &OldMgr = Eng.SubEngine.getAnalysisManager();
+
+ // Get the callee's translation unit.
+ idx::TranslationUnit *TU = CalleeCtx->getTranslationUnit();
+
+ // Create a new AnalysisManager with components of the callee's
+ // TranslationUnit.
+ // The Diagnostic is actually shared when we create ASTUnits from AST files.
+ AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(),
+ OldMgr.getLangOptions(),
+ OldMgr.getPathDiagnosticClient(),
+ OldMgr.getStoreManagerCreator(),
+ OldMgr.getConstraintManagerCreator(),
+ OldMgr.getIndexer(),
+ OldMgr.getMaxNodes(), OldMgr.getMaxLoop(),
+ OldMgr.shouldVisualizeGraphviz(),
+ OldMgr.shouldVisualizeUbigraph(),
+ OldMgr.shouldPurgeDead(),
+ OldMgr.shouldEagerlyAssume(),
+ OldMgr.shouldTrimGraph(),
+ OldMgr.shouldInlineCall(),
+ OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG());
+ llvm::OwningPtr<GRTransferFuncs> TF(MakeCFRefCountTF(AMgr.getASTContext(),
+ /* GCEnabled */ false,
+ AMgr.getLangOptions()));
+ // Create the new engine.
+ GRExprEngine NewEng(AMgr, TF.take());
+
+ // Create the new LocationContext.
+ AnalysisContext *NewAnaCtx = AMgr.getAnalysisContext(CalleeCtx->getDecl(),
+ CalleeCtx->getTranslationUnit());
+ const StackFrameContext *OldLocCtx = cast<StackFrameContext>(LocCtx);
+ const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx,
+ OldLocCtx->getParent(),
+ OldLocCtx->getCallSite(),
+ OldLocCtx->getCallSiteBlock(),
+ OldLocCtx->getIndex());
+
+ // Now create an initial state for the new engine.
+ const GRState *NewState = NewEng.getStateManager().MarshalState(state,
+ NewLocCtx);
+ ExplodedNodeSet ReturnNodes;
+ NewEng.ExecuteWorkListWithInitialState(NewLocCtx, AMgr.getMaxNodes(),
+ NewState, ReturnNodes);
+ return;
+ }
+
// Get the callee entry block.
const CFGBlock *Entry = &(LocCtx->getCFG()->getEntry());
assert(Entry->empty());
@@ -721,6 +765,6 @@ void GRCallExitNodeBuilder::GenerateNode(const GRState *state) {
ExplodedNode *Node = Eng.G->getNode(Loc, state, &isNew);
Node->addPredecessor(const_cast<ExplodedNode*>(Pred), *Eng.G);
if (isNew)
- Eng.WList->Enqueue(Node, *const_cast<CFGBlock*>(LocCtx->getCallSiteBlock()),
+ Eng.WList->Enqueue(Node, LocCtx->getCallSiteBlock(),
LocCtx->getIndex() + 1);
}
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index 07fee9d39e49..feb826e4a640 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -169,17 +169,18 @@ public:
// Checker worklist routines.
//===----------------------------------------------------------------------===//
-void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src, bool isPrevisit) {
+void GRExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, CallbackKind Kind) {
// Determine if we already have a cached 'CheckersOrdered' vector
- // specifically tailored for the provided <Stmt kind, isPrevisit>. This
+ // specifically tailored for the provided <CallbackKind, Stmt kind>. This
// can reduce the number of checkers actually called.
CheckersOrdered *CO = &Checkers;
llvm::OwningPtr<CheckersOrdered> NewCO;
-
- const std::pair<unsigned, unsigned> &K =
- std::make_pair((unsigned)S->getStmtClass(), isPrevisit ? 1U : 0U);
+
+ // The cache key is made up of the and the callback kind (pre- or post-visit)
+ // and the statement kind.
+ CallbackTag K = GetCallbackTag(Kind, S->getStmtClass());
CheckersOrdered *& CO_Ref = COCache[K];
@@ -204,7 +205,10 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
ExplodedNodeSet *PrevSet = &Src;
unsigned checkersEvaluated = 0;
- for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I){
+ for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I) {
+ // If all nodes are sunk, bail out early.
+ if (PrevSet->empty())
+ break;
ExplodedNodeSet *CurrSet = 0;
if (I+1 == E)
CurrSet = &Dst;
@@ -219,8 +223,8 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI) {
- checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, isPrevisit,
- respondsToCallback);
+ checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag,
+ Kind == PreVisitStmtCallback, respondsToCallback);
}
@@ -235,7 +239,9 @@ void GRExprEngine::CheckerVisit(Stmt *S, ExplodedNodeSet &Dst,
// If we built NewCO, check if we called all the checkers. This is important
// so that we know that we accurately determined the entire set of checkers
- // that responds to this callback.
+ // that responds to this callback. Note that 'checkersEvaluated' might
+ // not be the same as Checkers.size() if one of the Checkers generates
+ // a sink node.
if (NewCO.get() && checkersEvaluated == Checkers.size())
CO_Ref = NewCO.take();
@@ -300,10 +306,9 @@ bool GRExprEngine::CheckerEvalCall(const CallExpr *CE,
// FIXME: This is largely copy-paste from CheckerVisit(). Need to
// unify.
-void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
- ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src,
- SVal location, SVal val, bool isPrevisit) {
+void GRExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+ ExplodedNodeSet &Src, SVal location,
+ SVal val, bool isPrevisit) {
if (Checkers.empty()) {
Dst.insert(Src);
@@ -328,7 +333,7 @@ void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
NI != NE; ++NI)
- checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
+ checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,
*NI, tag, location, val, isPrevisit);
// Update which NodeSet is the current one.
@@ -457,7 +462,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
break;
SVal V = state->getSVal(loc::MemRegionVal(R));
- SVal Constraint_untested = EvalBinOp(state, BinaryOperator::GT, V,
+ SVal Constraint_untested = EvalBinOp(state, BO_GT, V,
ValMgr.makeZeroVal(T),
getContext().IntTy);
@@ -499,29 +504,135 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
/// logic for handling assumptions on symbolic values.
const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
bool assumption) {
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
+ // Determine if we already have a cached 'CheckersOrdered' vector
+ // specifically tailored for processing assumptions. This
+ // can reduce the number of checkers actually called.
+ CheckersOrdered *CO = &Checkers;
+ llvm::OwningPtr<CheckersOrdered> NewCO;
- if (!state)
- return NULL;
+ CallbackTag K = GetCallbackTag(ProcessAssumeCallback);
+ CheckersOrdered *& CO_Ref = COCache[K];
+
+ if (!CO_Ref) {
+ // If we have no previously cached CheckersOrdered vector for this
+ // statement kind, then create one.
+ NewCO.reset(new CheckersOrdered);
+ }
+ else {
+ // Use the already cached set.
+ CO = CO_Ref;
+ }
+
+ if (!CO->empty()) {
+ // Let the checkers have a crack at the assume before the transfer functions
+ // get their turn.
+ for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I!=E; ++I) {
- state = I->second->EvalAssume(state, cond, assumption);
+ // If any checker declares the state infeasible (or if it starts that
+ // way), bail out.
+ if (!state)
+ return NULL;
+
+ Checker *C = I->second;
+ bool respondsToCallback = true;
+
+ state = C->EvalAssume(state, cond, assumption, &respondsToCallback);
+
+ // Check if we're building the cache of checkers that care about Assumes.
+ if (NewCO.get() && respondsToCallback)
+ NewCO->push_back(*I);
+ }
+
+ // If we got through all the checkers, and we built a list of those that
+ // care about Assumes, save it.
+ if (NewCO.get())
+ CO_Ref = NewCO.take();
}
+ // If the state is infeasible at this point, bail out.
if (!state)
return NULL;
return TF->EvalAssume(state, cond, assumption);
}
+bool GRExprEngine::WantsRegionChangeUpdate(const GRState* state) {
+ CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
+ CheckersOrdered *CO = COCache[K];
+
+ if (!CO)
+ CO = &Checkers;
+
+ for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
+ Checker *C = I->second;
+ if (C->WantsRegionChangeUpdate(state))
+ return true;
+ }
+
+ return false;
+}
+
+const GRState *
+GRExprEngine::ProcessRegionChanges(const GRState *state,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ // FIXME: Most of this method is copy-pasted from ProcessAssume.
+
+ // Determine if we already have a cached 'CheckersOrdered' vector
+ // specifically tailored for processing region changes. This
+ // can reduce the number of checkers actually called.
+ CheckersOrdered *CO = &Checkers;
+ llvm::OwningPtr<CheckersOrdered> NewCO;
+
+ CallbackTag K = GetCallbackTag(EvalRegionChangesCallback);
+ CheckersOrdered *& CO_Ref = COCache[K];
+
+ if (!CO_Ref) {
+ // If we have no previously cached CheckersOrdered vector for this
+ // callback, then create one.
+ NewCO.reset(new CheckersOrdered);
+ }
+ else {
+ // Use the already cached set.
+ CO = CO_Ref;
+ }
+
+ // If there are no checkers, just return the state as is.
+ if (CO->empty())
+ return state;
+
+ for (CheckersOrdered::iterator I = CO->begin(), E = CO->end(); I != E; ++I) {
+ // If any checker declares the state infeasible (or if it starts that way),
+ // bail out.
+ if (!state)
+ return NULL;
+
+ Checker *C = I->second;
+ bool respondsToCallback = true;
+
+ state = C->EvalRegionChanges(state, Begin, End, &respondsToCallback);
+
+ // See if we're building a cache of checkers that care about region changes.
+ if (NewCO.get() && respondsToCallback)
+ NewCO->push_back(*I);
+ }
+
+ // If we got through all the checkers, and we built a list of those that
+ // care about region changes, save it.
+ if (NewCO.get())
+ CO_Ref = NewCO.take();
+
+ return state;
+}
+
void GRExprEngine::ProcessEndWorklist(bool hasWorkRemaining) {
for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
I != E; ++I) {
- I->second->VisitEndAnalysis(G, BR, hasWorkRemaining);
+ I->second->VisitEndAnalysis(G, BR, *this);
}
}
-void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
+void GRExprEngine::ProcessStmt(const CFGElement CE,GRStmtNodeBuilder& builder) {
CurrentStmt = CE.getStmt();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
CurrentStmt->getLocStart(),
@@ -535,15 +646,23 @@ void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
Builder->setAuditor(BatchAuditor.get());
// Create the cleaned state.
- const ExplodedNode *BasePred = Builder->getBasePredecessor();
+ const LocationContext *LC = EntryNode->getLocationContext();
+ SymbolReaper SymReaper(LC, CurrentStmt, SymMgr);
+
+ if (AMgr.shouldPurgeDead()) {
+ const GRState *St = EntryNode->getState();
- SymbolReaper SymReaper(BasePred->getLocationContext(), CurrentStmt, SymMgr);
+ for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
+ I != E; ++I) {
+ Checker *checker = I->second;
+ checker->MarkLiveSymbols(St, SymReaper);
+ }
- CleanedState = AMgr.shouldPurgeDead()
- ? StateMgr.RemoveDeadBindings(EntryNode->getState(),
- BasePred->getLocationContext()->getCurrentStackFrame(),
- SymReaper)
- : EntryNode->getState();
+ const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ CleanedState = StateMgr.RemoveDeadBindings(St, SFC, SymReaper);
+ } else {
+ CleanedState = EntryNode->getState();
+ }
// Process any special transfer function for dead symbols.
ExplodedNodeSet Tmp;
@@ -625,7 +744,8 @@ void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
Builder = NULL;
}
-void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
+void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
+ ExplodedNodeSet& Dst) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
S->getLocStart(),
"Error evaluating statement");
@@ -641,7 +761,6 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
switch (S->getStmtClass()) {
// C++ stuff we don't support yet.
- case Stmt::CXXBindReferenceExprClass:
case Stmt::CXXBindTemporaryExprClass:
case Stmt::CXXCatchStmtClass:
case Stmt::CXXConstructExprClass:
@@ -740,13 +859,13 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
break;
case Stmt::BinaryOperatorClass: {
- BinaryOperator* B = cast<BinaryOperator>(S);
+ const BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp()) {
VisitLogicalExpr(B, Pred, Dst);
break;
}
- else if (B->getOpcode() == BinaryOperator::Comma) {
+ else if (B->getOpcode() == BO_Comma) {
const GRState* state = GetState(Pred);
MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
break;
@@ -766,25 +885,25 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
case Stmt::CallExprClass:
case Stmt::CXXOperatorCallExprClass: {
- CallExpr* C = cast<CallExpr>(S);
+ const CallExpr* C = cast<CallExpr>(S);
VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
break;
}
case Stmt::CXXMemberCallExprClass: {
- CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
+ const CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
VisitCXXMemberCallExpr(MCE, Pred, Dst);
break;
}
case Stmt::CXXNewExprClass: {
- CXXNewExpr *NE = cast<CXXNewExpr>(S);
+ const CXXNewExpr *NE = cast<CXXNewExpr>(S);
VisitCXXNewExpr(NE, Pred, Dst);
break;
}
case Stmt::CXXDeleteExprClass: {
- CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
+ const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
VisitCXXDeleteExpr(CDE, Pred, Dst);
break;
}
@@ -792,7 +911,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
// the CFG do not model them as explicit control-flow.
case Stmt::ChooseExprClass: { // __builtin_choose_expr
- ChooseExpr* C = cast<ChooseExpr>(S);
+ const ChooseExpr* C = cast<ChooseExpr>(S);
VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
break;
}
@@ -806,7 +925,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
break;
case Stmt::ConditionalOperatorClass: { // '?' operator
- ConditionalOperator* C = cast<ConditionalOperator>(S);
+ const ConditionalOperator* C = cast<ConditionalOperator>(S);
VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
break;
}
@@ -836,7 +955,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
case Stmt::CXXReinterpretCastExprClass:
case Stmt::CXXConstCastExprClass:
case Stmt::CXXFunctionalCastExprClass: {
- CastExpr* C = cast<CastExpr>(S);
+ const CastExpr* C = cast<CastExpr>(S);
VisitCast(C, C->getSubExpr(), Pred, Dst, false);
break;
}
@@ -893,7 +1012,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
break;
case Stmt::StmtExprClass: {
- StmtExpr* SE = cast<StmtExpr>(S);
+ const StmtExpr* SE = cast<StmtExpr>(S);
if (SE->getSubStmt()->body_empty()) {
// Empty statement expression.
@@ -924,8 +1043,8 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
break;
case Stmt::UnaryOperatorClass: {
- UnaryOperator *U = cast<UnaryOperator>(S);
- if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UnaryOperator::LNot)) {
+ const UnaryOperator *U = cast<UnaryOperator>(S);
+ if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
ExplodedNodeSet Tmp;
VisitUnaryOperator(U, Pred, Tmp, false);
EvalEagerlyAssume(Dst, Tmp, U);
@@ -943,7 +1062,7 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) {
}
}
-void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
+void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -984,7 +1103,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
case Stmt::CallExprClass:
case Stmt::CXXOperatorCallExprClass: {
- CallExpr *C = cast<CallExpr>(Ex);
+ const CallExpr *C = cast<CallExpr>(Ex);
assert(CalleeReturnsReferenceOrRecord(C));
VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true);
break;
@@ -1000,7 +1119,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
case Stmt::ImplicitCastExprClass:
case Stmt::CStyleCastExprClass: {
- CastExpr *C = cast<CastExpr>(Ex);
+ const CastExpr *C = cast<CastExpr>(Ex);
QualType T = Ex->getType();
VisitCast(C, C->getSubExpr(), Pred, Dst, true);
break;
@@ -1015,7 +1134,7 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
return;
case Stmt::ObjCMessageExprClass: {
- ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex);
+ const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex);
assert(ReceiverReturnsReferenceOrRecord(ME));
VisitObjCMessageExpr(ME, Pred, Dst, true);
return;
@@ -1056,6 +1175,9 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
// In C++, binding an rvalue to a reference requires to create an object.
case Stmt::CXXBoolLiteralExprClass:
case Stmt::IntegerLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
CreateCXXTemporaryObject(Ex, Pred, Dst);
return;
@@ -1081,7 +1203,8 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred,
// Block entrance. (Update counters).
//===----------------------------------------------------------------------===//
-bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
+bool GRExprEngine::ProcessBlockEntrance(const CFGBlock* B,
+ const ExplodedNode *Pred,
GRBlockCounter BC) {
return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(),
B->getBlockID()) < AMgr.getMaxLoop();
@@ -1091,7 +1214,7 @@ bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
// Generic node creation.
//===----------------------------------------------------------------------===//
-ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, Stmt* S,
+ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K, const void *tag) {
assert (Builder && "GRStmtNodeBuilder not present.");
@@ -1105,8 +1228,8 @@ ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, Stmt* S,
//===----------------------------------------------------------------------===//
const GRState* GRExprEngine::MarkBranch(const GRState* state,
- Stmt* Terminator,
- bool branchTaken) {
+ const Stmt* Terminator,
+ bool branchTaken) {
switch (Terminator->getStmtClass()) {
default:
@@ -1114,10 +1237,10 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
case Stmt::BinaryOperatorClass: { // '&&' and '||'
- BinaryOperator* B = cast<BinaryOperator>(Terminator);
+ const BinaryOperator* B = cast<BinaryOperator>(Terminator);
BinaryOperator::Opcode Op = B->getOpcode();
- assert (Op == BinaryOperator::LAnd || Op == BinaryOperator::LOr);
+ assert (Op == BO_LAnd || Op == BO_LOr);
// For &&, if we take the true branch, then the value of the whole
// expression is that of the RHS expression.
@@ -1125,21 +1248,21 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
// For ||, if we take the false branch, then the value of the whole
// expression is that of the RHS expression.
- Expr* Ex = (Op == BinaryOperator::LAnd && branchTaken) ||
- (Op == BinaryOperator::LOr && !branchTaken)
- ? B->getRHS() : B->getLHS();
+ const Expr* Ex = (Op == BO_LAnd && branchTaken) ||
+ (Op == BO_LOr && !branchTaken)
+ ? B->getRHS() : B->getLHS();
return state->BindExpr(B, UndefinedVal(Ex));
}
case Stmt::ConditionalOperatorClass: { // ?:
- ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
+ const ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
// For ?, if branchTaken == true then the value is either the LHS or
// the condition itself. (GNU extension).
- Expr* Ex;
+ const Expr* Ex;
if (branchTaken)
Ex = C->getLHS() ? C->getLHS() : C->getCond();
@@ -1151,9 +1274,9 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
case Stmt::ChooseExprClass: { // ?:
- ChooseExpr* C = cast<ChooseExpr>(Terminator);
+ const ChooseExpr* C = cast<ChooseExpr>(Terminator);
- Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
+ const Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
return state->BindExpr(C, UndefinedVal(Ex));
}
}
@@ -1165,16 +1288,16 @@ const GRState* GRExprEngine::MarkBranch(const GRState* state,
/// This function returns the SVal bound to Condition->IgnoreCasts if all the
// cast(s) did was sign-extend the original value.
static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
- Stmt* Condition, ASTContext& Ctx) {
+ const Stmt* Condition, ASTContext& Ctx) {
- Expr *Ex = dyn_cast<Expr>(Condition);
+ const Expr *Ex = dyn_cast<Expr>(Condition);
if (!Ex)
return UnknownVal();
uint64_t bits = 0;
bool bitsInit = false;
- while (CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
+ while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
QualType T = CE->getType();
if (!T->isIntegerType())
@@ -1198,7 +1321,7 @@ static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
return state->getSVal(Ex);
}
-void GRExprEngine::ProcessBranch(Stmt* Condition, Stmt* Term,
+void GRExprEngine::ProcessBranch(const Stmt* Condition, const Stmt* Term,
GRBranchNodeBuilder& builder) {
// Check for NULL conditions; e.g. "for(;;)"
@@ -1285,7 +1408,7 @@ void GRExprEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) {
typedef GRIndirectGotoNodeBuilder::iterator iterator;
if (isa<loc::GotoLabel>(V)) {
- LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();
+ const LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();
for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {
if (I.getLabel() == L) {
@@ -1314,7 +1437,8 @@ void GRExprEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) {
}
-void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
+void GRExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L,
+ const Expr* R,
ExplodedNode* Pred, ExplodedNodeSet& Dst) {
assert(Ex == CurrentStmt &&
@@ -1325,7 +1449,7 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
assert (X.isUndef());
- Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
+ const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
assert(SE);
X = state->getSVal(SE);
@@ -1350,7 +1474,7 @@ void GRExprEngine::ProcessEndPath(GREndPathNodeBuilder& builder) {
void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
typedef GRSwitchNodeBuilder::iterator iterator;
const GRState* state = builder.getState();
- Expr* CondE = builder.getCondition();
+ const Expr* CondE = builder.getCondition();
SVal CondV_untested = state->getSVal(CondE);
if (CondV_untested.isUndef()) {
@@ -1363,10 +1487,12 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
const GRState *DefaultSt = state;
- bool defaultIsFeasible = false;
+
+ iterator I = builder.begin(), EI = builder.end();
+ bool defaultIsFeasible = I == EI;
- for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
- CaseStmt* Case = cast<CaseStmt>(I.getCase());
+ for ( ; I != EI; ++I) {
+ const CaseStmt* Case = I.getCase();
// Evaluate the LHS of the case value.
Expr::EvalResult V1;
@@ -1382,7 +1508,7 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
// Get the RHS of the case, if it exists.
Expr::EvalResult V2;
- if (Expr* E = Case->getRHS()) {
+ if (const Expr* E = Case->getRHS()) {
b = E->Evaluate(V2, getContext());
assert(b && V2.Val.isInt() && !V2.HasSideEffects
&& "Case condition must evaluate to an integer constant.");
@@ -1440,15 +1566,14 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
}
void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) {
- const FunctionDecl *FD = B.getCallee();
- const StackFrameContext *LocCtx = AMgr.getStackFrame(FD,
- B.getLocationContext(),
- B.getCallExpr(),
- B.getBlock(),
- B.getIndex());
+ const StackFrameContext *LocCtx
+ = AMgr.getStackFrame(B.getCalleeContext(),
+ B.getLocationContext(),
+ B.getCallExpr(),
+ B.getBlock(),
+ B.getIndex());
- const GRState *state = B.getState();
- state = getStoreManager().EnterStackFrame(state, LocCtx);
+ const GRState *state = B.getState()->EnterStackFrame(LocCtx);
B.GenerateNode(state, LocCtx);
}
@@ -1490,11 +1615,11 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
// Transfer functions: logical operations ('&&', '||').
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
+void GRExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
- assert(B->getOpcode() == BinaryOperator::LAnd ||
- B->getOpcode() == BinaryOperator::LOr);
+ assert(B->getOpcode() == BO_LAnd ||
+ B->getOpcode() == BO_LOr);
assert(B==CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
@@ -1534,7 +1659,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
// We took the LHS expression. Depending on whether we are '&&' or
// '||' we know what the value of the expression is via properties of
// the short-circuiting.
- X = ValMgr.makeIntVal(B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U,
+ X = ValMgr.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
B->getType());
MakeNode(Dst, B, Pred, state->BindExpr(B, X));
}
@@ -1544,7 +1669,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
// Transfer functions: Loads and stores.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred,
+void GRExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ExplodedNodeSet Tmp;
@@ -1557,21 +1682,21 @@ void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred,
ProgramPoint::PostLValueKind);
// Post-visit the BlockExpr.
- CheckerVisit(BE, Dst, Tmp, false);
+ CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback);
}
-void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred,
+void GRExprEngine::VisitDeclRefExpr(const DeclRefExpr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
}
-void GRExprEngine::VisitBlockDeclRefExpr(BlockDeclRefExpr *Ex,
+void GRExprEngine::VisitBlockDeclRefExpr(const BlockDeclRefExpr *Ex,
ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
}
-void GRExprEngine::VisitCommonDeclRefExpr(Expr *Ex, const NamedDecl *D,
+void GRExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue) {
@@ -1618,12 +1743,12 @@ void GRExprEngine::VisitCommonDeclRefExpr(Expr *Ex, const NamedDecl *D,
}
/// VisitArraySubscriptExpr - Transfer function for array accesses
-void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
+void GRExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr* A,
ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue){
- Expr* Base = A->getBase()->IgnoreParens();
- Expr* Idx = A->getIdx()->IgnoreParens();
+ const Expr* Base = A->getBase()->IgnoreParens();
+ const Expr* Idx = A->getIdx()->IgnoreParens();
ExplodedNodeSet Tmp;
if (Base->getType()->isVectorType()) {
@@ -1641,7 +1766,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
Visit(Idx, *I1, Tmp2); // Evaluate the index.
ExplodedNodeSet Tmp3;
- CheckerVisit(A, Tmp3, Tmp2, true);
+ CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback);
for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {
const GRState* state = GetState(*I2);
@@ -1658,7 +1783,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A,
}
/// VisitMemberExpr - Transfer function for member expressions.
-void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
+void GRExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue) {
Expr* Base = M->getBase()->IgnoreParens();
@@ -1689,16 +1814,15 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred,
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
- Stmt* StoreE, ExplodedNode* Pred,
- const GRState* state, SVal location, SVal Val,
- bool atDeclInit) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
+ ExplodedNode* Pred, const GRState* state,
+ SVal location, SVal Val, bool atDeclInit) {
// Do a previsit of the bind.
ExplodedNodeSet CheckedSet, Src;
Src.Add(Pred);
- CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
+ CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I!=E; ++I) {
@@ -1731,6 +1855,10 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
// The next thing to do is check if the GRTransferFuncs object wants to
// update the state based on the new binding. If the GRTransferFunc object
// doesn't do anything, just auto-propagate the current state.
+
+ // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'
+ // is non-NULL. Checkers typically care about
+
GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
newState != state);
@@ -1740,12 +1868,14 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
/// EvalStore - Handle the semantics of a store via an assignment.
/// @param Dst The node set to store generated state nodes
-/// @param Ex The expression representing the location of the store
+/// @param AssignE The assignment expression if the store happens in an
+/// assignment.
+/// @param LocatioinE The location expression that is stored to.
/// @param state The current simulation state
/// @param location The location to store the value
/// @param Val The value to be stored
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
- Expr* StoreE,
+void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
+ const Expr* LocationE,
ExplodedNode* Pred,
const GRState* state, SVal location, SVal Val,
const void *tag) {
@@ -1754,7 +1884,7 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
// Evaluate the location (checks for bad dereferences).
ExplodedNodeSet Tmp;
- EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
+ EvalLocation(Tmp, LocationE, Pred, state, location, tag, false);
if (Tmp.empty())
return;
@@ -1765,12 +1895,16 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, Expr *AssignE,
ProgramPoint::PostStoreKind);
SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
- // Proceed with the store.
+ // Proceed with the store. We use AssignE as the anchor for the PostStore
+ // ProgramPoint if it is non-NULL, and LocationE otherwise.
+ const Expr *StoreE = AssignE ? AssignE : LocationE;
+
for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
+ EvalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
}
-void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
+void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
+ ExplodedNode* Pred,
const GRState* state, SVal location,
const void *tag, QualType LoadTy) {
@@ -1780,7 +1914,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
if (const TypedRegion *TR =
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
- QualType ValTy = TR->getValueType(getContext());
+ QualType ValTy = TR->getValueType();
if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
static int loadReferenceTag = 0;
ExplodedNodeSet Tmp;
@@ -1800,7 +1934,7 @@ void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, Expr *Ex, ExplodedNode* Pred,
EvalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
}
-void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, Expr *Ex,
+void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
ExplodedNode* Pred,
const GRState* state, SVal location,
const void *tag, QualType LoadTy) {
@@ -1834,7 +1968,7 @@ void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, Expr *Ex,
}
}
-void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, Stmt *S,
+void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, const Stmt *S,
ExplodedNode* Pred,
const GRState* state, SVal location,
const void *tag, bool isLoad) {
@@ -1885,21 +2019,34 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
if (!FD)
return false;
- if (!FD->hasBody(FD))
- return false;
+ // Check if the function definition is in the same translation unit.
+ if (FD->hasBody(FD)) {
+ // Now we have the definition of the callee, create a CallEnter node.
+ CallEnter Loc(CE, AMgr.getAnalysisContext(FD), Pred->getLocationContext());
+
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+ Dst.Add(N);
+ return true;
+ }
- // Now we have the definition of the callee, create a CallEnter node.
- CallEnter Loc(CE, FD, Pred->getLocationContext());
+ // Check if we can find the function definition in other translation units.
+ if (AMgr.hasIndexer()) {
+ const AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);
+ if (C == 0)
+ return false;
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
- if (N)
+ CallEnter Loc(CE, C, Pred->getLocationContext());
+ ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
Dst.Add(N);
- return true;
+ return true;
+ }
+
+ return false;
}
-void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
- CallExpr::arg_iterator AI,
- CallExpr::arg_iterator AE,
+void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
+ CallExpr::const_arg_iterator AI,
+ CallExpr::const_arg_iterator AE,
ExplodedNodeSet& Dst, bool asLValue) {
// Determine the type of function we're calling (if available).
@@ -1946,7 +2093,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
// Now process the call itself.
ExplodedNodeSet DstTmp;
- Expr* Callee = CE->getCallee()->IgnoreParens();
+ const Expr* Callee = CE->getCallee()->IgnoreParens();
for (ExplodedNodeSet::iterator NI=ArgsEvaluated.begin(),
NE=ArgsEvaluated.end(); NI != NE; ++NI) {
@@ -1954,7 +2101,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
ExplodedNodeSet DstTmp2;
Visit(Callee, *NI, DstTmp2);
// Perform the previsit of the CallExpr, storing the results in DstTmp.
- CheckerVisit(CE, DstTmp, DstTmp2, true);
+ CheckerVisit(CE, DstTmp, DstTmp2, PreVisitStmtCallback);
}
// Finally, evaluate the function call. We try each of the checkers
@@ -2009,7 +2156,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
// If the callee returns a reference and we want an rvalue, skip this check
// and do the load.
if (!(!asLValue && CalleeReturnsReference(CE))) {
- CheckerVisit(CE, Dst, DstTmp3, false);
+ CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);
return;
}
@@ -2019,7 +2166,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
// FIXME: This conversion doesn't actually happen unless the result
// of CallExpr is consumed by another expression.
ExplodedNodeSet DstTmp4;
- CheckerVisit(CE, DstTmp4, DstTmp3, false);
+ CheckerVisit(CE, DstTmp4, DstTmp3, PostVisitStmtCallback);
QualType LoadTy = CE->getType();
static int *ConvertToRvalueTag = 0;
@@ -2039,7 +2186,7 @@ static std::pair<const void*,const void*> EagerlyAssumeTag
= std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));
void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- Expr *Ex) {
+ const Expr *Ex) {
for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
ExplodedNode *Pred = *I;
@@ -2082,10 +2229,11 @@ void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
// Transfer function: Objective-C ivar references.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, ExplodedNode* Pred,
+void GRExprEngine::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* Ex,
+ ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue) {
- Expr* Base = cast<Expr>(Ex->getBase());
+ const Expr* Base = cast<Expr>(Ex->getBase());
ExplodedNodeSet Tmp;
Visit(Base, Pred, Tmp);
@@ -2105,7 +2253,7 @@ void GRExprEngine::VisitObjCIvarRefExpr(ObjCIvarRefExpr* Ex, ExplodedNode* Pred,
// Transfer function: Objective-C fast enumeration 'for' statements.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
+void GRExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
ExplodedNode* Pred, ExplodedNodeSet& Dst) {
// ObjCForCollectionStmts are processed in two places. This method
@@ -2133,11 +2281,11 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
// container is empty. Thus this transfer function will by default
// result in state splitting.
- Stmt* elem = S->getElement();
+ const Stmt* elem = S->getElement();
SVal ElementV;
- if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
- VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
+ if (const DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
+ const VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
assert (ElemD->getInit() == 0);
ElementV = GetState(Pred)->getLValue(ElemD, Pred->getLocationContext());
VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
@@ -2153,12 +2301,12 @@ void GRExprEngine::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S,
}
}
-void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
+void GRExprEngine::VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
ExplodedNode* Pred, ExplodedNodeSet& Dst,
SVal ElementV) {
// Check if the location we are writing back to is a null pointer.
- Stmt* elem = S->getElement();
+ const Stmt* elem = S->getElement();
ExplodedNodeSet Tmp;
EvalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
@@ -2182,7 +2330,7 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
// 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());
+ QualType T = R->getValueType();
assert(Loc::IsLocType(T));
unsigned Count = Builder->getCurrentBlockCount();
SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
@@ -2207,23 +2355,24 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
namespace {
class ObjCMsgWLItem {
public:
- ObjCMessageExpr::arg_iterator I;
+ ObjCMessageExpr::const_arg_iterator I;
ExplodedNode *N;
- ObjCMsgWLItem(const ObjCMessageExpr::arg_iterator &i, ExplodedNode *n)
+ ObjCMsgWLItem(const ObjCMessageExpr::const_arg_iterator &i, ExplodedNode *n)
: I(i), N(n) {}
};
} // end anonymous namespace
-void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
+void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
+ ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue){
// Create a worklist to process both the arguments.
llvm::SmallVector<ObjCMsgWLItem, 20> WL;
// But first evaluate the receiver (if any).
- ObjCMessageExpr::arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();
- if (Expr *Receiver = ME->getInstanceReceiver()) {
+ ObjCMessageExpr::const_arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();
+ if (const Expr *Receiver = ME->getInstanceReceiver()) {
ExplodedNodeSet Tmp;
Visit(Receiver, Pred, Tmp);
@@ -2261,7 +2410,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
// Now that the arguments are processed, handle the previsits checks.
ExplodedNodeSet DstPrevisit;
- CheckerVisit(ME, DstPrevisit, ArgsEvaluated, true);
+ CheckerVisit(ME, DstPrevisit, ArgsEvaluated, PreVisitStmtCallback);
// Proceed with evaluate the message expression.
ExplodedNodeSet DstEval;
@@ -2364,7 +2513,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
// Finally, perform the post-condition check of the ObjCMessageExpr and store
// the created nodes in 'Dst'.
if (!(!asLValue && ReceiverReturnsReference(ME))) {
- CheckerVisit(ME, Dst, DstEval, false);
+ CheckerVisit(ME, Dst, DstEval, PostVisitStmtCallback);
return;
}
@@ -2374,7 +2523,7 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
// FIXME: This conversion doesn't actually happen unless the result
// of ObjCMessageExpr is consumed by another expression.
ExplodedNodeSet DstRValueConvert;
- CheckerVisit(ME, DstRValueConvert, DstEval, false);
+ CheckerVisit(ME, DstRValueConvert, DstEval, PostVisitStmtCallback);
QualType LoadTy = ME->getType();
static int *ConvertToRvalueTag = 0;
@@ -2390,8 +2539,9 @@ void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst, bool asLValue) {
+void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
+ ExplodedNode *Pred, ExplodedNodeSet &Dst,
+ bool asLValue) {
ExplodedNodeSet S1;
QualType T = CastE->getType();
QualType ExTy = Ex->getType();
@@ -2406,7 +2556,7 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
Visit(Ex, Pred, S1);
ExplodedNodeSet S2;
- CheckerVisit(CastE, S2, S1, true);
+ CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);
// If we are evaluating the cast in an lvalue context, we implicitly want
// the cast to evaluate to a location.
@@ -2417,14 +2567,14 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
}
switch (CastE->getCastKind()) {
- case CastExpr::CK_ToVoid:
+ case CK_ToVoid:
assert(!asLValue);
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
Dst.Add(*I);
return;
- case CastExpr::CK_NoOp:
- case CastExpr::CK_FunctionToPointerDecay:
+ case CK_NoOp:
+ case CK_FunctionToPointerDecay:
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
// Copy the SVal of Ex to CastE.
ExplodedNode *N = *I;
@@ -2435,20 +2585,21 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
}
return;
- case CastExpr::CK_Unknown:
- case CastExpr::CK_ArrayToPointerDecay:
- case CastExpr::CK_BitCast:
- case CastExpr::CK_LValueBitCast:
- case CastExpr::CK_IntegralCast:
- case CastExpr::CK_IntegralToPointer:
- case CastExpr::CK_PointerToIntegral:
- case CastExpr::CK_IntegralToFloating:
- case CastExpr::CK_FloatingToIntegral:
- case CastExpr::CK_FloatingCast:
- case CastExpr::CK_AnyPointerToObjCPointerCast:
- case CastExpr::CK_AnyPointerToBlockPointerCast:
- case CastExpr::CK_DerivedToBase:
- case CastExpr::CK_UncheckedDerivedToBase: {
+ case CK_Unknown:
+ case CK_ArrayToPointerDecay:
+ case CK_BitCast:
+ case CK_LValueBitCast:
+ case CK_IntegralCast:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingCast:
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_DerivedToBase:
+ case CK_UncheckedDerivedToBase:
+ case CK_ObjCObjectLValueCast: {
// Delegate to SValuator to process.
for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
ExplodedNode* N = *I;
@@ -2462,16 +2613,16 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
}
// Various C++ casts that are not handled yet.
- case CastExpr::CK_Dynamic:
- case CastExpr::CK_ToUnion:
- case CastExpr::CK_BaseToDerived:
- case CastExpr::CK_NullToMemberPointer:
- case CastExpr::CK_BaseToDerivedMemberPointer:
- case CastExpr::CK_DerivedToBaseMemberPointer:
- case CastExpr::CK_UserDefinedConversion:
- case CastExpr::CK_ConstructorConversion:
- case CastExpr::CK_VectorSplat:
- case CastExpr::CK_MemberPointerToBoolean: {
+ case CK_Dynamic:
+ case CK_ToUnion:
+ case CK_BaseToDerived:
+ case CK_NullToMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_UserDefinedConversion:
+ case CK_ConstructorConversion:
+ case CK_VectorSplat:
+ case CK_MemberPointerToBoolean: {
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
Builder->BuildSinks = true;
MakeNode(Dst, CastE, Pred, GetState(Pred));
@@ -2480,11 +2631,12 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
}
}
-void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
+void GRExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
ExplodedNode* Pred,
ExplodedNodeSet& Dst,
bool asLValue) {
- InitListExpr* ILE = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
+ const InitListExpr* ILE
+ = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
ExplodedNodeSet Tmp;
Visit(ILE, Pred, Tmp);
@@ -2502,17 +2654,17 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
}
}
-void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
+void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
ExplodedNodeSet& Dst) {
// The CFG has one DeclStmt per Decl.
- Decl* D = *DS->decl_begin();
+ const Decl* D = *DS->decl_begin();
if (!D || !isa<VarDecl>(D))
return;
const VarDecl* VD = dyn_cast<VarDecl>(D);
- Expr* InitEx = const_cast<Expr*>(VD->getInit());
+ const Expr* InitEx = VD->getInit();
// FIXME: static variables may have an initializer, but the second
// time a function is called those values may not be current.
@@ -2534,7 +2686,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
Tmp.Add(Pred);
ExplodedNodeSet Tmp2;
- CheckerVisit(DS, Tmp2, Tmp, true);
+ CheckerVisit(DS, Tmp2, Tmp, PreVisitStmtCallback);
for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {
ExplodedNode *N = *I;
@@ -2555,7 +2707,7 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
Builder->getCurrentBlockCount());
}
- EvalBind(Dst, DS, DS, *I, state,
+ EvalBind(Dst, DS, *I, state,
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
}
else {
@@ -2565,10 +2717,10 @@ void GRExprEngine::VisitDeclStmt(DeclStmt *DS, ExplodedNode *Pred,
}
}
-void GRExprEngine::VisitCondInit(VarDecl *VD, Stmt *S,
+void GRExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,
ExplodedNode *Pred, ExplodedNodeSet& Dst) {
- Expr* InitEx = VD->getInit();
+ const Expr* InitEx = VD->getInit();
ExplodedNodeSet Tmp;
Visit(InitEx, Pred, Tmp);
@@ -2587,7 +2739,7 @@ void GRExprEngine::VisitCondInit(VarDecl *VD, Stmt *S,
Builder->getCurrentBlockCount());
}
- EvalBind(Dst, S, S, N, state,
+ EvalBind(Dst, S, N, state,
loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
}
}
@@ -2599,16 +2751,16 @@ class InitListWLItem {
public:
llvm::ImmutableList<SVal> Vals;
ExplodedNode* N;
- InitListExpr::reverse_iterator Itr;
+ InitListExpr::const_reverse_iterator Itr;
InitListWLItem(ExplodedNode* n, llvm::ImmutableList<SVal> vals,
- InitListExpr::reverse_iterator itr)
+ InitListExpr::const_reverse_iterator itr)
: Vals(vals), N(n), Itr(itr) {}
};
}
-void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
+void GRExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
const GRState* state = GetState(Pred);
@@ -2630,7 +2782,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
llvm::SmallVector<InitListWLItem, 10> WorkList;
WorkList.reserve(NumInitElements);
WorkList.push_back(InitListWLItem(Pred, StartVals, E->rbegin()));
- InitListExpr::reverse_iterator ItrEnd = E->rend();
+ InitListExpr::const_reverse_iterator ItrEnd = E->rend();
assert(!(E->rbegin() == E->rend()));
// Process the worklist until it is empty.
@@ -2641,7 +2793,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet Tmp;
Visit(*X.Itr, X.N, Tmp);
- InitListExpr::reverse_iterator NewItr = X.Itr + 1;
+ InitListExpr::const_reverse_iterator NewItr = X.Itr + 1;
for (ExplodedNodeSet::iterator NI=Tmp.begin(),NE=Tmp.end();NI!=NE;++NI) {
// Get the last initializer value.
@@ -2673,7 +2825,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
if (Loc::IsLocType(T) || T->isIntegerType()) {
assert (E->getNumInits() == 1);
ExplodedNodeSet Tmp;
- Expr* Init = E->getInit(0);
+ const Expr* Init = E->getInit(0);
Visit(Init, Pred, Tmp);
for (ExplodedNodeSet::iterator I=Tmp.begin(), EI=Tmp.end(); I != EI; ++I) {
state = GetState(*I);
@@ -2686,7 +2838,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
}
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
-void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
+void GRExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
QualType T = Ex->getTypeOfArgument();
@@ -2709,7 +2861,7 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
// Get the size by getting the extent of the sub-expression.
// First, visit the sub-expression to find its region.
- Expr *Arg = Ex->getArgumentExpr();
+ const Expr *Arg = Ex->getArgumentExpr();
ExplodedNodeSet Tmp;
VisitLValue(Arg, Pred, Tmp);
@@ -2751,8 +2903,8 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
ValMgr.makeIntVal(amt.getQuantity(), Ex->getType())));
}
-void GRExprEngine::VisitOffsetOfExpr(OffsetOfExpr* OOE, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
+void GRExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE,
+ ExplodedNode* Pred, ExplodedNodeSet& Dst) {
Expr::EvalResult Res;
if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
const APSInt &IV = Res.Val.getInt();
@@ -2767,7 +2919,8 @@ void GRExprEngine::VisitOffsetOfExpr(OffsetOfExpr* OOE, ExplodedNode* Pred,
Dst.Add(Pred);
}
-void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
+void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
+ ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue) {
switch (U->getOpcode()) {
@@ -2775,9 +2928,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
default:
break;
- case UnaryOperator::Deref: {
+ case UO_Deref: {
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
ExplodedNodeSet Tmp;
Visit(Ex, Pred, Tmp);
@@ -2796,9 +2949,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
return;
}
- case UnaryOperator::Real: {
+ case UO_Real: {
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
ExplodedNodeSet Tmp;
Visit(Ex, Pred, Tmp);
@@ -2811,7 +2964,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
continue;
}
- // For all other types, UnaryOperator::Real is an identity operation.
+ // For all other types, UO_Real is an identity operation.
assert (U->getType() == Ex->getType());
const GRState* state = GetState(*I);
MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
@@ -2820,9 +2973,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
return;
}
- case UnaryOperator::Imag: {
+ case UO_Imag: {
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
ExplodedNodeSet Tmp;
Visit(Ex, Pred, Tmp);
@@ -2834,8 +2987,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
continue;
}
- // For all other types, UnaryOperator::Float returns 0.
- assert (Ex->getType()->isIntegerType());
+ // For all other types, UO_Imag returns 0.
const GRState* state = GetState(*I);
SVal X = ValMgr.makeZeroVal(Ex->getType());
MakeNode(Dst, U, *I, state->BindExpr(U, X));
@@ -2843,38 +2995,22 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
return;
}
-
- case UnaryOperator::OffsetOf: {
- Expr::EvalResult Res;
- if (U->Evaluate(Res, getContext()) && Res.Val.isInt()) {
- const APSInt &IV = Res.Val.getInt();
- assert(IV.getBitWidth() == getContext().getTypeSize(U->getType()));
- assert(U->getType()->isIntegerType());
- assert(IV.isSigned() == U->getType()->isSignedIntegerType());
- SVal X = ValMgr.makeIntVal(IV);
- MakeNode(Dst, U, Pred, GetState(Pred)->BindExpr(U, X));
- return;
- }
- // FIXME: Handle the case where __builtin_offsetof is not a constant.
- Dst.Add(Pred);
- return;
- }
- case UnaryOperator::Plus: assert(!asLValue); // FALL-THROUGH.
- case UnaryOperator::Extension: {
+ case UO_Plus: assert(!asLValue); // FALL-THROUGH.
+ case UO_Extension: {
// Unary "+" is a no-op, similar to a parentheses. We still have places
// where it may be a block-level expression, so we need to
// generate an extra node that just propagates the value of the
// subexpression.
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
ExplodedNodeSet Tmp;
if (asLValue)
- VisitLValue(Ex, Pred, Tmp);
+ VisitLValue(Ex, Pred, Tmp);
else
- Visit(Ex, Pred, Tmp);
+ Visit(Ex, Pred, Tmp);
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
const GRState* state = GetState(*I);
@@ -2884,10 +3020,10 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
return;
}
- case UnaryOperator::AddrOf: {
+ case UO_AddrOf: {
assert(!asLValue);
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
ExplodedNodeSet Tmp;
VisitLValue(Ex, Pred, Tmp);
@@ -2901,12 +3037,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
return;
}
- case UnaryOperator::LNot:
- case UnaryOperator::Minus:
- case UnaryOperator::Not: {
+ case UO_LNot:
+ case UO_Minus:
+ case UO_Not: {
assert (!asLValue);
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
ExplodedNodeSet Tmp;
Visit(Ex, Pred, Tmp);
@@ -2937,17 +3073,17 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
assert(false && "Invalid Opcode.");
break;
- case UnaryOperator::Not:
+ case UO_Not:
// FIXME: Do we need to handle promotions?
state = state->BindExpr(U, EvalComplement(cast<NonLoc>(V)));
break;
- case UnaryOperator::Minus:
+ case UO_Minus:
// FIXME: Do we need to handle promotions?
state = state->BindExpr(U, EvalMinus(cast<NonLoc>(V)));
break;
- case UnaryOperator::LNot:
+ case UO_LNot:
// C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
//
@@ -2957,12 +3093,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
if (isa<Loc>(V)) {
Loc X = ValMgr.makeNull();
- Result = EvalBinOp(state, BinaryOperator::EQ, cast<Loc>(V), X,
+ Result = EvalBinOp(state, BO_EQ, cast<Loc>(V), X,
U->getType());
}
else {
nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
- Result = EvalBinOp(state, BinaryOperator::EQ, cast<NonLoc>(V), X,
+ Result = EvalBinOp(state, BO_EQ, cast<NonLoc>(V), X,
U->getType());
}
@@ -2982,7 +3118,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
assert (U->isIncrementDecrementOp());
ExplodedNodeSet Tmp;
- Expr* Ex = U->getSubExpr()->IgnoreParens();
+ const Expr* Ex = U->getSubExpr()->IgnoreParens();
VisitLValue(Ex, Pred, Tmp);
for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
@@ -3007,8 +3143,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
// Handle all other values.
- BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
- : BinaryOperator::Sub;
+ BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add
+ : BO_Sub;
// If the UnaryOperator has non-location type, use its type to create the
// constant value. If the UnaryOperator has location type, create the
@@ -3057,14 +3193,14 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred,
}
}
-void GRExprEngine::VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred,
+void GRExprEngine::VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
}
-void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A,
- AsmStmt::outputs_iterator I,
- AsmStmt::outputs_iterator E,
+void GRExprEngine::VisitAsmStmtHelperOutputs(const AsmStmt* A,
+ AsmStmt::const_outputs_iterator I,
+ AsmStmt::const_outputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst) {
if (I == E) {
VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);
@@ -3080,9 +3216,9 @@ void GRExprEngine::VisitAsmStmtHelperOutputs(AsmStmt* A,
VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);
}
-void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
- AsmStmt::inputs_iterator I,
- AsmStmt::inputs_iterator E,
+void GRExprEngine::VisitAsmStmtHelperInputs(const AsmStmt* A,
+ AsmStmt::const_inputs_iterator I,
+ AsmStmt::const_inputs_iterator E,
ExplodedNode* Pred,
ExplodedNodeSet& Dst) {
if (I == E) {
@@ -3096,7 +3232,7 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
const GRState* state = GetState(Pred);
- for (AsmStmt::outputs_iterator OI = A->begin_outputs(),
+ for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
OE = A->end_outputs(); OI != OE; ++OI) {
SVal X = state->getSVal(*OI);
@@ -3119,10 +3255,10 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A,
VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
}
-void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
+void GRExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
ExplodedNodeSet Src;
- if (Expr *RetE = RS->getRetValue()) {
+ if (const Expr *RetE = RS->getRetValue()) {
// Record the returned expression in the state. It will be used in
// ProcessCallExit to bind the return value to the call expr.
{
@@ -3141,7 +3277,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
}
ExplodedNodeSet CheckedSet;
- CheckerVisit(RS, CheckedSet, Src, true);
+ CheckerVisit(RS, CheckedSet, Src, PreVisitStmtCallback);
for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
I != E; ++I) {
@@ -3167,7 +3303,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
// Transfer functions: Binary operators.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
+void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue) {
@@ -3194,7 +3330,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
Visit(RHS, *I1, Tmp2);
ExplodedNodeSet CheckedSet;
- CheckerVisit(B, CheckedSet, Tmp2, true);
+ CheckerVisit(B, CheckedSet, Tmp2, PreVisitStmtCallback);
// With both the LHS and RHS evaluated, process the operation itself.
@@ -3207,13 +3343,13 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
BinaryOperator::Opcode Op = B->getOpcode();
- if (Op == BinaryOperator::Assign) {
+ if (Op == BO_Assign) {
// EXPERIMENTAL: "Conjured" symbols.
// FIXME: Handle structs.
QualType T = RHS->getType();
- if ((RightV.isUnknown()||!getConstraintManager().canReasonAbout(RightV))
- && (Loc::IsLocType(T) || (T->isScalarType()&&T->isIntegerType()))) {
+ if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))
+ {
unsigned Count = Builder->getCurrentBlockCount();
RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
}
@@ -3253,16 +3389,16 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
switch (Op) {
default:
assert(0 && "Invalid opcode for compound assignment.");
- case BinaryOperator::MulAssign: Op = BinaryOperator::Mul; break;
- case BinaryOperator::DivAssign: Op = BinaryOperator::Div; break;
- case BinaryOperator::RemAssign: Op = BinaryOperator::Rem; break;
- case BinaryOperator::AddAssign: Op = BinaryOperator::Add; break;
- case BinaryOperator::SubAssign: Op = BinaryOperator::Sub; break;
- case BinaryOperator::ShlAssign: Op = BinaryOperator::Shl; break;
- case BinaryOperator::ShrAssign: Op = BinaryOperator::Shr; break;
- case BinaryOperator::AndAssign: Op = BinaryOperator::And; break;
- case BinaryOperator::XorAssign: Op = BinaryOperator::Xor; break;
- case BinaryOperator::OrAssign: Op = BinaryOperator::Or; break;
+ case BO_MulAssign: Op = BO_Mul; break;
+ case BO_DivAssign: Op = BO_Div; break;
+ case BO_RemAssign: Op = BO_Rem; break;
+ case BO_AddAssign: Op = BO_Add; break;
+ case BO_SubAssign: Op = BO_Sub; break;
+ case BO_ShlAssign: Op = BO_Shl; break;
+ case BO_ShrAssign: Op = BO_Shr; break;
+ case BO_AndAssign: Op = BO_And; break;
+ case BO_XorAssign: Op = BO_Xor; break;
+ case BO_OrAssign: Op = BO_Or; break;
}
// Perform a load (the LHS). This performs the checks for
@@ -3300,10 +3436,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
SVal LHSVal;
- if ((Result.isUnknown() ||
- !getConstraintManager().canReasonAbout(Result))
- && (Loc::IsLocType(CTy)
- || (CTy->isScalarType() && CTy->isIntegerType()))) {
+ if (Result.isUnknown() ||
+ !getConstraintManager().canReasonAbout(Result)) {
unsigned Count = Builder->getCurrentBlockCount();
@@ -3327,7 +3461,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
}
}
- CheckerVisit(B, Dst, Tmp3, false);
+ CheckerVisit(B, Dst, Tmp3, PostVisitStmtCallback);
}
//===----------------------------------------------------------------------===//
@@ -3457,7 +3591,7 @@ struct DOTGraphTraits<ExplodedNode*> :
Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
<< E.getDst()->getBlockID() << ')';
- if (Stmt* T = E.getSrc()->getTerminator()) {
+ if (const Stmt* T = E.getSrc()->getTerminator()) {
SourceLocation SLoc = T->getLocStart();
@@ -3473,15 +3607,15 @@ struct DOTGraphTraits<ExplodedNode*> :
}
if (isa<SwitchStmt>(T)) {
- Stmt* Label = E.getDst()->getLabel();
+ const Stmt* Label = E.getDst()->getLabel();
if (Label) {
- if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
+ if (const CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
Out << "\\lcase ";
LangOptions LO; // FIXME.
C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
- if (Stmt* RHS = C->getRHS()) {
+ if (const Stmt* RHS = C->getRHS()) {
Out << " .. ";
RHS->printPretty(Out, 0, PrintingPolicy(LO));
}
diff --git a/lib/Checker/GRExprEngineExperimentalChecks.cpp b/lib/Checker/GRExprEngineExperimentalChecks.cpp
index d138e81c4691..84262b004341 100644
--- a/lib/Checker/GRExprEngineExperimentalChecks.cpp
+++ b/lib/Checker/GRExprEngineExperimentalChecks.cpp
@@ -18,13 +18,14 @@
using namespace clang;
-void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {
+void clang::RegisterExperimentalChecks(GRExprEngine &Eng) {
// These are checks that never belong as internal checks
// within GRExprEngine.
- RegisterPthreadLockChecker(Eng);
+ RegisterCStringChecker(Eng);
RegisterMallocChecker(Eng);
+ RegisterPthreadLockChecker(Eng);
RegisterStreamChecker(Eng);
- RegisterCStringChecker(Eng);
+ RegisterUnreachableCodeChecker(Eng);
}
void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {
@@ -34,11 +35,10 @@ void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {
// Note that this must be registered after ReturnStackAddresEngsChecker.
RegisterReturnPointerRangeChecker(Eng);
+ RegisterArrayBoundChecker(Eng);
+ RegisterCastSizeChecker(Eng);
+ RegisterCastToStructChecker(Eng);
RegisterFixedAddressChecker(Eng);
- RegisterPointerSubChecker(Eng);
RegisterPointerArithChecker(Eng);
- RegisterCastToStructChecker(Eng);
- RegisterCastSizeChecker(Eng);
- RegisterArrayBoundChecker(Eng);
-
+ RegisterPointerSubChecker(Eng);
}
diff --git a/lib/Checker/GRExprEngineExperimentalChecks.h b/lib/Checker/GRExprEngineExperimentalChecks.h
index 7d1eb77f9fd6..7b5b0ed7ba00 100644
--- a/lib/Checker/GRExprEngineExperimentalChecks.h
+++ b/lib/Checker/GRExprEngineExperimentalChecks.h
@@ -20,10 +20,11 @@ namespace clang {
class GRExprEngine;
void RegisterCStringChecker(GRExprEngine &Eng);
-void RegisterPthreadLockChecker(GRExprEngine &Eng);
+void RegisterIdempotentOperationChecker(GRExprEngine &Eng);
void RegisterMallocChecker(GRExprEngine &Eng);
+void RegisterPthreadLockChecker(GRExprEngine &Eng);
void RegisterStreamChecker(GRExprEngine &Eng);
-void RegisterIdempotentOperationChecker(GRExprEngine &Eng);
+void RegisterUnreachableCodeChecker(GRExprEngine &Eng);
} // end clang namespace
#endif
diff --git a/lib/Checker/GRState.cpp b/lib/Checker/GRState.cpp
index 9e584b56148c..d38ae21fce94 100644
--- a/lib/Checker/GRState.cpp
+++ b/lib/Checker/GRState.cpp
@@ -14,6 +14,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Checker/PathSensitive/GRStateTrait.h"
#include "clang/Checker/PathSensitive/GRState.h"
+#include "clang/Checker/PathSensitive/GRSubEngine.h"
#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
#include "llvm/Support/raw_ostream.h"
@@ -51,22 +52,105 @@ GRStateManager::RemoveDeadBindings(const GRState* state,
state, RegionRoots);
// Clean up the store.
- const GRState *s = StoreMgr->RemoveDeadBindings(NewState, LCtx,
- SymReaper, RegionRoots);
+ NewState.St = StoreMgr->RemoveDeadBindings(NewState.St, LCtx,
+ SymReaper, RegionRoots);
+ state = getPersistentState(NewState);
+ return ConstraintMgr->RemoveDeadBindings(state, SymReaper);
+}
+
+const GRState *GRStateManager::MarshalState(const GRState *state,
+ const StackFrameContext *InitLoc) {
+ // make up an empty state for now.
+ GRState State(this,
+ EnvMgr.getInitialEnvironment(),
+ StoreMgr->getInitialStore(InitLoc),
+ GDMFactory.GetEmptyMap());
+
+ return getPersistentState(State);
+}
+
+const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
+ const LocationContext *LC,
+ SVal V) const {
+ Store new_store =
+ getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V);
+ return makeWithStore(new_store);
+}
+
+const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
+ Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal);
+ return makeWithStore(new_store);
+}
+
+const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
+ Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR);
+ return makeWithStore(new_store);
+}
+
+const GRState *GRState::bindLoc(Loc LV, SVal V) const {
+ GRStateManager &Mgr = getStateManager();
+ Store new_store = Mgr.StoreMgr->Bind(St, LV, V);
+ const GRState *new_state = makeWithStore(new_store);
- return ConstraintMgr->RemoveDeadBindings(s, SymReaper);
+ const MemRegion *MR = LV.getAsRegion();
+ if (MR)
+ return Mgr.getOwningEngine().ProcessRegionChange(new_state, MR);
+
+ return new_state;
+}
+
+const GRState *GRState::bindDefault(SVal loc, SVal V) const {
+ GRStateManager &Mgr = getStateManager();
+ const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
+ Store new_store = Mgr.StoreMgr->BindDefault(St, R, V);
+ const GRState *new_state = makeWithStore(new_store);
+ return Mgr.getOwningEngine().ProcessRegionChange(new_state, R);
+}
+
+const GRState *GRState::InvalidateRegions(const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ StoreManager::InvalidatedSymbols *IS,
+ bool invalidateGlobals) const {
+ GRStateManager &Mgr = getStateManager();
+ GRSubEngine &Eng = Mgr.getOwningEngine();
+
+ if (Eng.WantsRegionChangeUpdate(this)) {
+ StoreManager::InvalidatedRegions Regions;
+
+ Store new_store = Mgr.StoreMgr->InvalidateRegions(St, Begin, End,
+ E, Count, IS,
+ invalidateGlobals,
+ &Regions);
+ const GRState *new_state = makeWithStore(new_store);
+
+ return Eng.ProcessRegionChanges(new_state,
+ &Regions.front(),
+ &Regions.back()+1);
+ }
+
+ Store new_store = Mgr.StoreMgr->InvalidateRegions(St, Begin, End,
+ E, Count, IS,
+ invalidateGlobals,
+ NULL);
+ return makeWithStore(new_store);
}
const GRState *GRState::unbindLoc(Loc LV) const {
+ assert(!isa<loc::MemRegionVal>(LV) && "Use InvalidateRegion instead.");
+
Store OldStore = getStore();
Store NewStore = getStateManager().StoreMgr->Remove(OldStore, LV);
if (NewStore == OldStore)
return this;
- GRState NewSt = *this;
- NewSt.St = NewStore;
- return getStateManager().getPersistentState(NewSt);
+ return makeWithStore(NewStore);
+}
+
+const GRState *GRState::EnterStackFrame(const StackFrameContext *frame) const {
+ Store new_store = getStateManager().StoreMgr->EnterStackFrame(this, frame);
+ return makeWithStore(new_store);
}
SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
@@ -77,7 +161,7 @@ SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
return UnknownVal();
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
- QualType T = TR->getValueType(getStateManager().getContext());
+ QualType T = TR->getValueType();
if (Loc::IsLocType(T) || T->isIntegerType())
return getSVal(R);
}
@@ -85,9 +169,45 @@ SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
return UnknownVal();
}
+SVal GRState::getSimplifiedSVal(Loc location, QualType T) const {
+ SVal V = getSVal(cast<Loc>(location), T);
+
+ // If 'V' is a symbolic value that is *perfectly* constrained to
+ // be a constant value, use that value instead to lessen the burden
+ // on later analysis stages (so we have less symbolic values to reason
+ // about).
+ if (!T.isNull()) {
+ if (SymbolRef sym = V.getAsSymbol()) {
+ if (const llvm::APSInt *Int = getSymVal(sym)) {
+ // FIXME: Because we don't correctly model (yet) sign-extension
+ // and truncation of symbolic values, we need to convert
+ // the integer value to the correct signedness and bitwidth.
+ //
+ // This shows up in the following:
+ //
+ // char foo();
+ // unsigned x = foo();
+ // if (x == 54)
+ // ...
+ //
+ // The symbolic value stored to 'x' is actually the conjured
+ // symbol for the call to foo(); the type of that symbol is 'char',
+ // not unsigned.
+ const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
+
+ if (isa<Loc>(V))
+ return loc::ConcreteInt(NewV);
+ else
+ return nonloc::ConcreteInt(NewV);
+ }
+ }
+ }
+
+ return V;
+}
-const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{
- Environment NewEnv = getStateManager().EnvMgr.BindExpr(Env, Ex, V,
+const GRState *GRState::BindExpr(const Stmt* S, SVal V, bool Invalidate) const{
+ Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V,
Invalidate);
if (NewEnv == Env)
return this;
@@ -97,6 +217,63 @@ const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{
return getStateManager().getPersistentState(NewSt);
}
+const GRState *GRState::bindExprAndLocation(const Stmt *S, SVal location,
+ SVal V) const {
+ Environment NewEnv =
+ getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V);
+
+ if (NewEnv == Env)
+ return this;
+
+ GRState NewSt = *this;
+ NewSt.Env = NewEnv;
+ return getStateManager().getPersistentState(NewSt);
+}
+
+const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
+ DefinedOrUnknownSVal UpperBound,
+ bool Assumption) const {
+ if (Idx.isUnknown() || UpperBound.isUnknown())
+ return this;
+
+ // Build an expression for 0 <= Idx < UpperBound.
+ // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
+ // FIXME: This should probably be part of SValuator.
+ GRStateManager &SM = getStateManager();
+ ValueManager &VM = SM.getValueManager();
+ SValuator &SV = VM.getSValuator();
+ ASTContext &Ctx = VM.getContext();
+
+ // Get the offset: the minimum value of the array index type.
+ BasicValueFactory &BVF = VM.getBasicValueFactory();
+ // FIXME: This should be using ValueManager::ArrayIndexTy...somehow.
+ QualType IndexTy = Ctx.IntTy;
+ nonloc::ConcreteInt Min = BVF.getMinValue(IndexTy);
+
+ // Adjust the index.
+ SVal NewIdx = SV.EvalBinOpNN(this, BO_Add,
+ cast<NonLoc>(Idx), Min, IndexTy);
+ if (NewIdx.isUnknownOrUndef())
+ return this;
+
+ // Adjust the upper bound.
+ SVal NewBound = SV.EvalBinOpNN(this, BO_Add,
+ cast<NonLoc>(UpperBound), Min, IndexTy);
+ if (NewBound.isUnknownOrUndef())
+ return this;
+
+ // Build the actual comparison.
+ SVal InBound = SV.EvalBinOpNN(this, BO_LT,
+ cast<NonLoc>(NewIdx), cast<NonLoc>(NewBound),
+ Ctx.IntTy);
+ if (InBound.isUnknownOrUndef())
+ return this;
+
+ // Finally, let the constraint manager take care of it.
+ ConstraintManager &CM = SM.getConstraintManager();
+ return CM.Assume(this, cast<DefinedSVal>(InBound), Assumption);
+}
+
const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
GRState State(this,
EnvMgr.getInitialEnvironment(),
@@ -131,6 +308,11 @@ const GRState* GRState::makeWithStore(Store store) const {
// State pretty-printing.
//===----------------------------------------------------------------------===//
+static bool IsEnvLoc(const Stmt *S) {
+ // FIXME: This is a layering violation. Should be in environment.
+ return (bool) (((uintptr_t) S) & 0x1);
+}
+
void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
const char* sep) const {
// Print the store.
@@ -140,8 +322,9 @@ void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
// Print Subexpression bindings.
bool isFirst = true;
+ // FIXME: All environment printing should be moved inside Environment.
for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
- if (C.isBlkExpr(I.getKey()))
+ if (C.isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey()))
continue;
if (isFirst) {
@@ -174,6 +357,27 @@ void GRState::print(llvm::raw_ostream& Out, CFG &C, const char* nl,
I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
Out << " : " << I.getData();
}
+
+ // Print locations.
+ isFirst = true;
+
+ for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
+ if (!IsEnvLoc(I.getKey()))
+ continue;
+
+ if (isFirst) {
+ Out << nl << nl << "Load/store locations:" << nl;
+ isFirst = false;
+ }
+ else { Out << nl; }
+
+ const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
+
+ Out << " (" << (void*) S << ") ";
+ LangOptions LO; // FIXME.
+ S->printPretty(Out, 0, PrintingPolicy(LO));
+ Out << " : " << I.getData();
+ }
Mgr.getConstraintManager().print(this, Out, nl, sep);
diff --git a/lib/Checker/IdempotentOperationChecker.cpp b/lib/Checker/IdempotentOperationChecker.cpp
index 6ed18417a2c2..6411c790ef7c 100644
--- a/lib/Checker/IdempotentOperationChecker.cpp
+++ b/lib/Checker/IdempotentOperationChecker.cpp
@@ -36,25 +36,26 @@
// != | 0 | | | | | |
//===----------------------------------------------------------------------===//
//
-// Ways to reduce false positives (that need to be implemented):
-// - Don't flag downsizing casts
-// - Improved handling of static/global variables
-// - Per-block marking of incomplete analysis
-// - Handling ~0 values
-// - False positives involving silencing unused variable warnings
-//
-// Other things TODO:
+// Things TODO:
// - Improved error messages
// - Handle mixed assumptions (which assumptions can belong together?)
// - Finer grained false positive control (levels)
+// - Handling ~0 values
#include "GRExprEngineExperimentalChecks.h"
+#include "clang/Analysis/CFGStmtMap.h"
+#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
#include "clang/Checker/BugReporter/BugType.h"
+#include "clang/Checker/PathSensitive/CheckerHelpers.h"
#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/SVals.h"
#include "clang/AST/Stmt.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/ErrorHandling.h"
+#include <deque>
using namespace clang;
@@ -64,38 +65,41 @@ class IdempotentOperationChecker
public:
static void *getTag();
void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
- void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
- bool hasWorkRemaining);
+ void PostVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
+ void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, GRExprEngine &Eng);
private:
// Our assumption about a particular operation.
- enum Assumption { Possible, Impossible, Equal, LHSis1, RHSis1, LHSis0,
+ enum Assumption { Possible = 0, Impossible, Equal, LHSis1, RHSis1, LHSis0,
RHSis0 };
void UpdateAssumption(Assumption &A, const Assumption &New);
- /// contains* - Useful recursive methods to see if a statement contains an
- /// element somewhere. Used in static analysis to reduce false positives.
- static bool containsMacro(const Stmt *S);
- static bool containsEnum(const Stmt *S);
- static bool containsBuiltinOffsetOf(const Stmt *S);
- static bool containsZeroConstant(const Stmt *S);
- static bool containsOneConstant(const Stmt *S);
- template <class T> static bool containsStmt(const Stmt *S) {
- if (isa<T>(S))
- return true;
-
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsStmt<T>(child))
- return true;
-
- return false;
- }
-
- // Hash table
- typedef llvm::DenseMap<const BinaryOperator *, Assumption> AssumptionMap;
+ // False positive reduction methods
+ static bool isSelfAssign(const Expr *LHS, const Expr *RHS);
+ static bool isUnused(const Expr *E, AnalysisContext *AC);
+ //static bool isTruncationExtensionAssignment(const Expr *LHS,
+ // const Expr *RHS);
+ static bool PathWasCompletelyAnalyzed(const CFG *C,
+ const CFGBlock *CB,
+ const GRCoreEngine &CE);
+ static bool CanVary(const Expr *Ex,
+ AnalysisContext *AC);
+ static bool isConstantOrPseudoConstant(const DeclRefExpr *DR,
+ AnalysisContext *AC);
+ static bool containsNonLocalVarDecl(const Stmt *S);
+
+ // Hash table and related data structures
+ struct BinaryOperatorData {
+ BinaryOperatorData() : assumption(Possible), analysisContext(0) {}
+
+ Assumption assumption;
+ AnalysisContext *analysisContext;
+ ExplodedNodeSet explodedNodes; // Set of ExplodedNodes that refer to a
+ // BinaryOperator
+ };
+ typedef llvm::DenseMap<const BinaryOperator *, BinaryOperatorData>
+ AssumptionMap;
AssumptionMap hash;
};
}
@@ -112,30 +116,38 @@ void clang::RegisterIdempotentOperationChecker(GRExprEngine &Eng) {
void IdempotentOperationChecker::PreVisitBinaryOperator(
CheckerContext &C,
const BinaryOperator *B) {
- // Find or create an entry in the hash for this BinaryOperator instance
- AssumptionMap::iterator i = hash.find(B);
- Assumption &A = i == hash.end() ? hash[B] : i->second;
-
- // If we had to create an entry, initialise the value to Possible
- if (i == hash.end())
- A = Possible;
+ // Find or create an entry in the hash for this BinaryOperator instance.
+ // If we haven't done a lookup before, it will get default initialized to
+ // 'Possible'. At this stage we do not store the ExplodedNode, as it has not
+ // been created yet.
+ BinaryOperatorData &Data = hash[B];
+ Assumption &A = Data.assumption;
+ AnalysisContext *AC = C.getCurrentAnalysisContext();
+ Data.analysisContext = AC;
// If we already have visited this node on a path that does not contain an
// idempotent operation, return immediately.
if (A == Impossible)
return;
- // Skip binary operators containing common false positives
- if (containsMacro(B) || containsEnum(B) || containsStmt<SizeOfAlignOfExpr>(B)
- || containsZeroConstant(B) || containsOneConstant(B)
- || containsBuiltinOffsetOf(B)) {
- A = Impossible;
- return;
- }
-
+ // Retrieve both sides of the operator and determine if they can vary (which
+ // may mean this is a false positive.
const Expr *LHS = B->getLHS();
const Expr *RHS = B->getRHS();
+ // At this stage we can calculate whether each side contains a false positive
+ // that applies to all operators. We only need to calculate this the first
+ // time.
+ bool LHSContainsFalsePositive = false, RHSContainsFalsePositive = false;
+ if (A == Possible) {
+ // An expression contains a false positive if it can't vary, or if it
+ // contains a known false positive VarDecl.
+ LHSContainsFalsePositive = !CanVary(LHS, AC)
+ || containsNonLocalVarDecl(LHS);
+ RHSContainsFalsePositive = !CanVary(RHS, AC)
+ || containsNonLocalVarDecl(RHS);
+ }
+
const GRState *state = C.getState();
SVal LHSVal = state->getSVal(LHS);
@@ -154,16 +166,16 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
break;
// Fall through intentional
- case BinaryOperator::AddAssign:
- case BinaryOperator::SubAssign:
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::AndAssign:
- case BinaryOperator::OrAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::ShlAssign:
- case BinaryOperator::ShrAssign:
- case BinaryOperator::Assign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Assign:
// Assign statements have one extra level of indirection
if (!isa<Loc>(LHSVal)) {
A = Impossible;
@@ -181,20 +193,37 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
break; // We don't care about any other operators.
// Fall through intentional
- case BinaryOperator::SubAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::AndAssign:
- case BinaryOperator::OrAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::Assign:
- case BinaryOperator::Sub:
- case BinaryOperator::Div:
- case BinaryOperator::And:
- case BinaryOperator::Or:
- case BinaryOperator::Xor:
- case BinaryOperator::LOr:
- case BinaryOperator::LAnd:
- if (LHSVal != RHSVal)
+ case BO_Assign:
+ // x Assign x can be used to silence unused variable warnings intentionally.
+ // If this is a self assignment and the variable is referenced elsewhere,
+ // then it is a false positive.
+ if (isSelfAssign(LHS, RHS)) {
+ if (!isUnused(LHS, AC)) {
+ UpdateAssumption(A, Equal);
+ return;
+ }
+ else {
+ A = Impossible;
+ return;
+ }
+ }
+
+ case BO_SubAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_Sub:
+ case BO_Div:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ case BO_LOr:
+ case BO_LAnd:
+ case BO_EQ:
+ case BO_NE:
+ if (LHSVal != RHSVal || LHSContainsFalsePositive
+ || RHSContainsFalsePositive)
break;
UpdateAssumption(A, Equal);
return;
@@ -206,13 +235,13 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
break; // We don't care about any other operators.
// Fall through intentional
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
- case BinaryOperator::LOr:
- case BinaryOperator::LAnd:
- if (!RHSVal.isConstant(1))
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_Mul:
+ case BO_Div:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!RHSVal.isConstant(1) || RHSContainsFalsePositive)
break;
UpdateAssumption(A, RHSis1);
return;
@@ -224,11 +253,11 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
break; // We don't care about any other operators.
// Fall through intentional
- case BinaryOperator::MulAssign:
- case BinaryOperator::Mul:
- case BinaryOperator::LOr:
- case BinaryOperator::LAnd:
- if (!LHSVal.isConstant(1))
+ case BO_MulAssign:
+ case BO_Mul:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!LHSVal.isConstant(1) || LHSContainsFalsePositive)
break;
UpdateAssumption(A, LHSis1);
return;
@@ -240,23 +269,23 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
break; // We don't care about any other operators.
// Fall through intentional
- case BinaryOperator::AddAssign:
- case BinaryOperator::SubAssign:
- case BinaryOperator::MulAssign:
- case BinaryOperator::AndAssign:
- case BinaryOperator::OrAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
- case BinaryOperator::Mul:
- case BinaryOperator::And:
- case BinaryOperator::Or:
- case BinaryOperator::Xor:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
- case BinaryOperator::LOr:
- case BinaryOperator::LAnd:
- if (!RHSVal.isConstant(0))
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_MulAssign:
+ case BO_AndAssign:
+ case BO_OrAssign:
+ case BO_XorAssign:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Mul:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!RHSVal.isConstant(0) || RHSContainsFalsePositive)
break;
UpdateAssumption(A, RHSis0);
return;
@@ -268,27 +297,27 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
break; // We don't care about any other operators.
// Fall through intentional
- //case BinaryOperator::AddAssign: // Common false positive
- case BinaryOperator::SubAssign: // Check only if unsigned
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::AndAssign:
- //case BinaryOperator::OrAssign: // Common false positive
- //case BinaryOperator::XorAssign: // Common false positive
- case BinaryOperator::ShlAssign:
- case BinaryOperator::ShrAssign:
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
- case BinaryOperator::And:
- case BinaryOperator::Or:
- case BinaryOperator::Xor:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
- case BinaryOperator::LOr:
- case BinaryOperator::LAnd:
- if (!LHSVal.isConstant(0))
+ //case BO_AddAssign: // Common false positive
+ case BO_SubAssign: // Check only if unsigned
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_AndAssign:
+ //case BO_OrAssign: // Common false positive
+ //case BO_XorAssign: // Common false positive
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Mul:
+ case BO_Div:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LOr:
+ case BO_LAnd:
+ if (!LHSVal.isConstant(0) || LHSContainsFalsePositive)
break;
UpdateAssumption(A, LHSis0);
return;
@@ -298,47 +327,103 @@ void IdempotentOperationChecker::PreVisitBinaryOperator(
A = Impossible;
}
-void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
- BugReporter &B,
- bool hasWorkRemaining) {
- // If there is any work remaining we cannot be 100% sure about our warnings
- if (hasWorkRemaining)
- return;
+// At the post visit stage, the predecessor ExplodedNode will be the
+// BinaryOperator that was just created. We use this hook to collect the
+// ExplodedNode.
+void IdempotentOperationChecker::PostVisitBinaryOperator(
+ CheckerContext &C,
+ const BinaryOperator *B) {
+ // Add the ExplodedNode we just visited
+ BinaryOperatorData &Data = hash[B];
+ Data.explodedNodes.Add(C.getPredecessor());
+}
+void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &BR,
+ GRExprEngine &Eng) {
+ BugType *BT = new BugType("Idempotent operation", "Dead code");
// Iterate over the hash to see if we have any paths with definite
// idempotent operations.
- for (AssumptionMap::const_iterator i =
- hash.begin(); i != hash.end(); ++i) {
- if (i->second != Impossible) {
- // Select the error message.
- const char *msg = 0;
- switch (i->second) {
- case Equal:
- msg = "idempotent operation; both operands are always equal in value";
- break;
- case LHSis1:
- msg = "idempotent operation; the left operand is always 1";
- break;
- case RHSis1:
- msg = "idempotent operation; the right operand is always 1";
- break;
- case LHSis0:
- msg = "idempotent operation; the left operand is always 0";
- break;
- case RHSis0:
- msg = "idempotent operation; the right operand is always 0";
- break;
- case Possible:
- llvm_unreachable("Operation was never marked with an assumption");
- case Impossible:
- llvm_unreachable(0);
+ for (AssumptionMap::const_iterator i = hash.begin(); i != hash.end(); ++i) {
+ // Unpack the hash contents
+ const BinaryOperatorData &Data = i->second;
+ const Assumption &A = Data.assumption;
+ AnalysisContext *AC = Data.analysisContext;
+ const ExplodedNodeSet &ES = Data.explodedNodes;
+
+ const BinaryOperator *B = i->first;
+
+ if (A == Impossible)
+ continue;
+
+ // If the analyzer did not finish, check to see if we can still emit this
+ // warning
+ if (Eng.hasWorkRemaining()) {
+ const CFGStmtMap *CBM = CFGStmtMap::Build(AC->getCFG(),
+ &AC->getParentMap());
+
+ // If we can trace back
+ if (!PathWasCompletelyAnalyzed(AC->getCFG(),
+ CBM->getBlock(B),
+ Eng.getCoreEngine()))
+ continue;
+
+ delete CBM;
+ }
+
+ // Select the error message and SourceRanges to report.
+ llvm::SmallString<128> buf;
+ llvm::raw_svector_ostream os(buf);
+ bool LHSRelevant = false, RHSRelevant = false;
+ switch (A) {
+ case Equal:
+ LHSRelevant = true;
+ RHSRelevant = true;
+ if (B->getOpcode() == BO_Assign)
+ os << "Assigned value is always the same as the existing value";
+ else
+ os << "Both operands to '" << B->getOpcodeStr()
+ << "' always have the same value";
+ break;
+ case LHSis1:
+ LHSRelevant = true;
+ os << "The left operand to '" << B->getOpcodeStr() << "' is always 1";
+ break;
+ case RHSis1:
+ RHSRelevant = true;
+ os << "The right operand to '" << B->getOpcodeStr() << "' is always 1";
+ break;
+ case LHSis0:
+ LHSRelevant = true;
+ os << "The left operand to '" << B->getOpcodeStr() << "' is always 0";
+ break;
+ case RHSis0:
+ RHSRelevant = true;
+ os << "The right operand to '" << B->getOpcodeStr() << "' is always 0";
+ break;
+ case Possible:
+ llvm_unreachable("Operation was never marked with an assumption");
+ case Impossible:
+ llvm_unreachable(0);
+ }
+
+ // Add a report for each ExplodedNode
+ for (ExplodedNodeSet::iterator I = ES.begin(), E = ES.end(); I != E; ++I) {
+ EnhancedBugReport *report = new EnhancedBugReport(*BT, os.str(), *I);
+
+ // Add source ranges and visitor hooks
+ if (LHSRelevant) {
+ const Expr *LHS = i->first->getLHS();
+ report->addRange(LHS->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, LHS);
+ }
+ if (RHSRelevant) {
+ const Expr *RHS = i->first->getRHS();
+ report->addRange(i->first->getRHS()->getSourceRange());
+ report->addVisitorCreator(bugreporter::registerVarDeclsLastStore, RHS);
}
- // Create the SourceRange Arrays
- SourceRange S[2] = { i->first->getLHS()->getSourceRange(),
- i->first->getRHS()->getSourceRange() };
- B.EmitBasicReport("Idempotent operation", msg, i->first->getOperatorLoc(),
- S, 2);
+ BR.EmitReport(report);
}
}
}
@@ -346,6 +431,10 @@ void IdempotentOperationChecker::VisitEndAnalysis(ExplodedGraph &G,
// Updates the current assumption given the new assumption
inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
const Assumption &New) {
+// If the assumption is the same, there is nothing to do
+ if (A == New)
+ return;
+
switch (A) {
// If we don't currently have an assumption, set it
case Possible:
@@ -366,89 +455,249 @@ inline void IdempotentOperationChecker::UpdateAssumption(Assumption &A,
}
}
-// Recursively find any substatements containing macros
-bool IdempotentOperationChecker::containsMacro(const Stmt *S) {
- if (S->getLocStart().isMacroID())
- return true;
+// Check for a statement where a variable is self assigned to possibly avoid an
+// unused variable warning.
+bool IdempotentOperationChecker::isSelfAssign(const Expr *LHS, const Expr *RHS) {
+ LHS = LHS->IgnoreParenCasts();
+ RHS = RHS->IgnoreParenCasts();
- if (S->getLocEnd().isMacroID())
- return true;
+ const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS);
+ if (!LHS_DR)
+ return false;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsMacro(child))
- return true;
+ const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+ if (!VD)
+ return false;
- return false;
+ const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS);
+ if (!RHS_DR)
+ return false;
+
+ if (VD != RHS_DR->getDecl())
+ return false;
+
+ return true;
}
-// Recursively find any substatements containing enum constants
-bool IdempotentOperationChecker::containsEnum(const Stmt *S) {
- const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
+// Returns true if the Expr points to a VarDecl that is not read anywhere
+// outside of self-assignments.
+bool IdempotentOperationChecker::isUnused(const Expr *E,
+ AnalysisContext *AC) {
+ if (!E)
+ return false;
- if (DR && isa<EnumConstantDecl>(DR->getDecl()))
- return true;
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
+ if (!DR)
+ return false;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsEnum(child))
- return true;
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return false;
- return false;
+ if (AC->getPseudoConstantAnalysis()->wasReferenced(VD))
+ return false;
+
+ return true;
}
-// Recursively find any substatements containing __builtin_offset_of
-bool IdempotentOperationChecker::containsBuiltinOffsetOf(const Stmt *S) {
- const UnaryOperator *UO = dyn_cast<UnaryOperator>(S);
+#if 0
+// Check for self casts truncating/extending a variable
+bool IdempotentOperationChecker::isTruncationExtensionAssignment(
+ const Expr *LHS,
+ const Expr *RHS) {
- if (UO && UO->getOpcode() == UnaryOperator::OffsetOf)
- return true;
+ const DeclRefExpr *LHS_DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParenCasts());
+ if (!LHS_DR)
+ return false;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsBuiltinOffsetOf(child))
- return true;
+ const VarDecl *VD = dyn_cast<VarDecl>(LHS_DR->getDecl());
+ if (!VD)
+ return false;
- return false;
+ const DeclRefExpr *RHS_DR = dyn_cast<DeclRefExpr>(RHS->IgnoreParenCasts());
+ if (!RHS_DR)
+ return false;
+
+ if (VD != RHS_DR->getDecl())
+ return false;
+
+ return dyn_cast<DeclRefExpr>(RHS->IgnoreParens()) == NULL;
}
+#endif
+
+// Returns false if a path to this block was not completely analyzed, or true
+// otherwise.
+bool IdempotentOperationChecker::PathWasCompletelyAnalyzed(
+ const CFG *C,
+ const CFGBlock *CB,
+ const GRCoreEngine &CE) {
+ std::deque<const CFGBlock *> WorkList;
+ llvm::SmallSet<unsigned, 8> Aborted;
+ llvm::SmallSet<unsigned, 128> Visited;
+
+ // Create a set of all aborted blocks
+ typedef GRCoreEngine::BlocksAborted::const_iterator AbortedIterator;
+ for (AbortedIterator I = CE.blocks_aborted_begin(),
+ E = CE.blocks_aborted_end(); I != E; ++I) {
+ const BlockEdge &BE = I->first;
+
+ // The destination block on the BlockEdge is the first block that was not
+ // analyzed.
+ Aborted.insert(BE.getDst()->getBlockID());
+ }
-bool IdempotentOperationChecker::containsZeroConstant(const Stmt *S) {
- const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(S);
- if (IL && IL->getValue() == 0)
+ // Save the entry block ID for early exiting
+ unsigned EntryBlockID = C->getEntry().getBlockID();
+
+ // Create initial node
+ WorkList.push_back(CB);
+
+ while (!WorkList.empty()) {
+ const CFGBlock *Head = WorkList.front();
+ WorkList.pop_front();
+ Visited.insert(Head->getBlockID());
+
+ // If we found the entry block, then there exists a path from the target
+ // node to the entry point of this function -> the path was completely
+ // analyzed.
+ if (Head->getBlockID() == EntryBlockID)
+ return true;
+
+ // If any of the aborted blocks are on the path to the beginning, then all
+ // paths to this block were not analyzed.
+ if (Aborted.count(Head->getBlockID()))
+ return false;
+
+ // Add the predecessors to the worklist unless we have already visited them
+ for (CFGBlock::const_pred_iterator I = Head->pred_begin();
+ I != Head->pred_end(); ++I)
+ if (!Visited.count((*I)->getBlockID()))
+ WorkList.push_back(*I);
+ }
+
+ // If we get to this point, there is no connection to the entry block or an
+ // aborted block. This path is unreachable and we can report the error.
+ return true;
+}
+
+// Recursive function that determines whether an expression contains any element
+// that varies. This could be due to a compile-time constant like sizeof. An
+// expression may also involve a variable that behaves like a constant. The
+// function returns true if the expression varies, and false otherwise.
+bool IdempotentOperationChecker::CanVary(const Expr *Ex,
+ AnalysisContext *AC) {
+ // Parentheses and casts are irrelevant here
+ Ex = Ex->IgnoreParenCasts();
+
+ if (Ex->getLocStart().isMacroID())
+ return false;
+
+ switch (Ex->getStmtClass()) {
+ // Trivially true cases
+ case Stmt::ArraySubscriptExprClass:
+ case Stmt::MemberExprClass:
+ case Stmt::StmtExprClass:
+ case Stmt::CallExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ return true;
+ default:
return true;
- const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(S);
- if (FL && FL->getValue().isZero())
+ // Trivially false cases
+ case Stmt::IntegerLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::OffsetOfExprClass:
+ case Stmt::CompoundLiteralExprClass:
+ case Stmt::AddrLabelExprClass:
+ case Stmt::TypesCompatibleExprClass:
+ case Stmt::GNUNullExprClass:
+ case Stmt::InitListExprClass:
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::BlockExprClass:
+ case Stmt::BlockDeclRefExprClass:
+ return false;
+
+ // Cases requiring custom logic
+ case Stmt::SizeOfAlignOfExprClass: {
+ const SizeOfAlignOfExpr *SE = cast<const SizeOfAlignOfExpr>(Ex);
+ if (!SE->isSizeOf())
+ return false;
+ return SE->getTypeOfArgument()->isVariableArrayType();
+ }
+ case Stmt::DeclRefExprClass:
+ // Check for constants/pseudoconstants
+ return !isConstantOrPseudoConstant(cast<DeclRefExpr>(Ex), AC);
+
+ // The next cases require recursion for subexpressions
+ case Stmt::BinaryOperatorClass: {
+ const BinaryOperator *B = cast<const BinaryOperator>(Ex);
+ return CanVary(B->getRHS(), AC)
+ || CanVary(B->getLHS(), AC);
+ }
+ case Stmt::UnaryOperatorClass: {
+ const UnaryOperator *U = cast<const UnaryOperator>(Ex);
+ // Handle trivial case first
+ switch (U->getOpcode()) {
+ case UO_Extension:
+ return false;
+ default:
+ return CanVary(U->getSubExpr(), AC);
+ }
+ }
+ case Stmt::ChooseExprClass:
+ return CanVary(cast<const ChooseExpr>(Ex)->getChosenSubExpr(
+ AC->getASTContext()), AC);
+ case Stmt::ConditionalOperatorClass:
+ return CanVary(cast<const ConditionalOperator>(Ex)->getCond(), AC);
+ }
+}
+
+// Returns true if a DeclRefExpr is or behaves like a constant.
+bool IdempotentOperationChecker::isConstantOrPseudoConstant(
+ const DeclRefExpr *DR,
+ AnalysisContext *AC) {
+ // Check if the type of the Decl is const-qualified
+ if (DR->getType().isConstQualified())
return true;
- for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
- ++I)
- if (const Stmt *child = *I)
- if (containsZeroConstant(child))
- return true;
+ // Check for an enum
+ if (isa<EnumConstantDecl>(DR->getDecl()))
+ return true;
+
+ const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
+ if (!VD)
+ return true;
+
+ // Check if the Decl behaves like a constant. This check also takes care of
+ // static variables, which can only change between function calls if they are
+ // modified in the AST.
+ PseudoConstantAnalysis *PCA = AC->getPseudoConstantAnalysis();
+ if (PCA->isPseudoConstant(VD))
+ return true;
return false;
}
-bool IdempotentOperationChecker::containsOneConstant(const Stmt *S) {
- const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(S);
- if (IL && IL->getValue() == 1)
- return true;
+// Recursively find any substatements containing VarDecl's with storage other
+// than local
+bool IdempotentOperationChecker::containsNonLocalVarDecl(const Stmt *S) {
+ const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
- const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(S);
- const llvm::APFloat one(1.0);
- if (FL && FL->getValue().compare(one) == llvm::APFloat::cmpEqual)
- return true;
+ if (DR)
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
+ if (!VD->hasLocalStorage())
+ return true;
for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
++I)
if (const Stmt *child = *I)
- if (containsOneConstant(child))
+ if (containsNonLocalVarDecl(child))
return true;
return false;
}
-
diff --git a/lib/Checker/LLVMConventionsChecker.cpp b/lib/Checker/LLVMConventionsChecker.cpp
index c1212572f8f4..2f87da142c1a 100644
--- a/lib/Checker/LLVMConventionsChecker.cpp
+++ b/lib/Checker/LLVMConventionsChecker.cpp
@@ -128,7 +128,6 @@ public:
void VisitDeclStmt(DeclStmt *DS);
private:
void VisitVarDecl(VarDecl *VD);
- void CheckStringRefBoundtoTemporaryString(VarDecl *VD);
};
} // end anonymous namespace
diff --git a/lib/Checker/Makefile b/lib/Checker/Makefile
index 1bc652916403..4ec6f65a0bb1 100644
--- a/lib/Checker/Makefile
+++ b/lib/Checker/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangChecker
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Checker/MallocChecker.cpp b/lib/Checker/MallocChecker.cpp
index dcc21ca38619..c9b6d7588be1 100644
--- a/lib/Checker/MallocChecker.cpp
+++ b/lib/Checker/MallocChecker.cpp
@@ -24,15 +24,18 @@ using namespace clang;
namespace {
class RefState {
- enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped } K;
+ enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped,
+ Relinquished } K;
const Stmt *S;
public:
RefState(Kind k, const Stmt *s) : K(k), S(s) {}
bool isAllocated() const { return K == AllocateUnchecked; }
+ //bool isFailed() const { return K == AllocateFailed; }
bool isReleased() const { return K == Released; }
- bool isEscaped() const { return K == Escaped; }
+ //bool isEscaped() const { return K == Escaped; }
+ //bool isRelinquished() const { return K == Relinquished; }
bool operator==(const RefState &X) const {
return K == X.K && S == X.S;
@@ -46,6 +49,9 @@ public:
}
static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
+ static RefState getRelinquished(const Stmt *s) {
+ return RefState(Relinquished, s);
+ }
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(K);
@@ -59,23 +65,30 @@ class MallocChecker : public CheckerVisitor<MallocChecker> {
BuiltinBug *BT_DoubleFree;
BuiltinBug *BT_Leak;
BuiltinBug *BT_UseFree;
+ BuiltinBug *BT_UseRelinquished;
BuiltinBug *BT_BadFree;
IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
public:
MallocChecker()
- : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_BadFree(0),
+ : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_UseRelinquished(0),
+ BT_BadFree(0),
II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
static void *getTag();
bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
- const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption);
+ const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption,
+ bool *respondsToCallback);
void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val);
private:
void MallocMem(CheckerContext &C, const CallExpr *CE);
+ void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att);
const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
const Expr *SizeEx, SVal Init,
const GRState *state) {
@@ -86,8 +99,10 @@ private:
const GRState *state);
void FreeMem(CheckerContext &C, const CallExpr *CE);
+ void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att);
const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
- const GRState *state);
+ const GRState *state, unsigned Num, bool Hold);
void ReallocMem(CheckerContext &C, const CallExpr *CE);
void CallocMem(CheckerContext &C, const CallExpr *CE);
@@ -103,7 +118,7 @@ typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
namespace clang {
template <>
struct GRStateTrait<RegionState>
- : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, RefState> > {
+ : public GRStatePartialTrait<RegionStateTy> {
static void *GDMIndex() { return MallocChecker::getTag(); }
};
}
@@ -156,7 +171,32 @@ bool MallocChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
return true;
}
- return false;
+ // Check all the attributes, if there are any.
+ // There can be multiple of these attributes.
+ bool rv = false;
+ if (FD->hasAttrs()) {
+ for (specific_attr_iterator<OwnershipAttr>
+ i = FD->specific_attr_begin<OwnershipAttr>(),
+ e = FD->specific_attr_end<OwnershipAttr>();
+ i != e; ++i) {
+ switch ((*i)->getOwnKind()) {
+ case OwnershipAttr::Returns: {
+ MallocMemReturnsAttr(C, CE, *i);
+ rv = true;
+ break;
+ }
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds: {
+ FreeMemAttr(C, CE, *i);
+ rv = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ return rv;
}
void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
@@ -165,6 +205,23 @@ void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
C.addTransition(state);
}
+void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att) {
+ if (Att->getModule() != "malloc")
+ return;
+
+ OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+ if (I != E) {
+ const GRState *state =
+ MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
+ C.addTransition(state);
+ return;
+ }
+ const GRState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
+ C.getState());
+ C.addTransition(state);
+}
+
const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
const CallExpr *CE,
SVal Size, SVal Init,
@@ -196,25 +253,53 @@ const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
}
void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
- const GRState *state = FreeMemAux(C, CE, C.getState());
+ const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false);
if (state)
C.addTransition(state);
}
+void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
+ const OwnershipAttr* Att) {
+ if (Att->getModule() != "malloc")
+ return;
+
+ for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
+ I != E; ++I) {
+ const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
+ Att->getOwnKind() == OwnershipAttr::Holds);
+ if (state)
+ C.addTransition(state);
+ }
+}
+
const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
- const GRState *state) {
- const Expr *ArgExpr = CE->getArg(0);
+ const GRState *state, unsigned Num,
+ bool Hold) {
+ const Expr *ArgExpr = CE->getArg(Num);
SVal ArgVal = state->getSVal(ArgExpr);
- // If ptr is NULL, no operation is preformed.
- if (ArgVal.isZeroConstant())
+ DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(location))
return state;
-
+
+ // FIXME: Technically using 'Assume' here can result in a path
+ // bifurcation. In such cases we need to return two states, not just one.
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->Assume(location);
+
+ // The explicit NULL case, no operation is performed.
+ if (nullState && !notNullState)
+ return nullState;
+
+ assert(notNullState);
+
// Unknown values could easily be okay
// Undefined values are handled elsewhere
if (ArgVal.isUnknownOrUndef())
- return state;
+ return notNullState;
const MemRegion *R = ArgVal.getAsRegion();
@@ -253,24 +338,23 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
// Various cases could lead to non-symbol values here.
// For now, ignore them.
if (!SR)
- return state;
+ return notNullState;
SymbolRef Sym = SR->getSymbol();
-
const RefState *RS = state->get<RegionState>(Sym);
// If the symbol has not been tracked, return. This is possible when free() is
// called on a pointer that does not get its pointee directly from malloc().
// Full support of this requires inter-procedural analysis.
if (!RS)
- return state;
+ return notNullState;
// Check double free.
if (RS->isReleased()) {
- ExplodedNode *N = C.GenerateSink();
- if (N) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_DoubleFree)
- BT_DoubleFree = new BuiltinBug("Double free",
+ 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,
@@ -281,7 +365,9 @@ const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
}
// Normal free.
- return state->set<RegionState>(Sym, RefState::getReleased(CE));
+ if (Hold)
+ return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE));
+ return notNullState->set<RegionState>(Sym, RefState::getReleased(CE));
}
bool MallocChecker::SummarizeValue(llvm::raw_ostream& os, SVal V) {
@@ -376,8 +462,7 @@ bool MallocChecker::SummarizeRegion(llvm::raw_ostream& os,
void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
SourceRange range) {
- ExplodedNode *N = C.GenerateSink();
- if (N) {
+ if (ExplodedNode *N = C.GenerateSink()) {
if (!BT_BadFree)
BT_BadFree = new BuiltinBug("Bad free");
@@ -446,13 +531,13 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
ValMgr.makeIntValWithPtrWidth(0, false));
if (const GRState *stateSizeZero = stateNotEqual->Assume(SizeZero, true)) {
- const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero);
+ const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero, 0, false);
if (stateFree)
C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
}
if (const GRState *stateSizeNotZero=stateNotEqual->Assume(SizeZero,false)) {
- const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero);
+ const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero, 0, false);
if (stateFree) {
// FIXME: We should copy the content of the original buffer.
const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
@@ -471,7 +556,7 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
SVal Count = state->getSVal(CE->getArg(0));
SVal EleSize = state->getSVal(CE->getArg(1));
- SVal TotalSize = SVator.EvalBinOp(state, BinaryOperator::Mul, Count, EleSize,
+ SVal TotalSize = SVator.EvalBinOp(state, BO_Mul, Count, EleSize,
ValMgr.getContext().getSizeType());
SVal Zero = ValMgr.makeZeroVal(ValMgr.getContext().CharTy);
@@ -481,36 +566,42 @@ void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
}
void MallocChecker::EvalDeadSymbols(CheckerContext &C,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.GenerateSink();
- if (N) {
- if (!BT_Leak)
- BT_Leak = new BuiltinBug("Memory leak",
+ if (!SymReaper.hasDeadSymbols())
+ return;
+
+ const GRState *state = C.getState();
+ RegionStateTy RS = state->get<RegionState>();
+ RegionStateTy::Factory &F = state->get_context<RegionState>();
+
+ for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
+ if (SymReaper.isDead(I->first)) {
+ if (I->second.isAllocated()) {
+ if (ExplodedNode *N = C.GenerateNode()) {
+ 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);
+ // FIXME: where it is allocated.
+ BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
+ C.EmitReport(R);
+ }
}
+
+ // Remove the dead symbol from the map.
+ RS = F.Remove(RS, I->first);
}
}
+
+ state = state->set<RegionState>(RS);
+ C.GenerateNode(state);
}
void MallocChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {
SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
const GRState *state = B.getState();
- typedef llvm::ImmutableMap<SymbolRef, RefState> SymMap;
- SymMap M = state->get<RegionState>();
+ RegionStateTy M = state->get<RegionState>();
- for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ for (RegionStateTy::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());
@@ -549,7 +640,8 @@ void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
}
const GRState *MallocChecker::EvalAssume(const GRState *state, SVal Cond,
- bool Assumption) {
+ bool Assumption,
+ bool * /* respondsToCallback */) {
// If a symblic region is assumed to NULL, set its state to AllocateFailed.
// FIXME: should also check symbols assumed to non-null.
@@ -568,9 +660,8 @@ void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) {
SymbolRef Sym = l.getLocSymbolInBase();
if (Sym) {
const RefState *RS = C.getState()->get<RegionState>(Sym);
- if (RS)
- if (RS->isReleased()) {
- ExplodedNode *N = C.GenerateSink();
+ if (RS && RS->isReleased()) {
+ if (ExplodedNode *N = C.GenerateNode()) {
if (!BT_UseFree)
BT_UseFree = new BuiltinBug("Use dynamically allocated memory after"
" it is freed.");
@@ -579,5 +670,67 @@ void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) {
N);
C.EmitReport(R);
}
+ }
+ }
+}
+
+void MallocChecker::PreVisitBind(CheckerContext &C,
+ const Stmt *StoreE,
+ SVal location,
+ SVal val) {
+ // The PreVisitBind implements the same algorithm as already used by the
+ // Objective C ownership checker: if the pointer escaped from this scope by
+ // assignment, let it go. However, assigning to fields of a stack-storage
+ // structure does not transfer ownership.
+
+ const GRState *state = C.getState();
+ DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location);
+
+ // Check for null dereferences.
+ if (!isa<Loc>(l))
+ return;
+
+ // Before checking if the state is null, check if 'val' has a RefState.
+ // Only then should we check for null and bifurcate the state.
+ SymbolRef Sym = val.getLocSymbolInBase();
+ if (Sym) {
+ if (const RefState *RS = state->get<RegionState>(Sym)) {
+ // If ptr is NULL, no operation is performed.
+ const GRState *notNullState, *nullState;
+ llvm::tie(notNullState, nullState) = state->Assume(l);
+
+ // Generate a transition for 'nullState' to record the assumption
+ // that the state was null.
+ if (nullState)
+ C.addTransition(nullState);
+
+ if (!notNullState)
+ return;
+
+ if (RS->isAllocated()) {
+ // Something we presently own is being assigned somewhere.
+ const MemRegion *AR = location.getAsRegion();
+ if (!AR)
+ return;
+ AR = AR->StripCasts()->getBaseRegion();
+ do {
+ // If it is on the stack, we still own it.
+ if (AR->hasStackNonParametersStorage())
+ break;
+
+ // If the state can't represent this binding, we still own it.
+ if (notNullState == (notNullState->bindLoc(cast<Loc>(location),
+ UnknownVal())))
+ break;
+
+ // We no longer own this pointer.
+ notNullState =
+ notNullState->set<RegionState>(Sym,
+ RefState::getRelinquished(StoreE));
+ }
+ while (false);
+ }
+ C.addTransition(notNullState);
+ }
}
}
diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp
index 9cfeb7ae2b5c..3f706e145a82 100644
--- a/lib/Checker/MemRegion.cpp
+++ b/lib/Checker/MemRegion.cpp
@@ -18,6 +18,7 @@
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/RecordLayout.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -177,7 +178,7 @@ const StackFrameContext *VarRegion::getStackFrame() const {
DefinedOrUnknownSVal DeclRegion::getExtent(ValueManager& ValMgr) const {
ASTContext& Ctx = ValMgr.getContext();
- QualType T = getDesugaredValueType(Ctx);
+ QualType T = getDesugaredValueType();
if (isa<VariableArrayType>(T))
return nonloc::SymbolVal(ValMgr.getSymbolManager().getExtentSymbol(this));
@@ -195,8 +196,7 @@ DefinedOrUnknownSVal FieldRegion::getExtent(ValueManager& ValMgr) const {
// A zero-length array at the end of a struct often stands for dynamically-
// allocated extra memory.
if (Extent.isZeroConstant()) {
- ASTContext& Ctx = ValMgr.getContext();
- QualType T = getDesugaredValueType(Ctx);
+ QualType T = getDesugaredValueType();
if (isa<ConstantArrayType>(T))
return UnknownVal();
@@ -785,7 +785,7 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
return true;
}
-RegionRawOffset ElementRegion::getAsRawOffset() const {
+RegionRawOffset ElementRegion::getAsArrayOffset() const {
CharUnits offset = CharUnits::Zero();
const ElementRegion *ER = this;
const MemRegion *superR = NULL;
@@ -827,6 +827,67 @@ RegionRawOffset ElementRegion::getAsRawOffset() const {
return RegionRawOffset(superR, offset.getQuantity());
}
+RegionOffset MemRegion::getAsOffset() const {
+ const MemRegion *R = this;
+ int64_t Offset = 0;
+
+ while (1) {
+ switch (R->getKind()) {
+ default:
+ return RegionOffset(0);
+ case SymbolicRegionKind:
+ case AllocaRegionKind:
+ case CompoundLiteralRegionKind:
+ case CXXThisRegionKind:
+ case StringRegionKind:
+ case VarRegionKind:
+ case CXXObjectRegionKind:
+ goto Finish;
+ case ElementRegionKind: {
+ const ElementRegion *ER = cast<ElementRegion>(R);
+ QualType EleTy = ER->getValueType();
+
+ if (!IsCompleteType(getContext(), EleTy))
+ return RegionOffset(0);
+
+ SVal Index = ER->getIndex();
+ if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
+ int64_t i = CI->getValue().getSExtValue();
+ CharUnits Size = getContext().getTypeSizeInChars(EleTy);
+ Offset += i * Size.getQuantity() * 8;
+ } else {
+ // We cannot compute offset for non-concrete index.
+ return RegionOffset(0);
+ }
+ R = ER->getSuperRegion();
+ break;
+ }
+ case FieldRegionKind: {
+ const FieldRegion *FR = cast<FieldRegion>(R);
+ const RecordDecl *RD = FR->getDecl()->getParent();
+ if (!RD->isDefinition())
+ // We cannot compute offset for incomplete type.
+ return RegionOffset(0);
+ // Get the field number.
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator FI = RD->field_begin(),
+ FE = RD->field_end(); FI != FE; ++FI, ++idx)
+ if (FR->getDecl() == *FI)
+ break;
+
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
+ // This is offset in bits.
+ Offset += Layout.getFieldOffset(idx);
+ R = FR->getSuperRegion();
+ break;
+ }
+ }
+ }
+
+ Finish:
+ return RegionOffset(R, Offset);
+}
+
//===----------------------------------------------------------------------===//
// BlockDataRegion
//===----------------------------------------------------------------------===//
diff --git a/lib/Checker/OSAtomicChecker.cpp b/lib/Checker/OSAtomicChecker.cpp
index 1ea1bd98d6dc..02de0a84a4e4 100644
--- a/lib/Checker/OSAtomicChecker.cpp
+++ b/lib/Checker/OSAtomicChecker.cpp
@@ -110,9 +110,9 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
QualType LoadTy;
if (const TypedRegion *TR =
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
- LoadTy = TR->getValueType(Ctx);
+ LoadTy = TR->getValueType();
}
- Engine.EvalLoad(Tmp, const_cast<Expr *>(theValueExpr), C.getPredecessor(),
+ Engine.EvalLoad(Tmp, theValueExpr, C.getPredecessor(),
state, location, OSAtomicLoadTag, LoadTy);
if (Tmp.empty()) {
@@ -158,10 +158,10 @@ bool OSAtomicChecker::EvalOSAtomicCompareAndSwap(CheckerContext &C,
// Handle implicit value casts.
if (const TypedRegion *R =
dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
- val = SVator.EvalCast(val,R->getValueType(Ctx),newValueExpr->getType());
+ val = SVator.EvalCast(val,R->getValueType(), newValueExpr->getType());
}
- Engine.EvalStore(TmpStore, NULL, const_cast<Expr *>(theValueExpr), N,
+ Engine.EvalStore(TmpStore, NULL, theValueExpr, N,
stateEqual, location, val, OSAtomicStoreTag);
if (TmpStore.empty()) {
diff --git a/lib/Checker/PointerArithChecker.cpp b/lib/Checker/PointerArithChecker.cpp
index ed60c42613fe..cbac423b467c 100644
--- a/lib/Checker/PointerArithChecker.cpp
+++ b/lib/Checker/PointerArithChecker.cpp
@@ -36,8 +36,7 @@ void *PointerArithChecker::getTag() {
void PointerArithChecker::PreVisitBinaryOperator(CheckerContext &C,
const BinaryOperator *B) {
- if (B->getOpcode() != BinaryOperator::Sub &&
- B->getOpcode() != BinaryOperator::Add)
+ if (B->getOpcode() != BO_Sub && B->getOpcode() != BO_Add)
return;
const GRState *state = C.getState();
diff --git a/lib/Checker/PointerSubChecker.cpp b/lib/Checker/PointerSubChecker.cpp
index bc0fd24d19b4..d64b6ae3fe3f 100644
--- a/lib/Checker/PointerSubChecker.cpp
+++ b/lib/Checker/PointerSubChecker.cpp
@@ -39,7 +39,7 @@ 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)
+ if (B->getOpcode() != BO_Sub)
return;
const GRState *state = C.getState();
diff --git a/lib/Checker/RangeConstraintManager.cpp b/lib/Checker/RangeConstraintManager.cpp
index 2a35d326a988..697694e72a36 100644
--- a/lib/Checker/RangeConstraintManager.cpp
+++ b/lib/Checker/RangeConstraintManager.cpp
@@ -83,7 +83,6 @@ public:
typedef PrimRangeSet::iterator iterator;
RangeSet(PrimRangeSet RS) : ranges(RS) {}
- RangeSet(Factory& F) : ranges(F.GetEmptySet()) {}
iterator begin() const { return ranges.begin(); }
iterator end() const { return ranges.end(); }
diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp
index 74a7fee04889..1a3eded7cb06 100644
--- a/lib/Checker/RegionStore.cpp
+++ b/lib/Checker/RegionStore.cpp
@@ -44,10 +44,9 @@ private:
uint64_t Offset;
explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
- : P(r, (unsigned) k), Offset(offset) { assert(r); }
+ : P(r, (unsigned) k), Offset(offset) {}
public:
- bool isDefault() const { return P.getInt() == Default; }
bool isDirect() const { return P.getInt() == Direct; }
const MemRegion *getRegion() const { return P.getPointer(); }
@@ -72,9 +71,26 @@ public:
return P.getOpaqueValue() == X.P.getOpaqueValue() &&
Offset == X.Offset;
}
+
+ bool isValid() const {
+ return getRegion() != NULL;
+ }
};
} // end anonymous namespace
+BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+ const RegionRawOffset &O = ER->getAsArrayOffset();
+
+ // FIXME: There are some ElementRegions for which we cannot compute
+ // raw offsets yet, including regions with symbolic offsets. These will be
+ // ignored by the store.
+ return BindingKey(O.getRegion(), O.getByteOffset(), k);
+ }
+
+ return BindingKey(R, 0, k);
+}
+
namespace llvm {
static inline
llvm::raw_ostream& operator<<(llvm::raw_ostream& os, BindingKey K) {
@@ -101,35 +117,20 @@ struct maximal_features_tag {};
class RegionStoreFeatures {
bool SupportsFields;
- bool SupportsRemaining;
-
public:
RegionStoreFeatures(minimal_features_tag) :
- SupportsFields(false), SupportsRemaining(false) {}
+ SupportsFields(false) {}
RegionStoreFeatures(maximal_features_tag) :
- SupportsFields(true), SupportsRemaining(false) {}
+ SupportsFields(true) {}
void enableFields(bool t) { SupportsFields = t; }
bool supportsFields() const { return SupportsFields; }
- bool supportsRemaining() const { return SupportsRemaining; }
};
}
//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static bool IsAnyPointerOrIntptr(QualType ty, ASTContext &Ctx) {
- if (ty->isAnyPointerType())
- return true;
-
- return ty->isIntegerType() && ty->isScalarType() &&
- Ctx.getTypeSize(ty) == Ctx.getTypeSize(Ctx.VoidPtrTy);
-}
-
-//===----------------------------------------------------------------------===//
// Main RegionStore logic.
//===----------------------------------------------------------------------===//
@@ -180,6 +181,14 @@ public:
}
};
+void
+RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
+ const SubRegion *R) {
+ const MemRegion *superR = R->getSuperRegion();
+ if (add(superR, R))
+ if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
+ WL.push_back(sr);
+}
class RegionStoreManager : public StoreManager {
const RegionStoreFeatures Features;
@@ -197,7 +206,6 @@ public:
RegionStoreSubRegionMap *getRegionStoreSubRegionMap(Store store);
- Optional<SVal> getBinding(RegionBindings B, const MemRegion *R);
Optional<SVal> getDirectBinding(RegionBindings B, const MemRegion *R);
/// getDefaultBinding - Returns an SVal* representing an optional default
/// binding associated with a region and its subregions.
@@ -226,18 +234,13 @@ public:
// Binding values to regions.
//===-------------------------------------------------------------------===//
- Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
- unsigned Count, InvalidatedSymbols *IS) {
- return RegionStoreManager::InvalidateRegions(store, &R, &R+1, E, Count, IS,
- false);
- }
-
Store InvalidateRegions(Store store,
const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned Count,
InvalidatedSymbols *IS,
- bool invalidateGlobals);
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions);
public: // Made public for helper classes.
@@ -260,8 +263,6 @@ public: // Made public for helper classes.
return Remove(Remove(B, R, BindingKey::Direct), R, BindingKey::Default);
}
- Store Remove(Store store, BindingKey K);
-
public: // Part of public interface to class.
Store Bind(Store store, Loc LV, SVal V);
@@ -289,7 +290,7 @@ public: // Part of public interface to class.
Store BindArray(Store store, const TypedRegion* R, SVal V);
/// KillStruct - Set the entire struct to unknown.
- Store KillStruct(Store store, const TypedRegion* R);
+ Store KillStruct(Store store, const TypedRegion* R, SVal DefaultVal);
Store Remove(Store store, Loc LV);
@@ -352,13 +353,11 @@ public: // Part of public interface to class.
/// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
/// It returns a new Store with these values removed.
- const GRState *RemoveDeadBindings(GRState &state,
- const StackFrameContext *LCtx,
- SymbolReaper& SymReaper,
+ Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
+ SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots);
- const GRState *EnterStackFrame(const GRState *state,
- const StackFrameContext *frame);
+ Store EnterStackFrame(const GRState *state, const StackFrameContext *frame);
//===------------------------------------------------------------------===//
// Region "extents".
@@ -392,9 +391,6 @@ public: // Part of public interface to class.
}
}
}
-
- // FIXME: Remove.
- ASTContext& getContext() { return StateMgr.getContext(); }
};
} // end anonymous namespace
@@ -414,14 +410,6 @@ StoreManager *clang::CreateFieldsOnlyRegionStoreManager(GRStateManager &StMgr) {
return new RegionStoreManager(StMgr, F);
}
-void
-RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
- const SubRegion *R) {
- const MemRegion *superR = R->getSuperRegion();
- if (add(superR, R))
- if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
- WL.push_back(sr);
-}
RegionStoreSubRegionMap*
RegionStoreManager::getRegionStoreSubRegionMap(Store store) {
@@ -579,14 +567,16 @@ class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
const Expr *Ex;
unsigned Count;
StoreManager::InvalidatedSymbols *IS;
+ StoreManager::InvalidatedRegions *Regions;
public:
InvalidateRegionsWorker(RegionStoreManager &rm,
GRStateManager &stateMgr,
RegionBindings b,
const Expr *ex, unsigned count,
- StoreManager::InvalidatedSymbols *is)
+ StoreManager::InvalidatedSymbols *is,
+ StoreManager::InvalidatedRegions *r)
: ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
- Ex(ex), Count(count), IS(is) {}
+ Ex(ex), Count(count), IS(is), Regions(r) {}
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
void VisitBaseRegion(const MemRegion *baseR);
@@ -657,6 +647,10 @@ void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
return;
}
+ // Otherwise, we have a normal data region. Record that we touched the region.
+ if (Regions)
+ Regions->push_back(baseR);
+
if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
@@ -670,19 +664,12 @@ void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
return;
const TypedRegion *TR = cast<TypedRegion>(baseR);
- QualType T = TR->getValueType(Ctx);
+ QualType T = TR->getValueType();
// Invalidate the binding.
- if (const RecordType *RT = T->getAsStructureType()) {
- const RecordDecl *RD = RT->getDecl()->getDefinition();
- // No record definition. There is nothing we can do.
- if (!RD) {
- B = RM.Remove(B, baseR);
- return;
- }
-
- // Invalidate the region by setting its default value to
- // conjured symbol. The type of the symbol is irrelavant.
+ if (T->isStructureType()) {
+ // Invalidate the region by setting its default value to
+ // conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
Count);
B = RM.Add(B, baseR, BindingKey::Default, V);
@@ -707,10 +694,11 @@ Store RegionStoreManager::InvalidateRegions(Store store,
const MemRegion * const *E,
const Expr *Ex, unsigned Count,
InvalidatedSymbols *IS,
- bool invalidateGlobals) {
+ bool invalidateGlobals,
+ InvalidatedRegions *Regions) {
InvalidateRegionsWorker W(*this, StateMgr,
RegionStoreManager::GetRegionBindings(store),
- Ex, Count, IS);
+ Ex, Count, IS, Regions);
// Scan the bindings and generate the clusters.
W.GenerateClusters(invalidateGlobals);
@@ -733,6 +721,11 @@ Store RegionStoreManager::InvalidateRegions(Store store,
/* symbol type, doesn't matter */ Ctx.IntTy,
Count);
B = Add(B, BindingKey::Make(GS, BindingKey::Default), V);
+
+ // Even if there are no bindings in the global scope, we still need to
+ // record that we touched it.
+ if (Regions)
+ Regions->push_back(GS);
}
return B.getRoot();
@@ -752,7 +745,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
return UnknownVal();
CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
- CharUnits EleSize = getContext().getTypeSizeInChars(EleTy);
+ CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
// If a variable is reinterpreted as a type that doesn't fit into a larger
// type evenly, round it down.
@@ -781,13 +774,12 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
return UnknownVal();
// Strip off typedefs from the ArrayRegion's ValueType.
- QualType T = ArrayR->getValueType(getContext()).getDesugaredType();
+ QualType T = ArrayR->getValueType().getDesugaredType();
ArrayType *AT = cast<ArrayType>(T);
T = AT->getElementType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR,
- getContext()));
+ return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, ArrayR, Ctx));
}
//===----------------------------------------------------------------------===//
@@ -806,8 +798,8 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
default:
// Handle it normally.
break;
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
+ case BO_Add:
+ case BO_Sub:
// FIXME: does this need to be casted to match resultTy?
return L;
}
@@ -820,7 +812,7 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
case MemRegion::SymbolicRegionKind: {
const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
SymbolRef Sym = SR->getSymbol();
- QualType T = Sym->getType(getContext());
+ QualType T = Sym->getType(Ctx);
QualType EleTy;
if (const PointerType *PT = T->getAs<PointerType>())
@@ -829,14 +821,14 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
EleTy = T->getAs<ObjCObjectPointerType>()->getPointeeType();
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, getContext());
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR, Ctx);
break;
}
case MemRegion::AllocaRegionKind: {
const AllocaRegion *AR = cast<AllocaRegion>(MR);
- QualType EleTy = getContext().CharTy; // Create an ElementRegion of bytes.
+ QualType EleTy = Ctx.CharTy; // Create an ElementRegion of bytes.
SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, getContext());
+ ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR, Ctx);
break;
}
@@ -891,13 +883,13 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R,
cast<nonloc::ConcreteInt>(ValMgr.convertToArrayIndex(*Offset)));
const MemRegion* NewER =
MRMgr.getElementRegion(ER->getElementType(), NewIdx,
- ER->getSuperRegion(), getContext());
+ ER->getSuperRegion(), Ctx);
return ValMgr.makeLoc(NewER);
}
if (0 == Base->getValue()) {
const MemRegion* NewER =
MRMgr.getElementRegion(ER->getElementType(), R,
- ER->getSuperRegion(), getContext());
+ ER->getSuperRegion(), Ctx);
return ValMgr.makeLoc(NewER);
}
}
@@ -922,7 +914,7 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
const MemRegion *R) {
if (R->isBoundable())
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R))
- if (TR->getValueType(getContext())->isUnionType())
+ if (TR->getValueType()->isUnionType())
return UnknownVal();
if (const SVal *V = Lookup(B, R, BindingKey::Default))
@@ -931,38 +923,6 @@ Optional<SVal> RegionStoreManager::getDefaultBinding(RegionBindings B,
return Optional<SVal>();
}
-Optional<SVal> RegionStoreManager::getBinding(RegionBindings B,
- const MemRegion *R) {
-
- if (const Optional<SVal> &V = getDirectBinding(B, R))
- return V;
-
- return getDefaultBinding(B, R);
-}
-
-static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
- RTy = Ctx.getCanonicalType(RTy);
- UsedTy = Ctx.getCanonicalType(UsedTy);
-
- if (RTy == UsedTy)
- return false;
-
-
- // Recursively check the types. We basically want to see if a pointer value
- // is ever reinterpreted as a non-pointer, e.g. void** and intptr_t*
- // represents a reinterpretation.
- if (Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy)) {
- const PointerType *PRTy = RTy->getAs<PointerType>();
- const PointerType *PUsedTy = UsedTy->getAs<PointerType>();
-
- return PUsedTy && PRTy &&
- IsReinterpreted(PRTy->getPointeeType(),
- PUsedTy->getPointeeType(), Ctx);
- }
-
- return true;
-}
-
SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -977,7 +937,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
if (isa<AllocaRegion>(MR) || isa<SymbolicRegion>(MR)) {
if (T.isNull()) {
const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
- T = SR->getSymbol()->getType(getContext());
+ T = SR->getSymbol()->getType(Ctx);
}
MR = GetElementZeroRegion(MR, T);
}
@@ -990,7 +950,7 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
// FIXME: Perhaps this method should just take a 'const MemRegion*' argument
// instead of 'Loc', and have the other Loc cases handled at a higher level.
const TypedRegion *R = cast<TypedRegion>(MR);
- QualType RTy = R->getValueType(getContext());
+ QualType RTy = R->getValueType();
// FIXME: We should eventually handle funny addressing. e.g.:
//
@@ -1001,17 +961,6 @@ SVal RegionStoreManager::Retrieve(Store store, Loc L, QualType T) {
//
// Such funny addressing will occur due to layering of regions.
-#if 0
- ASTContext &Ctx = getContext();
- if (!T.isNull() && IsReinterpreted(RTy, T, Ctx)) {
- SVal ZeroIdx = ValMgr.makeZeroArrayIndex();
- R = MRMgr.getElementRegion(T, ZeroIdx, R, Ctx);
- RTy = T;
- assert(Ctx.getCanonicalType(RTy) ==
- Ctx.getCanonicalType(R->getValueType(Ctx)));
- }
-#endif
-
if (RTy->isStructureOrClassType())
return RetrieveStruct(store, R);
@@ -1121,8 +1070,7 @@ SVal RegionStoreManager::RetrieveElement(Store store,
if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
// FIXME: Handle loads from strings where the literal is treated as
// an integer, e.g., *((unsigned int*)"hello")
- ASTContext &Ctx = getContext();
- QualType T = Ctx.getAsArrayType(StrR->getValueType(Ctx))->getElementType();
+ QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
if (T != Ctx.getCanonicalType(R->getElementType()))
return UnknownVal();
@@ -1131,16 +1079,18 @@ SVal RegionStoreManager::RetrieveElement(Store store,
if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) {
int64_t i = CI->getValue().getSExtValue();
int64_t byteLength = Str->getByteLength();
- if (i > byteLength) {
- // Buffer overflow checking in GRExprEngine should handle this case,
- // but we shouldn't rely on it to not overflow here if that checking
- // is disabled.
- return UnknownVal();
- }
- char c = (i == byteLength) ? '\0' : Str->getStrData()[i];
+ // Technically, only i == byteLength is guaranteed to be null.
+ // However, such overflows should be caught before reaching this point;
+ // the only time such an access would be made is if a string literal was
+ // used to initialize a larger array.
+ char c = (i >= byteLength) ? '\0' : Str->getString()[i];
return ValMgr.makeIntVal(c, T);
}
}
+
+ // Check for loads from a code text region. For such loads, just give up.
+ if (isa<CodeTextRegion>(superR))
+ return UnknownVal();
// Handle the case where we are indexing into a larger scalar object.
// For example, this handles:
@@ -1148,9 +1098,9 @@ SVal RegionStoreManager::RetrieveElement(Store store,
// char *y = &x;
// return *y;
// FIXME: This is a hack, and doesn't do anything really intelligent yet.
- const RegionRawOffset &O = R->getAsRawOffset();
+ const RegionRawOffset &O = R->getAsArrayOffset();
if (const TypedRegion *baseR = dyn_cast_or_null<TypedRegion>(O.getRegion())) {
- QualType baseT = baseR->getValueType(Ctx);
+ QualType baseT = baseR->getValueType();
if (baseT->isScalarType()) {
QualType elemT = R->getElementType();
if (elemT->isScalarType()) {
@@ -1180,7 +1130,7 @@ SVal RegionStoreManager::RetrieveField(Store store,
if (const Optional<SVal> &V = getDirectBinding(B, R))
return *V;
- QualType Ty = R->getValueType(getContext());
+ QualType Ty = R->getValueType();
return RetrieveFieldOrElementCommon(store, R, Ty, R->getSuperRegion());
}
@@ -1243,13 +1193,18 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(Store store,
}
if (R->hasStackNonParametersStorage()) {
- if (isa<ElementRegion>(R)) {
+ if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
// Currently we don't reason specially about Clang-style vectors. Check
// if superR is a vector and if so return Unknown.
if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) {
- if (typedSuperR->getValueType(getContext())->isVectorType())
+ if (typedSuperR->getValueType()->isVectorType())
return UnknownVal();
}
+
+ // FIXME: We also need to take ElementRegions with symbolic indexes into
+ // account.
+ if (!ER->getIndex().isConstant())
+ return UnknownVal();
}
return UndefinedVal();
@@ -1332,21 +1287,18 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) {
}
SVal RegionStoreManager::RetrieveLazySymbol(const TypedRegion *R) {
-
- QualType valTy = R->getValueType(getContext());
-
// All other values are symbolic.
return ValMgr.getRegionValueSymbolVal(R);
}
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
- QualType T = R->getValueType(getContext());
+ QualType T = R->getValueType();
assert(T->isStructureOrClassType());
return ValMgr.makeLazyCompoundVal(store, R);
}
SVal RegionStoreManager::RetrieveArray(Store store, const TypedRegion * R) {
- assert(isa<ConstantArrayType>(R->getValueType(getContext())));
+ assert(isa<ConstantArrayType>(R->getValueType()));
return ValMgr.makeLazyCompoundVal(store, R);
}
@@ -1371,38 +1323,26 @@ Store RegionStoreManager::Bind(Store store, Loc L, SVal V) {
// Check if the region is a struct region.
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getValueType(getContext())->isStructureOrClassType())
+ if (TR->getValueType()->isStructureOrClassType())
return BindStruct(store, TR, V);
- // Special case: the current region represents a cast and it and the super
- // region both have pointer types or intptr_t types. If so, perform the
- // bind to the super region.
- // This is needed to support OSAtomicCompareAndSwap and friends or other
- // loads that treat integers as pointers and vis versa.
if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
if (ER->getIndex().isZeroConstant()) {
if (const TypedRegion *superR =
dyn_cast<TypedRegion>(ER->getSuperRegion())) {
- ASTContext &Ctx = getContext();
- QualType superTy = superR->getValueType(Ctx);
- QualType erTy = ER->getValueType(Ctx);
-
- if (IsAnyPointerOrIntptr(superTy, Ctx) &&
- IsAnyPointerOrIntptr(erTy, Ctx)) {
- V = ValMgr.getSValuator().EvalCast(V, superTy, erTy);
- return Bind(store, loc::MemRegionVal(superR), V);
- }
+ QualType superTy = superR->getValueType();
// For now, just invalidate the fields of the struct/union/class.
+ // This is for test rdar_test_7185607 in misc-ps-region-store.m.
// FIXME: Precisely handle the fields of the record.
- if (superTy->isRecordType())
- return InvalidateRegion(store, superR, NULL, 0, NULL);
+ if (superTy->isStructureOrClassType())
+ return KillStruct(store, superR, UnknownVal());
}
}
}
else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
// Binding directly to a symbolic region should be treated as binding
// to element 0.
- QualType T = SR->getSymbol()->getType(getContext());
+ QualType T = SR->getSymbol()->getType(Ctx);
// FIXME: Is this the right way to handle symbols that are references?
if (const PointerType *PT = T->getAs<PointerType>())
@@ -1454,7 +1394,7 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store,
else if (T->isStructureOrClassType() || T->isArrayType()) {
// Set the default value to a zero constant when it is a structure
// or array. The type doesn't really matter.
- V = ValMgr.makeZeroVal(ValMgr.getContext().IntTy);
+ V = ValMgr.makeZeroVal(Ctx.IntTy);
}
else {
return store;
@@ -1466,44 +1406,21 @@ Store RegionStoreManager::setImplicitDefaultValue(Store store,
Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
SVal Init) {
- ASTContext &Ctx = getContext();
- const ArrayType *AT =
- cast<ArrayType>(Ctx.getCanonicalType(R->getValueType(Ctx)));
+ const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
QualType ElementTy = AT->getElementType();
Optional<uint64_t> Size;
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
Size = CAT->getSize().getZExtValue();
- // Check if the init expr is a StringLiteral.
- if (isa<loc::MemRegionVal>(Init)) {
- const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
- const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
- const char* str = S->getStrData();
- unsigned len = S->getByteLength();
- unsigned j = 0;
-
- // Copy bytes from the string literal into the target array. Trailing bytes
- // in the array that are not covered by the string literal are initialized
- // to zero.
+ // Check if the init expr is a string literal.
+ if (loc::MemRegionVal *MRV = dyn_cast<loc::MemRegionVal>(&Init)) {
+ const StringRegion *S = cast<StringRegion>(MRV->getRegion());
- // We assume that string constants are bound to
- // constant arrays.
- uint64_t size = Size.getValue();
-
- for (uint64_t i = 0; i < size; ++i, ++j) {
- if (j >= len)
- break;
-
- SVal Idx = ValMgr.makeArrayIndex(i);
- const ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx, R,
- getContext());
-
- SVal V = ValMgr.makeIntVal(str[j], sizeof(char)*8, true);
- store = Bind(store, loc::MemRegionVal(ER), V);
- }
-
- return store;
+ // Treat the string as a lazy compound value.
+ nonloc::LazyCompoundVal LCV =
+ cast<nonloc::LazyCompoundVal>(ValMgr.makeLazyCompoundVal(store, S));
+ return CopyLazyBindings(LCV, store, R);
}
// Handle lazy compound values.
@@ -1525,10 +1442,12 @@ Store RegionStoreManager::BindArray(Store store, const TypedRegion* R,
break;
SVal Idx = ValMgr.makeArrayIndex(i);
- const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext());
+ const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
if (ElementTy->isStructureOrClassType())
store = BindStruct(store, ER, *VI);
+ else if (ElementTy->isArrayType())
+ store = BindArray(store, ER, *VI);
else
store = Bind(store, ValMgr.makeLoc(ER), *VI);
}
@@ -1547,7 +1466,7 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
if (!Features.supportsFields())
return store;
- QualType T = R->getValueType(getContext());
+ QualType T = R->getValueType();
assert(T->isStructureOrClassType());
const RecordType* RT = T->getAs<RecordType>();
@@ -1560,10 +1479,13 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
if (const nonloc::LazyCompoundVal *LCV=dyn_cast<nonloc::LazyCompoundVal>(&V))
return CopyLazyBindings(*LCV, store, R);
- // We may get non-CompoundVal accidentally due to imprecise cast logic.
- // Ignore them and kill the field values.
- if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
- return KillStruct(store, R);
+ // We may get non-CompoundVal accidentally due to imprecise cast logic or
+ // that we are binding symbolic struct value. Kill the field values, and if
+ // the value is symbolic go and bind it as a "default" binding.
+ if (V.isUnknown() || !isa<nonloc::CompoundVal>(V)) {
+ SVal SV = isa<nonloc::SymbolVal>(V) ? V : UnknownVal();
+ return KillStruct(store, R, SV);
+ }
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
@@ -1596,14 +1518,15 @@ Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R,
return store;
}
-Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R) {
+Store RegionStoreManager::KillStruct(Store store, const TypedRegion* R,
+ SVal DefaultVal) {
RegionBindings B = GetRegionBindings(store);
llvm::OwningPtr<RegionStoreSubRegionMap>
SubRegions(getRegionStoreSubRegionMap(store));
RemoveSubRegionBindings(B, R, *SubRegions);
// Set the default value of the struct region to "unknown".
- return Add(B, R, BindingKey::Default, UnknownVal()).getRoot();
+ return Add(B, R, BindingKey::Default, DefaultVal).getRoot();
}
Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
@@ -1627,21 +1550,10 @@ Store RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
// "Raw" retrievals and bindings.
//===----------------------------------------------------------------------===//
-BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
- if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
- const RegionRawOffset &O = ER->getAsRawOffset();
-
- if (O.getRegion())
- return BindingKey(O.getRegion(), O.getByteOffset(), k);
-
- // FIXME: There are some ElementRegions for which we cannot compute
- // raw offsets yet, including regions with symbolic offsets.
- }
-
- return BindingKey(R, 0, k);
-}
RegionBindings RegionStoreManager::Add(RegionBindings B, BindingKey K, SVal V) {
+ if (!K.isValid())
+ return B;
return RBFactory.Add(B, K, V);
}
@@ -1651,6 +1563,8 @@ RegionBindings RegionStoreManager::Add(RegionBindings B, const MemRegion *R,
}
const SVal *RegionStoreManager::Lookup(RegionBindings B, BindingKey K) {
+ if (!K.isValid())
+ return NULL;
return B.lookup(K);
}
@@ -1661,6 +1575,8 @@ const SVal *RegionStoreManager::Lookup(RegionBindings B,
}
RegionBindings RegionStoreManager::Remove(RegionBindings B, BindingKey K) {
+ if (!K.isValid())
+ return B;
return RBFactory.Remove(B, K);
}
@@ -1669,11 +1585,6 @@ RegionBindings RegionStoreManager::Remove(RegionBindings B, const MemRegion *R,
return Remove(B, BindingKey::Make(R, k));
}
-Store RegionStoreManager::Remove(Store store, BindingKey K) {
- RegionBindings B = GetRegionBindings(store);
- return Remove(B, K).getRoot();
-}
-
//===----------------------------------------------------------------------===//
// State pruning.
//===----------------------------------------------------------------------===//
@@ -1818,12 +1729,12 @@ bool RemoveDeadBindingsWorker::UpdatePostponed() {
return changed;
}
-const GRState *RegionStoreManager::RemoveDeadBindings(GRState &state,
+Store RegionStoreManager::RemoveDeadBindings(Store store,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
- RegionBindings B = GetRegionBindings(state.getStore());
+ RegionBindings B = GetRegionBindings(store);
RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
W.GenerateClusters();
@@ -1856,14 +1767,13 @@ const GRState *RegionStoreManager::RemoveDeadBindings(GRState &state,
for (; SI != SE; ++SI)
SymReaper.maybeDead(*SI);
}
- state.setStore(B.getRoot());
- const GRState *s = StateMgr.getPersistentState(state);
- return s;
+
+ return B.getRoot();
}
-GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
- StackFrameContext const *frame) {
+Store RegionStoreManager::EnterStackFrame(const GRState *state,
+ const StackFrameContext *frame) {
FunctionDecl const *FD = cast<FunctionDecl>(frame->getDecl());
FunctionDecl::param_const_iterator PI = FD->param_begin();
Store store = state->getStore();
@@ -1887,9 +1797,9 @@ GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,
store = Bind(store, ValMgr.makeLoc(MRMgr.getVarRegion(*PI,frame)),ArgVal);
}
} else
- assert(0 && "Unhandled call expression.");
+ llvm_unreachable("Unhandled call expression.");
- return state->makeWithStore(store);
+ return store;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Checker/ReturnPointerRangeChecker.cpp b/lib/Checker/ReturnPointerRangeChecker.cpp
index 14edf5668983..a9eb5ce1a700 100644
--- a/lib/Checker/ReturnPointerRangeChecker.cpp
+++ b/lib/Checker/ReturnPointerRangeChecker.cpp
@@ -66,7 +66,7 @@ void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
DefinedOrUnknownSVal NumElements
= C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
- ER->getValueType(C.getASTContext()));
+ ER->getValueType());
const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
diff --git a/lib/Checker/ReturnUndefChecker.cpp b/lib/Checker/ReturnUndefChecker.cpp
index 52a0b3076b6a..73d1890f336f 100644
--- a/lib/Checker/ReturnUndefChecker.cpp
+++ b/lib/Checker/ReturnUndefChecker.cpp
@@ -61,6 +61,7 @@ void ReturnUndefChecker::PreVisitReturnStmt(CheckerContext &C,
EnhancedBugReport *report =
new EnhancedBugReport(*BT, BT->getDescription(), N);
+ report->addRange(RetE->getSourceRange());
report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
C.EmitReport(report);
diff --git a/lib/Checker/SVals.cpp b/lib/Checker/SVals.cpp
index 7a99e8681df9..97ba74e94878 100644
--- a/lib/Checker/SVals.cpp
+++ b/lib/Checker/SVals.cpp
@@ -62,6 +62,9 @@ const FunctionDecl *SVal::getAsFunctionDecl() const {
/// wraps a symbol, return that SymbolRef. Otherwise return 0.
// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
SymbolRef SVal::getAsLocSymbol() const {
+ if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this))
+ return X->getLoc().getAsLocSymbol();
+
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
const MemRegion *R = X->StripCasts();
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
@@ -247,8 +250,8 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
BinaryOperator::Opcode Op,
const loc::ConcreteInt& R) const {
- assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
- (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
+ assert (Op == BO_Add || Op == BO_Sub ||
+ (Op >= BO_LT && Op <= BO_NE));
const llvm::APSInt* X = BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
diff --git a/lib/Checker/SValuator.cpp b/lib/Checker/SValuator.cpp
index a7e15fc3fd73..273e5742a8e2 100644
--- a/lib/Checker/SValuator.cpp
+++ b/lib/Checker/SValuator.cpp
@@ -37,7 +37,7 @@ SVal SValuator::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
if (isa<Loc>(R)) {
// Support pointer arithmetic where the addend is on the left
// and the pointer on the right.
- assert(Op == BinaryOperator::Add);
+ assert(Op == BO_Add);
// Commute the operands.
return EvalBinOpLN(ST, Op, cast<Loc>(R), cast<NonLoc>(L), T);
@@ -49,7 +49,7 @@ SVal SValuator::EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
DefinedOrUnknownSVal SValuator::EvalEQ(const GRState *ST,
DefinedOrUnknownSVal L,
DefinedOrUnknownSVal R) {
- return cast<DefinedOrUnknownSVal>(EvalBinOp(ST, BinaryOperator::EQ, L, R,
+ return cast<DefinedOrUnknownSVal>(EvalBinOp(ST, BO_EQ, L, R,
ValMgr.getContext().IntTy));
}
diff --git a/lib/Checker/SimpleConstraintManager.cpp b/lib/Checker/SimpleConstraintManager.cpp
index 321381b045ad..04496e1e3332 100644
--- a/lib/Checker/SimpleConstraintManager.cpp
+++ b/lib/Checker/SimpleConstraintManager.cpp
@@ -31,17 +31,17 @@ bool SimpleConstraintManager::canReasonAbout(SVal X) const {
if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
switch (SIE->getOpcode()) {
// We don't reason yet about bitwise-constraints on symbolic values.
- case BinaryOperator::And:
- case BinaryOperator::Or:
- case BinaryOperator::Xor:
+ case BO_And:
+ case BO_Or:
+ case BO_Xor:
return false;
// We don't reason yet about these arithmetic constraints on
// symbolic values.
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
- case BinaryOperator::Rem:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Shl:
+ case BO_Shr:
return false;
// All other cases.
default:
@@ -125,12 +125,12 @@ static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
switch (op) {
default:
assert(false && "Invalid opcode.");
- case BinaryOperator::LT: return BinaryOperator::GE;
- case BinaryOperator::GT: return BinaryOperator::LE;
- case BinaryOperator::LE: return BinaryOperator::GT;
- case BinaryOperator::GE: return BinaryOperator::LT;
- case BinaryOperator::EQ: return BinaryOperator::NE;
- case BinaryOperator::NE: return BinaryOperator::EQ;
+ case BO_LT: return BO_GE;
+ case BO_GT: return BO_LE;
+ case BO_LE: return BO_GT;
+ case BO_GE: return BO_LT;
+ case BO_EQ: return BO_NE;
+ case BO_NE: return BO_EQ;
}
}
@@ -178,7 +178,7 @@ const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
if (!BinaryOperator::isComparisonOp(op)) {
QualType T = SymMgr.getType(SE);
const llvm::APSInt &zero = BasicVals.getValue(0, T);
- op = (Assumption ? BinaryOperator::NE : BinaryOperator::EQ);
+ op = (Assumption ? BO_NE : BO_EQ);
return AssumeSymRel(state, SE, op, zero);
}
@@ -238,10 +238,10 @@ const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
// Get the constant out of the expression "($sym+constant1)".
switch (SE->getOpcode()) {
- case BinaryOperator::Add:
+ case BO_Add:
Adjustment = SE->getRHS();
break;
- case BinaryOperator::Sub:
+ case BO_Sub:
Adjustment = -SE->getRHS();
break;
default:
@@ -276,48 +276,24 @@ const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
// No logic yet for other operators. Assume the constraint is feasible.
return state;
- case BinaryOperator::EQ:
+ case BO_EQ:
return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment);
- case BinaryOperator::NE:
+ case BO_NE:
return AssumeSymNE(state, Sym, ConvertedInt, Adjustment);
- case BinaryOperator::GT:
+ case BO_GT:
return AssumeSymGT(state, Sym, ConvertedInt, Adjustment);
- case BinaryOperator::GE:
+ case BO_GE:
return AssumeSymGE(state, Sym, ConvertedInt, Adjustment);
- case BinaryOperator::LT:
+ case BO_LT:
return AssumeSymLT(state, Sym, ConvertedInt, Adjustment);
- case BinaryOperator::LE:
+ case BO_LE:
return AssumeSymLE(state, Sym, ConvertedInt, Adjustment);
} // end switch
}
-const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
- DefinedSVal Idx,
- DefinedSVal UpperBound,
- bool Assumption) {
-
- // Only support ConcreteInt for now.
- if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
- return state;
-
- const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
- llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
- // IdxV might be too narrow.
- if (IdxV.getBitWidth() < Zero.getBitWidth())
- IdxV.extend(Zero.getBitWidth());
- // UBV might be too narrow, too.
- llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
- if (UBV.getBitWidth() < Zero.getBitWidth())
- UBV.extend(Zero.getBitWidth());
-
- bool InBound = (Zero <= IdxV) && (IdxV < UBV);
- bool isFeasible = Assumption ? InBound : !InBound;
- return isFeasible ? state : NULL;
-}
-
} // end of namespace clang
diff --git a/lib/Checker/SimpleConstraintManager.h b/lib/Checker/SimpleConstraintManager.h
index 45057e64f31f..96811b3e36e6 100644
--- a/lib/Checker/SimpleConstraintManager.h
+++ b/lib/Checker/SimpleConstraintManager.h
@@ -43,10 +43,6 @@ public:
BinaryOperator::Opcode op,
const llvm::APSInt& Int);
- const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx,
- DefinedSVal UpperBound,
- bool Assumption);
-
protected:
//===------------------------------------------------------------------===//
diff --git a/lib/Checker/SimpleSValuator.cpp b/lib/Checker/SimpleSValuator.cpp
index 3bc4ee7d0613..782cd4f5e68b 100644
--- a/lib/Checker/SimpleSValuator.cpp
+++ b/lib/Checker/SimpleSValuator.cpp
@@ -168,12 +168,12 @@ static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
switch (op) {
default:
assert(false && "Invalid opcode.");
- case BinaryOperator::LT: return BinaryOperator::GE;
- case BinaryOperator::GT: return BinaryOperator::LE;
- case BinaryOperator::LE: return BinaryOperator::GT;
- case BinaryOperator::GE: return BinaryOperator::LT;
- case BinaryOperator::EQ: return BinaryOperator::NE;
- case BinaryOperator::NE: return BinaryOperator::EQ;
+ case BO_LT: return BO_GE;
+ case BO_GT: return BO_LE;
+ case BO_LE: return BO_GT;
+ case BO_GE: return BO_LT;
+ case BO_EQ: return BO_NE;
+ case BO_NE: return BO_EQ;
}
}
@@ -181,12 +181,12 @@ static BinaryOperator::Opcode ReverseComparison(BinaryOperator::Opcode op) {
switch (op) {
default:
assert(false && "Invalid opcode.");
- case BinaryOperator::LT: return BinaryOperator::GT;
- case BinaryOperator::GT: return BinaryOperator::LT;
- case BinaryOperator::LE: return BinaryOperator::GE;
- case BinaryOperator::GE: return BinaryOperator::LE;
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
+ case BO_LT: return BO_GT;
+ case BO_GT: return BO_LT;
+ case BO_LE: return BO_GE;
+ case BO_GE: return BO_LE;
+ case BO_EQ:
+ case BO_NE:
return op;
}
}
@@ -202,14 +202,14 @@ SVal SimpleSValuator::MakeSymIntVal(const SymExpr *LHS,
default:
// We can't reduce this case; just treat it normally.
break;
- case BinaryOperator::Mul:
+ case BO_Mul:
// a*0 and a*1
if (RHS == 0)
return ValMgr.makeIntVal(0, resultTy);
else if (RHS == 1)
isIdempotent = true;
break;
- case BinaryOperator::Div:
+ case BO_Div:
// a/0 and a/1
if (RHS == 0)
// This is also handled elsewhere.
@@ -217,7 +217,7 @@ SVal SimpleSValuator::MakeSymIntVal(const SymExpr *LHS,
else if (RHS == 1)
isIdempotent = true;
break;
- case BinaryOperator::Rem:
+ case BO_Rem:
// a%0 and a%1
if (RHS == 0)
// This is also handled elsewhere.
@@ -225,23 +225,23 @@ SVal SimpleSValuator::MakeSymIntVal(const SymExpr *LHS,
else if (RHS == 1)
return ValMgr.makeIntVal(0, resultTy);
break;
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
- case BinaryOperator::Xor:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_Xor:
// a+0, a-0, a<<0, a>>0, a^0
if (RHS == 0)
isIdempotent = true;
break;
- case BinaryOperator::And:
+ case BO_And:
// a&0 and a&(~0)
if (RHS == 0)
return ValMgr.makeIntVal(0, resultTy);
else if (RHS.isAllOnesValue())
isIdempotent = true;
break;
- case BinaryOperator::Or:
+ case BO_Or:
// a|0 and a|(~0)
if (RHS == 0)
isIdempotent = true;
@@ -275,19 +275,19 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
switch (op) {
default:
break;
- case BinaryOperator::EQ:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
+ case BO_EQ:
+ case BO_LE:
+ case BO_GE:
return ValMgr.makeTruthVal(true, resultTy);
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::NE:
+ case BO_LT:
+ case BO_GT:
+ case BO_NE:
return ValMgr.makeTruthVal(false, resultTy);
- case BinaryOperator::Xor:
- case BinaryOperator::Sub:
+ case BO_Xor:
+ case BO_Sub:
return ValMgr.makeIntVal(0, resultTy);
- case BinaryOperator::Or:
- case BinaryOperator::And:
+ case BO_Or:
+ case BO_And:
return EvalCastNL(lhs, resultTy);
}
@@ -312,9 +312,9 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
}
default:
switch (op) {
- case BinaryOperator::EQ:
+ case BO_EQ:
return ValMgr.makeTruthVal(false, resultTy);
- case BinaryOperator::NE:
+ case BO_NE:
return ValMgr.makeTruthVal(true, resultTy);
default:
// This case also handles pointer arithmetic.
@@ -333,7 +333,7 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
return UnknownVal();
// Is this a logical not? (!x is represented as x == 0.)
- if (op == BinaryOperator::EQ && rhs.isZeroConstant()) {
+ if (op == BO_EQ && rhs.isZeroConstant()) {
// We know how to negate certain expressions. Simplify them here.
BinaryOperator::Opcode opc = symIntExpr->getOpcode();
@@ -342,34 +342,34 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
// We don't know how to negate this operation.
// Just handle it as if it were a normal comparison to 0.
break;
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr:
+ case BO_LAnd:
+ case BO_LOr:
assert(false && "Logical operators handled by branching logic.");
return UnknownVal();
- case BinaryOperator::Assign:
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::RemAssign:
- case BinaryOperator::AddAssign:
- case BinaryOperator::SubAssign:
- case BinaryOperator::ShlAssign:
- case BinaryOperator::ShrAssign:
- case BinaryOperator::AndAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::OrAssign:
- case BinaryOperator::Comma:
+ case BO_Assign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
+ case BO_Comma:
assert(false && "'=' and ',' operators handled by GRExprEngine.");
return UnknownVal();
- case BinaryOperator::PtrMemD:
- case BinaryOperator::PtrMemI:
+ case BO_PtrMemD:
+ case BO_PtrMemI:
assert(false && "Pointer arithmetic not handled here.");
return UnknownVal();
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
// Negate the comparison and make a value.
opc = NegateComparison(opc);
assert(symIntExpr->getType(ValMgr.getContext()) == resultTy);
@@ -402,9 +402,9 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
const llvm::APSInt *newRHS;
if (lop == op)
- newRHS = BVF.EvaluateAPSInt(BinaryOperator::Add, first, second);
+ newRHS = BVF.EvaluateAPSInt(BO_Add, first, second);
else
- newRHS = BVF.EvaluateAPSInt(BinaryOperator::Sub, first, second);
+ newRHS = BVF.EvaluateAPSInt(BO_Sub, first, second);
return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy);
}
}
@@ -429,26 +429,26 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
lhs = tmp;
switch (op) {
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
op = ReverseComparison(op);
continue;
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
- case BinaryOperator::Add:
- case BinaryOperator::Mul:
- case BinaryOperator::And:
- case BinaryOperator::Xor:
- case BinaryOperator::Or:
+ case BO_EQ:
+ case BO_NE:
+ case BO_Add:
+ case BO_Mul:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
continue;
- case BinaryOperator::Shr:
+ case BO_Shr:
if (lhsValue.isAllOnesValue() && lhsValue.isSigned())
// At this point lhs and rhs have been swapped.
return rhs;
// FALL-THROUGH
- case BinaryOperator::Shl:
+ case BO_Shl:
if (lhsValue == 0)
// At this point lhs and rhs have been swapped.
return rhs;
@@ -461,10 +461,12 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
case nonloc::SymbolValKind: {
nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
SymbolRef Sym = slhs->getSymbol();
-
+
+ ASTContext& Ctx = ValMgr.getContext();
+
// Does the symbol simplify to a constant? If so, "fold" the constant
// by setting 'lhs' to a ConcreteInt and try again.
- if (Sym->getType(ValMgr.getContext())->isIntegerType())
+ if (Sym->getType(Ctx)->isIntegerType())
if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
// The symbol evaluates to a constant. If necessary, promote the
// folded constant (LHS) to the result type.
@@ -474,7 +476,7 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
// Also promote the RHS (if necessary).
- // For shifts, it necessary promote the RHS to the result type.
+ // For shifts, it is not necessary to promote the RHS.
if (BinaryOperator::isShiftOp(op))
continue;
@@ -486,7 +488,20 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,
continue;
}
-
+
+ // Is the RHS a symbol we can simplify?
+ if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) {
+ SymbolRef RSym = srhs->getSymbol();
+ if (RSym->getType(Ctx)->isIntegerType()) {
+ if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
+ // The symbol evaluates to a constant.
+ BasicValueFactory &BVF = ValMgr.getBasicValueFactory();
+ const llvm::APSInt &rhs_I = BVF.Convert(resultTy, *Constant);
+ rhs = nonloc::ConcreteInt(rhs_I);
+ }
+ }
+ }
+
if (isa<nonloc::ConcreteInt>(rhs)) {
return MakeSymIntVal(slhs->getSymbol(), op,
cast<nonloc::ConcreteInt>(rhs).getValue(),
@@ -510,7 +525,7 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
// calling this function with another operation (PR7527). We don't attempt to
// model this for now, but it could be useful, particularly when the
// "location" is actually an integer value that's been passed through a void*.
- if (!(BinaryOperator::isComparisonOp(op) || op == BinaryOperator::Sub))
+ if (!(BinaryOperator::isComparisonOp(op) || op == BO_Sub))
return UnknownVal();
// Special cases for when both sides are identical.
@@ -519,15 +534,15 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
default:
assert(false && "Unimplemented operation for two identical values");
return UnknownVal();
- case BinaryOperator::Sub:
+ case BO_Sub:
return ValMgr.makeZeroVal(resultTy);
- case BinaryOperator::EQ:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
+ case BO_EQ:
+ case BO_LE:
+ case BO_GE:
return ValMgr.makeTruthVal(true, resultTy);
- case BinaryOperator::NE:
- case BinaryOperator::LT:
- case BinaryOperator::GT:
+ case BO_NE:
+ case BO_LT:
+ case BO_GT:
return ValMgr.makeTruthVal(false, resultTy);
}
}
@@ -543,15 +558,15 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
switch (op) {
default:
break;
- case BinaryOperator::Sub:
+ case BO_Sub:
return EvalCastL(lhs, resultTy);
- case BinaryOperator::EQ:
- case BinaryOperator::LE:
- case BinaryOperator::LT:
+ case BO_EQ:
+ case BO_LE:
+ case BO_LT:
return ValMgr.makeTruthVal(false, resultTy);
- case BinaryOperator::NE:
- case BinaryOperator::GT:
- case BinaryOperator::GE:
+ case BO_NE:
+ case BO_GT:
+ case BO_GE:
return ValMgr.makeTruthVal(true, resultTy);
}
}
@@ -594,13 +609,13 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
switch (op) {
default:
break;
- case BinaryOperator::EQ:
- case BinaryOperator::GT:
- case BinaryOperator::GE:
+ case BO_EQ:
+ case BO_GT:
+ case BO_GE:
return ValMgr.makeTruthVal(false, resultTy);
- case BinaryOperator::NE:
- case BinaryOperator::LT:
- case BinaryOperator::LE:
+ case BO_NE:
+ case BO_LT:
+ case BO_LE:
return ValMgr.makeTruthVal(true, resultTy);
}
}
@@ -624,15 +639,15 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
switch (op) {
default:
break;
- case BinaryOperator::Sub:
+ case BO_Sub:
return EvalCastL(lhs, resultTy);
- case BinaryOperator::EQ:
- case BinaryOperator::LT:
- case BinaryOperator::LE:
+ case BO_EQ:
+ case BO_LT:
+ case BO_LE:
return ValMgr.makeTruthVal(false, resultTy);
- case BinaryOperator::NE:
- case BinaryOperator::GT:
- case BinaryOperator::GE:
+ case BO_NE:
+ case BO_GT:
+ case BO_GE:
return ValMgr.makeTruthVal(true, resultTy);
}
}
@@ -660,9 +675,9 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
switch (op) {
default:
return UnknownVal();
- case BinaryOperator::EQ:
+ case BO_EQ:
return ValMgr.makeTruthVal(false, resultTy);
- case BinaryOperator::NE:
+ case BO_NE:
return ValMgr.makeTruthVal(true, resultTy);
}
}
@@ -711,8 +726,8 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
}
// If the element indexes aren't comparable, see if the raw offsets are.
- RegionRawOffset LeftOffset = LeftER->getAsRawOffset();
- RegionRawOffset RightOffset = RightER->getAsRawOffset();
+ RegionRawOffset LeftOffset = LeftER->getAsArrayOffset();
+ RegionRawOffset RightOffset = RightER->getAsArrayOffset();
if (LeftOffset.getRegion() != NULL &&
LeftOffset.getRegion() == RightOffset.getRegion()) {
@@ -722,17 +737,17 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
switch (op) {
default:
return UnknownVal();
- case BinaryOperator::LT:
+ case BO_LT:
return ValMgr.makeTruthVal(left < right, resultTy);
- case BinaryOperator::GT:
+ case BO_GT:
return ValMgr.makeTruthVal(left > right, resultTy);
- case BinaryOperator::LE:
+ case BO_LE:
return ValMgr.makeTruthVal(left <= right, resultTy);
- case BinaryOperator::GE:
+ case BO_GE:
return ValMgr.makeTruthVal(left >= right, resultTy);
- case BinaryOperator::EQ:
+ case BO_EQ:
return ValMgr.makeTruthVal(left == right, resultTy);
- case BinaryOperator::NE:
+ case BO_NE:
return ValMgr.makeTruthVal(left != right, resultTy);
}
}
@@ -770,16 +785,16 @@ SVal SimpleSValuator::EvalBinOpLL(const GRState *state,
// We know for sure that the two fields are not the same, since that
// would have given us the same SVal.
- if (op == BinaryOperator::EQ)
+ if (op == BO_EQ)
return ValMgr.makeTruthVal(false, resultTy);
- if (op == BinaryOperator::NE)
+ if (op == BO_NE)
return ValMgr.makeTruthVal(true, resultTy);
// Iterate through the fields and see which one comes first.
// [C99 6.7.2.1.13] "Within a structure object, the non-bit-field
// members and the units in which bit-fields reside have addresses that
// increase in the order in which they are declared."
- bool leftFirst = (op == BinaryOperator::LT || op == BinaryOperator::LE);
+ bool leftFirst = (op == BO_LT || op == BO_LE);
for (RecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I!=E; ++I) {
if (*I == LeftFD)
@@ -818,8 +833,41 @@ SVal SimpleSValuator::EvalBinOpLN(const GRState *state,
}
}
}
+
+ // We are dealing with pointer arithmetic.
+
+ // Handle pointer arithmetic on constant values.
+ if (nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
+ if (loc::ConcreteInt *lhsInt = dyn_cast<loc::ConcreteInt>(&lhs)) {
+ const llvm::APSInt &leftI = lhsInt->getValue();
+ assert(leftI.isUnsigned());
+ llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true);
+
+ // Convert the bitwidth of rightI. This should deal with overflow
+ // since we are dealing with concrete values.
+ rightI.extOrTrunc(leftI.getBitWidth());
+
+ // Offset the increment by the pointer size.
+ llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true);
+ rightI *= Multiplicand;
+
+ // Compute the adjusted pointer.
+ switch (op) {
+ case BO_Add:
+ rightI = leftI + rightI;
+ break;
+ case BO_Sub:
+ rightI = leftI - rightI;
+ break;
+ default:
+ llvm_unreachable("Invalid pointer arithmetic operation");
+ }
+ return loc::ConcreteInt(ValMgr.getBasicValueFactory().getValue(rightI));
+ }
+ }
+
- // Delegate pointer arithmetic to the StoreManager.
+ // Delegate remaining pointer arithmetic to the StoreManager.
return state->getStateManager().getStoreManager().EvalBinOp(op, lhs,
rhs, resultTy);
}
diff --git a/lib/Checker/StackAddrLeakChecker.cpp b/lib/Checker/StackAddrLeakChecker.cpp
index f4a9db62df4b..c67a81dced0a 100644
--- a/lib/Checker/StackAddrLeakChecker.cpp
+++ b/lib/Checker/StackAddrLeakChecker.cpp
@@ -108,7 +108,7 @@ void StackAddrLeakChecker::EmitStackError(CheckerContext &C, const MemRegion *R,
report->addRange(range);
C.EmitReport(report);
-}
+}
void StackAddrLeakChecker::PreVisitReturnStmt(CheckerContext &C,
const ReturnStmt *RS) {
diff --git a/lib/Checker/Store.cpp b/lib/Checker/Store.cpp
index b12833170506..1cb5cd70cae6 100644
--- a/lib/Checker/Store.cpp
+++ b/lib/Checker/Store.cpp
@@ -21,6 +21,11 @@ StoreManager::StoreManager(GRStateManager &stateMgr)
: ValMgr(stateMgr.getValueManager()), StateMgr(stateMgr),
MRMgr(ValMgr.getRegionManager()), Ctx(stateMgr.getContext()) {}
+Store StoreManager::EnterStackFrame(const GRState *state,
+ const StackFrameContext *frame) {
+ return state->getStore();
+}
+
const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,
QualType EleTy, uint64_t index) {
SVal idx = ValMgr.makeArrayIndex(index);
@@ -78,7 +83,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// Handle casts from compatible types.
if (R->isBoundable())
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
- QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx));
+ QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
if (CanonPointeeTy == ObjTy)
return R;
}
@@ -96,17 +101,10 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
assert(0 && "Invalid region cast");
break;
}
-
+
case MemRegion::FunctionTextRegionKind:
case MemRegion::BlockTextRegionKind:
- case MemRegion::BlockDataRegionKind: {
- // CodeTextRegion should be cast to only a function or block pointer type,
- // although they can in practice be casted to anything, e.g, void*, char*,
- // etc.
- // Just return the region.
- return R;
- }
-
+ case MemRegion::BlockDataRegionKind:
case MemRegion::StringRegionKind:
// FIXME: Need to handle arbitrary downcasts.
case MemRegion::SymbolicRegionKind:
@@ -139,7 +137,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// FIXME: Handle symbolic raw offsets.
const ElementRegion *elementR = cast<ElementRegion>(R);
- const RegionRawOffset &rawOff = elementR->getAsRawOffset();
+ const RegionRawOffset &rawOff = elementR->getAsArrayOffset();
const MemRegion *baseR = rawOff.getRegion();
// If we cannot compute a raw offset, throw up our hands and return
@@ -154,7 +152,7 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy)
// check to see if type we are casting to is the same as the base
// region. If so, just return the base region.
if (const TypedRegion *TR = dyn_cast<TypedRegion>(baseR)) {
- QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx));
+ QualType ObjTy = Ctx.getCanonicalType(TR->getValueType());
QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
if (CanonPointeeTy == ObjTy)
return baseR;
@@ -217,7 +215,7 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
if (performTestOnly) {
// Automatically translate references to pointers.
- QualType T = R->getValueType(Ctx);
+ QualType T = R->getValueType();
if (const ReferenceType *RT = T->getAs<ReferenceType>())
T = Ctx.getPointerType(RT->getPointeeType());
@@ -279,10 +277,6 @@ SVal StoreManager::getLValueElement(QualType elementType, SVal Offset,
if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base))
return Base;
- // Only handle integer offsets... for now.
- if (!isa<nonloc::ConcreteInt>(Offset))
- return UnknownVal();
-
const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion();
// Pointer of any type can be cast and used as array base.
@@ -311,6 +305,19 @@ SVal StoreManager::getLValueElement(QualType elementType, SVal Offset,
return UnknownVal();
const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue();
+
+ // Only allow non-integer offsets if the base region has no offset itself.
+ // FIXME: This is a somewhat arbitrary restriction. We should be using
+ // SValuator here to add the two offsets without checking their types.
+ if (!isa<nonloc::ConcreteInt>(Offset)) {
+ if (isa<ElementRegion>(BaseRegion->StripCasts()))
+ return UnknownVal();
+
+ return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
+ ElemR->getSuperRegion(),
+ Ctx));
+ }
+
const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue();
assert(BaseIdxI.isSigned());
diff --git a/lib/Checker/StreamChecker.cpp b/lib/Checker/StreamChecker.cpp
index c527ca24496f..8553875a24ff 100644
--- a/lib/Checker/StreamChecker.cpp
+++ b/lib/Checker/StreamChecker.cpp
@@ -23,18 +23,49 @@ using namespace clang;
namespace {
+struct StreamState {
+ enum Kind { Opened, Closed, OpenFailed, Escaped } K;
+ const Stmt *S;
+
+ StreamState(Kind k, const Stmt *s) : K(k), S(s) {}
+
+ bool isOpened() const { return K == Opened; }
+ bool isClosed() const { return K == Closed; }
+ //bool isOpenFailed() const { return K == OpenFailed; }
+ //bool isEscaped() const { return K == Escaped; }
+
+ bool operator==(const StreamState &X) const {
+ return K == X.K && S == X.S;
+ }
+
+ static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); }
+ static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); }
+ static StreamState getOpenFailed(const Stmt *s) {
+ return StreamState(OpenFailed, s);
+ }
+ static StreamState getEscaped(const Stmt *s) {
+ return StreamState(Escaped, s);
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(K);
+ ID.AddPointer(S);
+ }
+};
+
class StreamChecker : public CheckerVisitor<StreamChecker> {
- IdentifierInfo *II_fopen, *II_fread, *II_fwrite,
+ IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, *II_fwrite,
*II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos,
*II_clearerr, *II_feof, *II_ferror, *II_fileno;
- BuiltinBug *BT_nullfp, *BT_illegalwhence;
+ BuiltinBug *BT_nullfp, *BT_illegalwhence, *BT_doubleclose, *BT_ResourceLeak;
public:
StreamChecker()
- : II_fopen(0), II_fread(0), II_fwrite(0),
+ : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0),
II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0),
II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0),
- BT_nullfp(0), BT_illegalwhence(0) {}
+ BT_nullfp(0), BT_illegalwhence(0), BT_doubleclose(0),
+ BT_ResourceLeak(0) {}
static void *getTag() {
static int x;
@@ -42,9 +73,14 @@ public:
}
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+ void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
+ void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng);
+ void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
private:
void Fopen(CheckerContext &C, const CallExpr *CE);
+ void Tmpfile(CheckerContext &C, const CallExpr *CE);
+ void Fclose(CheckerContext &C, const CallExpr *CE);
void Fread(CheckerContext &C, const CallExpr *CE);
void Fwrite(CheckerContext &C, const CallExpr *CE);
void Fseek(CheckerContext &C, const CallExpr *CE);
@@ -56,14 +92,25 @@ private:
void Feof(CheckerContext &C, const CallExpr *CE);
void Ferror(CheckerContext &C, const CallExpr *CE);
void Fileno(CheckerContext &C, const CallExpr *CE);
+
+ void OpenFileAux(CheckerContext &C, const CallExpr *CE);
- // Return true indicates the stream pointer is NULL.
const GRState *CheckNullStream(SVal SV, const GRState *state,
CheckerContext &C);
+ const GRState *CheckDoubleClose(const CallExpr *CE, const GRState *state,
+ CheckerContext &C);
};
} // end anonymous namespace
+namespace clang {
+ template <>
+ struct GRStateTrait<StreamState>
+ : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > {
+ static void *GDMIndex() { return StreamChecker::getTag(); }
+ };
+}
+
void clang::RegisterStreamChecker(GRExprEngine &Eng) {
Eng.registerCheck(new StreamChecker());
}
@@ -79,6 +126,10 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
ASTContext &Ctx = C.getASTContext();
if (!II_fopen)
II_fopen = &Ctx.Idents.get("fopen");
+ if (!II_tmpfile)
+ II_tmpfile = &Ctx.Idents.get("tmpfile");
+ if (!II_fclose)
+ II_fclose = &Ctx.Idents.get("fclose");
if (!II_fread)
II_fread = &Ctx.Idents.get("fread");
if (!II_fwrite)
@@ -106,6 +157,14 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
Fopen(C, CE);
return true;
}
+ if (FD->getIdentifier() == II_tmpfile) {
+ Tmpfile(C, CE);
+ return true;
+ }
+ if (FD->getIdentifier() == II_fclose) {
+ Fclose(C, CE);
+ return true;
+ }
if (FD->getIdentifier() == II_fread) {
Fread(C, CE);
return true;
@@ -155,21 +214,43 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
}
void StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) {
+ OpenFileAux(C, CE);
+}
+
+void StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) {
+ OpenFileAux(C, CE);
+}
+
+void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) {
const GRState *state = C.getState();
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
ValueManager &ValMgr = C.getValueManager();
DefinedSVal RetVal = cast<DefinedSVal>(ValMgr.getConjuredSymbolVal(0, CE,
Count));
state = state->BindExpr(CE, RetVal);
-
+
ConstraintManager &CM = C.getConstraintManager();
// Bifurcate the state into two: one with a valid FILE* pointer, the other
// with a NULL.
const GRState *stateNotNull, *stateNull;
llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, RetVal);
+
+ if (SymbolRef Sym = RetVal.getAsSymbol()) {
+ // if RetVal is not NULL, set the symbol's state to Opened.
+ stateNotNull =
+ stateNotNull->set<StreamState>(Sym,StreamState::getOpened(CE));
+ stateNull =
+ stateNull->set<StreamState>(Sym, StreamState::getOpenFailed(CE));
+
+ C.addTransition(stateNotNull);
+ C.addTransition(stateNull);
+ }
+}
- C.addTransition(stateNotNull);
- C.addTransition(stateNull);
+void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = CheckDoubleClose(CE, C.getState(), C);
+ if (state)
+ C.addTransition(state);
}
void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) {
@@ -285,3 +366,103 @@ const GRState *StreamChecker::CheckNullStream(SVal SV, const GRState *state,
}
return stateNotNull;
}
+
+const GRState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
+ const GRState *state,
+ CheckerContext &C) {
+ SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
+ if (!Sym)
+ return state;
+
+ const StreamState *SS = state->get<StreamState>(Sym);
+
+ // If the file stream is not tracked, return.
+ if (!SS)
+ return state;
+
+ // Check: Double close a File Descriptor could cause undefined behaviour.
+ // Conforming to man-pages
+ if (SS->isClosed()) {
+ ExplodedNode *N = C.GenerateSink();
+ if (N) {
+ if (!BT_doubleclose)
+ BT_doubleclose = new BuiltinBug("Double fclose",
+ "Try to close a file Descriptor already"
+ " closed. Cause undefined behaviour.");
+ BugReport *R = new BugReport(*BT_doubleclose,
+ BT_doubleclose->getDescription(), N);
+ C.EmitReport(R);
+ }
+ return NULL;
+ }
+
+ // Close the File Descriptor.
+ return state->set<StreamState>(Sym, StreamState::getClosed(CE));
+}
+
+void StreamChecker::EvalDeadSymbols(CheckerContext &C,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 StreamState *SS = state->get<StreamState>(Sym);
+ if (!SS)
+ return;
+
+ if (SS->isOpened()) {
+ ExplodedNode *N = C.GenerateSink();
+ if (N) {
+ if (!BT_ResourceLeak)
+ BT_ResourceLeak = new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak.");
+ BugReport *R = new BugReport(*BT_ResourceLeak,
+ BT_ResourceLeak->getDescription(), N);
+ C.EmitReport(R);
+ }
+ }
+ }
+}
+
+void StreamChecker::EvalEndPath(GREndPathNodeBuilder &B, void *tag,
+ GRExprEngine &Eng) {
+ SaveAndRestore<bool> OldHasGen(B.HasGeneratedNode);
+ const GRState *state = B.getState();
+ typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap;
+ SymMap M = state->get<StreamState>();
+
+ for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ StreamState SS = I->second;
+ if (SS.isOpened()) {
+ ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
+ if (N) {
+ if (!BT_ResourceLeak)
+ BT_ResourceLeak = new BuiltinBug("Resource Leak",
+ "Opened File never closed. Potential Resource leak.");
+ BugReport *R = new BugReport(*BT_ResourceLeak,
+ BT_ResourceLeak->getDescription(), N);
+ Eng.getBugReporter().EmitReport(R);
+ }
+ }
+ }
+}
+
+void StreamChecker::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 StreamState *SS = state->get<StreamState>(Sym);
+ if(!SS)
+ return;
+
+ if (SS->isOpened())
+ state = state->set<StreamState>(Sym, StreamState::getEscaped(S));
+
+ C.addTransition(state);
+}
diff --git a/lib/Checker/SymbolManager.cpp b/lib/Checker/SymbolManager.cpp
index c2b557ea57db..3b1bb6d98d95 100644
--- a/lib/Checker/SymbolManager.cpp
+++ b/lib/Checker/SymbolManager.cpp
@@ -28,22 +28,22 @@ static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) {
default:
assert(false && "operator printing not implemented");
break;
- case BinaryOperator::Mul: os << '*' ; break;
- case BinaryOperator::Div: os << '/' ; break;
- case BinaryOperator::Rem: os << '%' ; break;
- case BinaryOperator::Add: os << '+' ; break;
- case BinaryOperator::Sub: os << '-' ; break;
- case BinaryOperator::Shl: os << "<<" ; break;
- case BinaryOperator::Shr: os << ">>" ; break;
- case BinaryOperator::LT: os << "<" ; break;
- case BinaryOperator::GT: os << '>' ; break;
- case BinaryOperator::LE: os << "<=" ; break;
- case BinaryOperator::GE: os << ">=" ; break;
- case BinaryOperator::EQ: os << "==" ; break;
- case BinaryOperator::NE: os << "!=" ; break;
- case BinaryOperator::And: os << '&' ; break;
- case BinaryOperator::Xor: os << '^' ; break;
- case BinaryOperator::Or: os << '|' ; break;
+ case BO_Mul: os << '*' ; break;
+ case BO_Div: os << '/' ; break;
+ case BO_Rem: os << '%' ; break;
+ case BO_Add: os << '+' ; break;
+ case BO_Sub: os << '-' ; break;
+ case BO_Shl: os << "<<" ; break;
+ case BO_Shr: os << ">>" ; break;
+ case BO_LT: os << "<" ; break;
+ case BO_GT: os << '>' ; break;
+ case BO_LE: os << "<=" ; break;
+ case BO_GE: os << ">=" ; break;
+ case BO_EQ: os << "==" ; break;
+ case BO_NE: os << "!=" ; break;
+ case BO_And: os << '&' ; break;
+ case BO_Xor: os << '^' ; break;
+ case BO_Or: os << '|' ; break;
}
}
@@ -78,6 +78,11 @@ void SymbolExtent::dumpToStream(llvm::raw_ostream& os) const {
os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
}
+void SymbolMetadata::dumpToStream(llvm::raw_ostream& os) const {
+ os << "meta_$" << getSymbolID() << '{'
+ << getRegion() << ',' << T.getAsString() << '}';
+}
+
void SymbolRegionValue::dumpToStream(llvm::raw_ostream& os) const {
os << "reg_$" << getSymbolID() << "<" << R << ">";
}
@@ -150,6 +155,24 @@ SymbolManager::getExtentSymbol(const SubRegion *R) {
return cast<SymbolExtent>(SD);
}
+const SymbolMetadata*
+SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt* S, QualType T,
+ unsigned Count, const void* SymbolTag) {
+
+ llvm::FoldingSetNodeID profile;
+ SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
+ new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolMetadata>(SD);
+}
+
const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
BinaryOperator::Opcode op,
const llvm::APSInt& v,
@@ -191,21 +214,34 @@ QualType SymbolConjured::getType(ASTContext&) const {
}
QualType SymbolDerived::getType(ASTContext& Ctx) const {
- return R->getValueType(Ctx);
+ return R->getValueType();
}
QualType SymbolExtent::getType(ASTContext& Ctx) const {
return Ctx.getSizeType();
}
+QualType SymbolMetadata::getType(ASTContext&) const {
+ return T;
+}
+
QualType SymbolRegionValue::getType(ASTContext& C) const {
- return R->getValueType(C);
+ return R->getValueType();
}
SymbolManager::~SymbolManager() {}
bool SymbolManager::canSymbolicate(QualType T) {
- return Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType());
+ if (Loc::IsLocType(T))
+ return true;
+
+ if (T->isIntegerType())
+ return T->isScalarType();
+
+ if (T->isRecordType())
+ return true;
+
+ return false;
}
void SymbolReaper::markLive(SymbolRef sym) {
@@ -213,6 +249,11 @@ void SymbolReaper::markLive(SymbolRef sym) {
TheDead.erase(sym);
}
+void SymbolReaper::markInUse(SymbolRef sym) {
+ if (isa<SymbolMetadata>(sym))
+ MetadataInUse.insert(sym);
+}
+
bool SymbolReaper::maybeDead(SymbolRef sym) {
if (isLive(sym))
return false;
@@ -221,6 +262,31 @@ bool SymbolReaper::maybeDead(SymbolRef sym) {
return true;
}
+static bool IsLiveRegion(SymbolReaper &Reaper, const MemRegion *MR) {
+ MR = MR->getBaseRegion();
+
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ return Reaper.isLive(SR->getSymbol());
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
+ return Reaper.isLive(VR);
+
+ // FIXME: This is a gross over-approximation. What we really need is a way to
+ // tell if anything still refers to this region. Unlike SymbolicRegions,
+ // AllocaRegions don't have associated symbols, though, so we don't actually
+ // have a way to track their liveness.
+ if (isa<AllocaRegion>(MR))
+ return true;
+
+ if (isa<CXXThisRegion>(MR))
+ return true;
+
+ if (isa<MemSpaceRegion>(MR))
+ return true;
+
+ return false;
+}
+
bool SymbolReaper::isLive(SymbolRef sym) {
if (TheLiving.count(sym))
return true;
@@ -234,11 +300,21 @@ bool SymbolReaper::isLive(SymbolRef sym) {
}
if (const SymbolExtent *extent = dyn_cast<SymbolExtent>(sym)) {
- const MemRegion *Base = extent->getRegion()->getBaseRegion();
- if (const VarRegion *VR = dyn_cast<VarRegion>(Base))
- return isLive(VR);
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Base))
- return isLive(SR->getSymbol());
+ if (IsLiveRegion(*this, extent->getRegion())) {
+ markLive(sym);
+ return true;
+ }
+ return false;
+ }
+
+ if (const SymbolMetadata *metadata = dyn_cast<SymbolMetadata>(sym)) {
+ if (MetadataInUse.count(sym)) {
+ if (IsLiveRegion(*this, metadata->getRegion())) {
+ markLive(sym);
+ MetadataInUse.erase(sym);
+ return true;
+ }
+ }
return false;
}
@@ -248,16 +324,19 @@ bool SymbolReaper::isLive(SymbolRef sym) {
}
bool SymbolReaper::isLive(const Stmt* ExprVal) const {
- return LCtx->getLiveVariables()->isLive(Loc, ExprVal);
+ return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+ isLive(Loc, ExprVal);
}
bool SymbolReaper::isLive(const VarRegion *VR) const {
- const StackFrameContext *SFC = VR->getStackFrame();
+ const StackFrameContext *VarContext = VR->getStackFrame();
+ const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
+
+ if (VarContext == CurrentContext)
+ return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+ isLive(Loc, VR->getDecl());
- if (SFC == LCtx->getCurrentStackFrame())
- return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl());
- else
- return SFC->isParentOf(LCtx->getCurrentStackFrame());
+ return VarContext->isParentOf(CurrentContext);
}
SymbolVisitor::~SymbolVisitor() {}
diff --git a/lib/Checker/UndefBranchChecker.cpp b/lib/Checker/UndefBranchChecker.cpp
index 90883456b17c..1ff0641be5df 100644
--- a/lib/Checker/UndefBranchChecker.cpp
+++ b/lib/Checker/UndefBranchChecker.cpp
@@ -29,27 +29,28 @@ class UndefBranchChecker : public Checker {
FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
- Expr* FindExpr(Expr* Ex) {
+ const Expr* FindExpr(const Expr* Ex) {
if (!MatchesCriteria(Ex))
return 0;
- for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
- if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
- Expr* E2 = FindExpr(ExI);
+ for (Stmt::const_child_iterator I = Ex->child_begin(),
+ E = Ex->child_end();I!=E;++I)
+ if (const Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
+ const Expr* E2 = FindExpr(ExI);
if (E2) return E2;
}
return Ex;
}
- bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
+ bool MatchesCriteria(const Expr* Ex) { return St->getSVal(Ex).isUndef(); }
};
public:
UndefBranchChecker() : BT(0) {}
static void *getTag();
void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng,
- Stmt *Condition, void *tag);
+ const Stmt *Condition, void *tag);
};
}
@@ -65,7 +66,7 @@ void *UndefBranchChecker::getTag() {
void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder,
GRExprEngine &Eng,
- Stmt *Condition, void *tag) {
+ const Stmt *Condition, void *tag){
const GRState *state = Builder.getState();
SVal X = state->getSVal(Condition);
if (X.isUndef()) {
@@ -81,7 +82,7 @@ void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder,
// subexpressions and roughly look for the most nested subexpression
// that binds to Undefined. We then highlight that expression's range.
BlockEdge B = cast<BlockEdge>(N->getLocation());
- Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
+ const Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
assert (Ex && "Block must have a terminator.");
// Get the predecessor node and check if is a PostStmt with the Stmt
diff --git a/lib/Checker/UndefinedAssignmentChecker.cpp b/lib/Checker/UndefinedAssignmentChecker.cpp
index 6cef60eaee29..ccc97489e631 100644
--- a/lib/Checker/UndefinedAssignmentChecker.cpp
+++ b/lib/Checker/UndefinedAssignmentChecker.cpp
@@ -25,9 +25,8 @@ class UndefinedAssignmentChecker
public:
UndefinedAssignmentChecker() : BT(0) {}
static void *getTag();
- virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
- const Stmt *StoreE, SVal location,
- SVal val);
+ virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+ SVal location, SVal val);
};
}
@@ -41,7 +40,6 @@ void *UndefinedAssignmentChecker::getTag() {
}
void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
- const Stmt *AssignE,
const Stmt *StoreE,
SVal location,
SVal val) {
@@ -61,8 +59,8 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
// Generate a report for this bug.
const Expr *ex = 0;
- while (AssignE) {
- if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE)) {
+ while (StoreE) {
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
if (B->isCompoundAssignmentOp()) {
const GRState *state = C.getState();
if (state->getSVal(B->getLHS()).isUndef()) {
@@ -77,7 +75,7 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
break;
}
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
ex = VD->getInit();
}
diff --git a/lib/Checker/UnixAPIChecker.cpp b/lib/Checker/UnixAPIChecker.cpp
index e9b8f0966ae1..de7346d6273a 100644
--- a/lib/Checker/UnixAPIChecker.cpp
+++ b/lib/Checker/UnixAPIChecker.cpp
@@ -100,7 +100,7 @@ static void CheckOpen(CheckerContext &C, UnixAPIChecker &UC,
NonLoc ocreateFlag =
cast<NonLoc>(C.getValueManager().makeIntVal(UC.Val_O_CREAT.getValue(),
oflagsEx->getType()));
- SVal maskedFlagsUC = C.getSValuator().EvalBinOpNN(state, BinaryOperator::And,
+ SVal maskedFlagsUC = C.getSValuator().EvalBinOpNN(state, BO_And,
oflags, ocreateFlag,
oflagsEx->getType());
if (maskedFlagsUC.isUnknownOrUndef())
diff --git a/lib/Checker/UnreachableCodeChecker.cpp b/lib/Checker/UnreachableCodeChecker.cpp
new file mode 100644
index 000000000000..7a56c7f46b48
--- /dev/null
+++ b/lib/Checker/UnreachableCodeChecker.cpp
@@ -0,0 +1,226 @@
+//==- UnreachableCodeChecker.cpp - Generalized dead code 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 implements a generalized unreachable code checker using a
+// path-sensitive analysis. We mark any path visited, and then walk the CFG as a
+// post-analysis to determine what was never visited.
+//
+// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ParentMap.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/ExplodedGraph.h"
+#include "clang/Checker/PathSensitive/SVals.h"
+#include "clang/Checker/PathSensitive/CheckerHelpers.h"
+#include "clang/Checker/BugReporter/BugReporter.h"
+#include "GRExprEngineExperimentalChecks.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+// The number of CFGBlock pointers we want to reserve memory for. This is used
+// once for each function we analyze.
+#define DEFAULT_CFGBLOCKS 256
+
+using namespace clang;
+
+namespace {
+class UnreachableCodeChecker : public CheckerVisitor<UnreachableCodeChecker> {
+public:
+ static void *getTag();
+ void VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &B,
+ GRExprEngine &Eng);
+private:
+ static inline const Stmt *getUnreachableStmt(const CFGBlock *CB);
+ void FindUnreachableEntryPoints(const CFGBlock *CB);
+ static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM);
+ static inline bool isEmptyCFGBlock(const CFGBlock *CB);
+
+ llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> reachable;
+ llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> visited;
+};
+}
+
+void *UnreachableCodeChecker::getTag() {
+ static int x = 0;
+ return &x;
+}
+
+void clang::RegisterUnreachableCodeChecker(GRExprEngine &Eng) {
+ Eng.registerCheck(new UnreachableCodeChecker());
+}
+
+void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
+ BugReporter &B,
+ GRExprEngine &Eng) {
+ // Bail out if we didn't cover all paths
+ if (Eng.hasWorkRemaining())
+ return;
+
+ CFG *C = 0;
+ ParentMap *PM = 0;
+ // Iterate over ExplodedGraph
+ for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end();
+ I != E; ++I) {
+ const ProgramPoint &P = I->getLocation();
+ const LocationContext *LC = P.getLocationContext();
+
+ // Save the CFG if we don't have it already
+ if (!C)
+ C = LC->getAnalysisContext()->getUnoptimizedCFG();
+ if (!PM)
+ PM = &LC->getParentMap();
+
+ if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) {
+ const CFGBlock *CB = BE->getBlock();
+ reachable.insert(CB->getBlockID());
+ }
+ }
+
+ // Bail out if we didn't get the CFG or the ParentMap.
+ if (!C || !PM)
+ return;
+
+ ASTContext &Ctx = B.getContext();
+
+ // Find CFGBlocks that were not covered by any node
+ for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
+ const CFGBlock *CB = *I;
+ // Check if the block is unreachable
+ if (reachable.count(CB->getBlockID()))
+ continue;
+
+ // Check if the block is empty (an artificial block)
+ if (isEmptyCFGBlock(CB))
+ continue;
+
+ // Find the entry points for this block
+ FindUnreachableEntryPoints(CB);
+
+ // This block may have been pruned; check if we still want to report it
+ if (reachable.count(CB->getBlockID()))
+ continue;
+
+ // Check for false positives
+ if (CB->size() > 0 && isInvalidPath(CB, *PM))
+ continue;
+
+ // Special case for __builtin_unreachable.
+ // FIXME: This should be extended to include other unreachable markers,
+ // such as llvm_unreachable.
+ if (!CB->empty()) {
+ const Stmt *First = CB->front();
+ if (const CallExpr *CE = dyn_cast<CallExpr>(First)) {
+ if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
+ continue;
+ }
+ }
+
+ // We found a block that wasn't covered - find the statement to report
+ SourceRange SR;
+ SourceLocation SL;
+ if (const Stmt *S = getUnreachableStmt(CB)) {
+ SR = S->getSourceRange();
+ SL = S->getLocStart();
+ if (SR.isInvalid() || SL.isInvalid())
+ continue;
+ }
+ else
+ continue;
+
+ // Check if the SourceLocation is in a system header
+ const SourceManager &SM = B.getSourceManager();
+ if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL))
+ continue;
+
+ B.EmitBasicReport("Unreachable code", "Dead code", "This statement is never"
+ " executed", SL, SR);
+ }
+}
+
+// Recursively finds the entry point(s) for this dead CFGBlock.
+void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB) {
+ bool allPredecessorsReachable = true;
+
+ visited.insert(CB->getBlockID());
+
+ for (CFGBlock::const_pred_iterator I = CB->pred_begin(); I != CB->pred_end();
+ ++I) {
+ // Recurse over all unreachable blocks
+ if (!reachable.count((*I)->getBlockID())) {
+ // At least one predeccessor was unreachable
+ allPredecessorsReachable = false;
+
+ // Only visit the block once
+ if (!visited.count((*I)->getBlockID()))
+ FindUnreachableEntryPoints(*I);
+ }
+ }
+
+ // If at least one predecessor is unreachable, mark this block as reachable
+ // so we don't report this block.
+ if (!allPredecessorsReachable) {
+ reachable.insert(CB->getBlockID());
+ }
+}
+
+// Find the Stmt* in a CFGBlock for reporting a warning
+const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) {
+ if (CB->size() > 0)
+ return CB->front().getStmt();
+ else if (const Stmt *S = CB->getTerminator())
+ return S;
+ else
+ return 0;
+}
+
+// Determines if the path to this CFGBlock contained an element that infers this
+// block is a false positive. We assume that FindUnreachableEntryPoints has
+// already marked only the entry points to any dead code, so we need only to
+// find the condition that led to this block (the predecessor of this block.)
+// There will never be more than one predecessor.
+bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB,
+ const ParentMap &PM) {
+ // We only expect a predecessor size of 0 or 1. If it is >1, then an external
+ // condition has broken our assumption (for example, a sink being placed by
+ // another check). In these cases, we choose not to report.
+ if (CB->pred_size() > 1)
+ return true;
+
+ // If there are no predecessors, then this block is trivially unreachable
+ if (CB->pred_size() == 0)
+ return false;
+
+ const CFGBlock *pred = *CB->pred_begin();
+
+ // Get the predecessor block's terminator conditon
+ const Stmt *cond = pred->getTerminatorCondition();
+
+ //assert(cond && "CFGBlock's predecessor has a terminator condition");
+ // The previous assertion is invalid in some cases (eg do/while). Leaving
+ // reporting of these situations on at the moment to help triage these cases.
+ if (!cond)
+ return false;
+
+ // Run each of the checks on the conditions
+ if (containsMacro(cond) || containsEnum(cond)
+ || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond)
+ || containsStmt<SizeOfAlignOfExpr>(cond))
+ return true;
+
+ return false;
+}
+
+// Returns true if the given CFGBlock is empty
+bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) {
+ return CB->getLabel() == 0 // No labels
+ && CB->size() == 0 // No statements
+ && CB->getTerminator() == 0; // No terminator
+}
diff --git a/lib/Checker/VLASizeChecker.cpp b/lib/Checker/VLASizeChecker.cpp
index 936991d6133c..0800b8be1881 100644
--- a/lib/Checker/VLASizeChecker.cpp
+++ b/lib/Checker/VLASizeChecker.cpp
@@ -117,7 +117,7 @@ void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
SVal EleSizeVal = ValMgr.makeIntVal(EleSize.getQuantity(), SizeTy);
// Multiply the array length by the element size.
- SVal ArraySizeVal = SV.EvalBinOpNN(state, BinaryOperator::Mul, ArrayLength,
+ SVal ArraySizeVal = SV.EvalBinOpNN(state, BO_Mul, ArrayLength,
cast<NonLoc>(EleSizeVal), SizeTy);
// Finally, Assume that the array's extent matches the given size.
diff --git a/lib/Checker/ValueManager.cpp b/lib/Checker/ValueManager.cpp
index aa0c3c877dde..8b7cd7bbdb68 100644
--- a/lib/Checker/ValueManager.cpp
+++ b/lib/Checker/ValueManager.cpp
@@ -72,7 +72,7 @@ SVal ValueManager::convertToArrayIndex(SVal V) {
DefinedOrUnknownSVal
ValueManager::getRegionValueSymbolVal(const TypedRegion* R) {
- QualType T = R->getValueType(SymMgr.getContext());
+ QualType T = R->getValueType();
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
@@ -117,11 +117,24 @@ DefinedOrUnknownSVal ValueManager::getConjuredSymbolVal(const void *SymbolTag,
return nonloc::SymbolVal(sym);
}
+DefinedSVal ValueManager::getMetadataSymbolVal(const void *SymbolTag,
+ const MemRegion *MR,
+ const Expr *E, QualType T,
+ unsigned Count) {
+ assert(SymbolManager::canSymbolicate(T) && "Invalid metadata symbol type");
+
+ SymbolRef sym = SymMgr.getMetadataSymbol(MR, E, T, Count, SymbolTag);
+
+ if (Loc::IsLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ return nonloc::SymbolVal(sym);
+}
DefinedOrUnknownSVal
ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
const TypedRegion *R) {
- QualType T = R->getValueType(R->getContext());
+ QualType T = R->getValueType();
if (!SymbolManager::canSymbolicate(T))
return UnknownVal();
diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h
index 85524acbe1f7..91b7742557f5 100644
--- a/lib/CodeGen/ABIInfo.h
+++ b/lib/CodeGen/ABIInfo.h
@@ -16,52 +16,52 @@
namespace llvm {
class Value;
class LLVMContext;
+ class TargetData;
}
namespace clang {
class ASTContext;
- // FIXME: This is a layering issue if we want to move ABIInfo
- // down. Fortunately CGFunctionInfo has no real tie to CodeGen.
namespace CodeGen {
class CGFunctionInfo;
class CodeGenFunction;
+ class CodeGenTypes;
}
- /* FIXME: All of this stuff should be part of the target interface
- somehow. It is currently here because it is not clear how to factor
- the targets to support this, since the Targets currently live in a
- layer below types n'stuff.
- */
+ // FIXME: All of this stuff should be part of the target interface
+ // somehow. It is currently here because it is not clear how to factor
+ // the targets to support this, since the Targets currently live in a
+ // layer below types n'stuff.
/// ABIArgInfo - Helper class to encapsulate information about how a
/// specific C type should be passed to or returned from a function.
class ABIArgInfo {
public:
enum Kind {
- Direct, /// Pass the argument directly using the normal
- /// converted LLVM type. Complex and structure types
- /// are passed using first class aggregates.
-
- Extend, /// Valid only for integer argument types. Same as 'direct'
- /// but also emit a zero/sign extension attribute.
-
- Indirect, /// Pass the argument indirectly via a hidden pointer
- /// with the specified alignment (0 indicates default
- /// alignment).
-
- Ignore, /// Ignore the argument (treat as void). Useful for
- /// void and empty structs.
-
- Coerce, /// Only valid for aggregate return types, the argument
- /// should be accessed by coercion to a provided type.
-
- Expand, /// Only valid for aggregate argument types. The
- /// structure should be expanded into consecutive
- /// arguments for its constituent fields. Currently
- /// expand is only allowed on structures whose fields
- /// are all scalar types or are themselves expandable
- /// types.
+ /// Direct - Pass the argument directly using the normal converted LLVM
+ /// type, or by coercing to another specified type stored in
+ /// 'CoerceToType'). If an offset is specified (in UIntData), then the
+ /// argument passed is offset by some number of bytes in the memory
+ /// representation.
+ Direct,
+
+ /// Extend - Valid only for integer argument types. Same as 'direct'
+ /// but also emit a zero/sign extension attribute.
+ Extend,
+
+ /// Indirect - Pass the argument indirectly via a hidden pointer
+ /// with the specified alignment (0 indicates default alignment).
+ Indirect,
+
+ /// Ignore - Ignore the argument (treat as void). Useful for void and
+ /// empty structs.
+ Ignore,
+
+ /// Expand - Only valid for aggregate argument types. The structure should
+ /// be expanded into consecutive arguments for its constituent fields.
+ /// Currently expand is only allowed on structures whose fields
+ /// are all scalar types or are themselves expandable types.
+ Expand,
KindFirst=Direct, KindLast=Expand
};
@@ -79,18 +79,15 @@ namespace clang {
public:
ABIArgInfo() : TheKind(Direct), TypeData(0), UIntData(0) {}
- static ABIArgInfo getDirect() {
- return ABIArgInfo(Direct);
+ static ABIArgInfo getDirect(const llvm::Type *T = 0, unsigned Offset = 0) {
+ return ABIArgInfo(Direct, T, Offset);
}
- static ABIArgInfo getExtend() {
- return ABIArgInfo(Extend);
+ static ABIArgInfo getExtend(const llvm::Type *T = 0) {
+ return ABIArgInfo(Extend, T, 0);
}
static ABIArgInfo getIgnore() {
return ABIArgInfo(Ignore);
}
- static ABIArgInfo getCoerce(const llvm::Type *T) {
- return ABIArgInfo(Coerce, T);
- }
static ABIArgInfo getIndirect(unsigned Alignment, bool ByVal = true) {
return ABIArgInfo(Indirect, 0, Alignment, ByVal);
}
@@ -102,16 +99,28 @@ namespace clang {
bool isDirect() const { return TheKind == Direct; }
bool isExtend() const { return TheKind == Extend; }
bool isIgnore() const { return TheKind == Ignore; }
- bool isCoerce() const { return TheKind == Coerce; }
bool isIndirect() const { return TheKind == Indirect; }
bool isExpand() const { return TheKind == Expand; }
- // Coerce accessors
+ bool canHaveCoerceToType() const {
+ return TheKind == Direct || TheKind == Extend;
+ }
+
+ // Direct/Extend accessors
+ unsigned getDirectOffset() const {
+ assert((isDirect() || isExtend()) && "Not a direct or extend kind");
+ return UIntData;
+ }
const llvm::Type *getCoerceToType() const {
- assert(TheKind == Coerce && "Invalid kind!");
+ assert(canHaveCoerceToType() && "Invalid kind!");
return TypeData;
}
-
+
+ void setCoerceToType(const llvm::Type *T) {
+ assert(canHaveCoerceToType() && "Invalid kind!");
+ TypeData = T;
+ }
+
// Indirect accessors
unsigned getIndirectAlign() const {
assert(TheKind == Indirect && "Invalid kind!");
@@ -130,15 +139,16 @@ namespace clang {
/// passed or returned from functions.
class ABIInfo {
public:
+ CodeGen::CodeGenTypes &CGT;
+
+ ABIInfo(CodeGen::CodeGenTypes &cgt) : CGT(cgt) {}
virtual ~ABIInfo();
+
+ ASTContext &getContext() const;
+ llvm::LLVMContext &getVMContext() const;
+ const llvm::TargetData &getTargetData() const;
- virtual void computeInfo(CodeGen::CGFunctionInfo &FI,
- ASTContext &Ctx,
- llvm::LLVMContext &VMContext,
- // This is the preferred type for argument lowering
- // which can be used to generate better IR.
- const llvm::Type *const *PrefTypes = 0,
- unsigned NumPrefTypes = 0) const = 0;
+ virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;
/// EmitVAArg - Emit the target dependent code to load a value of
/// \arg Ty from the va_list pointed to by \arg VAListAddr.
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index cb9e63622185..04f1ef24b297 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -24,36 +24,6 @@
using namespace clang;
using namespace CodeGen;
-/// CGBlockInfo - Information to generate a block literal.
-class clang::CodeGen::CGBlockInfo {
-public:
- /// Name - The name of the block, kindof.
- const char *Name;
-
- /// DeclRefs - Variables from parent scopes that have been
- /// imported into this block.
- llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
-
- /// InnerBlocks - This block and the blocks it encloses.
- llvm::SmallPtrSet<const DeclContext *, 4> InnerBlocks;
-
- /// CXXThisRef - Non-null if 'this' was required somewhere, in
- /// which case this is that expression.
- const CXXThisExpr *CXXThisRef;
-
- /// NeedsObjCSelf - True if something in this block has an implicit
- /// reference to 'self'.
- bool NeedsObjCSelf;
-
- /// These are initialized by GenerateBlockFunction.
- bool BlockHasCopyDispose;
- CharUnits BlockSize;
- CharUnits BlockAlign;
- llvm::SmallVector<const Expr*, 8> BlockLayout;
-
- CGBlockInfo(const char *Name);
-};
-
CGBlockInfo::CGBlockInfo(const char *N)
: Name(N), CXXThisRef(0), NeedsObjCSelf(false) {
@@ -64,9 +34,12 @@ CGBlockInfo::CGBlockInfo(const char *N)
llvm::Constant *CodeGenFunction::
-BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size,
+BuildDescriptorBlockDecl(const BlockExpr *BE, const CGBlockInfo &Info,
const llvm::StructType* Ty,
+ llvm::Constant *BlockVarLayout,
std::vector<HelperInfo> *NoteForHelper) {
+ bool BlockHasCopyDispose = Info.BlockHasCopyDispose;
+ CharUnits Size = Info.BlockSize;
const llvm::Type *UnsignedLongTy
= CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
llvm::Constant *C;
@@ -100,7 +73,8 @@ BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnit
CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty));
// Layout.
- C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+ C = BlockVarLayout;
+
Elts.push_back(C);
C = llvm::ConstantStruct::get(VMContext, Elts, false);
@@ -111,20 +85,6 @@ BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnit
return C;
}
-llvm::Constant *BlockModule::getNSConcreteGlobalBlock() {
- if (NSConcreteGlobalBlock == 0)
- NSConcreteGlobalBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty,
- "_NSConcreteGlobalBlock");
- return NSConcreteGlobalBlock;
-}
-
-llvm::Constant *BlockModule::getNSConcreteStackBlock() {
- if (NSConcreteStackBlock == 0)
- NSConcreteStackBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty,
- "_NSConcreteStackBlock");
- return NSConcreteStackBlock;
-}
-
static void CollectBlockDeclRefInfo(const Stmt *S, CGBlockInfo &Info) {
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
I != E; ++I)
@@ -198,6 +158,21 @@ static void AllocateAllBlockDeclRefs(CodeGenFunction &CGF, CGBlockInfo &Info) {
}
}
+static unsigned computeBlockFlag(CodeGenModule &CGM,
+ const BlockExpr *BE, unsigned flags) {
+ QualType BPT = BE->getType();
+ const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
+ QualType ResultType = ftype->getResultType();
+
+ CallArgList Args;
+ CodeGenTypes &Types = CGM.getTypes();
+ const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args,
+ FunctionType::ExtInfo());
+ if (CGM.ReturnTypeUsesSRet(FnInfo))
+ flags |= CodeGenFunction::BLOCK_USE_STRET;
+ return flags;
+}
+
// FIXME: Push most into CGM, passing down a few bits, like current function
// name.
llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
@@ -221,6 +196,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
llvm::Value *V;
{
+ llvm::Constant *BlockVarLayout;
// C = BuildBlockStructInitlist();
unsigned int flags = BLOCK_HAS_SIGNATURE;
@@ -229,6 +205,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
// __invoke
llvm::Function *Fn
= CodeGenFunction(CGM).GenerateBlockFunction(CurGD, BE, Info, CurFuncDecl,
+ BlockVarLayout,
LocalDeclMap);
BlockHasCopyDispose |= Info.BlockHasCopyDispose;
Elts[3] = Fn;
@@ -244,18 +221,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
Elts[0] = C;
// __flags
- {
- QualType BPT = BE->getType();
- const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
- QualType ResultType = ftype->getResultType();
-
- CallArgList Args;
- CodeGenTypes &Types = CGM.getTypes();
- const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args,
- FunctionType::ExtInfo());
- if (CGM.ReturnTypeUsesSRet(FnInfo))
- flags |= BLOCK_USE_STRET;
- }
+ flags = computeBlockFlag(CGM, BE, flags);
const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
CGM.getTypes().ConvertType(CGM.getContext().IntTy));
C = llvm::ConstantInt::get(IntTy, flags);
@@ -267,8 +233,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (Info.BlockLayout.empty()) {
// __descriptor
- Elts[4] = BuildDescriptorBlockDecl(BE, Info.BlockHasCopyDispose,
- Info.BlockSize, 0, 0);
+ C = llvm::Constant::getNullValue(PtrToInt8Ty);
+ Elts[4] = BuildDescriptorBlockDecl(BE, Info, 0, C, 0);
// Optimize to being a global block.
Elts[0] = CGM.getNSConcreteGlobalBlock();
@@ -371,7 +337,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
SourceLocation());
if (VD->getType()->isReferenceType()) {
E = new (getContext())
- UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf,
+ UnaryOperator(const_cast<Expr*>(E), UO_AddrOf,
getContext().getPointerType(E->getType()),
SourceLocation());
}
@@ -381,7 +347,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (BDRE->isByRef()) {
E = new (getContext())
- UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf,
+ UnaryOperator(const_cast<Expr*>(E), UO_AddrOf,
getContext().getPointerType(E->getType()),
SourceLocation());
}
@@ -422,9 +388,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
NoteForHelper.resize(NumHelpers);
// __descriptor
- llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE,
- Info.BlockHasCopyDispose,
- Info.BlockSize, Ty,
+ llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE, Info, Ty,
+ BlockVarLayout,
&NoteForHelper);
Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
@@ -693,18 +658,23 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
std::vector<llvm::Constant*> LiteralFields(FieldCount);
CGBlockInfo Info(n);
+ llvm::Constant *BlockVarLayout;
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
llvm::Function *Fn
- = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE, Info, 0, LocalDeclMap);
+ = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE,
+ Info, 0, BlockVarLayout,
+ LocalDeclMap);
assert(Info.BlockSize == BlockLiteralSize
&& "no imports allowed for global block");
// isa
- LiteralFields[0] = getNSConcreteGlobalBlock();
+ LiteralFields[0] = CGM.getNSConcreteGlobalBlock();
- // Flags
+ // __flags
+ unsigned flags = computeBlockFlag(CGM, BE,
+ (BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE));
LiteralFields[1] =
- llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE);
+ llvm::ConstantInt::get(IntTy, flags);
// Reserved
LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
@@ -737,6 +707,7 @@ llvm::Function *
CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
CGBlockInfo &Info,
const Decl *OuterFuncDecl,
+ llvm::Constant *& BlockVarLayout,
llvm::DenseMap<const Decl*, llvm::Value*> ldm) {
// Check if we should generate debug info for this block.
@@ -751,7 +722,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
++i) {
const VarDecl *VD = dyn_cast<VarDecl>(i->first);
- if (VD->getStorageClass() == VarDecl::Static || VD->hasExternalStorage())
+ if (VD->getStorageClass() == SC_Static || VD->hasExternalStorage())
LocalDeclMap[VD] = i->second;
}
@@ -784,6 +755,12 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
// Build the block struct now.
AllocateAllBlockDeclRefs(*this, Info);
+ // Capture block layout info. here.
+ if (CGM.getContext().getLangOptions().ObjC1)
+ BlockVarLayout = CGM.getObjCRuntime().GCBlockLayout(*this, Info.DeclRefs);
+ else
+ BlockVarLayout = llvm::Constant::getNullValue(PtrToInt8Ty);
+
QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
BlockLayout);
@@ -813,7 +790,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
Name.getString(), &CGM.getModule());
CGM.SetInternalFunctionAttributes(BD, Fn, FI);
-
+ StartFunction(BD, ResultType, Fn, Args,
+ BExpr->getBody()->getLocEnd());
+
+ CurFuncDecl = OuterFuncDecl;
+
QualType FnType(BlockFunctionType, 0);
bool HasPrototype = isa<FunctionProtoType>(BlockFunctionType);
@@ -822,15 +803,22 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
getContext().getTranslationUnitDecl(),
SourceLocation(), ID, FnType,
0,
- FunctionDecl::Static,
- FunctionDecl::None,
+ SC_Static,
+ SC_None,
false, HasPrototype);
+ if (FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FnType)) {
+ const FunctionDecl *CFD = dyn_cast<FunctionDecl>(CurCodeDecl);
+ FunctionDecl *FD = const_cast<FunctionDecl *>(CFD);
+ llvm::SmallVector<ParmVarDecl*, 16> Params;
+ for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
+ Params.push_back(ParmVarDecl::Create(getContext(), FD,
+ SourceLocation(), 0,
+ FT->getArgType(i), /*TInfo=*/0,
+ SC_None, SC_None, 0));
+ FD->setParams(Params.data(), Params.size());
+ }
+
- StartFunction(BD, ResultType, Fn, Args,
- BExpr->getBody()->getLocEnd());
-
- CurFuncDecl = OuterFuncDecl;
-
// If we have a C++ 'this' reference, go ahead and force it into
// existence now.
if (Info.CXXThisRef) {
@@ -928,7 +916,7 @@ CharUnits BlockFunction::getBlockOffset(CharUnits Size, CharUnits Align) {
getContext().getTranslationUnitDecl(),
SourceLocation(),
0, QualType(PadTy), 0,
- VarDecl::None, VarDecl::None);
+ SC_None, SC_None);
Expr *E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(),
SourceLocation());
BlockLayout.push_back(E);
@@ -974,8 +962,8 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
SourceLocation(), II, R, 0,
- FunctionDecl::Static,
- FunctionDecl::None,
+ SC_Static,
+ SC_None,
false,
true);
CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
@@ -1012,7 +1000,7 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty);
llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
- llvm::Value *F = getBlockObjectAssign();
+ llvm::Value *F = CGM.getBlockObjectAssign();
Builder.CreateCall3(F, Dstv, Srcv, N);
}
}
@@ -1056,8 +1044,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
SourceLocation(), II, R, 0,
- FunctionDecl::Static,
- FunctionDecl::None,
+ SC_Static,
+ SC_None,
false, true);
CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
@@ -1141,8 +1129,8 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
SourceLocation(), II, R, 0,
- FunctionDecl::Static,
- FunctionDecl::None,
+ SC_Static,
+ SC_None,
false, true);
CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
@@ -1164,7 +1152,7 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
flag |= BLOCK_BYREF_CALLER;
llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
- llvm::Value *F = getBlockObjectAssign();
+ llvm::Value *F = CGM.getBlockObjectAssign();
Builder.CreateCall3(F, DstObj, SrcObj, N);
CGF.FinishFunction();
@@ -1205,8 +1193,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
SourceLocation(), II, R, 0,
- FunctionDecl::Static,
- FunctionDecl::None,
+ SC_Static,
+ SC_None,
false, true);
CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
@@ -1259,37 +1247,8 @@ llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag);
}
-llvm::Value *BlockFunction::getBlockObjectDispose() {
- if (CGM.BlockObjectDispose == 0) {
- const llvm::FunctionType *FTy;
- std::vector<const llvm::Type*> ArgTys;
- const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
- ArgTys.push_back(PtrToInt8Ty);
- ArgTys.push_back(CGF.Int32Ty);
- FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
- CGM.BlockObjectDispose
- = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
- }
- return CGM.BlockObjectDispose;
-}
-
-llvm::Value *BlockFunction::getBlockObjectAssign() {
- if (CGM.BlockObjectAssign == 0) {
- const llvm::FunctionType *FTy;
- std::vector<const llvm::Type*> ArgTys;
- const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
- ArgTys.push_back(PtrToInt8Ty);
- ArgTys.push_back(PtrToInt8Ty);
- ArgTys.push_back(CGF.Int32Ty);
- FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
- CGM.BlockObjectAssign
- = CGM.CreateRuntimeFunction(FTy, "_Block_object_assign");
- }
- return CGM.BlockObjectAssign;
-}
-
void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) {
- llvm::Value *F = getBlockObjectDispose();
+ llvm::Value *F = CGM.getBlockObjectDispose();
llvm::Value *N;
V = Builder.CreateBitCast(V, PtrToInt8Ty);
N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 772a62c24f1f..743e3c83be33 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -73,8 +73,6 @@ class BlockModule : public BlockBase {
CodeGenTypes &getTypes() { return Types; }
const llvm::TargetData &getTargetData() const { return TheTargetData; }
public:
- llvm::Constant *getNSConcreteGlobalBlock();
- llvm::Constant *getNSConcreteStackBlock();
int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
const llvm::Type *getBlockDescriptorType();
@@ -82,14 +80,6 @@ public:
llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
- /// NSConcreteGlobalBlock - Cached reference to the class pointer for global
- /// blocks.
- llvm::Constant *NSConcreteGlobalBlock;
-
- /// NSConcreteStackBlock - Cached reference to the class poinnter for stack
- /// blocks.
- llvm::Constant *NSConcreteStackBlock;
-
const llvm::Type *BlockDescriptorType;
const llvm::Type *GenericBlockLiteralType;
@@ -97,8 +87,6 @@ public:
int GlobalUniqueCount;
} Block;
- llvm::Value *BlockObjectAssign;
- llvm::Value *BlockObjectDispose;
const llvm::PointerType *PtrToInt8Ty;
std::map<uint64_t, llvm::Constant *> AssignCache;
@@ -108,9 +96,7 @@ public:
CodeGenTypes &T, CodeGenModule &CodeGen)
: Context(C), TheModule(M), TheTargetData(TD), Types(T),
CGM(CodeGen), VMContext(M.getContext()),
- NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
- GenericBlockLiteralType(0),
- BlockObjectAssign(0), BlockObjectDispose(0) {
+ BlockDescriptorType(0), GenericBlockLiteralType(0) {
Block.GlobalUniqueCount = 0;
PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());
}
@@ -207,8 +193,6 @@ public:
llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
unsigned Align);
- llvm::Value *getBlockObjectAssign();
- llvm::Value *getBlockObjectDispose();
void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
bool BlockRequiresCopying(QualType Ty)
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index fff4bacab6b5..986f621f64f5 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -41,6 +41,31 @@ static void EmitMemoryBarrier(CodeGenFunction &CGF,
C, C + 5);
}
+static Value *EmitCastToInt(CodeGenFunction &CGF,
+ const llvm::Type *ToType, Value *Val) {
+ if (Val->getType()->isPointerTy()) {
+ return CGF.Builder.CreatePtrToInt(Val, ToType);
+ }
+ assert(Val->getType()->isIntegerTy() &&
+ "Used a non-integer and non-pointer type with atomic builtin");
+ assert(Val->getType()->getScalarSizeInBits() <=
+ ToType->getScalarSizeInBits() && "Integer type too small");
+ return CGF.Builder.CreateSExtOrBitCast(Val, ToType);
+}
+
+static Value *EmitCastFromInt(CodeGenFunction &CGF, QualType ToQualType,
+ Value *Val) {
+ const llvm::Type *ToType = CGF.ConvertType(ToQualType);
+ if (ToType->isPointerTy()) {
+ return CGF.Builder.CreateIntToPtr(Val, ToType);
+ }
+ assert(Val->getType()->isIntegerTy() &&
+ "Used a non-integer and non-pointer type with atomic builtin");
+ assert(Val->getType()->getScalarSizeInBits() >=
+ ToType->getScalarSizeInBits() && "Integer type too small");
+ return CGF.Builder.CreateTruncOrBitCast(Val, ToType);
+}
+
// The atomic builtins are also full memory barriers. This is a utility for
// wrapping a call to the builtins with memory barriers.
static Value *EmitCallWithBarrier(CodeGenFunction &CGF, Value *Fn,
@@ -60,13 +85,20 @@ static Value *EmitCallWithBarrier(CodeGenFunction &CGF, Value *Fn,
/// and the expression node.
static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
Intrinsic::ID Id, const CallExpr *E) {
- Value *Args[2] = { CGF.EmitScalarExpr(E->getArg(0)),
- CGF.EmitScalarExpr(E->getArg(1)) };
- const llvm::Type *ResType[2];
- ResType[0] = CGF.ConvertType(E->getType());
- ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
- Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
- return RValue::get(EmitCallWithBarrier(CGF, AtomF, Args, Args + 2));
+ const llvm::Type *ValueType =
+ llvm::IntegerType::get(CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(E->getType()));
+ const llvm::Type *PtrType = ValueType->getPointerTo();
+ const llvm::Type *IntrinsicTypes[2] = { ValueType, PtrType };
+ Value *AtomF = CGF.CGM.getIntrinsic(Id, IntrinsicTypes, 2);
+
+ Value *Args[2] = { CGF.Builder.CreateBitCast(CGF.EmitScalarExpr(E->getArg(0)),
+ PtrType),
+ EmitCastToInt(CGF, ValueType,
+ CGF.EmitScalarExpr(E->getArg(1))) };
+ return RValue::get(EmitCastFromInt(CGF, E->getType(),
+ EmitCallWithBarrier(CGF, AtomF, Args,
+ Args + 2)));
}
/// Utility to insert an atomic instruction based Instrinsic::ID and
@@ -75,14 +107,21 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF,
static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF,
Intrinsic::ID Id, const CallExpr *E,
Instruction::BinaryOps Op) {
- const llvm::Type *ResType[2];
- ResType[0] = CGF.ConvertType(E->getType());
- ResType[1] = CGF.ConvertType(E->getArg(0)->getType());
- Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2);
- Value *Args[2] = { CGF.EmitScalarExpr(E->getArg(0)),
- CGF.EmitScalarExpr(E->getArg(1)) };
+ const llvm::Type *ValueType =
+ llvm::IntegerType::get(CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(E->getType()));
+ const llvm::Type *PtrType = ValueType->getPointerTo();
+ const llvm::Type *IntrinsicTypes[2] = { ValueType, PtrType };
+ Value *AtomF = CGF.CGM.getIntrinsic(Id, IntrinsicTypes, 2);
+
+ Value *Args[2] = { CGF.Builder.CreateBitCast(CGF.EmitScalarExpr(E->getArg(0)),
+ PtrType),
+ EmitCastToInt(CGF, ValueType,
+ CGF.EmitScalarExpr(E->getArg(1))) };
Value *Result = EmitCallWithBarrier(CGF, AtomF, Args, Args + 2);
- return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Args[1]));
+ return RValue::get(EmitCastFromInt(CGF, E->getType(),
+ CGF.Builder.CreateBinOp(Op, Result,
+ Args[1])));
}
/// EmitFAbs - Emit a call to fabs/fabsf/fabsl, depending on the type of ValTy,
@@ -245,9 +284,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
"cast");
return RValue::get(Result);
}
- case Builtin::BI__builtin_expect:
+ case Builtin::BI__builtin_expect: {
// FIXME: pass expect through to LLVM
+ if (E->getArg(1)->HasSideEffects(getContext()))
+ (void)EmitScalarExpr(E->getArg(1));
return RValue::get(EmitScalarExpr(E->getArg(0)));
+ }
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64: {
Value *ArgValue = EmitScalarExpr(E->getArg(0));
@@ -746,14 +788,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_val_compare_and_swap_4:
case Builtin::BI__sync_val_compare_and_swap_8:
case Builtin::BI__sync_val_compare_and_swap_16: {
- const llvm::Type *ResType[2];
- ResType[0]= ConvertType(E->getType());
- ResType[1] = ConvertType(E->getArg(0)->getType());
- Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
- Value *Args[3] = { EmitScalarExpr(E->getArg(0)),
- EmitScalarExpr(E->getArg(1)),
- EmitScalarExpr(E->getArg(2)) };
- return RValue::get(EmitCallWithBarrier(*this, AtomF, Args, Args + 3));
+ const llvm::Type *ValueType =
+ llvm::IntegerType::get(CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(E->getType()));
+ const llvm::Type *PtrType = ValueType->getPointerTo();
+ const llvm::Type *IntrinsicTypes[2] = { ValueType, PtrType };
+ Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap,
+ IntrinsicTypes, 2);
+
+ Value *Args[3] = { Builder.CreateBitCast(CGF.EmitScalarExpr(E->getArg(0)),
+ PtrType),
+ EmitCastToInt(CGF, ValueType,
+ CGF.EmitScalarExpr(E->getArg(1))),
+ EmitCastToInt(CGF, ValueType,
+ CGF.EmitScalarExpr(E->getArg(2))) };
+ return RValue::get(EmitCastFromInt(CGF, E->getType(),
+ EmitCallWithBarrier(CGF, AtomF, Args,
+ Args + 3)));
}
case Builtin::BI__sync_bool_compare_and_swap_1:
@@ -761,14 +812,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_bool_compare_and_swap_4:
case Builtin::BI__sync_bool_compare_and_swap_8:
case Builtin::BI__sync_bool_compare_and_swap_16: {
- const llvm::Type *ResType[2];
- ResType[0]= ConvertType(E->getArg(1)->getType());
- ResType[1] = llvm::PointerType::getUnqual(ResType[0]);
- Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
- Value *OldVal = EmitScalarExpr(E->getArg(1));
- Value *Args[3] = { EmitScalarExpr(E->getArg(0)),
- OldVal,
- EmitScalarExpr(E->getArg(2)) };
+ const llvm::Type *ValueType =
+ llvm::IntegerType::get(
+ CGF.getLLVMContext(),
+ CGF.getContext().getTypeSize(E->getArg(1)->getType()));
+ const llvm::Type *PtrType = ValueType->getPointerTo();
+ const llvm::Type *IntrinsicTypes[2] = { ValueType, PtrType };
+ Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap,
+ IntrinsicTypes, 2);
+
+ Value *Args[3] = { Builder.CreateBitCast(CGF.EmitScalarExpr(E->getArg(0)),
+ PtrType),
+ EmitCastToInt(CGF, ValueType,
+ CGF.EmitScalarExpr(E->getArg(1))),
+ EmitCastToInt(CGF, ValueType,
+ CGF.EmitScalarExpr(E->getArg(2))) };
+ Value *OldVal = Args[1];
Value *PrevVal = EmitCallWithBarrier(*this, AtomF, Args, Args + 3);
Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
// zext bool to int.
@@ -953,8 +1012,10 @@ const llvm::VectorType *GetNeonType(LLVMContext &C, unsigned type, bool q) {
return 0;
}
-Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C) {
+Value *CodeGenFunction::EmitNeonSplat(Value *V, Constant *C, bool widen) {
unsigned nElts = cast<llvm::VectorType>(V->getType())->getNumElements();
+ if (widen)
+ nElts <<= 1;
SmallVector<Constant*, 16> Indices(nElts, C);
Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size());
return Builder.CreateShuffleVector(V, V, SV, "lane");
@@ -989,6 +1050,28 @@ Value *CodeGenFunction::EmitNeonShiftVector(Value *V, const llvm::Type *Ty,
return llvm::ConstantVector::get(CV.begin(), CV.size());
}
+/// GetPointeeAlignment - Given an expression with a pointer type, find the
+/// alignment of the type referenced by the pointer. Skip over implicit
+/// casts.
+static Value *GetPointeeAlignment(CodeGenFunction &CGF, const Expr *Addr) {
+ unsigned Align = 1;
+ // Check if the type is a pointer. The implicit cast operand might not be.
+ while (Addr->getType()->isPointerType()) {
+ QualType PtTy = Addr->getType()->getPointeeType();
+ unsigned NewA = CGF.getContext().getTypeAlignInChars(PtTy).getQuantity();
+ if (NewA > Align)
+ Align = NewA;
+
+ // If the address is an implicit cast, repeat with the cast operand.
+ if (const ImplicitCastExpr *CastAddr = dyn_cast<ImplicitCastExpr>(Addr)) {
+ Addr = CastAddr->getSubExpr();
+ continue;
+ }
+ break;
+ }
+ return llvm::ConstantInt::get(CGF.Int32Ty, Align);
+}
+
Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
const CallExpr *E) {
if (BuiltinID == ARM::BI__clear_cache) {
@@ -1002,9 +1085,6 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
a, b);
}
- // Determine the type of this overloaded NEON intrinsic.
- assert(BuiltinID > ARM::BI__builtin_thread_pointer);
-
llvm::SmallVector<Value*, 4> Ops;
for (unsigned i = 0, e = E->getNumArgs() - 1; i != e; i++)
Ops.push_back(EmitScalarExpr(E->getArg(i)));
@@ -1014,6 +1094,25 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
if (!Arg->isIntegerConstantExpr(Result, getContext()))
return 0;
+ if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f ||
+ BuiltinID == ARM::BI__builtin_arm_vcvtr_d) {
+ // Determine the overloaded type of this builtin.
+ const llvm::Type *Ty;
+ if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f)
+ Ty = llvm::Type::getFloatTy(VMContext);
+ else
+ Ty = llvm::Type::getDoubleTy(VMContext);
+
+ // Determine whether this is an unsigned conversion or not.
+ bool usgn = Result.getZExtValue() == 1;
+ unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr;
+
+ // Call the appropriate intrinsic.
+ Function *F = CGM.getIntrinsic(Int, &Ty, 1);
+ return Builder.CreateCall(F, Ops.begin(), Ops.end(), "vcvtr");
+ }
+
+ // Determine the type of this overloaded NEON intrinsic.
unsigned type = Result.getZExtValue();
bool usgn = type & 0x08;
bool quad = type & 0x10;
@@ -1029,19 +1128,36 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
switch (BuiltinID) {
default: return 0;
case ARM::BI__builtin_neon_vaba_v:
- case ARM::BI__builtin_neon_vabaq_v:
- Int = usgn ? Intrinsic::arm_neon_vabau : Intrinsic::arm_neon_vabas;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vaba");
- case ARM::BI__builtin_neon_vabal_v:
- Int = usgn ? Intrinsic::arm_neon_vabalu : Intrinsic::arm_neon_vabals;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vabal");
+ case ARM::BI__builtin_neon_vabaq_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ SmallVector<Value*, 2> Args;
+ Args.push_back(Ops[1]);
+ Args.push_back(Ops[2]);
+ Int = usgn ? Intrinsic::arm_neon_vabdu : Intrinsic::arm_neon_vabds;
+ Ops[1] = EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Args, "vaba");
+ return Builder.CreateAdd(Ops[0], Ops[1], "vaba");
+ }
+ case ARM::BI__builtin_neon_vabal_v: {
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ SmallVector<Value*, 2> Args;
+ Args.push_back(Ops[1]);
+ Args.push_back(Ops[2]);
+ Int = usgn ? Intrinsic::arm_neon_vabdu : Intrinsic::arm_neon_vabds;
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[1] = EmitNeonCall(CGM.getIntrinsic(Int, &DTy, 1), Args, "vabal");
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ return Builder.CreateAdd(Ops[0], Ops[1], "vabal");
+ }
case ARM::BI__builtin_neon_vabd_v:
case ARM::BI__builtin_neon_vabdq_v:
Int = usgn ? Intrinsic::arm_neon_vabdu : Intrinsic::arm_neon_vabds;
return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vabd");
- case ARM::BI__builtin_neon_vabdl_v:
- Int = usgn ? Intrinsic::arm_neon_vabdlu : Intrinsic::arm_neon_vabdls;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vabdl");
+ case ARM::BI__builtin_neon_vabdl_v: {
+ Int = usgn ? Intrinsic::arm_neon_vabdu : Intrinsic::arm_neon_vabds;
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = EmitNeonCall(CGM.getIntrinsic(Int, &DTy, 1), Ops, "vabdl");
+ return Builder.CreateZExt(Ops[0], Ty, "vabdl");
+ }
case ARM::BI__builtin_neon_vabs_v:
case ARM::BI__builtin_neon_vabsq_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vabs, &Ty, 1),
@@ -1049,12 +1165,29 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vaddhn_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vaddhn, &Ty, 1),
Ops, "vaddhn");
- case ARM::BI__builtin_neon_vaddl_v:
- Int = usgn ? Intrinsic::arm_neon_vaddlu : Intrinsic::arm_neon_vaddls;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vaddl");
- case ARM::BI__builtin_neon_vaddw_v:
- Int = usgn ? Intrinsic::arm_neon_vaddws : Intrinsic::arm_neon_vaddwu;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vaddw");
+ case ARM::BI__builtin_neon_vaddl_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], DTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ if (usgn) {
+ Ops[0] = Builder.CreateZExt(Ops[0], Ty);
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ } else {
+ Ops[0] = Builder.CreateSExt(Ops[0], Ty);
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ }
+ return Builder.CreateAdd(Ops[0], Ops[1], "vaddl");
+ }
+ case ARM::BI__builtin_neon_vaddw_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ if (usgn)
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ else
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ return Builder.CreateAdd(Ops[0], Ops[1], "vaddw");
+ }
case ARM::BI__builtin_neon_vcale_v:
std::swap(Ops[0], Ops[1]);
case ARM::BI__builtin_neon_vcage_v: {
@@ -1126,6 +1259,12 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Function *F = CGM.getIntrinsic(Int, Tys, 2);
return EmitNeonCall(F, Ops, "vcvt_n");
}
+ case ARM::BI__builtin_neon_vdup_lane_v:
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return EmitNeonSplat(Ops[0], cast<Constant>(Ops[1]));
+ case ARM::BI__builtin_neon_vdupq_lane_v:
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ return EmitNeonSplat(Ops[0], cast<Constant>(Ops[1]), true);
case ARM::BI__builtin_neon_vext_v:
case ARM::BI__builtin_neon_vextq_v: {
ConstantInt *C = dyn_cast<ConstantInt>(Ops[2]);
@@ -1161,6 +1300,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vhsub");
case ARM::BI__builtin_neon_vld1_v:
case ARM::BI__builtin_neon_vld1q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vld1, &Ty, 1),
Ops, "vld1");
case ARM::BI__builtin_neon_vld1_lane_v:
@@ -1183,7 +1323,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vld2_v:
case ARM::BI__builtin_neon_vld2q_v: {
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld2, &Ty, 1);
- Ops[1] = Builder.CreateCall(F, Ops[1], "vld2");
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld2");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
return Builder.CreateStore(Ops[1], Ops[0]);
@@ -1191,7 +1332,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vld3_v:
case ARM::BI__builtin_neon_vld3q_v: {
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld3, &Ty, 1);
- Ops[1] = Builder.CreateCall(F, Ops[1], "vld3");
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld3");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
return Builder.CreateStore(Ops[1], Ops[0]);
@@ -1199,7 +1341,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vld4_v:
case ARM::BI__builtin_neon_vld4q_v: {
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld4, &Ty, 1);
- Ops[1] = Builder.CreateCall(F, Ops[1], "vld4");
+ Value *Align = GetPointeeAlignment(*this, E->getArg(1));
+ Ops[1] = Builder.CreateCall2(F, Ops[1], Align, "vld4");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
return Builder.CreateStore(Ops[1], Ops[0]);
@@ -1209,6 +1352,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Function *F = CGM.getIntrinsic(Intrinsic::arm_neon_vld2lane, &Ty, 1);
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(1)));
Ops[1] = Builder.CreateCall(F, Ops.begin() + 1, Ops.end(), "vld2_lane");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
@@ -1220,6 +1364,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Ops[2] = Builder.CreateBitCast(Ops[2], Ty);
Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
Ops[4] = Builder.CreateBitCast(Ops[4], Ty);
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(1)));
Ops[1] = Builder.CreateCall(F, Ops.begin() + 1, Ops.end(), "vld3_lane");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
@@ -1232,6 +1377,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
Ops[3] = Builder.CreateBitCast(Ops[3], Ty);
Ops[4] = Builder.CreateBitCast(Ops[4], Ty);
Ops[5] = Builder.CreateBitCast(Ops[5], Ty);
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(1)));
Ops[1] = Builder.CreateCall(F, Ops.begin() + 1, Ops.end(), "vld3_lane");
Ty = llvm::PointerType::getUnqual(Ops[1]->getType());
Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
@@ -1261,6 +1407,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
llvm::Constant *CI = ConstantInt::get(Int32Ty, 0);
Args.push_back(CI);
+ Args.push_back(GetPointeeAlignment(*this, E->getArg(1)));
Ops[1] = Builder.CreateCall(F, Args.begin(), Args.end(), "vld_dup");
// splat lane 0 to all elts in each vector of the result.
@@ -1283,28 +1430,79 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
case ARM::BI__builtin_neon_vminq_v:
Int = usgn ? Intrinsic::arm_neon_vminu : Intrinsic::arm_neon_vmins;
return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmin");
- case ARM::BI__builtin_neon_vmlal_lane_v:
- splat = true;
- case ARM::BI__builtin_neon_vmlal_v:
- Int = usgn ? Intrinsic::arm_neon_vmlalu : Intrinsic::arm_neon_vmlals;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmlal", splat);
- case ARM::BI__builtin_neon_vmlsl_lane_v:
- splat = true;
- case ARM::BI__builtin_neon_vmlsl_v:
- Int = usgn ? Intrinsic::arm_neon_vmlslu : Intrinsic::arm_neon_vmlsls;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmlsl", splat);
- case ARM::BI__builtin_neon_vmovl_v:
- Int = usgn ? Intrinsic::arm_neon_vmovlu : Intrinsic::arm_neon_vmovls;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmovl");
- case ARM::BI__builtin_neon_vmovn_v:
- return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmovn, &Ty, 1),
- Ops, "vmovn");
- case ARM::BI__builtin_neon_vmull_lane_v:
- splat = true;
- case ARM::BI__builtin_neon_vmull_v:
- Int = usgn ? Intrinsic::arm_neon_vmullu : Intrinsic::arm_neon_vmulls;
- Int = poly ? (unsigned)Intrinsic::arm_neon_vmullp : Int;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vmlal", splat);
+ case ARM::BI__builtin_neon_vmlal_lane_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[2] = Builder.CreateBitCast(Ops[2], DTy);
+ Ops[2] = EmitNeonSplat(Ops[2], cast<Constant>(Ops[3]));
+ }
+ case ARM::BI__builtin_neon_vmlal_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ Ops[2] = Builder.CreateBitCast(Ops[2], DTy);
+ if (usgn) {
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ Ops[2] = Builder.CreateZExt(Ops[2], Ty);
+ } else {
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ Ops[2] = Builder.CreateSExt(Ops[2], Ty);
+ }
+ Ops[1] = Builder.CreateMul(Ops[1], Ops[2]);
+ return Builder.CreateAdd(Ops[0], Ops[1], "vmlal");
+ }
+ case ARM::BI__builtin_neon_vmlsl_lane_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[2] = Builder.CreateBitCast(Ops[2], DTy);
+ Ops[2] = EmitNeonSplat(Ops[2], cast<Constant>(Ops[3]));
+ }
+ case ARM::BI__builtin_neon_vmlsl_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ Ops[2] = Builder.CreateBitCast(Ops[2], DTy);
+ if (usgn) {
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ Ops[2] = Builder.CreateZExt(Ops[2], Ty);
+ } else {
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ Ops[2] = Builder.CreateSExt(Ops[2], Ty);
+ }
+ Ops[1] = Builder.CreateMul(Ops[1], Ops[2]);
+ return Builder.CreateSub(Ops[0], Ops[1], "vmlsl");
+ }
+ case ARM::BI__builtin_neon_vmovl_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], DTy);
+ if (usgn)
+ return Builder.CreateZExt(Ops[0], Ty, "vmovl");
+ return Builder.CreateSExt(Ops[0], Ty, "vmovl");
+ }
+ case ARM::BI__builtin_neon_vmovn_v: {
+ const llvm::Type *QTy = llvm::VectorType::getExtendedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], QTy);
+ return Builder.CreateTrunc(Ops[0], Ty, "vmovn");
+ }
+ case ARM::BI__builtin_neon_vmull_lane_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ Ops[1] = EmitNeonSplat(Ops[1], cast<Constant>(Ops[2]));
+ }
+ case ARM::BI__builtin_neon_vmull_v: {
+ if (poly)
+ return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vmullp, &Ty, 1),
+ Ops, "vmull");
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], DTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ if (usgn) {
+ Ops[0] = Builder.CreateZExt(Ops[0], Ty);
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ } else {
+ Ops[0] = Builder.CreateSExt(Ops[0], Ty);
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ }
+ return Builder.CreateMul(Ops[0], Ops[1], "vmull");
+ }
case ARM::BI__builtin_neon_vpadal_v:
case ARM::BI__builtin_neon_vpadalq_v:
Int = usgn ? Intrinsic::arm_neon_vpadalu : Intrinsic::arm_neon_vpadals;
@@ -1503,6 +1701,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return Builder.CreateAdd(Ops[0], Ops[1]);
case ARM::BI__builtin_neon_vst1_v:
case ARM::BI__builtin_neon_vst1q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst1, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vst1_lane_v:
@@ -1513,37 +1712,60 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
return Builder.CreateStore(Ops[1], Builder.CreateBitCast(Ops[0], Ty));
case ARM::BI__builtin_neon_vst2_v:
case ARM::BI__builtin_neon_vst2q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst2, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vst2_lane_v:
case ARM::BI__builtin_neon_vst2q_lane_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst2lane, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vst3_v:
case ARM::BI__builtin_neon_vst3q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst3, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vst3_lane_v:
case ARM::BI__builtin_neon_vst3q_lane_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst3lane, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vst4_v:
case ARM::BI__builtin_neon_vst4q_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vst4_lane_v:
case ARM::BI__builtin_neon_vst4q_lane_v:
+ Ops.push_back(GetPointeeAlignment(*this, E->getArg(0)));
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vst4lane, &Ty, 1),
Ops, "");
case ARM::BI__builtin_neon_vsubhn_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vsubhn, &Ty, 1),
Ops, "vsubhn");
- case ARM::BI__builtin_neon_vsubl_v:
- Int = usgn ? Intrinsic::arm_neon_vsublu : Intrinsic::arm_neon_vsubls;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vsubl");
- case ARM::BI__builtin_neon_vsubw_v:
- Int = usgn ? Intrinsic::arm_neon_vsubws : Intrinsic::arm_neon_vsubwu;
- return EmitNeonCall(CGM.getIntrinsic(Int, &Ty, 1), Ops, "vsubw");
+ case ARM::BI__builtin_neon_vsubl_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], DTy);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ if (usgn) {
+ Ops[0] = Builder.CreateZExt(Ops[0], Ty);
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ } else {
+ Ops[0] = Builder.CreateSExt(Ops[0], Ty);
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ }
+ return Builder.CreateSub(Ops[0], Ops[1], "vsubl");
+ }
+ case ARM::BI__builtin_neon_vsubw_v: {
+ const llvm::Type *DTy =llvm::VectorType::getTruncatedElementVectorType(VTy);
+ Ops[0] = Builder.CreateBitCast(Ops[0], Ty);
+ Ops[1] = Builder.CreateBitCast(Ops[1], DTy);
+ if (usgn)
+ Ops[1] = Builder.CreateZExt(Ops[1], Ty);
+ else
+ Ops[1] = Builder.CreateSExt(Ops[1], Ty);
+ return Builder.CreateSub(Ops[0], Ops[1], "vsubw");
+ }
case ARM::BI__builtin_neon_vtbl1_v:
return EmitNeonCall(CGM.getIntrinsic(Intrinsic::arm_neon_vtbl1),
Ops, "vtbl1");
@@ -1626,8 +1848,8 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
for (unsigned vi = 0; vi != 2; ++vi) {
SmallVector<Constant*, 16> Indices;
for (unsigned i = 0, e = VTy->getNumElements(); i != e; i += 2) {
- Indices.push_back(ConstantInt::get(Int32Ty, (i >> 1)));
- Indices.push_back(ConstantInt::get(Int32Ty, (i >> 1)+e));
+ Indices.push_back(ConstantInt::get(Int32Ty, (i + vi*e) >> 1));
+ Indices.push_back(ConstantInt::get(Int32Ty, ((i + vi*e) >> 1)+e));
}
Value *Addr = Builder.CreateConstInBoundsGEP1_32(Ops[0], vi);
SV = llvm::ConstantVector::get(Indices.begin(), Indices.size());
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index 7b7be9a260ed..179716f631a8 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -287,44 +287,6 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD));
}
-llvm::Constant *
-CodeGenModule::GetCXXMemberFunctionPointerValue(const CXXMethodDecl *MD) {
- assert(MD->isInstance() && "Member function must not be static!");
-
- MD = MD->getCanonicalDecl();
-
- const llvm::Type *PtrDiffTy = Types.ConvertType(Context.getPointerDiffType());
-
- // Get the function pointer (or index if this is a virtual function).
- if (MD->isVirtual()) {
- uint64_t Index = VTables.getMethodVTableIndex(MD);
-
- // FIXME: We shouldn't use / 8 here.
- uint64_t PointerWidthInBytes = Context.Target.getPointerWidth(0) / 8;
-
- // Itanium C++ ABI 2.3:
- // For a non-virtual function, this field is a simple function pointer.
- // For a virtual function, it is 1 plus the virtual table offset
- // (in bytes) of the function, represented as a ptrdiff_t.
- return llvm::ConstantInt::get(PtrDiffTy, (Index * PointerWidthInBytes) + 1);
- }
-
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *Ty;
- // Check whether the function has a computable LLVM signature.
- if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
- // The function has a computable LLVM signature; use the correct type.
- Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
- } else {
- // Use an arbitrary non-function type to tell GetAddrOfFunction that the
- // function type is incomplete.
- Ty = PtrDiffTy;
- }
-
- llvm::Constant *FuncPtr = GetAddrOfFunction(MD, Ty);
- return llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy);
-}
-
static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VTableIndex,
llvm::Value *This, const llvm::Type *Ty) {
Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();
@@ -356,4 +318,154 @@ CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type,
return ::BuildVirtualCall(*this, VTableIndex, This, Ty);
}
-CXXABI::~CXXABI() {}
+/// Implementation for CGCXXABI. Possibly this should be moved into
+/// the incomplete ABI implementations?
+
+CGCXXABI::~CGCXXABI() {}
+
+static void ErrorUnsupportedABI(CodeGenFunction &CGF,
+ llvm::StringRef S) {
+ Diagnostic &Diags = CGF.CGM.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
+ "cannot yet compile %1 in this ABI");
+ Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
+ DiagID)
+ << S;
+}
+
+static llvm::Constant *GetBogusMemberPointer(CodeGenModule &CGM,
+ QualType T) {
+ return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
+}
+
+const llvm::Type *
+CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
+ return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+}
+
+llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "calls through member pointers");
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+ const llvm::FunctionType *FTy =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+ FPT->isVariadic());
+ return llvm::Constant::getNullValue(FTy->getPointerTo());
+}
+
+llvm::Value *CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "loads of member pointers");
+ const llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
+ return llvm::Constant::getNullValue(Ty);
+}
+
+llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src) {
+ ErrorUnsupportedABI(CGF, "member function pointer conversions");
+ return GetBogusMemberPointer(CGM, E->getType());
+}
+
+llvm::Value *
+CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ ErrorUnsupportedABI(CGF, "member function pointer comparison");
+ return CGF.Builder.getFalse();
+}
+
+llvm::Value *
+CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ ErrorUnsupportedABI(CGF, "member function pointer null testing");
+ return CGF.Builder.getFalse();
+}
+
+llvm::Constant *
+CGCXXABI::EmitMemberPointerConversion(llvm::Constant *C, const CastExpr *E) {
+ return GetBogusMemberPointer(CGM, E->getType());
+}
+
+llvm::Constant *
+CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
+ return GetBogusMemberPointer(CGM, QualType(MPT, 0));
+}
+
+llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+ return GetBogusMemberPointer(CGM,
+ CGM.getContext().getMemberPointerType(MD->getType(),
+ MD->getParent()->getTypeForDecl()));
+}
+
+llvm::Constant *CGCXXABI::EmitMemberPointer(const FieldDecl *FD) {
+ return GetBogusMemberPointer(CGM,
+ CGM.getContext().getMemberPointerType(FD->getType(),
+ FD->getParent()->getTypeForDecl()));
+}
+
+bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
+ // Fake answer.
+ return true;
+}
+
+void CGCXXABI::BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+
+ // FIXME: I'm not entirely sure I like using a fake decl just for code
+ // generation. Maybe we can come up with a better way?
+ ImplicitParamDecl *ThisDecl
+ = ImplicitParamDecl::Create(CGM.getContext(), 0, MD->getLocation(),
+ &CGM.getContext().Idents.get("this"),
+ MD->getThisType(CGM.getContext()));
+ Params.push_back(std::make_pair(ThisDecl, ThisDecl->getType()));
+ getThisDecl(CGF) = ThisDecl;
+}
+
+void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
+ /// Initialize the 'this' slot.
+ assert(getThisDecl(CGF) && "no 'this' variable for function");
+ getThisValue(CGF)
+ = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
+ "this");
+}
+
+void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
+ RValue RV, QualType ResultType) {
+ CGF.EmitReturnOfRValue(RV, ResultType);
+}
+
+CharUnits CGCXXABI::GetArrayCookieSize(QualType ElementType) {
+ return CharUnits::Zero();
+}
+
+llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ QualType ElementType) {
+ // Should never be called.
+ ErrorUnsupportedABI(CGF, "array cookie initialization");
+ return 0;
+}
+
+void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize) {
+ ErrorUnsupportedABI(CGF, "array cookie reading");
+
+ // This should be enough to avoid assertions.
+ NumElements = 0;
+ AllocPtr = llvm::Constant::getNullValue(CGF.Builder.getInt8PtrTy());
+ CookieSize = CharUnits::Zero();
+}
diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h
index e1bbb0a79cce..367e345918a2 100644
--- a/lib/CodeGen/CGCXXABI.h
+++ b/lib/CodeGen/CGCXXABI.h
@@ -15,23 +15,215 @@
#ifndef CLANG_CODEGEN_CXXABI_H
#define CLANG_CODEGEN_CXXABI_H
+#include "CodeGenFunction.h"
+
+namespace llvm {
+ class Constant;
+ class Type;
+ class Value;
+
+ template <class T> class SmallVectorImpl;
+}
+
namespace clang {
+ class CastExpr;
+ class CXXConstructorDecl;
+ class CXXDestructorDecl;
+ class CXXMethodDecl;
+ class CXXRecordDecl;
+ class FieldDecl;
+
namespace CodeGen {
+ class CodeGenFunction;
class CodeGenModule;
class MangleContext;
/// Implements C++ ABI-specific code generation functions.
-class CXXABI {
+class CGCXXABI {
+protected:
+ CodeGenModule &CGM;
+
+ CGCXXABI(CodeGenModule &CGM) : CGM(CGM) {}
+
+protected:
+ ImplicitParamDecl *&getThisDecl(CodeGenFunction &CGF) {
+ return CGF.CXXThisDecl;
+ }
+ llvm::Value *&getThisValue(CodeGenFunction &CGF) {
+ return CGF.CXXThisValue;
+ }
+
+ ImplicitParamDecl *&getVTTDecl(CodeGenFunction &CGF) {
+ return CGF.CXXVTTDecl;
+ }
+ llvm::Value *&getVTTValue(CodeGenFunction &CGF) {
+ return CGF.CXXVTTValue;
+ }
+
+ /// Build a parameter variable suitable for 'this'.
+ void BuildThisParam(CodeGenFunction &CGF, FunctionArgList &Params);
+
+ /// Perform prolog initialization of the parameter variable suitable
+ /// for 'this' emitted by BuildThisParam.
+ void EmitThisParam(CodeGenFunction &CGF);
+
+ ASTContext &getContext() const { return CGM.getContext(); }
+
public:
- virtual ~CXXABI();
+
+ virtual ~CGCXXABI();
/// Gets the mangle context.
virtual MangleContext &getMangleContext() = 0;
+
+ /// Find the LLVM type used to represent the given member pointer
+ /// type.
+ virtual const llvm::Type *
+ ConvertMemberPointerType(const MemberPointerType *MPT);
+
+ /// Load a member function from an object and a member function
+ /// pointer. Apply the this-adjustment and set 'This' to the
+ /// adjusted value.
+ virtual llvm::Value *
+ EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ /// Calculate an l-value from an object and a data member pointer.
+ virtual llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ /// Perform a derived-to-base or base-to-derived member pointer
+ /// conversion.
+ virtual llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src);
+
+ /// Perform a derived-to-base or base-to-derived member pointer
+ /// conversion on a constant member pointer.
+ virtual llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C,
+ const CastExpr *E);
+
+ /// Return true if the given member pointer can be zero-initialized
+ /// (in the C++ sense) with an LLVM zeroinitializer.
+ virtual bool isZeroInitializable(const MemberPointerType *MPT);
+
+ /// Create a null member pointer of the given type.
+ virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
+
+ /// Create a member pointer for the given method.
+ virtual llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+
+ /// Create a member pointer for the given field.
+ virtual llvm::Constant *EmitMemberPointer(const FieldDecl *FD);
+
+ /// Emit a comparison between two member pointers. Returns an i1.
+ virtual llvm::Value *
+ EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
+ /// Determine if a member pointer is non-null. Returns an i1.
+ virtual llvm::Value *
+ EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ /// Build the signature of the given constructor variant by adding
+ /// any required parameters. For convenience, ResTy has been
+ /// initialized to 'void', and ArgTys has been initialized with the
+ /// type of 'this' (although this may be changed by the ABI) and
+ /// will have the formal parameters added to it afterwards.
+ ///
+ /// If there are ever any ABIs where the implicit parameters are
+ /// intermixed with the formal parameters, we can address those
+ /// then.
+ virtual void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
+
+ /// Build the signature of the given destructor variant by adding
+ /// any required parameters. For convenience, ResTy has been
+ /// initialized to 'void' and ArgTys has been initialized with the
+ /// type of 'this' (although this may be changed by the ABI).
+ virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) = 0;
+
+ /// Build the ABI-specific portion of the parameter list for a
+ /// function. This generally involves a 'this' parameter and
+ /// possibly some extra data for constructors and destructors.
+ ///
+ /// ABIs may also choose to override the return type, which has been
+ /// initialized with the formal return type of the function.
+ virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) = 0;
+
+ /// Emit the ABI-specific prolog for the function.
+ virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
+
+ virtual void EmitReturnFromThunk(CodeGenFunction &CGF,
+ RValue RV, QualType ResultType);
+
+ /**************************** Array cookies ******************************/
+
+ /// Returns the extra size required in order to store the array
+ /// cookie for the given type. May return 0 to indicate that no
+ /// array cookie is required.
+ ///
+ /// Several cases are filtered out before this method is called:
+ /// - non-array allocations never need a cookie
+ /// - calls to ::operator new(size_t, void*) never need a cookie
+ ///
+ /// \param ElementType - the allocated type of the expression,
+ /// i.e. the pointee type of the expression result type
+ virtual CharUnits GetArrayCookieSize(QualType ElementType);
+
+ /// Initialize the array cookie for the given allocation.
+ ///
+ /// \param NewPtr - a char* which is the presumed-non-null
+ /// return value of the allocation function
+ /// \param NumElements - the computed number of elements,
+ /// potentially collapsed from the multidimensional array case
+ /// \param ElementType - the base element allocated type,
+ /// i.e. the allocated type after stripping all array types
+ virtual llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ QualType ElementType);
+
+ /// Reads the array cookie associated with the given pointer,
+ /// if it has one.
+ ///
+ /// \param Ptr - a pointer to the first element in the array
+ /// \param ElementType - the base element type of elements of the array
+ /// \param NumElements - an out parameter which will be initialized
+ /// with the number of elements allocated, or zero if there is no
+ /// cookie
+ /// \param AllocPtr - an out parameter which will be initialized
+ /// with a char* pointing to the address returned by the allocation
+ /// function
+ /// \param CookieSize - an out parameter which will be initialized
+ /// with the size of the cookie, or zero if there is no cookie
+ virtual void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
};
/// Creates an instance of a C++ ABI class.
-CXXABI *CreateItaniumCXXABI(CodeGenModule &CGM);
-CXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM);
+CGCXXABI *CreateARMCXXABI(CodeGenModule &CGM);
+CGCXXABI *CreateItaniumCXXABI(CodeGenModule &CGM);
+CGCXXABI *CreateMicrosoftCXXABI(CodeGenModule &CGM);
+
}
}
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 3d1e143dca2b..475dfa5c102a 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "CGCall.h"
+#include "CGCXXABI.h"
#include "ABIInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -35,6 +36,7 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
+ // TODO: add support for CC_X86Pascal to llvm
}
}
@@ -99,6 +101,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D) {
if (D->hasAttr<ThisCallAttr>())
return CC_X86ThisCall;
+ if (D->hasAttr<PascalAttr>())
+ return CC_X86Pascal;
+
return CC_C;
}
@@ -116,6 +121,9 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXRecordDecl *RD,
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
llvm::SmallVector<CanQualType, 16> ArgTys;
+ assert(!isa<CXXConstructorDecl>(MD) && "wrong method for contructors!");
+ assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
+
// Add the 'this' pointer unless this is a static method.
if (MD->isInstance())
ArgTys.push_back(GetThisType(Context, MD->getParent()));
@@ -126,29 +134,32 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXMethodDecl *MD) {
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXConstructorDecl *D,
CXXCtorType Type) {
llvm::SmallVector<CanQualType, 16> ArgTys;
-
- // Add the 'this' pointer.
ArgTys.push_back(GetThisType(Context, D->getParent()));
+ CanQualType ResTy = Context.VoidTy;
- // Check if we need to add a VTT parameter (which has type void **).
- if (Type == Ctor_Base && D->getParent()->getNumVBases() != 0)
- ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+ TheCXXABI.BuildConstructorSignature(D, Type, ResTy, ArgTys);
- return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
+ CanQual<FunctionProtoType> FTP = GetFormalType(D);
+
+ // Add the formal parameters.
+ for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+ ArgTys.push_back(FTP->getArgType(i));
+
+ return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const CXXDestructorDecl *D,
CXXDtorType Type) {
- llvm::SmallVector<CanQualType, 16> ArgTys;
-
- // Add the 'this' pointer.
+ llvm::SmallVector<CanQualType, 2> ArgTys;
ArgTys.push_back(GetThisType(Context, D->getParent()));
-
- // Check if we need to add a VTT parameter (which has type void **).
- if (Type == Dtor_Base && D->getParent()->getNumVBases() != 0)
- ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+ CanQualType ResTy = Context.VoidTy;
+
+ TheCXXABI.BuildDestructorSignature(D, Type, ResTy, ArgTys);
- return ::getFunctionInfo(*this, ArgTys, GetFormalType(D));
+ CanQual<FunctionProtoType> FTP = GetFormalType(D);
+ assert(FTP->getNumArgs() == 0 && "dtor with formal parameters");
+
+ return getFunctionInfo(ResTy, ArgTys, FTP->getExtInfo());
}
const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const FunctionDecl *FD) {
@@ -243,34 +254,26 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
ArgTys.data(), ArgTys.size());
FunctionInfos.InsertNode(FI, InsertPos);
- // ABI lowering wants to know what our preferred type for the argument is in
- // various situations, pass it in.
- llvm::SmallVector<const llvm::Type *, 8> PreferredArgTypes;
- for (llvm::SmallVectorImpl<CanQualType>::const_iterator
- I = ArgTys.begin(), E = ArgTys.end(); I != E; ++I) {
- // If this is being called from the guts of the ConvertType loop, make sure
- // to call ConvertTypeRecursive so we don't get into issues with cyclic
- // pointer type structures.
- PreferredArgTypes.push_back(ConvertTypeRecursive(*I));
- }
-
// Compute ABI information.
- getABIInfo().computeInfo(*FI, getContext(), TheModule.getContext(),
- PreferredArgTypes.data(), PreferredArgTypes.size());
+ getABIInfo().computeInfo(*FI);
+
+ // Loop over all of the computed argument and return value info. If any of
+ // them are direct or extend without a specified coerce type, specify the
+ // default now.
+ ABIArgInfo &RetInfo = FI->getReturnInfo();
+ if (RetInfo.canHaveCoerceToType() && RetInfo.getCoerceToType() == 0)
+ RetInfo.setCoerceToType(ConvertTypeRecursive(FI->getReturnType()));
+
+ for (CGFunctionInfo::arg_iterator I = FI->arg_begin(), E = FI->arg_end();
+ I != E; ++I)
+ if (I->info.canHaveCoerceToType() && I->info.getCoerceToType() == 0)
+ I->info.setCoerceToType(ConvertTypeRecursive(I->type));
// If this is a top-level call and ConvertTypeRecursive hit unresolved pointer
// types, resolve them now. These pointers may point to this function, which
// we *just* filled in the FunctionInfo for.
- if (!IsRecursive && !PointersToResolve.empty()) {
- // Use PATypeHolder's so that our preferred types don't dangle under
- // refinement.
- llvm::SmallVector<llvm::PATypeHolder, 8> Handles(PreferredArgTypes.begin(),
- PreferredArgTypes.end());
+ if (!IsRecursive && !PointersToResolve.empty())
HandleLateResolvedPointers();
- PreferredArgTypes.clear();
- PreferredArgTypes.append(Handles.begin(), Handles.end());
- }
-
return *FI;
}
@@ -311,11 +314,10 @@ void CodeGenTypes::GetExpandedTypes(QualType Ty,
"Cannot expand structure with bit-field members.");
QualType FT = FD->getType();
- if (CodeGenFunction::hasAggregateLLVMType(FT)) {
+ if (CodeGenFunction::hasAggregateLLVMType(FT))
GetExpandedTypes(FT, ArgTys, IsRecursive);
- } else {
+ else
ArgTys.push_back(ConvertType(FT, IsRecursive));
- }
}
}
@@ -613,7 +615,7 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
case ABIArgInfo::Extend:
case ABIArgInfo::Direct:
- ResultType = ConvertType(RetTy, IsRecursive);
+ ResultType = RetAI.getCoerceToType();
break;
case ABIArgInfo::Indirect: {
@@ -627,10 +629,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
case ABIArgInfo::Ignore:
ResultType = llvm::Type::getVoidTy(getLLVMContext());
break;
-
- case ABIArgInfo::Coerce:
- ResultType = RetAI.getCoerceToType();
- break;
}
for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
@@ -641,7 +639,15 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
case ABIArgInfo::Ignore:
break;
- case ABIArgInfo::Coerce: {
+ case ABIArgInfo::Indirect: {
+ // indirect arguments are always on the stack, which is addr space #0.
+ const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
+ ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
+ break;
+ }
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
// If the coerce-to type is a first class aggregate, flatten it. Either
// way is semantically identical, but fast-isel and the optimizer
// generally likes scalar values better than FCAs.
@@ -655,18 +661,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
break;
}
- case ABIArgInfo::Indirect: {
- // indirect arguments are always on the stack, which is addr space #0.
- const llvm::Type *LTy = ConvertTypeForMem(it->type, IsRecursive);
- ArgTys.push_back(llvm::PointerType::getUnqual(LTy));
- break;
- }
-
- case ABIArgInfo::Extend:
- case ABIArgInfo::Direct:
- ArgTys.push_back(ConvertType(it->type, IsRecursive));
- break;
-
case ABIArgInfo::Expand:
GetExpandedTypes(it->type, ArgTys, IsRecursive);
break;
@@ -676,12 +670,18 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI, bool IsVariadic,
return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
}
-const llvm::Type *
-CodeGenTypes::GetFunctionTypeForVTable(const CXXMethodDecl *MD) {
+const llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- if (!VerifyFuncTypeComplete(FPT))
- return GetFunctionType(getFunctionInfo(MD), FPT->isVariadic(), false);
+ if (!VerifyFuncTypeComplete(FPT)) {
+ const CGFunctionInfo *Info;
+ if (isa<CXXDestructorDecl>(MD))
+ Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
+ else
+ Info = &getFunctionInfo(MD);
+ return GetFunctionType(*Info, FPT->isVariadic(), false);
+ }
return llvm::OpaqueType::get(getLLVMContext());
}
@@ -730,13 +730,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
case ABIArgInfo::Extend:
- if (RetTy->isSignedIntegerType()) {
+ if (RetTy->hasSignedIntegerRepresentation())
RetAttrs |= llvm::Attribute::SExt;
- } else if (RetTy->isUnsignedIntegerType()) {
+ else if (RetTy->hasUnsignedIntegerRepresentation())
RetAttrs |= llvm::Attribute::ZExt;
- }
- // FALLTHROUGH
+ break;
case ABIArgInfo::Direct:
+ case ABIArgInfo::Ignore:
break;
case ABIArgInfo::Indirect:
@@ -748,10 +748,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
llvm::Attribute::ReadNone);
break;
- case ABIArgInfo::Ignore:
- case ABIArgInfo::Coerce:
- break;
-
case ABIArgInfo::Expand:
assert(0 && "Invalid ABI kind for return argument");
}
@@ -759,7 +755,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
if (RetAttrs)
PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs));
- // FIXME: we need to honour command line settings also...
+ // FIXME: we need to honor command line settings also.
// FIXME: RegParm should be reduced in case of nested functions and/or global
// register variable.
signed RegParm = FI.getRegParm();
@@ -774,15 +770,27 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
// have the corresponding parameter variable. It doesn't make
// sense to do it here because parameters are so fucked up.
-
switch (AI.getKind()) {
- case ABIArgInfo::Coerce:
+ case ABIArgInfo::Extend:
+ if (ParamType->isSignedIntegerType())
+ Attributes |= llvm::Attribute::SExt;
+ else if (ParamType->isUnsignedIntegerType())
+ Attributes |= llvm::Attribute::ZExt;
+ // FALL THROUGH
+ case ABIArgInfo::Direct:
+ if (RegParm > 0 &&
+ (ParamType->isIntegerType() || ParamType->isPointerType())) {
+ RegParm -=
+ (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
+ if (RegParm >= 0)
+ Attributes |= llvm::Attribute::InReg;
+ }
+ // FIXME: handle sseregparm someday...
+
if (const llvm::StructType *STy =
- dyn_cast<llvm::StructType>(AI.getCoerceToType()))
- Index += STy->getNumElements();
- else
- ++Index;
- continue; // Skip index increment.
+ dyn_cast<llvm::StructType>(AI.getCoerceToType()))
+ Index += STy->getNumElements()-1; // 1 will be added below.
+ break;
case ABIArgInfo::Indirect:
if (AI.getIndirectByVal())
@@ -795,24 +803,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
llvm::Attribute::ReadNone);
break;
- case ABIArgInfo::Extend:
- if (ParamType->isSignedIntegerType()) {
- Attributes |= llvm::Attribute::SExt;
- } else if (ParamType->isUnsignedIntegerType()) {
- Attributes |= llvm::Attribute::ZExt;
- }
- // FALLS THROUGH
- case ABIArgInfo::Direct:
- if (RegParm > 0 &&
- (ParamType->isIntegerType() || ParamType->isPointerType())) {
- RegParm -=
- (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
- if (RegParm >= 0)
- Attributes |= llvm::Attribute::InReg;
- }
- // FIXME: handle sseregparm someday...
- break;
-
case ABIArgInfo::Ignore:
// Skip increment, no matching LLVM parameter.
continue;
@@ -881,7 +871,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// reference.
} else {
// Load scalar value from indirect argument.
- V = EmitLoadOfScalar(V, false, Ty);
+ unsigned Alignment = getContext().getTypeAlignInChars(Ty).getQuantity();
+ V = EmitLoadOfScalar(V, false, Alignment, Ty);
if (!getContext().typesAreCompatible(Ty, Arg->getType())) {
// This must be a promotion, for something like
// "void a(x) short x; {..."
@@ -894,15 +885,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
case ABIArgInfo::Extend:
case ABIArgInfo::Direct: {
- assert(AI != Fn->arg_end() && "Argument mismatch!");
- llvm::Value *V = AI;
- if (hasAggregateLLVMType(Ty)) {
- // Create a temporary alloca to hold the argument; the rest of
- // codegen expects to access aggregates & complex values by
- // reference.
- V = CreateMemTemp(Ty);
- Builder.CreateStore(AI, V);
- } else {
+ // If we have the trivial case, handle it with no muss and fuss.
+ if (!isa<llvm::StructType>(ArgI.getCoerceToType()) &&
+ ArgI.getCoerceToType() == ConvertType(Ty) &&
+ ArgI.getDirectOffset() == 0) {
+ assert(AI != Fn->arg_end() && "Argument mismatch!");
+ llvm::Value *V = AI;
+
if (Arg->getType().isRestrictQualified())
AI->addAttr(llvm::Attribute::NoAlias);
@@ -911,53 +900,36 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// "void a(x) short x; {..."
V = EmitScalarConversion(V, Ty, Arg->getType());
}
+ EmitParmDecl(*Arg, V);
+ break;
}
- EmitParmDecl(*Arg, V);
- break;
- }
-
- case ABIArgInfo::Expand: {
- // If this structure was expanded into multiple arguments then
- // we need to create a temporary and reconstruct it from the
- // arguments.
- llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
- // FIXME: What are the right qualifiers here?
- llvm::Function::arg_iterator End =
- ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI);
- EmitParmDecl(*Arg, Temp);
-
- // Name the arguments used in expansion and increment AI.
- unsigned Index = 0;
- for (; AI != End; ++AI, ++Index)
- AI->setName(Arg->getName() + "." + llvm::Twine(Index));
- continue;
- }
-
- case ABIArgInfo::Ignore:
- // Initialize the local variable appropriately.
- if (hasAggregateLLVMType(Ty)) {
- EmitParmDecl(*Arg, CreateMemTemp(Ty));
- } else {
- EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
- }
-
- // Skip increment, no matching LLVM parameter.
- continue;
- case ABIArgInfo::Coerce: {
- // FIXME: This is very wasteful; EmitParmDecl is just going to drop the
- // result in a new alloca anyway, so we could just store into that
- // directly if we broke the abstraction down more.
llvm::AllocaInst *Alloca = CreateMemTemp(Ty, "coerce");
- Alloca->setAlignment(getContext().getDeclAlign(Arg).getQuantity());
+
+ // The alignment we need to use is the max of the requested alignment for
+ // the argument plus the alignment required by our access code below.
+ unsigned AlignmentToUse =
+ CGF.CGM.getTargetData().getABITypeAlignment(ArgI.getCoerceToType());
+ AlignmentToUse = std::max(AlignmentToUse,
+ (unsigned)getContext().getDeclAlign(Arg).getQuantity());
+
+ Alloca->setAlignment(AlignmentToUse);
llvm::Value *V = Alloca;
+ llvm::Value *Ptr = V; // Pointer to store into.
+
+ // If the value is offset in memory, apply the offset now.
+ if (unsigned Offs = ArgI.getDirectOffset()) {
+ Ptr = Builder.CreateBitCast(Ptr, Builder.getInt8PtrTy());
+ Ptr = Builder.CreateConstGEP1_32(Ptr, Offs);
+ Ptr = Builder.CreateBitCast(Ptr,
+ llvm::PointerType::getUnqual(ArgI.getCoerceToType()));
+ }
// If the coerce-to type is a first class aggregate, we flatten it and
// pass the elements. Either way is semantically identical, but fast-isel
// and the optimizer generally likes scalar values better than FCAs.
if (const llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType())) {
- llvm::Value *Ptr = V;
Ptr = Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy));
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -970,13 +942,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Simple case, just do a coerced store of the argument into the alloca.
assert(AI != Fn->arg_end() && "Argument mismatch!");
AI->setName(Arg->getName() + ".coerce");
- CreateCoercedStore(AI++, V, /*DestIsVolatile=*/false, *this);
+ CreateCoercedStore(AI++, Ptr, /*DestIsVolatile=*/false, *this);
}
// Match to what EmitParmDecl is expecting for this type.
if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
- V = EmitLoadOfScalar(V, false, Ty);
+ V = EmitLoadOfScalar(V, false, AlignmentToUse, Ty);
if (!getContext().typesAreCompatible(Ty, Arg->getType())) {
// This must be a promotion, for something like
// "void a(x) short x; {..."
@@ -986,6 +958,32 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
EmitParmDecl(*Arg, V);
continue; // Skip ++AI increment, already done.
}
+
+ case ABIArgInfo::Expand: {
+ // If this structure was expanded into multiple arguments then
+ // we need to create a temporary and reconstruct it from the
+ // arguments.
+ llvm::Value *Temp = CreateMemTemp(Ty, Arg->getName() + ".addr");
+ llvm::Function::arg_iterator End =
+ ExpandTypeFromArgs(Ty, MakeAddrLValue(Temp, Ty), AI);
+ EmitParmDecl(*Arg, Temp);
+
+ // Name the arguments used in expansion and increment AI.
+ unsigned Index = 0;
+ for (; AI != End; ++AI, ++Index)
+ AI->setName(Arg->getName() + "." + llvm::Twine(Index));
+ continue;
+ }
+
+ case ABIArgInfo::Ignore:
+ // Initialize the local variable appropriately.
+ if (hasAggregateLLVMType(Ty))
+ EmitParmDecl(*Arg, CreateMemTemp(Ty));
+ else
+ EmitParmDecl(*Arg, llvm::UndefValue::get(ConvertType(Arg->getType())));
+
+ // Skip increment, no matching LLVM parameter.
+ continue;
}
++AI;
@@ -1000,13 +998,14 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
return;
}
- llvm::MDNode *RetDbgInfo = 0;
+ llvm::DebugLoc RetDbgLoc;
llvm::Value *RV = 0;
QualType RetTy = FI.getReturnType();
const ABIArgInfo &RetAI = FI.getReturnInfo();
switch (RetAI.getKind()) {
- case ABIArgInfo::Indirect:
+ case ABIArgInfo::Indirect: {
+ unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
if (RetTy->isAnyComplexType()) {
ComplexPairTy RT = LoadComplexFromAddr(ReturnValue, false);
StoreComplexToAddr(RT, CurFn->arg_begin(), false);
@@ -1014,43 +1013,54 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
// Do nothing; aggregrates get evaluated directly into the destination.
} else {
EmitStoreOfScalar(Builder.CreateLoad(ReturnValue), CurFn->arg_begin(),
- false, RetTy);
+ false, Alignment, RetTy);
}
break;
+ }
case ABIArgInfo::Extend:
- case ABIArgInfo::Direct: {
- // The internal return value temp always will have pointer-to-return-type
- // type, just do a load.
-
- // If the instruction right before the insertion point is a store to the
- // return value, we can elide the load, zap the store, and usually zap the
- // alloca.
- llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
- llvm::StoreInst *SI = 0;
- if (InsertBB->empty() ||
- !(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
- SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
- RV = Builder.CreateLoad(ReturnValue);
+ case ABIArgInfo::Direct:
+ if (RetAI.getCoerceToType() == ConvertType(RetTy) &&
+ RetAI.getDirectOffset() == 0) {
+ // The internal return value temp always will have pointer-to-return-type
+ // type, just do a load.
+
+ // If the instruction right before the insertion point is a store to the
+ // return value, we can elide the load, zap the store, and usually zap the
+ // alloca.
+ llvm::BasicBlock *InsertBB = Builder.GetInsertBlock();
+ llvm::StoreInst *SI = 0;
+ if (InsertBB->empty() ||
+ !(SI = dyn_cast<llvm::StoreInst>(&InsertBB->back())) ||
+ SI->getPointerOperand() != ReturnValue || SI->isVolatile()) {
+ RV = Builder.CreateLoad(ReturnValue);
+ } else {
+ // Get the stored value and nuke the now-dead store.
+ RetDbgLoc = SI->getDebugLoc();
+ RV = SI->getValueOperand();
+ SI->eraseFromParent();
+
+ // If that was the only use of the return value, nuke it as well now.
+ if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
+ cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
+ ReturnValue = 0;
+ }
+ }
} else {
- // Get the stored value and nuke the now-dead store.
- RetDbgInfo = SI->getDbgMetadata();
- RV = SI->getValueOperand();
- SI->eraseFromParent();
-
- // If that was the only use of the return value, nuke it as well now.
- if (ReturnValue->use_empty() && isa<llvm::AllocaInst>(ReturnValue)) {
- cast<llvm::AllocaInst>(ReturnValue)->eraseFromParent();
- ReturnValue = 0;
+ llvm::Value *V = ReturnValue;
+ // If the value is offset in memory, apply the offset now.
+ if (unsigned Offs = RetAI.getDirectOffset()) {
+ V = Builder.CreateBitCast(V, Builder.getInt8PtrTy());
+ V = Builder.CreateConstGEP1_32(V, Offs);
+ V = Builder.CreateBitCast(V,
+ llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
}
+
+ RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
}
break;
- }
- case ABIArgInfo::Ignore:
- break;
- case ABIArgInfo::Coerce:
- RV = CreateCoercedLoad(ReturnValue, RetAI.getCoerceToType(), *this);
+ case ABIArgInfo::Ignore:
break;
case ABIArgInfo::Expand:
@@ -1058,8 +1068,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
}
llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid();
- if (RetDbgInfo)
- Ret->setDbgMetadata(RetDbgInfo);
+ if (!RetDbgLoc.isUnknown())
+ Ret->setDebugLoc(RetDbgLoc);
}
RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
@@ -1089,7 +1099,8 @@ RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
if (hasAggregateLLVMType(ArgType))
return RValue::getAggregate(Local);
- return RValue::get(EmitLoadOfScalar(Local, false, ArgType));
+ unsigned Alignment = getContext().getDeclAlign(Param).getQuantity();
+ return RValue::get(EmitLoadOfScalar(Local, false, Alignment, ArgType));
}
RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
@@ -1149,49 +1160,60 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
const ABIArgInfo &ArgInfo = info_it->info;
RValue RV = I->first;
+ unsigned Alignment =
+ getContext().getTypeAlignInChars(I->second).getQuantity();
switch (ArgInfo.getKind()) {
- case ABIArgInfo::Indirect:
+ case ABIArgInfo::Indirect: {
if (RV.isScalar() || RV.isComplex()) {
// Make a temporary alloca to pass the argument.
Args.push_back(CreateMemTemp(I->second));
if (RV.isScalar())
- EmitStoreOfScalar(RV.getScalarVal(), Args.back(), false, I->second);
+ EmitStoreOfScalar(RV.getScalarVal(), Args.back(), false,
+ Alignment, I->second);
else
StoreComplexToAddr(RV.getComplexVal(), Args.back(), false);
} else {
Args.push_back(RV.getAggregateAddr());
}
break;
-
- case ABIArgInfo::Extend:
- case ABIArgInfo::Direct:
- if (RV.isScalar()) {
- Args.push_back(RV.getScalarVal());
- } else if (RV.isComplex()) {
- llvm::Value *Tmp = llvm::UndefValue::get(ConvertType(I->second));
- Tmp = Builder.CreateInsertValue(Tmp, RV.getComplexVal().first, 0);
- Tmp = Builder.CreateInsertValue(Tmp, RV.getComplexVal().second, 1);
- Args.push_back(Tmp);
- } else {
- Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
- }
- break;
+ }
case ABIArgInfo::Ignore:
break;
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
+ if (!isa<llvm::StructType>(ArgInfo.getCoerceToType()) &&
+ ArgInfo.getCoerceToType() == ConvertType(info_it->type) &&
+ ArgInfo.getDirectOffset() == 0) {
+ if (RV.isScalar())
+ Args.push_back(RV.getScalarVal());
+ else
+ Args.push_back(Builder.CreateLoad(RV.getAggregateAddr()));
+ break;
+ }
- case ABIArgInfo::Coerce: {
// FIXME: Avoid the conversion through memory if possible.
llvm::Value *SrcPtr;
if (RV.isScalar()) {
SrcPtr = CreateMemTemp(I->second, "coerce");
- EmitStoreOfScalar(RV.getScalarVal(), SrcPtr, false, I->second);
+ EmitStoreOfScalar(RV.getScalarVal(), SrcPtr, false, Alignment,
+ I->second);
} else if (RV.isComplex()) {
SrcPtr = CreateMemTemp(I->second, "coerce");
StoreComplexToAddr(RV.getComplexVal(), SrcPtr, false);
} else
SrcPtr = RV.getAggregateAddr();
+ // If the value is offset in memory, apply the offset now.
+ if (unsigned Offs = ArgInfo.getDirectOffset()) {
+ SrcPtr = Builder.CreateBitCast(SrcPtr, Builder.getInt8PtrTy());
+ SrcPtr = Builder.CreateConstGEP1_32(SrcPtr, Offs);
+ SrcPtr = Builder.CreateBitCast(SrcPtr,
+ llvm::PointerType::getUnqual(ArgInfo.getCoerceToType()));
+
+ }
+
// If the coerce-to type is a first class aggregate, we flatten it and
// pass the elements. Either way is semantically identical, but fast-isel
// and the optimizer generally likes scalar values better than FCAs.
@@ -1201,7 +1223,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::PointerType::getUnqual(STy));
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
llvm::Value *EltPtr = Builder.CreateConstGEP2_32(SrcPtr, 0, i);
- Args.push_back(Builder.CreateLoad(EltPtr));
+ llvm::LoadInst *LI = Builder.CreateLoad(EltPtr);
+ // We don't know what we're loading from.
+ LI->setAlignment(1);
+ Args.push_back(LI);
}
} else {
// In the simple case, just pass the coerced loaded value.
@@ -1294,39 +1319,43 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
CI->setName("call");
switch (RetAI.getKind()) {
- case ABIArgInfo::Indirect:
+ case ABIArgInfo::Indirect: {
+ unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
if (RetTy->isAnyComplexType())
return RValue::getComplex(LoadComplexFromAddr(Args[0], false));
if (CodeGenFunction::hasAggregateLLVMType(RetTy))
return RValue::getAggregate(Args[0]);
- return RValue::get(EmitLoadOfScalar(Args[0], false, RetTy));
-
- case ABIArgInfo::Extend:
- case ABIArgInfo::Direct:
- if (RetTy->isAnyComplexType()) {
- llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
- llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
- return RValue::getComplex(std::make_pair(Real, Imag));
- }
- if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
- llvm::Value *DestPtr = ReturnValue.getValue();
- bool DestIsVolatile = ReturnValue.isVolatile();
-
- if (!DestPtr) {
- DestPtr = CreateMemTemp(RetTy, "agg.tmp");
- DestIsVolatile = false;
- }
- Builder.CreateStore(CI, DestPtr, DestIsVolatile);
- return RValue::getAggregate(DestPtr);
- }
- return RValue::get(CI);
+ return RValue::get(EmitLoadOfScalar(Args[0], false, Alignment, RetTy));
+ }
case ABIArgInfo::Ignore:
// If we are ignoring an argument that had a result, make sure to
// construct the appropriate return value for our caller.
return GetUndefRValue(RetTy);
+
+ case ABIArgInfo::Extend:
+ case ABIArgInfo::Direct: {
+ if (RetAI.getCoerceToType() == ConvertType(RetTy) &&
+ RetAI.getDirectOffset() == 0) {
+ if (RetTy->isAnyComplexType()) {
+ llvm::Value *Real = Builder.CreateExtractValue(CI, 0);
+ llvm::Value *Imag = Builder.CreateExtractValue(CI, 1);
+ return RValue::getComplex(std::make_pair(Real, Imag));
+ }
+ if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ llvm::Value *DestPtr = ReturnValue.getValue();
+ bool DestIsVolatile = ReturnValue.isVolatile();
- case ABIArgInfo::Coerce: {
+ if (!DestPtr) {
+ DestPtr = CreateMemTemp(RetTy, "agg.tmp");
+ DestIsVolatile = false;
+ }
+ Builder.CreateStore(CI, DestPtr, DestIsVolatile);
+ return RValue::getAggregate(DestPtr);
+ }
+ return RValue::get(CI);
+ }
+
llvm::Value *DestPtr = ReturnValue.getValue();
bool DestIsVolatile = ReturnValue.isVolatile();
@@ -1335,12 +1364,22 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
DestIsVolatile = false;
}
- CreateCoercedStore(CI, DestPtr, DestIsVolatile, *this);
+ // If the value is offset in memory, apply the offset now.
+ llvm::Value *StorePtr = DestPtr;
+ if (unsigned Offs = RetAI.getDirectOffset()) {
+ StorePtr = Builder.CreateBitCast(StorePtr, Builder.getInt8PtrTy());
+ StorePtr = Builder.CreateConstGEP1_32(StorePtr, Offs);
+ StorePtr = Builder.CreateBitCast(StorePtr,
+ llvm::PointerType::getUnqual(RetAI.getCoerceToType()));
+ }
+ CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this);
+
+ unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();
if (RetTy->isAnyComplexType())
return RValue::getComplex(LoadComplexFromAddr(DestPtr, false));
if (CodeGenFunction::hasAggregateLLVMType(RetTy))
return RValue::getAggregate(DestPtr);
- return RValue::get(EmitLoadOfScalar(DestPtr, false, RetTy));
+ return RValue::get(EmitLoadOfScalar(DestPtr, false, Alignment, RetTy));
}
case ABIArgInfo::Expand:
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index c50fe90f8a81..bf26799b83f3 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
@@ -22,13 +23,13 @@ using namespace CodeGen;
static uint64_t
ComputeNonVirtualBaseClassOffset(ASTContext &Context,
const CXXRecordDecl *DerivedClass,
- CXXBaseSpecifierArray::iterator Start,
- CXXBaseSpecifierArray::iterator End) {
+ CastExpr::path_const_iterator Start,
+ CastExpr::path_const_iterator End) {
uint64_t Offset = 0;
const CXXRecordDecl *RD = DerivedClass;
- for (CXXBaseSpecifierArray::iterator I = Start; I != End; ++I) {
+ for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
const CXXBaseSpecifier *Base = *I;
assert(!Base->isVirtual() && "Should not see virtual bases here!");
@@ -50,12 +51,13 @@ ComputeNonVirtualBaseClassOffset(ASTContext &Context,
llvm::Constant *
CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
- const CXXBaseSpecifierArray &BasePath) {
- assert(!BasePath.empty() && "Base path should not be empty!");
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd) {
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
uint64_t Offset =
- ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
- BasePath.begin(), BasePath.end());
+ ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl,
+ PathBegin, PathEnd);
if (!Offset)
return 0;
@@ -131,11 +133,12 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ThisPtr,
llvm::Value *
CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue) {
- assert(!BasePath.empty() && "Base path should not be empty!");
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
- CXXBaseSpecifierArray::iterator Start = BasePath.begin();
+ CastExpr::path_const_iterator Start = PathBegin;
const CXXRecordDecl *VBase = 0;
// Get the virtual base.
@@ -147,11 +150,11 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
uint64_t NonVirtualOffset =
ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived,
- Start, BasePath.end());
+ Start, PathEnd);
// Get the base pointer type.
const llvm::Type *BasePtrTy =
- ConvertType((BasePath.end()[-1])->getType())->getPointerTo();
+ ConvertType((PathEnd[-1])->getType())->getPointerTo();
if (!NonVirtualOffset && !VBase) {
// Just cast back.
@@ -206,16 +209,17 @@ CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value,
llvm::Value *
CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue) {
- assert(!BasePath.empty() && "Base path should not be empty!");
+ assert(PathBegin != PathEnd && "Base path should not be empty!");
QualType DerivedTy =
getContext().getCanonicalType(getContext().getTagDeclType(Derived));
const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo();
llvm::Value *NonVirtualOffset =
- CGM.GetNonVirtualBaseClassOffset(Derived, BasePath);
+ CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
if (!NonVirtualOffset) {
// No offset, we can just cast back.
@@ -310,6 +314,28 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
return VTT;
}
+namespace {
+ /// Call the destructor for a direct base class.
+ struct CallBaseDtor : EHScopeStack::Cleanup {
+ const CXXRecordDecl *BaseClass;
+ bool BaseIsVirtual;
+ CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
+ : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const CXXRecordDecl *DerivedClass =
+ cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
+
+ const CXXDestructorDecl *D = BaseClass->getDestructor();
+ llvm::Value *Addr =
+ CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThis(),
+ DerivedClass, BaseClass,
+ BaseIsVirtual);
+ CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, Addr);
+ }
+ };
+}
+
static void EmitBaseInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXBaseOrMemberInitializer *BaseInit,
@@ -333,18 +359,14 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
// virtual bases, and we only do virtual bases for complete ctors.
llvm::Value *V =
CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
- BaseClassDecl,
- BaseInit->isBaseVirtual());
+ BaseClassDecl,
+ isBaseVirtual);
CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true);
- if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) {
- // FIXME: Is this OK for C++0x delegating constructors?
- CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup);
-
- CXXDestructorDecl *DD = BaseClassDecl->getDestructor();
- CGF.EmitCXXDestructorCall(DD, Dtor_Base, isBaseVirtual, V);
- }
+ if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor())
+ CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl,
+ isBaseVirtual);
}
static void EmitAggMemberInitializer(CodeGenFunction &CGF,
@@ -432,6 +454,25 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
// Emit the fall-through block.
CGF.EmitBlock(AfterFor, true);
}
+
+namespace {
+ struct CallMemberDtor : EHScopeStack::Cleanup {
+ FieldDecl *Field;
+ CXXDestructorDecl *Dtor;
+
+ CallMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor)
+ : Field(Field), Dtor(Dtor) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // FIXME: Is this OK for C++0x delegating constructors?
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
+
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ LHS.getAddress());
+ }
+ };
+}
static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
@@ -487,7 +528,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
BasePtr = llvm::PointerType::getUnqual(BasePtr);
llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(),
BasePtr);
- LHS = LValue::MakeAddr(BaseAddrPtr, CGF.MakeQualifiers(BaseElementTy));
+ LHS = CGF.MakeAddrLValue(BaseAddrPtr, BaseElementTy);
// Create an array index that will be used to walk over all of the
// objects we're constructing.
@@ -532,17 +573,9 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
return;
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (!RD->hasTrivialDestructor()) {
- // FIXME: Is this OK for C++0x delegating constructors?
- CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup);
-
- llvm::Value *ThisPtr = CGF.LoadCXXThis();
- LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
-
- CXXDestructorDecl *DD = RD->getDestructor();
- CGF.EmitCXXDestructorCall(DD, Dtor_Complete, /*ForVirtualBase=*/false,
- LHS.getAddress());
- }
+ if (!RD->hasTrivialDestructor())
+ CGF.EHStack.pushCleanup<CallMemberDtor>(EHCleanup, Field,
+ RD->getDestructor());
}
}
@@ -598,6 +631,8 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
// Before we go any further, try the complete->base constructor
// delegation optimization.
if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor)) {
+ if (CGDebugInfo *DI = getDebugInfo())
+ DI->EmitStopPoint(Builder);
EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args);
return;
}
@@ -663,113 +698,158 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
CXXDtorType DtorType = CurGD.getDtorType();
+ // The call to operator delete in a deleting destructor happens
+ // outside of the function-try-block, which means it's always
+ // possible to delegate the destructor body to the complete
+ // destructor. Do so.
+ if (DtorType == Dtor_Deleting) {
+ EnterDtorCleanups(Dtor, Dtor_Deleting);
+ EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ LoadCXXThis());
+ PopCleanupBlock();
+ return;
+ }
+
Stmt *Body = Dtor->getBody();
// If the body is a function-try-block, enter the try before
- // anything else --- unless we're in a deleting destructor, in which
- // case we're just going to call the complete destructor and then
- // call operator delete() on the way out.
- bool isTryBody = (DtorType != Dtor_Deleting &&
- Body && isa<CXXTryStmt>(Body));
+ // anything else.
+ bool isTryBody = (Body && isa<CXXTryStmt>(Body));
if (isTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
- // Emit the destructor epilogue now. If this is a complete
- // destructor with a function-try-block, perform the base epilogue
- // as well.
- //
- // FIXME: This isn't really right, because an exception in the
- // non-EH epilogue should jump to the appropriate place in the
- // EH epilogue.
- {
- CleanupBlock Cleanup(*this, NormalCleanup);
-
- if (isTryBody && DtorType == Dtor_Complete)
- EmitDtorEpilogue(Dtor, Dtor_Base);
- EmitDtorEpilogue(Dtor, DtorType);
-
- if (Exceptions) {
- Cleanup.beginEHCleanup();
-
- if (isTryBody && DtorType == Dtor_Complete)
- EmitDtorEpilogue(Dtor, Dtor_Base);
- EmitDtorEpilogue(Dtor, DtorType);
- }
- }
-
- bool SkipBody = false; // should get jump-threaded
-
- // If this is the deleting variant, just invoke the complete
- // variant, then call the appropriate operator delete() on the way
- // out.
- if (DtorType == Dtor_Deleting) {
- EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- LoadCXXThis());
- SkipBody = true;
-
+ // Enter the epilogue cleanups.
+ RunCleanupsScope DtorEpilogue(*this);
+
// If this is the complete variant, just invoke the base variant;
// the epilogue will destruct the virtual bases. But we can't do
// this optimization if the body is a function-try-block, because
// we'd introduce *two* handler blocks.
- } else if (!isTryBody && DtorType == Dtor_Complete) {
- EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
- LoadCXXThis());
- SkipBody = true;
+ switch (DtorType) {
+ case Dtor_Deleting: llvm_unreachable("already handled deleting case");
+
+ case Dtor_Complete:
+ // Enter the cleanup scopes for virtual bases.
+ EnterDtorCleanups(Dtor, Dtor_Complete);
+
+ if (!isTryBody) {
+ EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
+ LoadCXXThis());
+ break;
+ }
+ // Fallthrough: act like we're in the base variant.
- // Otherwise, we're in the base variant, so we need to ensure the
- // vtable ptrs are right before emitting the body.
- } else {
+ case Dtor_Base:
+ // Enter the cleanup scopes for fields and non-virtual bases.
+ EnterDtorCleanups(Dtor, Dtor_Base);
+
+ // Initialize the vtable pointers before entering the body.
InitializeVTablePointers(Dtor->getParent());
- }
- // Emit the body of the statement.
- if (SkipBody)
- (void) 0;
- else if (isTryBody)
- EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
- else if (Body)
- EmitStmt(Body);
- else {
- assert(Dtor->isImplicit() && "bodyless dtor not implicit");
- // nothing to do besides what's in the epilogue
+ if (isTryBody)
+ EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
+ else if (Body)
+ EmitStmt(Body);
+ else {
+ assert(Dtor->isImplicit() && "bodyless dtor not implicit");
+ // nothing to do besides what's in the epilogue
+ }
+ break;
}
- // We're done with the epilogue cleanup.
- PopCleanupBlock();
+ // Jump out through the epilogue cleanups.
+ DtorEpilogue.ForceCleanup();
// Exit the try if applicable.
if (isTryBody)
ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
}
+namespace {
+ /// Call the operator delete associated with the current destructor.
+ struct CallDtorDelete : EHScopeStack::Cleanup {
+ CallDtorDelete() {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(), CGF.LoadCXXThis(),
+ CGF.getContext().getTagDeclType(ClassDecl));
+ }
+ };
+
+ struct CallArrayFieldDtor : EHScopeStack::Cleanup {
+ const FieldDecl *Field;
+ CallArrayFieldDtor(const FieldDecl *Field) : Field(Field) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ QualType FieldType = Field->getType();
+ const ConstantArrayType *Array =
+ CGF.getContext().getAsConstantArrayType(FieldType);
+
+ QualType BaseType =
+ CGF.getContext().getBaseElementType(Array->getElementType());
+ const CXXRecordDecl *FieldClassDecl = BaseType->getAsCXXRecordDecl();
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS = CGF.EmitLValueForField(ThisPtr, Field,
+ // FIXME: Qualifiers?
+ /*CVRQualifiers=*/0);
+
+ const llvm::Type *BasePtr = CGF.ConvertType(BaseType)->getPointerTo();
+ llvm::Value *BaseAddrPtr =
+ CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+ CGF.EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(),
+ Array, BaseAddrPtr);
+ }
+ };
+
+ struct CallFieldDtor : EHScopeStack::Cleanup {
+ const FieldDecl *Field;
+ CallFieldDtor(const FieldDecl *Field) : Field(Field) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const CXXRecordDecl *FieldClassDecl =
+ Field->getType()->getAsCXXRecordDecl();
+
+ llvm::Value *ThisPtr = CGF.LoadCXXThis();
+ LValue LHS = CGF.EmitLValueForField(ThisPtr, Field,
+ // FIXME: Qualifiers?
+ /*CVRQualifiers=*/0);
+
+ CGF.EmitCXXDestructorCall(FieldClassDecl->getDestructor(),
+ Dtor_Complete, /*ForVirtualBase=*/false,
+ LHS.getAddress());
+ }
+ };
+}
+
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
/// destructor. This is to call destructors on members and base classes
/// in reverse order of their construction.
-void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
- CXXDtorType DtorType) {
+void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
+ CXXDtorType DtorType) {
assert(!DD->isTrivial() &&
"Should not emit dtor epilogue for trivial dtor!");
- const CXXRecordDecl *ClassDecl = DD->getParent();
-
- // In a deleting destructor, we've already called the complete
- // destructor as a subroutine, so we just have to delete the
- // appropriate value.
+ // The deleting-destructor phase just needs to call the appropriate
+ // operator delete that Sema picked up.
if (DtorType == Dtor_Deleting) {
assert(DD->getOperatorDelete() &&
"operator delete missing - EmitDtorEpilogue");
- EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(),
- getContext().getTagDeclType(ClassDecl));
+ EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
return;
}
- // For complete destructors, we've already called the base
- // destructor (in GenerateBody), so we just need to destruct all the
- // virtual bases.
+ const CXXRecordDecl *ClassDecl = DD->getParent();
+
+ // The complete-destructor phase just destructs all the virtual bases.
if (DtorType == Dtor_Complete) {
- // Handle virtual bases.
- for (CXXRecordDecl::reverse_base_class_const_iterator I =
- ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend();
+
+ // We push them in the forward order so that they'll be popped in
+ // the reverse order.
+ for (CXXRecordDecl::base_class_const_iterator I =
+ ClassDecl->vbases_begin(), E = ClassDecl->vbases_end();
I != E; ++I) {
const CXXBaseSpecifier &Base = *I;
CXXRecordDecl *BaseClassDecl
@@ -778,26 +858,48 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
// Ignore trivial destructors.
if (BaseClassDecl->hasTrivialDestructor())
continue;
- const CXXDestructorDecl *D = BaseClassDecl->getDestructor();
- llvm::Value *V =
- GetAddressOfDirectBaseInCompleteClass(LoadCXXThis(),
- ClassDecl, BaseClassDecl,
- /*BaseIsVirtual=*/true);
- EmitCXXDestructorCall(D, Dtor_Base, /*ForVirtualBase=*/true, V);
+
+ EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup,
+ BaseClassDecl,
+ /*BaseIsVirtual*/ true);
}
+
return;
}
assert(DtorType == Dtor_Base);
+
+ // Destroy non-virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I =
+ ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) {
+ const CXXBaseSpecifier &Base = *I;
+
+ // Ignore virtual bases.
+ if (Base.isVirtual())
+ continue;
+
+ CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl();
+
+ // Ignore trivial destructors.
+ if (BaseClassDecl->hasTrivialDestructor())
+ continue;
+
+ EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup,
+ BaseClassDecl,
+ /*BaseIsVirtual*/ false);
+ }
- // Collect the fields.
+ // Destroy direct 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 ConstantArrayType *Array =
+ getContext().getAsConstantArrayType(FieldType);
+ if (Array)
+ FieldType = getContext().getBaseElementType(Array->getElementType());
const RecordType *RT = FieldType->getAs<RecordType>();
if (!RT)
@@ -806,64 +908,11 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (FieldClassDecl->hasTrivialDestructor())
continue;
-
- FieldDecls.push_back(Field);
- }
-
- // 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,
- // 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(),
- Array, BaseAddrPtr);
- } else
- EmitCXXDestructorCall(FieldClassDecl->getDestructor(),
- Dtor_Complete, /*ForVirtualBase=*/false,
- LHS.getAddress());
- }
-
- // 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());
-
- // Ignore trivial destructors.
- if (BaseClassDecl->hasTrivialDestructor())
- continue;
-
- const CXXDestructorDecl *D = BaseClassDecl->getDestructor();
- llvm::Value *V =
- GetAddressOfDirectBaseInCompleteClass(LoadCXXThis(), ClassDecl,
- BaseClassDecl,
- /*BaseIsVirtual=*/false);
-
- EmitCXXDestructorCall(D, Dtor_Base, /*ForVirtualBase=*/false, V);
+ if (Array)
+ EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
+ else
+ EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
}
}
@@ -873,19 +922,24 @@ void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD,
/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the
/// array type and 'ArrayPtr' points to the beginning fo the array.
/// It is assumed that all relevant checks have been made by the caller.
+///
+/// \param ZeroInitialization True if each element should be zero-initialized
+/// before it is constructed.
void
CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
- const ConstantArrayType *ArrayTy,
- llvm::Value *ArrayPtr,
- CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd) {
+ const ConstantArrayType *ArrayTy,
+ llvm::Value *ArrayPtr,
+ CallExpr::const_arg_iterator ArgBeg,
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization) {
const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
llvm::Value * NumElements =
llvm::ConstantInt::get(SizeTy,
getContext().getConstantArrayElementCount(ArrayTy));
- EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd);
+ EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd,
+ ZeroInitialization);
}
void
@@ -893,7 +947,8 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *NumElements,
llvm::Value *ArrayPtr,
CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd) {
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization) {
const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
// Create a temporary for the loop index and initialize it with 0.
@@ -924,6 +979,11 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter,
"arrayidx");
+ // Zero initialize the storage, if requested.
+ if (ZeroInitialization)
+ EmitNullInitialization(Address,
+ getContext().getTypeDeclType(D->getParent()));
+
// C++ [class.temporary]p4:
// There are two contexts in which temporaries are destroyed at a different
// point than the end of the full-expression. The first context is when a
@@ -1109,21 +1169,33 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0);
}
+namespace {
+ struct CallLocalDtor : EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+ llvm::Value *Addr;
+
+ CallLocalDtor(const CXXDestructorDecl *D, llvm::Value *Addr)
+ : Dtor(D), Addr(Addr) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false, Addr);
+ }
+ };
+}
+
+void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
+ llvm::Value *Addr) {
+ EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr);
+}
+
void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl();
if (!ClassDecl) return;
if (ClassDecl->hasTrivialDestructor()) return;
const CXXDestructorDecl *D = ClassDecl->getDestructor();
-
- CleanupBlock Scope(*this, NormalCleanup);
-
- EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Addr);
-
- if (Exceptions) {
- Scope.beginEHCleanup();
- EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Addr);
- }
+ PushDestructorCleanup(D, Addr);
}
llvm::Value *
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 4e158955f894..406db886eeed 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -15,7 +15,9 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/Basic/SourceManager.h"
@@ -37,7 +39,7 @@ using namespace clang::CodeGen;
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugFactory(CGM.getModule()),
- FwdDeclCount(0), BlockLiteralGenericSet(false) {
+ BlockLiteralGenericSet(false) {
CreateCompileUnit();
}
@@ -93,6 +95,58 @@ llvm::StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
return llvm::StringRef(StrPtr, NS.length());
}
+llvm::StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
+ llvm::SmallString<256> MethodName;
+ llvm::raw_svector_ostream OS(MethodName);
+ OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
+ const DeclContext *DC = OMD->getDeclContext();
+ if (const ObjCImplementationDecl *OID = dyn_cast<const ObjCImplementationDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const ObjCCategoryImplDecl *OCD = dyn_cast<const ObjCCategoryImplDecl>(DC)){
+ OS << ((NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
+ OCD->getIdentifier()->getNameStart() << ')';
+ }
+ OS << ' ' << OMD->getSelector().getAsString() << ']';
+
+ char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
+ memcpy(StrPtr, MethodName.begin(), OS.tell());
+ return llvm::StringRef(StrPtr, OS.tell());
+}
+
+/// getClassName - Get class name including template argument list.
+llvm::StringRef
+CGDebugInfo::getClassName(RecordDecl *RD) {
+ ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(RD);
+ if (!Spec)
+ return RD->getName();
+
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ std::string Buffer;
+ if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(TAW->getType());
+ Args = TST->getArgs();
+ NumArgs = TST->getNumArgs();
+ } else {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ Args = TemplateArgs.getFlatArgumentList();
+ NumArgs = TemplateArgs.flat_size();
+ }
+ Buffer = RD->getIdentifier()->getNameStart();
+ PrintingPolicy Policy(CGM.getLangOptions());
+ Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
+ NumArgs,
+ Policy);
+
+ // Copy this name on the side and use its reference.
+ char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length());
+ memcpy(StrPtr, Buffer.data(), Buffer.length());
+ return llvm::StringRef(StrPtr, Buffer.length());
+
+}
+
/// getOrCreateFile - Get the file debug info descriptor for the input location.
llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
if (!Loc.isValid())
@@ -113,13 +167,8 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
return llvm::DIFile(cast<llvm::MDNode>(it->second));
}
- // FIXME: We shouldn't even need to call 'makeAbsolute()' in the cases
- // where we can consult the FileEntry.
- llvm::sys::Path AbsFileName(PLoc.getFilename());
- AbsFileName.makeAbsolute();
-
- llvm::DIFile F = DebugFactory.CreateFile(AbsFileName.getLast(),
- AbsFileName.getDirname(), TheCU);
+ llvm::DIFile F = DebugFactory.CreateFile(PLoc.getFilename(),
+ getCurrentDirname(), TheCU);
DIFileCache[fname] = F;
return F;
@@ -144,6 +193,16 @@ unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
return PLoc.getColumn();
}
+llvm::StringRef CGDebugInfo::getCurrentDirname() {
+ if (!CWDName.empty())
+ return CWDName;
+ char *CompDirnamePtr = NULL;
+ llvm::sys::Path CWD = llvm::sys::Path::GetCurrentDirectory();
+ CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
+ memcpy(CompDirnamePtr, CWD.c_str(), CWD.size());
+ return CWDName = llvm::StringRef(CompDirnamePtr, CWD.size());
+}
+
/// CreateCompileUnit - Create new compile unit.
void CGDebugInfo::CreateCompileUnit() {
@@ -153,19 +212,22 @@ void CGDebugInfo::CreateCompileUnit() {
if (MainFileName.empty())
MainFileName = "<unknown>";
- llvm::sys::Path AbsFileName(MainFileName);
- AbsFileName.makeAbsolute();
-
// The main file name provided via the "-main-file-name" option contains just
// the file name itself with no path information. This file name may have had
// a relative path, so we look into the actual file entry for the main
// file to determine the real absolute path for the file.
std::string MainFileDir;
- if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID()))
+ if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
MainFileDir = MainFile->getDir()->getName();
- else
- MainFileDir = AbsFileName.getDirname();
+ if (MainFileDir != ".")
+ MainFileName = MainFileDir + "/" + MainFileName;
+ }
+ // Save filename string.
+ char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
+ memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
+ llvm::StringRef Filename(FilenamePtr, MainFileName.length());
+
unsigned LangTag;
const LangOptions &LO = CGM.getLangOptions();
if (LO.CPlusPlus) {
@@ -181,11 +243,7 @@ void CGDebugInfo::CreateCompileUnit() {
LangTag = llvm::dwarf::DW_LANG_C89;
}
- const char *Producer =
-#ifdef CLANG_VENDOR
- CLANG_VENDOR
-#endif
- "clang " CLANG_VERSION_STRING;
+ std::string Producer = getClangFullVersion();
// Figure out which version of the ObjC runtime we have.
unsigned RuntimeVers = 0;
@@ -194,7 +252,8 @@ void CGDebugInfo::CreateCompileUnit() {
// Create new compile unit.
TheCU = DebugFactory.CreateCompileUnit(
- LangTag, AbsFileName.getLast(), MainFileDir, Producer, true,
+ LangTag, Filename, getCurrentDirname(),
+ Producer, true,
LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
}
@@ -203,10 +262,49 @@ void CGDebugInfo::CreateCompileUnit() {
llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
llvm::DIFile Unit) {
unsigned Encoding = 0;
+ const char *BTName = NULL;
switch (BT->getKind()) {
default:
case BuiltinType::Void:
return llvm::DIType();
+ case BuiltinType::ObjCClass:
+ return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
+ Unit, "objc_class", Unit, 0, 0, 0, 0,
+ llvm::DIType::FlagFwdDecl,
+ llvm::DIType(), llvm::DIArray());
+ case BuiltinType::ObjCId: {
+ // typedef struct objc_class *Class;
+ // typedef struct objc_object {
+ // Class isa;
+ // } *id;
+
+ llvm::DIType OCTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
+ Unit, "objc_class", Unit, 0, 0, 0, 0,
+ llvm::DIType::FlagFwdDecl,
+ llvm::DIType(), llvm::DIArray());
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+
+ llvm::DIType ISATy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type,
+ Unit, "", Unit,
+ 0, Size, 0, 0, 0, OCTy);
+
+ llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
+
+ llvm::DIType FieldTy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "isa", Unit,
+ 0,Size, 0, 0, 0, ISATy);
+ EltTys.push_back(FieldTy);
+ llvm::DIArray Elements =
+ DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type,
+ Unit, "objc_object", Unit, 0, 0, 0, 0,
+ 0,
+ llvm::DIType(), Elements);
+ }
case BuiltinType::UChar:
case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
case BuiltinType::Char_S:
@@ -224,14 +322,23 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
case BuiltinType::LongDouble:
case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
}
+
+ switch (BT->getKind()) {
+ case BuiltinType::Long: BTName = "long int"; break;
+ case BuiltinType::LongLong: BTName = "long long int"; break;
+ case BuiltinType::ULong: BTName = "long unsigned int"; break;
+ case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;
+ default:
+ BTName = BT->getName(CGM.getContext().getLangOptions());
+ break;
+ }
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
uint64_t Offset = 0;
-
+
llvm::DIType DbgTy =
- DebugFactory.CreateBasicType(Unit,
- BT->getName(CGM.getContext().getLangOptions()),
+ DebugFactory.CreateBasicType(Unit, BTName,
Unit, 0, Size, Align,
Offset, /*flags*/ 0, Encoding);
return DbgTy;
@@ -461,7 +568,6 @@ CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
I != E; ++I, ++FieldNo) {
FieldDecl *Field = *I;
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
-
llvm::StringRef FieldName = Field->getName();
// Ignore unnamed fields. Do not ignore unnamed records.
@@ -481,7 +587,6 @@ CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit,
Expr *BitWidth = Field->getBitWidth();
if (BitWidth)
FieldSize = BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
-
FieldAlign = CGM.getContext().getTypeAlign(FType);
}
@@ -516,9 +621,12 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
0),
Unit);
- // Static methods do not need "this" pointer argument.
- if (Method->isStatic())
- return FnTy;
+ unsigned BFlags=0;
+ AccessSpecifier Access = Method->getAccess();
+ if (Access == clang::AS_private)
+ BFlags |= llvm::DIType::FlagPrivate;
+ else if (Access == clang::AS_protected)
+ BFlags |= llvm::DIType::FlagProtected;
// Add "this" pointer.
@@ -530,27 +638,18 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
// First element is always return type. For 'void' functions it is NULL.
Elts.push_back(Args.getElement(0));
- // "this" pointer is always first argument.
- ASTContext &Context = CGM.getContext();
- QualType ThisPtr =
- Context.getPointerType(Context.getTagDeclType(Method->getParent()));
- llvm::DIType ThisPtrType =
- DebugFactory.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
-
- unsigned Quals = Method->getTypeQualifiers();
- if (Quals & Qualifiers::Const)
- ThisPtrType =
- DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_const_type,
- Unit, "", Unit,
- 0, 0, 0, 0, 0, ThisPtrType);
- if (Quals & Qualifiers::Volatile)
- ThisPtrType =
- DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_volatile_type,
- Unit, "", Unit,
- 0, 0, 0, 0, 0, ThisPtrType);
-
- TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
- Elts.push_back(ThisPtrType);
+ if (!Method->isStatic())
+ {
+ // "this" pointer is always first argument.
+ ASTContext &Context = CGM.getContext();
+ QualType ThisPtr =
+ Context.getPointerType(Context.getTagDeclType(Method->getParent()));
+ llvm::DIType ThisPtrType =
+ DebugFactory.CreateArtificialType(getOrCreateType(ThisPtr, Unit));
+
+ TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
+ Elts.push_back(ThisPtrType);
+ }
// Copy rest of the arguments.
for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
@@ -571,7 +670,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DISubprogram
CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile Unit,
- llvm::DICompositeType &RecordTy) {
+ llvm::DIType RecordTy) {
bool IsCtorOrDtor =
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
@@ -612,7 +711,9 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
MethodDefUnit, MethodLine,
MethodTy, /*isLocalToUnit=*/false,
/* isDefintion=*/ false,
- Virtuality, VIndex, ContainingType);
+ Virtuality, VIndex, ContainingType,
+ Method->isImplicit(),
+ CGM.getLangOptions().Optimize);
// Don't cache ctors or dtors since we have to emit multiple functions for
// a single ctor or dtor.
@@ -628,7 +729,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
void CGDebugInfo::
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
- llvm::DICompositeType &RecordTy) {
+ llvm::DIType RecordTy) {
for(CXXRecordDecl::method_iterator I = RD->method_begin(),
E = RD->method_end(); I != E; ++I) {
const CXXMethodDecl *Method = *I;
@@ -640,13 +741,41 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
}
}
+/// CollectCXXFriends - A helper function to collect debug info for
+/// C++ base classes. This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
+ llvm::DIType RecordTy) {
+
+ for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
+ BE = RD->friend_end(); BI != BE; ++BI) {
+
+ TypeSourceInfo *TInfo = (*BI)->getFriendType();
+ if(TInfo)
+ {
+ llvm::DIType Ty = getOrCreateType(TInfo->getType(), Unit);
+
+ llvm::DIType DTy =
+ DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_friend,
+ RecordTy, llvm::StringRef(),
+ Unit, 0, 0, 0,
+ 0, 0, Ty);
+
+ EltTys.push_back(DTy);
+ }
+
+ }
+}
+
/// CollectCXXBases - A helper function to collect debug info for
/// C++ base classes. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::
CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
- llvm::DICompositeType &RecordTy) {
+ llvm::DIType RecordTy) {
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
@@ -786,14 +915,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
return FwdDecl;
}
- // A RD->getName() is not unique. However, the debug info descriptors
- // are uniqued so use type name to ensure uniquness.
- llvm::SmallString<128> FwdDeclName;
- llvm::raw_svector_ostream(FwdDeclName) << "fwd.type." << FwdDeclCount++;
- llvm::DICompositeType FwdDecl =
- DebugFactory.CreateCompositeType(Tag, FDContext, FwdDeclName,
- DefUnit, Line, 0, 0, 0, 0,
- llvm::DIType(), llvm::DIArray());
+ llvm::DIType FwdDecl = DebugFactory.CreateTemporaryType();
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -812,10 +934,36 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl);
CollectVTableInfo(CXXDecl, Unit, EltTys);
}
+
+ // Collect static variables with initializers.
+ for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
+ I != E; ++I)
+ if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
+ if (const Expr *Init = V->getInit()) {
+ Expr::EvalResult Result;
+ if (Init->Evaluate(Result, CGM.getContext()) && Result.Val.isInt()) {
+ llvm::ConstantInt *CI
+ = llvm::ConstantInt::get(CGM.getLLVMContext(), Result.Val.getInt());
+
+ // Create the descriptor for static variable.
+ llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
+ llvm::StringRef VName = V->getName();
+ llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
+ // Do not use DIGlobalVariable for enums.
+ if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
+ DebugFactory.CreateGlobalVariable(FwdDecl, VName, VName, VName, VUnit,
+ getLineNumber(V->getLocation()),
+ VTy, true, true, CI);
+ }
+ }
+ }
+ }
+
CollectRecordFields(RD, Unit, EltTys);
llvm::MDNode *ContainingType = NULL;
if (CXXDecl) {
CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl);
+ CollectCXXFriends(CXXDecl, Unit, EltTys, FwdDecl);
// A class's primary base or the class itself contains the vtable.
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
@@ -841,16 +989,22 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
llvm::DIDescriptor RDContext =
getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit);
+
+ llvm::StringRef RDName = RD->getName();
+ // If this is a class, include the template arguments also.
+ if (Tag == llvm::dwarf::DW_TAG_class_type)
+ RDName = getClassName(RD);
+
llvm::DICompositeType RealDecl =
DebugFactory.CreateCompositeType(Tag, RDContext,
- RD->getName(),
+ RDName,
DefUnit, Line, Size, Align, 0, 0,
llvm::DIType(), Elements,
0, ContainingType);
// 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.
- llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
+ llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
RegionMap[RD] = llvm::WeakVH(RealDecl);
return RealDecl;
}
@@ -873,21 +1027,24 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
unsigned Line = getLineNumber(ID->getLocation());
unsigned RuntimeLang = TheCU.getLanguage();
+ // If this is just a forward declaration, return a special forward-declaration
+ // debug type.
+ if (ID->isForwardDecl()) {
+ llvm::DICompositeType FwdDecl =
+ DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(),
+ DefUnit, Line, 0, 0, 0, 0,
+ llvm::DIType(), llvm::DIArray(),
+ RuntimeLang);
+ return FwdDecl;
+ }
+
// To handle recursive interface, we
// first generate a debug descriptor for the struct as a forward declaration.
// Then (if it is a definition) we go through and get debug info for all of
// its members. Finally, we create a descriptor for the complete type (which
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DICompositeType FwdDecl =
- DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(),
- DefUnit, Line, 0, 0, 0, 0,
- llvm::DIType(), llvm::DIArray(),
- RuntimeLang);
-
- // If this is just a forward declaration, return it.
- if (ID->isForwardDecl())
- return FwdDecl;
+ llvm::DIType FwdDecl = DebugFactory.CreateTemporaryType();
llvm::MDNode *MN = FwdDecl;
llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
@@ -982,7 +1139,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// 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.
- llvm::DIDerivedType(FwdDeclNode).replaceAllUsesWith(RealDecl);
+ llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl);
RegionMap[ID] = llvm::WeakVH(RealDecl);
return RealDecl;
@@ -990,39 +1147,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
llvm::DIFile Unit) {
- EnumDecl *ED = Ty->getDecl();
-
- llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
-
- // Create DIEnumerator elements for each enumerator.
- for (EnumDecl::enumerator_iterator
- Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
- Enum != EnumEnd; ++Enum) {
- Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getName(),
- Enum->getInitVal().getZExtValue()));
- }
+ return CreateEnumType(Ty->getDecl(), Unit);
- // Return a CompositeType for the enum itself.
- llvm::DIArray EltArray =
- DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size());
-
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
- unsigned Line = getLineNumber(ED->getLocation());
-
- // Size and align of the type.
- uint64_t Size = 0;
- unsigned Align = 0;
- if (!Ty->isIncompleteType()) {
- Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
- }
-
- llvm::DIType DbgTy =
- DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
- Unit, ED->getName(), DefUnit, Line,
- Size, Align, 0, 0,
- llvm::DIType(), EltArray);
- return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
@@ -1036,7 +1162,7 @@ llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
}
llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
- llvm::DIFile Unit) {
+ llvm::DIFile Unit) {
llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
uint64_t NumElems = Ty->getNumElements();
if (NumElems > 0)
@@ -1052,7 +1178,7 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty,
DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_vector_type,
Unit, "", Unit,
0, Size, Align, 0, 0,
- ElementTy, SubscriptArray);
+ ElementTy, SubscriptArray);
}
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
@@ -1149,6 +1275,38 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
0, 0, 0, llvm::DIType(), Elements);
}
+/// CreateEnumType - get enumeration type.
+llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED, llvm::DIFile Unit){
+ llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
+
+ // Create DIEnumerator elements for each enumerator.
+ for (EnumDecl::enumerator_iterator
+ Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
+ Enum != EnumEnd; ++Enum) {
+ Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getName(),
+ Enum->getInitVal().getZExtValue()));
+ }
+
+ // Return a CompositeType for the enum itself.
+ llvm::DIArray EltArray =
+ DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size());
+
+ llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
+ unsigned Line = getLineNumber(ED->getLocation());
+ uint64_t Size = 0;
+ uint64_t Align = 0;
+ if (!ED->getTypeForDecl()->isIncompleteType()) {
+ Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
+ Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ }
+ llvm::DIType DbgTy =
+ DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
+ Unit, ED->getName(), DefUnit, Line,
+ Size, Align, 0, 0,
+ llvm::DIType(), EltArray);
+ return DbgTy;
+}
+
static QualType UnwrapTypeForDebugInfo(QualType T) {
do {
QualType LastT = T;
@@ -1312,6 +1470,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
llvm::StringRef Name;
llvm::StringRef LinkageName;
+ FnBeginRegionCount.push_back(RegionStack.size());
+
const Decl *D = GD.getDecl();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// If there is a DISubprogram for this function available then use it.
@@ -1329,6 +1489,9 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
Name = getFunctionName(FD);
// Use mangled name as linkage name for c/c++ functions.
LinkageName = CGM.getMangledName(GD);
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+ Name = getObjCMethodName(OMD);
+ LinkageName = Name;
} else {
// Use llvm function name as linkage name.
Name = Fn->getName();
@@ -1346,16 +1509,22 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
llvm::DISubprogram SP =
DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo,
getOrCreateType(FnType, Unit),
- Fn->hasInternalLinkage(), true/*definition*/);
+ Fn->hasInternalLinkage(), true/*definition*/,
+ 0, 0, llvm::DIType(),
+ D->isImplicit(),
+ CGM.getLangOptions().Optimize, Fn);
// Push function on region stack.
llvm::MDNode *SPN = SP;
RegionStack.push_back(SPN);
RegionMap[D] = llvm::WeakVH(SP);
+
+ // Clear stack used to keep track of #line directives.
+ LineDirectiveFiles.clear();
}
-void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
+void CGDebugInfo::EmitStopPoint(CGBuilderTy &Builder) {
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
// Don't bother if things are the same as last time.
@@ -1377,13 +1546,63 @@ void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
Scope));
}
+/// UpdateLineDirectiveRegion - Update region stack only if #line directive
+/// has introduced scope change.
+void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) {
+ if (CurLoc.isInvalid() || CurLoc.isMacroID() ||
+ PrevLoc.isInvalid() || PrevLoc.isMacroID())
+ return;
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
+ PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
+
+ if (!strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
+ return;
+
+ // If #line directive stack is empty then we are entering a new scope.
+ if (LineDirectiveFiles.empty()) {
+ EmitRegionStart(Builder);
+ LineDirectiveFiles.push_back(PCLoc.getFilename());
+ return;
+ }
+
+ assert (RegionStack.size() >= LineDirectiveFiles.size()
+ && "error handling #line regions!");
+
+ bool SeenThisFile = false;
+ for(std::vector<const char *>::iterator I = LineDirectiveFiles.begin(),
+ E = LineDirectiveFiles.end(); I != E; ++I)
+ if (!strcmp(PPLoc.getFilename(), *I)) {
+ SeenThisFile = true;
+ break;
+ }
+
+ // If #line for this file is seen earlier then pop out #line regions.
+ if (SeenThisFile) {
+ while (!LineDirectiveFiles.empty()) {
+ const char *LastFile = LineDirectiveFiles.back();
+ RegionStack.pop_back();
+ LineDirectiveFiles.pop_back();
+ if (!strcmp(PPLoc.getFilename(), LastFile))
+ break;
+ }
+ return;
+ }
+
+ // .. otherwise insert new #line region.
+ EmitRegionStart(Builder);
+ LineDirectiveFiles.push_back(PCLoc.getFilename());
+
+ return;
+}
/// EmitRegionStart- Constructs the debug code for entering a declarative
/// region - "llvm.dbg.region.start.".
-void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
+void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) {
llvm::DIDescriptor D =
DebugFactory.CreateLexicalBlock(RegionStack.empty() ?
llvm::DIDescriptor() :
llvm::DIDescriptor(RegionStack.back()),
+ getOrCreateFile(CurLoc),
getLineNumber(CurLoc),
getColumnNumber(CurLoc));
llvm::MDNode *DN = D;
@@ -1392,15 +1611,27 @@ void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
/// region - "llvm.dbg.region.end."
-void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) {
+void CGDebugInfo::EmitRegionEnd(CGBuilderTy &Builder) {
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
// Provide an region stop point.
- EmitStopPoint(Fn, Builder);
+ EmitStopPoint(Builder);
RegionStack.pop_back();
}
+/// EmitFunctionEnd - Constructs the debug code for exiting a function.
+void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
+ assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
+ unsigned RCount = FnBeginRegionCount.back();
+ assert(RCount <= RegionStack.size() && "Region stack mismatch");
+
+ // Pop all regions for this function.
+ while (RegionStack.size() != RCount)
+ EmitRegionEnd(Builder);
+ FnBeginRegionCount.pop_back();
+}
+
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
@@ -1643,6 +1874,26 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
true/*definition*/, Var);
}
+/// EmitGlobalVariable - Emit global variable's debug info.
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
+ llvm::ConstantInt *Init,
+ CGBuilderTy &Builder) {
+ // Create the descriptor for the variable.
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::StringRef Name = VD->getName();
+ llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
+ if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {
+ if (const EnumDecl *ED = dyn_cast<EnumDecl>(ECD->getDeclContext()))
+ Ty = CreateEnumType(ED, Unit);
+ }
+ // Do not use DIGlobalVariable for enums.
+ if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
+ return;
+ DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit,
+ getLineNumber(VD->getLocation()),
+ Ty, true, true, Init);
+}
+
/// getOrCreateNamesSpace - Return namespace descriptor for the given
/// namespace decl.
llvm::DINameSpace
@@ -1659,7 +1910,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl,
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()), Unit);
llvm::DINameSpace NS =
DebugFactory.CreateNameSpace(Context, NSDecl->getName(),
- llvm::DIFile(Unit), LineNo);
+ llvm::DIFile(Unit), LineNo);
NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
return NS;
}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 620a5f2f8480..a1ad012353e5 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -46,9 +46,6 @@ class CGDebugInfo {
llvm::DICompileUnit TheCU;
SourceLocation CurLoc, PrevLoc;
llvm::DIType VTablePtrType;
- /// FwdDeclCount - This counter is used to ensure unique names for forward
- /// record decls.
- unsigned FwdDeclCount;
/// TypeCache - Cache of previously constructed Types.
llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
@@ -58,10 +55,19 @@ class CGDebugInfo {
std::vector<llvm::TrackingVH<llvm::MDNode> > RegionStack;
llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;
+ // FnBeginRegionCount - Keep track of RegionStack counter at the beginning
+ // of a function. This is used to pop unbalanced regions at the end of a
+ // function.
+ std::vector<unsigned> FnBeginRegionCount;
+
+ /// LineDirectiveFiles - This stack is used to keep track of
+ /// scopes introduced by #line directives.
+ std::vector<const char *> LineDirectiveFiles;
/// DebugInfoNames - This is a storage for names that are
/// constructed on demand. For example, C++ destructors, C++ operators etc..
llvm::BumpPtrAllocator DebugInfoNames;
+ llvm::StringRef CWDName;
llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
@@ -86,6 +92,7 @@ class CGDebugInfo {
llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);
llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateEnumType(const EnumDecl *ED, llvm::DIFile Unit);
llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile F);
llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
@@ -98,16 +105,22 @@ class CGDebugInfo {
llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile F,
- llvm::DICompositeType &RecordTy);
+ llvm::DIType RecordTy);
void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
llvm::DIFile F,
llvm::SmallVectorImpl<llvm::DIDescriptor> &E,
- llvm::DICompositeType &T);
+ llvm::DIType T);
+
+ void CollectCXXFriends(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
+ llvm::DIType RecordTy);
+
void CollectCXXBases(const CXXRecordDecl *Decl,
llvm::DIFile F,
llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys,
- llvm::DICompositeType &RecordTy);
+ llvm::DIType RecordTy);
void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
@@ -127,20 +140,27 @@ public:
/// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of
/// source line.
- void EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder);
+ void EmitStopPoint(CGBuilderTy &Builder);
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
/// start of a new function.
void EmitFunctionStart(GlobalDecl GD, QualType FnType,
llvm::Function *Fn, CGBuilderTy &Builder);
+ /// EmitFunctionEnd - Constructs the debug code for exiting a function.
+ void EmitFunctionEnd(CGBuilderTy &Builder);
+
+ /// UpdateLineDirectiveRegion - Update region stack only if #line directive
+ /// has introduced scope change.
+ void UpdateLineDirectiveRegion(CGBuilderTy &Builder);
+
/// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
/// of a new block.
- void EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder);
+ void EmitRegionStart(CGBuilderTy &Builder);
/// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a
/// block.
- void EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder);
+ void EmitRegionEnd(CGBuilderTy &Builder);
/// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic
/// variable declaration.
@@ -165,6 +185,10 @@ public:
/// EmitGlobalVariable - Emit information about an objective-c interface.
void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);
+ /// EmitGlobalVariable - Emit global variable's debug info.
+ void EmitGlobalVariable(const ValueDecl *VD, llvm::ConstantInt *Init,
+ CGBuilderTy &Builder);
+
private:
/// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
@@ -183,6 +207,9 @@ private:
llvm::DIDescriptor getContextDescriptor(const Decl *Decl,
llvm::DIDescriptor &CU);
+ /// getCurrentDirname - Return current directory name.
+ llvm::StringRef getCurrentDirname();
+
/// CreateCompileUnit - Create new compile unit.
void CreateCompileUnit();
@@ -205,6 +232,12 @@ private:
/// name is constructred on demand (e.g. C++ destructor) then the name
/// is stored on the side.
llvm::StringRef getFunctionName(const FunctionDecl *FD);
+ /// getObjCMethodName - Returns the unmangled name of an Objective-C method.
+ /// This is the display name for the debugging info.
+ llvm::StringRef getObjCMethodName(const ObjCMethodDecl *FD);
+
+ /// getClassName - Get class name including template argument list.
+ llvm::StringRef getClassName(RecordDecl *RD);
/// getVTableName - Get vtable name for the given Class.
llvm::StringRef getVTableName(const CXXRecordDecl *Decl);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 1a62ea95555d..57e5236c67e5 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -107,11 +107,11 @@ void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
CGM.ErrorUnsupported(&D, "__asm__");
switch (D.getStorageClass()) {
- case VarDecl::None:
- case VarDecl::Auto:
- case VarDecl::Register:
+ case SC_None:
+ case SC_Auto:
+ case SC_Register:
return EmitLocalBlockVarDecl(D);
- case VarDecl::Static: {
+ case SC_Static: {
llvm::GlobalValue::LinkageTypes Linkage =
llvm::GlobalValue::InternalLinkage;
@@ -126,8 +126,8 @@ void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) {
return EmitStaticBlockVarDecl(D, Linkage);
}
- case VarDecl::Extern:
- case VarDecl::PrivateExtern:
+ case SC_Extern:
+ case SC_PrivateExtern:
// Don't emit it now, allow it to be emitted lazily on its first use.
return;
}
@@ -183,7 +183,7 @@ llvm::GlobalVariable *
CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D,
llvm::GlobalVariable *GV) {
llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), D.getType(), this);
-
+
// If constant emission failed, then this should be a C++ static
// initializer.
if (!Init) {
@@ -198,12 +198,12 @@ CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D,
}
return GV;
}
-
+
// The initializer may differ in type from the global. Rewrite
// the global to match the initializer. (We have to do this
// because some types, like unions, can't be completely represented
// in the LLVM type system.)
- if (GV->getType() != Init->getType()) {
+ if (GV->getType()->getElementType() != Init->getType()) {
llvm::GlobalVariable *OldGV = GV;
GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
@@ -373,7 +373,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {
}
// T x;
- Types.push_back(ConvertType(Ty));
+ Types.push_back(ConvertTypeForMem(Ty));
const llvm::Type *T = llvm::StructType::get(VMContext, Types, Packed);
@@ -389,7 +389,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {
}
namespace {
- struct CallArrayDtor : EHScopeStack::LazyCleanup {
+ struct CallArrayDtor : EHScopeStack::Cleanup {
CallArrayDtor(const CXXDestructorDecl *Dtor,
const ConstantArrayType *Type,
llvm::Value *Loc)
@@ -408,7 +408,7 @@ namespace {
}
};
- struct CallVarDtor : EHScopeStack::LazyCleanup {
+ struct CallVarDtor : EHScopeStack::Cleanup {
CallVarDtor(const CXXDestructorDecl *Dtor,
llvm::Value *NRVOFlag,
llvm::Value *Loc)
@@ -440,12 +440,64 @@ namespace {
};
}
+namespace {
+ struct CallStackRestore : EHScopeStack::Cleanup {
+ llvm::Value *Stack;
+ CallStackRestore(llvm::Value *Stack) : Stack(Stack) {}
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ llvm::Value *V = CGF.Builder.CreateLoad(Stack, "tmp");
+ llvm::Value *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
+ CGF.Builder.CreateCall(F, V);
+ }
+ };
+
+ struct CallCleanupFunction : EHScopeStack::Cleanup {
+ llvm::Constant *CleanupFn;
+ const CGFunctionInfo &FnInfo;
+ llvm::Value *Addr;
+ const VarDecl &Var;
+
+ CallCleanupFunction(llvm::Constant *CleanupFn, const CGFunctionInfo *Info,
+ llvm::Value *Addr, const VarDecl *Var)
+ : CleanupFn(CleanupFn), FnInfo(*Info), Addr(Addr), Var(*Var) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // In some cases, the type of the function argument will be different from
+ // the type of the pointer. An example of this is
+ // void f(void* arg);
+ // __attribute__((cleanup(f))) void *g;
+ //
+ // To fix this we insert a bitcast here.
+ QualType ArgTy = FnInfo.arg_begin()->type;
+ llvm::Value *Arg =
+ CGF.Builder.CreateBitCast(Addr, CGF.ConvertType(ArgTy));
+
+ CallArgList Args;
+ Args.push_back(std::make_pair(RValue::get(Arg),
+ CGF.getContext().getPointerType(Var.getType())));
+ CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args);
+ }
+ };
+
+ struct CallBlockRelease : EHScopeStack::Cleanup {
+ llvm::Value *Addr;
+ CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ llvm::Value *V = CGF.Builder.CreateStructGEP(Addr, 1, "forwarding");
+ V = CGF.Builder.CreateLoad(V);
+ CGF.BuildBlockRelease(V);
+ }
+ };
+}
+
/// EmitLocalBlockVarDecl - Emit code and set up an entry in LocalDeclMap for a
/// variable declaration with auto, register, or no storage class specifier.
/// These turn into simple stack objects, or GlobalValues depending on target.
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
SpecialInitFn *SpecialInit) {
QualType Ty = D.getType();
+ unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
bool isByRef = D.hasAttr<BlocksAttr>();
bool needsDispose = false;
CharUnits Align = CharUnits::Zero();
@@ -461,10 +513,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
// If this value is an array or struct, is POD, and if the initializer is
// a staticly determinable constant, try to optimize it (unless the NRVO
// is already optimizing this).
- if (D.getInit() && !isByRef &&
+ if (!NRVO && D.getInit() && !isByRef &&
(Ty->isArrayType() || Ty->isRecordType()) &&
Ty->isPODType() &&
- D.getInit()->isConstantInitializer(getContext()) && !NRVO) {
+ D.getInit()->isConstantInitializer(getContext(), false)) {
// If this variable is marked 'const', emit the value as a global.
if (CGM.getCodeGenOpts().MergeAllConstants &&
Ty.isConstant(getContext())) {
@@ -516,7 +568,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
} else {
// Targets that don't support recursion emit locals as globals.
const char *Class =
- D.getStorageClass() == VarDecl::Register ? ".reg." : ".auto.";
+ D.getStorageClass() == SC_Register ? ".reg." : ".auto.";
DeclPtr = CreateStaticBlockVarDecl(D, Class,
llvm::GlobalValue
::InternalLinkage);
@@ -540,20 +592,14 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
DidCallStackSave = true;
- {
- // Push a cleanup block and restore the stack there.
- CleanupBlock scope(*this, NormalCleanup);
-
- V = Builder.CreateLoad(Stack, "tmp");
- llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::stackrestore);
- Builder.CreateCall(F, V);
- }
+ // Push a cleanup block and restore the stack there.
+ EHStack.pushCleanup<CallStackRestore>(NormalCleanup, Stack);
}
// Get the element type.
const llvm::Type *LElemTy = ConvertTypeForMem(Ty);
const llvm::Type *LElemPtrTy =
- llvm::PointerType::get(LElemTy, D.getType().getAddressSpace());
+ llvm::PointerType::get(LElemTy, Ty.getAddressSpace());
llvm::Value *VLASize = EmitVLASize(Ty);
@@ -658,13 +704,12 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D),
D.getNameAsString());
- bool isVolatile =
- getContext().getCanonicalType(D.getType()).isVolatileQualified();
+ bool isVolatile = getContext().getCanonicalType(Ty).isVolatileQualified();
// If the initializer was a simple constant initializer, we can optimize it
// in various ways.
if (IsSimpleConstantInitializer) {
- llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(),D.getType(),this);
+ llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(), Ty,this);
assert(Init != 0 && "Wasn't a simple constant init?");
llvm::Value *AlignVal =
@@ -708,10 +753,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
}
} else if (Ty->isReferenceType()) {
RValue RV = EmitReferenceBindingToExpr(Init, &D);
- EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty);
+ EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Alignment, Ty);
} else if (!hasAggregateLLVMType(Init->getType())) {
llvm::Value *V = EmitScalarExpr(Init);
- EmitStoreOfScalar(V, Loc, isVolatile, D.getType());
+ EmitStoreOfScalar(V, Loc, isVolatile, Alignment, Ty);
} else if (Init->getType()->isAnyComplexType()) {
EmitComplexExprIntoAddr(Init, Loc, isVolatile);
} else {
@@ -738,11 +783,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
if (const ConstantArrayType *Array =
getContext().getAsConstantArrayType(Ty)) {
- EHStack.pushLazyCleanup<CallArrayDtor>(NormalAndEHCleanup,
- D, Array, Loc);
+ EHStack.pushCleanup<CallArrayDtor>(NormalAndEHCleanup,
+ D, Array, Loc);
} else {
- EHStack.pushLazyCleanup<CallVarDtor>(NormalAndEHCleanup,
- D, NRVOFlag, Loc);
+ EHStack.pushCleanup<CallVarDtor>(NormalAndEHCleanup,
+ D, NRVOFlag, Loc);
}
}
}
@@ -755,52 +800,14 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D,
assert(F && "Could not find function!");
const CGFunctionInfo &Info = CGM.getTypes().getFunctionInfo(FD);
-
- // In some cases, the type of the function argument will be different from
- // the type of the pointer. An example of this is
- // void f(void* arg);
- // __attribute__((cleanup(f))) void *g;
- //
- // To fix this we insert a bitcast here.
- QualType ArgTy = Info.arg_begin()->type;
-
- CleanupBlock CleanupScope(*this, NormalCleanup);
-
- // Normal cleanup.
- CallArgList Args;
- Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
- ConvertType(ArgTy))),
- getContext().getPointerType(D.getType())));
- EmitCall(Info, F, ReturnValueSlot(), Args);
-
- // EH cleanup.
- if (Exceptions) {
- CleanupScope.beginEHCleanup();
-
- CallArgList Args;
- Args.push_back(std::make_pair(RValue::get(Builder.CreateBitCast(DeclPtr,
- ConvertType(ArgTy))),
- getContext().getPointerType(D.getType())));
- EmitCall(Info, F, ReturnValueSlot(), Args);
- }
+ EHStack.pushCleanup<CallCleanupFunction>(NormalAndEHCleanup,
+ F, &Info, DeclPtr, &D);
}
- if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
- CleanupBlock CleanupScope(*this, NormalCleanup);
-
- llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
- V = Builder.CreateLoad(V);
- BuildBlockRelease(V);
-
- // FIXME: Turn this on and audit the codegen
- if (0 && Exceptions) {
- CleanupScope.beginEHCleanup();
-
- llvm::Value *V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
- V = Builder.CreateLoad(V);
- BuildBlockRelease(V);
- }
- }
+ // If this is a block variable, clean it up.
+ // FIXME: this should be an EH cleanup as well. rdar://problem/8224178
+ if (needsDispose && CGM.getLangOptions().getGCMode() != LangOptions::GCOnly)
+ EHStack.pushCleanup<CallBlockRelease>(NormalCleanup, DeclPtr);
}
/// Emit an alloca (or GlobalValue depending on target)
@@ -822,7 +829,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
DeclPtr = CreateMemTemp(Ty, D.getName() + ".addr");
// Store the initial value into the alloca.
- EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Ty);
+ unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
+ EmitStoreOfScalar(Arg, DeclPtr, CTy.isVolatileQualified(), Alignment, Ty);
}
Arg->setName(D.getName());
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp
index ec3f38667b7a..e2f197522b26 100644
--- a/lib/CodeGen/CGDeclCXX.cpp
+++ b/lib/CodeGen/CGDeclCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"
@@ -30,9 +31,10 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
QualType T = D.getType();
bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();
+ unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
if (!CGF.hasAggregateLLVMType(T)) {
llvm::Value *V = CGF.EmitScalarExpr(Init);
- CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, T);
+ CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
} else if (T->isAnyComplexType()) {
CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
} else {
@@ -45,19 +47,15 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
CodeGenModule &CGM = CGF.CGM;
ASTContext &Context = CGF.getContext();
- const Expr *Init = D.getInit();
QualType T = D.getType();
- if (!CGF.hasAggregateLLVMType(T) || T->isAnyComplexType())
- return;
-
- // Avoid generating destructor(s) for initialized objects.
- if (!isa<CXXConstructExpr>(Init))
- return;
+ // Drill down past array types.
const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
if (Array)
T = Context.getBaseElementType(Array);
+ /// If that's not a record, we're done.
+ /// FIXME: __attribute__((cleanup)) ?
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
return;
@@ -94,8 +92,9 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
return;
}
+ unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
RValue RV = EmitReferenceBindingToExpr(Init, &D);
- EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, T);
+ EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
}
void
@@ -174,13 +173,26 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D) {
unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
+ DelayedCXXInitPosition.erase(D);
+ }
+ else {
+ llvm::DenseMap<const Decl *, unsigned>::iterator I =
+ DelayedCXXInitPosition.find(D);
+ if (I == DelayedCXXInitPosition.end()) {
+ CXXGlobalInits.push_back(Fn);
+ } else {
+ assert(CXXGlobalInits[I->second] == 0);
+ CXXGlobalInits[I->second] = Fn;
+ DelayedCXXInitPosition.erase(I);
+ }
}
- else
- CXXGlobalInits.push_back(Fn);
}
void
CodeGenModule::EmitCXXGlobalInitFunc() {
+ while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
+ CXXGlobalInits.pop_back();
+
if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
return;
@@ -200,8 +212,7 @@ CodeGenModule::EmitCXXGlobalInitFunc() {
llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
LocalCXXGlobalInits.push_back(Fn);
}
- for (unsigned i = 0; i < CXXGlobalInits.size(); i++)
- LocalCXXGlobalInits.push_back(CXXGlobalInits[i]);
+ LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
&LocalCXXGlobalInits[0],
LocalCXXGlobalInits.size());
@@ -247,7 +258,8 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
SourceLocation());
for (unsigned i = 0; i != NumDecls; ++i)
- Builder.CreateCall(Decls[i]);
+ if (Decls[i])
+ Builder.CreateCall(Decls[i]);
FinishFunction();
}
@@ -316,6 +328,20 @@ static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) {
return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort");
}
+namespace {
+ struct CallGuardAbort : EHScopeStack::Cleanup {
+ llvm::GlobalVariable *Guard;
+ CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // It shouldn't be possible for this to throw, but if it can,
+ // this should allow for the possibility of an invoke.
+ CGF.Builder.CreateCall(getGuardAbortFn(CGF), Guard)
+ ->setDoesNotThrow();
+ }
+ };
+}
+
void
CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
llvm::GlobalVariable *GV) {
@@ -325,10 +351,10 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics;
llvm::SmallString<256> GuardVName;
- CGM.getMangleContext().mangleGuardVariable(&D, GuardVName);
+ CGM.getCXXABI().getMangleContext().mangleGuardVariable(&D, GuardVName);
// Create the guard variable.
- llvm::GlobalValue *GuardVariable =
+ llvm::GlobalVariable *GuardVariable =
new llvm::GlobalVariable(CGM.getModule(), Int64Ty,
false, GV->getLinkage(),
llvm::Constant::getNullValue(Int64Ty),
@@ -360,23 +386,25 @@ CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D,
InitBlock, EndBlock);
// Call __cxa_guard_abort along the exceptional edge.
- if (Exceptions) {
- CleanupBlock Cleanup(*this, EHCleanup);
- Builder.CreateCall(getGuardAbortFn(*this), GuardVariable);
- }
+ if (Exceptions)
+ EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable);
EmitBlock(InitBlock);
}
if (D.getType()->isReferenceType()) {
+ unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
QualType T = D.getType();
RValue RV = EmitReferenceBindingToExpr(D.getInit(), &D);
- EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, T);
-
+ EmitStoreOfScalar(RV.getScalarVal(), GV, /*Volatile=*/false, Alignment, T);
} else
EmitDeclInit(*this, D, GV);
if (ThreadsafeStatics) {
+ // Pop the guard-abort cleanup if we pushed one.
+ if (Exceptions)
+ PopCleanupBlock();
+
// Call __cxa_guard_release. This cannot throw.
Builder.CreateCall(getGuardReleaseFn(*this), GuardVariable);
} else {
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index 4980aad1b383..7fb616e5a150 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -16,8 +16,10 @@
#include "llvm/Intrinsics.h"
#include "llvm/Support/CallSite.h"
+#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CGException.h"
+#include "TargetInfo.h"
using namespace clang;
using namespace CodeGen;
@@ -62,29 +64,26 @@ EHScopeStack::getEnclosingEHCleanup(iterator it) const {
return stabilize(it);
return cast<EHCleanupScope>(*it).getEnclosingEHCleanup();
}
- if (isa<EHLazyCleanupScope>(*it)) {
- if (cast<EHLazyCleanupScope>(*it).isEHCleanup())
- return stabilize(it);
- return cast<EHLazyCleanupScope>(*it).getEnclosingEHCleanup();
- }
++it;
} while (it != end());
return stable_end();
}
-void *EHScopeStack::pushLazyCleanup(CleanupKind Kind, size_t Size) {
+void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned");
- char *Buffer = allocate(EHLazyCleanupScope::getSizeForCleanupSize(Size));
- bool IsNormalCleanup = Kind != EHCleanup;
- bool IsEHCleanup = Kind != NormalCleanup;
- EHLazyCleanupScope *Scope =
- new (Buffer) EHLazyCleanupScope(IsNormalCleanup,
- IsEHCleanup,
- Size,
- BranchFixups.size(),
- InnermostNormalCleanup,
- InnermostEHCleanup);
+ char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
+ bool IsNormalCleanup = Kind & NormalCleanup;
+ bool IsEHCleanup = Kind & EHCleanup;
+ bool IsActive = !(Kind & InactiveCleanup);
+ EHCleanupScope *Scope =
+ new (Buffer) EHCleanupScope(IsNormalCleanup,
+ IsEHCleanup,
+ IsActive,
+ Size,
+ BranchFixups.size(),
+ InnermostNormalCleanup,
+ InnermostEHCleanup);
if (IsNormalCleanup)
InnermostNormalCleanup = stable_begin();
if (IsEHCleanup)
@@ -93,36 +92,19 @@ void *EHScopeStack::pushLazyCleanup(CleanupKind Kind, size_t Size) {
return Scope->getCleanupBuffer();
}
-void EHScopeStack::pushCleanup(llvm::BasicBlock *NormalEntry,
- llvm::BasicBlock *NormalExit,
- llvm::BasicBlock *EHEntry,
- llvm::BasicBlock *EHExit) {
- char *Buffer = allocate(EHCleanupScope::getSize());
- new (Buffer) EHCleanupScope(BranchFixups.size(),
- InnermostNormalCleanup,
- InnermostEHCleanup,
- NormalEntry, NormalExit, EHEntry, EHExit);
- if (NormalEntry)
- InnermostNormalCleanup = stable_begin();
- if (EHEntry)
- InnermostEHCleanup = stable_begin();
-}
-
void EHScopeStack::popCleanup() {
assert(!empty() && "popping exception stack when not empty");
- if (isa<EHLazyCleanupScope>(*begin())) {
- EHLazyCleanupScope &Cleanup = cast<EHLazyCleanupScope>(*begin());
- InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
- InnermostEHCleanup = Cleanup.getEnclosingEHCleanup();
- StartOfData += Cleanup.getAllocatedSize();
- } else {
- assert(isa<EHCleanupScope>(*begin()));
- EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
- InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
- InnermostEHCleanup = Cleanup.getEnclosingEHCleanup();
- StartOfData += EHCleanupScope::getSize();
- }
+ assert(isa<EHCleanupScope>(*begin()));
+ EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
+ InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
+ InnermostEHCleanup = Cleanup.getEnclosingEHCleanup();
+ StartOfData += Cleanup.getAllocatedSize();
+
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
+ // Destroy the cleanup.
+ Cleanup.~EHCleanupScope();
// Check whether we can shrink the branch-fixups stack.
if (!BranchFixups.empty()) {
@@ -149,6 +131,8 @@ void EHScopeStack::popFilter() {
EHFilterScope &Filter = cast<EHFilterScope>(*begin());
StartOfData += EHFilterScope::getSizeForNumFilters(Filter.getNumFilters());
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
assert(CatchDepth > 0 && "mismatched filter push/pop");
CatchDepth--;
}
@@ -156,13 +140,16 @@ void EHScopeStack::popFilter() {
EHCatchScope *EHScopeStack::pushCatch(unsigned NumHandlers) {
char *Buffer = allocate(EHCatchScope::getSizeForNumHandlers(NumHandlers));
CatchDepth++;
- return new (Buffer) EHCatchScope(NumHandlers);
+ EHCatchScope *Scope = new (Buffer) EHCatchScope(NumHandlers);
+ for (unsigned I = 0; I != NumHandlers; ++I)
+ Scope->getHandlers()[I].Index = getNextEHDestIndex();
+ return Scope;
}
void EHScopeStack::pushTerminate() {
char *Buffer = allocate(EHTerminateScope::getSize());
CatchDepth++;
- new (Buffer) EHTerminateScope();
+ new (Buffer) EHTerminateScope(getNextEHDestIndex());
}
/// Remove any 'null' fixups on the stack. However, we can't pop more
@@ -176,11 +163,7 @@ void EHScopeStack::popNullFixups() {
assert(hasNormalCleanups());
EHScopeStack::iterator it = find(InnermostNormalCleanup);
- unsigned MinSize;
- if (isa<EHCleanupScope>(*it))
- MinSize = cast<EHCleanupScope>(*it).getFixupDepth();
- else
- MinSize = cast<EHLazyCleanupScope>(*it).getFixupDepth();
+ unsigned MinSize = cast<EHCleanupScope>(*it).getFixupDepth();
assert(BranchFixups.size() >= MinSize && "fixup stack out of order");
while (BranchFixups.size() > MinSize &&
@@ -188,20 +171,6 @@ void EHScopeStack::popNullFixups() {
BranchFixups.pop_back();
}
-void EHScopeStack::resolveBranchFixups(llvm::BasicBlock *Dest) {
- assert(Dest && "null block passed to resolveBranchFixups");
-
- if (BranchFixups.empty()) return;
- assert(hasNormalCleanups() &&
- "branch fixups exist with no normal cleanups on stack");
-
- for (unsigned I = 0, E = BranchFixups.size(); I != E; ++I)
- if (BranchFixups[I].Destination == Dest)
- BranchFixups[I].Destination = 0;
-
- popNullFixups();
-}
-
static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) {
// void *__cxa_allocate_exception(size_t thrown_size);
const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
@@ -303,7 +272,7 @@ llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {
false);
if (CGM.getLangOptions().SjLjExceptions)
- return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
+ return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow");
return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
}
@@ -317,74 +286,88 @@ static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort");
}
-static const char *getCPersonalityFn(CodeGenFunction &CGF) {
- return "__gcc_personality_v0";
+static llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF,
+ const char *Name) {
+ const llvm::Type *Int8PtrTy =
+ llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ std::vector<const llvm::Type*> Args(1, Int8PtrTy);
+
+ const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext());
+ const llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, Args, false);
+
+ return CGF.CGM.CreateRuntimeFunction(FTy, Name);
+}
+
+const EHPersonality EHPersonality::GNU_C("__gcc_personality_v0");
+const EHPersonality EHPersonality::NeXT_ObjC("__objc_personality_v0");
+const EHPersonality EHPersonality::GNU_CPlusPlus("__gxx_personality_v0");
+const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ("__gxx_personality_sj0");
+const EHPersonality EHPersonality::GNU_ObjC("__gnu_objc_personality_v0",
+ "objc_exception_throw");
+
+static const EHPersonality &getCPersonality(const LangOptions &L) {
+ return EHPersonality::GNU_C;
}
-static const char *getObjCPersonalityFn(CodeGenFunction &CGF) {
- if (CGF.CGM.getLangOptions().NeXTRuntime) {
- if (CGF.CGM.getLangOptions().ObjCNonFragileABI)
- return "__objc_personality_v0";
- else
- return getCPersonalityFn(CGF);
+static const EHPersonality &getObjCPersonality(const LangOptions &L) {
+ if (L.NeXTRuntime) {
+ if (L.ObjCNonFragileABI) return EHPersonality::NeXT_ObjC;
+ else return getCPersonality(L);
} else {
- return "__gnu_objc_personality_v0";
+ return EHPersonality::GNU_ObjC;
}
}
-static const char *getCXXPersonalityFn(CodeGenFunction &CGF) {
- if (CGF.CGM.getLangOptions().SjLjExceptions)
- return "__gxx_personality_sj0";
+static const EHPersonality &getCXXPersonality(const LangOptions &L) {
+ if (L.SjLjExceptions)
+ return EHPersonality::GNU_CPlusPlus_SJLJ;
else
- return "__gxx_personality_v0";
+ return EHPersonality::GNU_CPlusPlus;
}
/// Determines the personality function to use when both C++
/// and Objective-C exceptions are being caught.
-static const char *getObjCXXPersonalityFn(CodeGenFunction &CGF) {
+static const EHPersonality &getObjCXXPersonality(const LangOptions &L) {
// The ObjC personality defers to the C++ personality for non-ObjC
// handlers. Unlike the C++ case, we use the same personality
// function on targets using (backend-driven) SJLJ EH.
- if (CGF.CGM.getLangOptions().NeXTRuntime) {
- if (CGF.CGM.getLangOptions().ObjCNonFragileABI)
- return "__objc_personality_v0";
+ if (L.NeXTRuntime) {
+ if (L.ObjCNonFragileABI)
+ return EHPersonality::NeXT_ObjC;
// In the fragile ABI, just use C++ exception handling and hope
// they're not doing crazy exception mixing.
else
- return getCXXPersonalityFn(CGF);
+ return getCXXPersonality(L);
}
- // I'm pretty sure the GNU runtime doesn't support mixed EH.
- // TODO: we don't necessarily need mixed EH here; remember what
- // kind of exceptions we actually try to catch in this function.
- CGF.CGM.ErrorUnsupported(CGF.CurCodeDecl,
- "the GNU Objective C runtime does not support "
- "catching C++ and Objective C exceptions in the "
- "same function");
- // Use the C++ personality just to avoid returning null.
- return getCXXPersonalityFn(CGF);
+ // The GNU runtime's personality function inherently doesn't support
+ // mixed EH. Use the C++ personality just to avoid returning null.
+ return getCXXPersonality(L);
}
-static llvm::Constant *getPersonalityFn(CodeGenFunction &CGF) {
- const char *Name;
- const LangOptions &Opts = CGF.CGM.getLangOptions();
- if (Opts.CPlusPlus && Opts.ObjC1)
- Name = getObjCXXPersonalityFn(CGF);
- else if (Opts.CPlusPlus)
- Name = getCXXPersonalityFn(CGF);
- else if (Opts.ObjC1)
- Name = getObjCPersonalityFn(CGF);
+const EHPersonality &EHPersonality::get(const LangOptions &L) {
+ if (L.CPlusPlus && L.ObjC1)
+ return getObjCXXPersonality(L);
+ else if (L.CPlusPlus)
+ return getCXXPersonality(L);
+ else if (L.ObjC1)
+ return getObjCPersonality(L);
else
- Name = getCPersonalityFn(CGF);
+ return getCPersonality(L);
+}
+
+static llvm::Constant *getPersonalityFn(CodeGenFunction &CGF,
+ const EHPersonality &Personality) {
+ const char *Name = Personality.getPersonalityFnName();
- llvm::Constant *Personality =
+ llvm::Constant *Fn =
CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(
llvm::Type::getInt32Ty(
CGF.CGM.getLLVMContext()),
true),
Name);
- return llvm::ConstantExpr::getBitCast(Personality, CGF.CGM.PtrToInt8Ty);
+ return llvm::ConstantExpr::getBitCast(Fn, CGF.CGM.PtrToInt8Ty);
}
/// Returns the value to inject into a selector to indicate the
@@ -403,7 +386,7 @@ static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) {
namespace {
/// A cleanup to free the exception object if its initialization
/// throws.
- struct FreeExceptionCleanup : EHScopeStack::LazyCleanup {
+ struct FreeExceptionCleanup : EHScopeStack::Cleanup {
FreeExceptionCleanup(llvm::Value *ShouldFreeVar,
llvm::Value *ExnLocVar)
: ShouldFreeVar(ShouldFreeVar), ExnLocVar(ExnLocVar) {}
@@ -453,9 +436,9 @@ static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E,
// exception during initialization.
// FIXME: stmt expressions might require this to be a normal
// cleanup, too.
- CGF.EHStack.pushLazyCleanup<FreeExceptionCleanup>(EHCleanup,
- ShouldFreeVar,
- ExnLocVar);
+ CGF.EHStack.pushCleanup<FreeExceptionCleanup>(EHCleanup,
+ ShouldFreeVar,
+ ExnLocVar);
EHScopeStack::stable_iterator Cleanup = CGF.EHStack.stable_begin();
CGF.Builder.CreateStore(ExnLoc, ExnLocVar);
@@ -637,7 +620,12 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
QualType CaughtType = C->getCaughtType();
CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType();
- llvm::Value *TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, true);
+
+ llvm::Value *TypeInfo = 0;
+ if (CaughtType->isObjCObjectPointerType())
+ TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
+ else
+ TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, true);
CatchScope->setHandler(I, TypeInfo, Handler);
} else {
// No exception decl indicates '...', a catch-all.
@@ -653,8 +641,6 @@ static bool isNonEHScope(const EHScope &S) {
switch (S.getKind()) {
case EHScope::Cleanup:
return !cast<EHCleanupScope>(S).isEHCleanup();
- case EHScope::LazyCleanup:
- return !cast<EHLazyCleanupScope>(S).isEHCleanup();
case EHScope::Filter:
case EHScope::Catch:
case EHScope::Terminate:
@@ -753,6 +739,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Save the current IR generation state.
CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
+ const EHPersonality &Personality =
+ EHPersonality::get(CGF.CGM.getLangOptions());
+
// Create and configure the landing pad.
llvm::BasicBlock *LP = createBasicBlock("lpad");
EmitBlock(LP);
@@ -768,11 +757,11 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Build the selector arguments.
llvm::SmallVector<llvm::Value*, 8> EHSelector;
EHSelector.push_back(Exn);
- EHSelector.push_back(getPersonalityFn(*this));
+ EHSelector.push_back(getPersonalityFn(*this, Personality));
// Accumulate all the handlers in scope.
- llvm::DenseMap<llvm::Value*, JumpDest> EHHandlers;
- JumpDest CatchAll;
+ llvm::DenseMap<llvm::Value*, UnwindDest> EHHandlers;
+ UnwindDest CatchAll;
bool HasEHCleanup = false;
bool HasEHFilter = false;
llvm::SmallVector<llvm::Value*, 8> EHFilters;
@@ -780,12 +769,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
I != E; ++I) {
switch (I->getKind()) {
- case EHScope::LazyCleanup:
- if (!HasEHCleanup)
- HasEHCleanup = cast<EHLazyCleanupScope>(*I).isEHCleanup();
- // We otherwise don't care about cleanups.
- continue;
-
case EHScope::Cleanup:
if (!HasEHCleanup)
HasEHCleanup = cast<EHCleanupScope>(*I).isEHCleanup();
@@ -794,7 +777,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
case EHScope::Filter: {
assert(I.next() == EHStack.end() && "EH filter is not end of EH stack");
- assert(!CatchAll.Block && "EH filter reached after catch-all");
+ assert(!CatchAll.isValid() && "EH filter reached after catch-all");
// Filter scopes get added to the selector in wierd ways.
EHFilterScope &Filter = cast<EHFilterScope>(*I);
@@ -812,9 +795,10 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
case EHScope::Terminate:
// Terminate scopes are basically catch-alls.
- assert(!CatchAll.Block);
- CatchAll.Block = getTerminateHandler();
- CatchAll.ScopeDepth = EHStack.getEnclosingEHCleanup(I);
+ assert(!CatchAll.isValid());
+ CatchAll = UnwindDest(getTerminateHandler(),
+ EHStack.getEnclosingEHCleanup(I),
+ cast<EHTerminateScope>(*I).getDestIndex());
goto done;
case EHScope::Catch:
@@ -827,30 +811,32 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Catch-all. We should only have one of these per catch.
if (!Handler.Type) {
- assert(!CatchAll.Block);
- CatchAll.Block = Handler.Block;
- CatchAll.ScopeDepth = EHStack.getEnclosingEHCleanup(I);
+ assert(!CatchAll.isValid());
+ CatchAll = UnwindDest(Handler.Block,
+ EHStack.getEnclosingEHCleanup(I),
+ Handler.Index);
continue;
}
// Check whether we already have a handler for this type.
- JumpDest &Dest = EHHandlers[Handler.Type];
- if (Dest.Block) continue;
+ UnwindDest &Dest = EHHandlers[Handler.Type];
+ if (Dest.isValid()) continue;
EHSelector.push_back(Handler.Type);
- Dest.Block = Handler.Block;
- Dest.ScopeDepth = EHStack.getEnclosingEHCleanup(I);
+ Dest = UnwindDest(Handler.Block,
+ EHStack.getEnclosingEHCleanup(I),
+ Handler.Index);
}
// Stop if we found a catch-all.
- if (CatchAll.Block) break;
+ if (CatchAll.isValid()) break;
}
done:
unsigned LastToEmitInLoop = EHSelector.size();
// If we have a catch-all, add null to the selector.
- if (CatchAll.Block) {
+ if (CatchAll.isValid()) {
EHSelector.push_back(getCatchAllValue(CGF));
// If we have an EH filter, we need to add those handlers in the
@@ -899,14 +885,15 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// filter (possibly with a cleanup), a catch-all, or another catch).
for (unsigned I = 2; I != LastToEmitInLoop; ++I) {
llvm::Value *Type = EHSelector[I];
- JumpDest Dest = EHHandlers[Type];
- assert(Dest.Block && "no handler entry for value in selector?");
+ UnwindDest Dest = EHHandlers[Type];
+ assert(Dest.isValid() && "no handler entry for value in selector?");
// Figure out where to branch on a match. As a debug code-size
// optimization, if the scope depth matches the innermost cleanup,
// we branch directly to the catch handler.
- llvm::BasicBlock *Match = Dest.Block;
- bool MatchNeedsCleanup = Dest.ScopeDepth != EHStack.getInnermostEHCleanup();
+ llvm::BasicBlock *Match = Dest.getBlock();
+ bool MatchNeedsCleanup =
+ Dest.getScopeDepth() != EHStack.getInnermostEHCleanup();
if (MatchNeedsCleanup)
Match = createBasicBlock("eh.match");
@@ -932,7 +919,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// Emit the final case in the selector.
// This might be a catch-all....
- if (CatchAll.Block) {
+ if (CatchAll.isValid()) {
assert(isa<llvm::ConstantPointerNull>(EHSelector.back()));
EmitBranchThroughEHCleanup(CatchAll);
@@ -951,7 +938,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
}
llvm::BasicBlock *CleanupContBB = createBasicBlock("ehspec.cleanup.cont");
- EmitBranchThroughEHCleanup(JumpDest(CleanupContBB, EHStack.stable_end()));
+ EmitBranchThroughEHCleanup(UnwindDest(CleanupContBB, EHStack.stable_end(),
+ EHStack.getNextEHDestIndex()));
EmitBlock(CleanupContBB);
if (HasEHCleanup)
@@ -996,22 +984,7 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
// ...or a cleanup.
} else {
- // We emit a jump to a notional label at the outermost unwind state.
- llvm::BasicBlock *Unwind = createBasicBlock("eh.resume");
- JumpDest Dest(Unwind, EHStack.stable_end());
- EmitBranchThroughEHCleanup(Dest);
-
- // The unwind block. We have to reload the exception here because
- // we might have unwound through arbitrary blocks, so the landing
- // pad might not dominate.
- EmitBlock(Unwind);
-
- // This can always be a call because we necessarily didn't find
- // anything on the EH stack which needs our help.
- Builder.CreateCall(getUnwindResumeOrRethrowFn(),
- Builder.CreateLoad(getExceptionSlot()))
- ->setDoesNotReturn();
- Builder.CreateUnreachable();
+ EmitBranchThroughEHCleanup(getRethrowDest());
}
// Restore the old IR generation state.
@@ -1033,7 +1006,7 @@ namespace {
/// of the caught type, so we have to assume the actual thrown
/// exception type might have a throwing destructor, even if the
/// caught type's destructor is trivial or nothrow.
- struct CallEndCatch : EHScopeStack::LazyCleanup {
+ struct CallEndCatch : EHScopeStack::Cleanup {
CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
bool MightThrow;
@@ -1058,7 +1031,7 @@ static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
llvm::CallInst *Call = CGF.Builder.CreateCall(getBeginCatchFn(CGF), Exn);
Call->setDoesNotThrow();
- CGF.EHStack.pushLazyCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);
+ CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);
return Call;
}
@@ -1078,11 +1051,57 @@ static void InitCatchParam(CodeGenFunction &CGF,
// If we're catching by reference, we can just cast the object
// pointer to the appropriate pointer.
if (isa<ReferenceType>(CatchType)) {
- bool EndCatchMightThrow = cast<ReferenceType>(CatchType)->getPointeeType()
- ->isRecordType();
+ QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
+ bool EndCatchMightThrow = CaughtType->isRecordType();
// __cxa_begin_catch returns the adjusted object pointer.
llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);
+
+ // We have no way to tell the personality function that we're
+ // catching by reference, so if we're catching a pointer,
+ // __cxa_begin_catch will actually return that pointer by value.
+ if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
+ QualType PointeeType = PT->getPointeeType();
+
+ // When catching by reference, generally we should just ignore
+ // this by-value pointer and use the exception object instead.
+ if (!PointeeType->isRecordType()) {
+
+ // Exn points to the struct _Unwind_Exception header, which
+ // we have to skip past in order to reach the exception data.
+ unsigned HeaderSize =
+ CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
+ AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);
+
+ // However, if we're catching a pointer-to-record type that won't
+ // work, because the personality function might have adjusted
+ // the pointer. There's actually no way for us to fully satisfy
+ // the language/ABI contract here: we can't use Exn because it
+ // might have the wrong adjustment, but we can't use the by-value
+ // pointer because it's off by a level of abstraction.
+ //
+ // The current solution is to dump the adjusted pointer into an
+ // alloca, which breaks language semantics (because changing the
+ // pointer doesn't change the exception) but at least works.
+ // The better solution would be to filter out non-exact matches
+ // and rethrow them, but this is tricky because the rethrow
+ // really needs to be catchable by other sites at this landing
+ // pad. The best solution is to fix the personality function.
+ } else {
+ // Pull the pointer for the reference type off.
+ const llvm::Type *PtrTy =
+ cast<llvm::PointerType>(LLVMCatchTy)->getElementType();
+
+ // Create the temporary and write the adjusted pointer into it.
+ llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");
+ llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
+ CGF.Builder.CreateStore(Casted, ExnPtrTmp);
+
+ // Bind the reference to the temporary.
+ AdjustedExn = ExnPtrTmp;
+ }
+ }
+
llvm::Value *ExnCast =
CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
CGF.Builder.CreateStore(ExnCast, ParamAddr);
@@ -1113,8 +1132,11 @@ static void InitCatchParam(CodeGenFunction &CGF,
CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false),
ParamAddr, /*volatile*/ false);
} else {
+ unsigned Alignment =
+ CGF.getContext().getDeclAlign(&CatchParam).getQuantity();
llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar");
- CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, CatchType);
+ CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, Alignment,
+ CatchType);
}
return;
}
@@ -1203,7 +1225,7 @@ static void BeginCatch(CodeGenFunction &CGF,
}
namespace {
- struct CallRethrow : EHScopeStack::LazyCleanup {
+ struct CallRethrow : EHScopeStack::Cleanup {
void Emit(CodeGenFunction &CGF, bool IsForEH) {
CGF.EmitCallOrInvoke(getReThrowFn(CGF), 0, 0);
}
@@ -1253,7 +1275,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
// _cxa_rethrow. This needs to happen before __cxa_end_catch is
// called, and so it is pushed after BeginCatch.
if (ImplicitRethrow)
- EHStack.pushLazyCleanup<CallRethrow>(NormalCleanup);
+ EHStack.pushCleanup<CallRethrow>(NormalCleanup);
// Perform the body of the catch.
EmitStmt(C->getHandlerBlock());
@@ -1269,6 +1291,97 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
EmitBlock(ContBB);
}
+namespace {
+ struct CallEndCatchForFinally : EHScopeStack::Cleanup {
+ llvm::Value *ForEHVar;
+ llvm::Value *EndCatchFn;
+ CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn)
+ : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch");
+ llvm::BasicBlock *CleanupContBB =
+ CGF.createBasicBlock("finally.cleanup.cont");
+
+ llvm::Value *ShouldEndCatch =
+ CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch");
+ CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB);
+ CGF.EmitBlock(EndCatchBB);
+ CGF.EmitCallOrInvoke(EndCatchFn, 0, 0); // catch-all, so might throw
+ CGF.EmitBlock(CleanupContBB);
+ }
+ };
+
+ struct PerformFinally : EHScopeStack::Cleanup {
+ const Stmt *Body;
+ llvm::Value *ForEHVar;
+ llvm::Value *EndCatchFn;
+ llvm::Value *RethrowFn;
+ llvm::Value *SavedExnVar;
+
+ PerformFinally(const Stmt *Body, llvm::Value *ForEHVar,
+ llvm::Value *EndCatchFn,
+ llvm::Value *RethrowFn, llvm::Value *SavedExnVar)
+ : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn),
+ RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // Enter a cleanup to call the end-catch function if one was provided.
+ if (EndCatchFn)
+ CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup,
+ ForEHVar, EndCatchFn);
+
+ // Save the current cleanup destination in case there are
+ // cleanups in the finally block.
+ llvm::Value *SavedCleanupDest =
+ CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(),
+ "cleanup.dest.saved");
+
+ // Emit the finally block.
+ CGF.EmitStmt(Body);
+
+ // If the end of the finally is reachable, check whether this was
+ // for EH. If so, rethrow.
+ if (CGF.HaveInsertPoint()) {
+ llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow");
+ llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont");
+
+ llvm::Value *ShouldRethrow =
+ CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
+ CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
+
+ CGF.EmitBlock(RethrowBB);
+ if (SavedExnVar) {
+ llvm::Value *Args[] = { CGF.Builder.CreateLoad(SavedExnVar) };
+ CGF.EmitCallOrInvoke(RethrowFn, Args, Args+1);
+ } else {
+ CGF.EmitCallOrInvoke(RethrowFn, 0, 0);
+ }
+ CGF.Builder.CreateUnreachable();
+
+ CGF.EmitBlock(ContBB);
+
+ // Restore the cleanup destination.
+ CGF.Builder.CreateStore(SavedCleanupDest,
+ CGF.getNormalCleanupDestSlot());
+ }
+
+ // Leave the end-catch cleanup. As an optimization, pretend that
+ // the fallthrough path was inaccessible; we've dynamically proven
+ // that we're not in the EH case along that path.
+ if (EndCatchFn) {
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
+ CGF.PopCleanupBlock();
+ CGF.Builder.restoreIP(SavedIP);
+ }
+
+ // Now make sure we actually have an insertion point or the
+ // cleanup gods will hate us.
+ CGF.EnsureInsertPoint();
+ }
+ };
+}
+
/// Enters a finally block for an implementation using zero-cost
/// exceptions. This is mostly general, but hard-codes some
/// language/ABI-specific behavior in the catch-all sections.
@@ -1320,62 +1433,9 @@ CodeGenFunction::EnterFinallyBlock(const Stmt *Body,
InitTempAlloca(ForEHVar, llvm::ConstantInt::getFalse(getLLVMContext()));
// Enter a normal cleanup which will perform the @finally block.
- {
- CodeGenFunction::CleanupBlock Cleanup(*this, NormalCleanup);
-
- // Enter a cleanup to call the end-catch function if one was provided.
- if (EndCatchFn) {
- CodeGenFunction::CleanupBlock FinallyExitCleanup(CGF, NormalAndEHCleanup);
-
- llvm::BasicBlock *EndCatchBB = createBasicBlock("finally.endcatch");
- llvm::BasicBlock *CleanupContBB = createBasicBlock("finally.cleanup.cont");
-
- llvm::Value *ShouldEndCatch =
- Builder.CreateLoad(ForEHVar, "finally.endcatch");
- Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB);
- EmitBlock(EndCatchBB);
- EmitCallOrInvoke(EndCatchFn, 0, 0); // catch-all, so might throw
- EmitBlock(CleanupContBB);
- }
-
- // Emit the finally block.
- EmitStmt(Body);
-
- // If the end of the finally is reachable, check whether this was
- // for EH. If so, rethrow.
- if (HaveInsertPoint()) {
- llvm::BasicBlock *RethrowBB = createBasicBlock("finally.rethrow");
- llvm::BasicBlock *ContBB = createBasicBlock("finally.cont");
-
- llvm::Value *ShouldRethrow =
- Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
- Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);
-
- EmitBlock(RethrowBB);
- if (SavedExnVar) {
- llvm::Value *Args[] = { Builder.CreateLoad(SavedExnVar) };
- EmitCallOrInvoke(RethrowFn, Args, Args+1);
- } else {
- EmitCallOrInvoke(RethrowFn, 0, 0);
- }
- Builder.CreateUnreachable();
-
- EmitBlock(ContBB);
- }
-
- // Leave the end-catch cleanup. As an optimization, pretend that
- // the fallthrough path was inaccessible; we've dynamically proven
- // that we're not in the EH case along that path.
- if (EndCatchFn) {
- CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
- PopCleanupBlock();
- Builder.restoreIP(SavedIP);
- }
-
- // Now make sure we actually have an insertion point or the
- // cleanup gods will hate us.
- EnsureInsertPoint();
- }
+ EHStack.pushCleanup<PerformFinally>(NormalCleanup, Body,
+ ForEHVar, EndCatchFn,
+ RethrowFn, SavedExnVar);
// Enter a catch-all scope.
llvm::BasicBlock *CatchAllBB = createBasicBlock("finally.catchall");
@@ -1437,10 +1497,12 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
llvm::CallInst *Exn =
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
Exn->setDoesNotThrow();
+
+ const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());
// Tell the backend what the exception table should be:
// nothing but a catch-all.
- llvm::Value *Args[3] = { Exn, getPersonalityFn(*this),
+ llvm::Value *Args[3] = { Exn, getPersonalityFn(*this, Personality),
getCatchAllValue(*this) };
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
Args, Args+3, "eh.selector")
@@ -1478,69 +1540,35 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
return TerminateHandler;
}
-CodeGenFunction::CleanupBlock::CleanupBlock(CodeGenFunction &CGF,
- CleanupKind Kind)
- : CGF(CGF), SavedIP(CGF.Builder.saveIP()), NormalCleanupExitBB(0) {
- llvm::BasicBlock *EntryBB = CGF.createBasicBlock("cleanup");
- CGF.Builder.SetInsertPoint(EntryBB);
-
- switch (Kind) {
- case NormalAndEHCleanup:
- NormalCleanupEntryBB = EHCleanupEntryBB = EntryBB;
- break;
-
- case NormalCleanup:
- NormalCleanupEntryBB = EntryBB;
- EHCleanupEntryBB = 0;
- break;
-
- case EHCleanup:
- NormalCleanupEntryBB = 0;
- EHCleanupEntryBB = EntryBB;
- CGF.EHStack.pushTerminate();
- break;
- }
-}
+CodeGenFunction::UnwindDest CodeGenFunction::getRethrowDest() {
+ if (RethrowBlock.isValid()) return RethrowBlock;
-void CodeGenFunction::CleanupBlock::beginEHCleanup() {
- assert(EHCleanupEntryBB == 0 && "already started an EH cleanup");
- NormalCleanupExitBB = CGF.Builder.GetInsertBlock();
- assert(NormalCleanupExitBB && "end of normal cleanup is unreachable");
-
- EHCleanupEntryBB = CGF.createBasicBlock("eh.cleanup");
- CGF.Builder.SetInsertPoint(EHCleanupEntryBB);
- CGF.EHStack.pushTerminate();
-}
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
-CodeGenFunction::CleanupBlock::~CleanupBlock() {
- llvm::BasicBlock *EHCleanupExitBB = 0;
+ // We emit a jump to a notional label at the outermost unwind state.
+ llvm::BasicBlock *Unwind = createBasicBlock("eh.resume");
+ Builder.SetInsertPoint(Unwind);
- // If we're currently writing the EH cleanup...
- if (EHCleanupEntryBB) {
- // Set the EH cleanup exit block.
- EHCleanupExitBB = CGF.Builder.GetInsertBlock();
- assert(EHCleanupExitBB && "end of EH cleanup is unreachable");
+ const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());
- // If we're actually writing both at once, set the normal exit, too.
- if (EHCleanupEntryBB == NormalCleanupEntryBB)
- NormalCleanupExitBB = EHCleanupExitBB;
+ // This can always be a call because we necessarily didn't find
+ // anything on the EH stack which needs our help.
+ llvm::Constant *RethrowFn;
+ if (const char *RethrowName = Personality.getCatchallRethrowFnName())
+ RethrowFn = getCatchallRethrowFn(*this, RethrowName);
+ else
+ RethrowFn = getUnwindResumeOrRethrowFn();
- // Otherwise, we must have pushed a terminate handler.
- else
- CGF.EHStack.popTerminate();
+ Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot()))
+ ->setDoesNotReturn();
+ Builder.CreateUnreachable();
- // Otherwise, just set the normal cleanup exit block.
- } else {
- NormalCleanupExitBB = CGF.Builder.GetInsertBlock();
- assert(NormalCleanupExitBB && "end of normal cleanup is unreachable");
- }
-
- CGF.EHStack.pushCleanup(NormalCleanupEntryBB, NormalCleanupExitBB,
- EHCleanupEntryBB, EHCleanupExitBB);
+ Builder.restoreIP(SavedIP);
- CGF.Builder.restoreIP(SavedIP);
+ RethrowBlock = UnwindDest(Unwind, EHStack.stable_end(), 0);
+ return RethrowBlock;
}
-EHScopeStack::LazyCleanup::~LazyCleanup() {
- llvm_unreachable("LazyCleanup is indestructable");
+EHScopeStack::Cleanup::~Cleanup() {
+ llvm_unreachable("Cleanup is indestructable");
}
diff --git a/lib/CodeGen/CGException.h b/lib/CodeGen/CGException.h
index 80739cd8d73e..f1294746a42d 100644
--- a/lib/CodeGen/CGException.h
+++ b/lib/CodeGen/CGException.h
@@ -27,17 +27,43 @@ namespace llvm {
namespace clang {
namespace CodeGen {
+/// The exceptions personality for a function. When
+class EHPersonality {
+ const char *PersonalityFn;
+
+ // If this is non-null, this personality requires a non-standard
+ // function for rethrowing an exception after a catchall cleanup.
+ // This function must have prototype void(void*).
+ const char *CatchallRethrowFn;
+
+ EHPersonality(const char *PersonalityFn,
+ const char *CatchallRethrowFn = 0)
+ : PersonalityFn(PersonalityFn),
+ CatchallRethrowFn(CatchallRethrowFn) {}
+
+public:
+ static const EHPersonality &get(const LangOptions &Lang);
+ static const EHPersonality GNU_C;
+ static const EHPersonality GNU_ObjC;
+ static const EHPersonality NeXT_ObjC;
+ static const EHPersonality GNU_CPlusPlus;
+ static const EHPersonality GNU_CPlusPlus_SJLJ;
+
+ const char *getPersonalityFnName() const { return PersonalityFn; }
+ const char *getCatchallRethrowFnName() const { return CatchallRethrowFn; }
+};
+
/// A protected scope for zero-cost EH handling.
class EHScope {
llvm::BasicBlock *CachedLandingPad;
- unsigned K : 3;
+ unsigned K : 2;
protected:
- enum { BitsRemaining = 29 };
+ enum { BitsRemaining = 30 };
public:
- enum Kind { Cleanup, LazyCleanup, Catch, Terminate, Filter };
+ enum Kind { Cleanup, Catch, Terminate, Filter };
EHScope(Kind K) : CachedLandingPad(0), K(K) {}
@@ -74,15 +100,13 @@ public:
/// The catch handler for this type.
llvm::BasicBlock *Block;
- static Handler make(llvm::Value *Type, llvm::BasicBlock *Block) {
- Handler Temp;
- Temp.Type = Type;
- Temp.Block = Block;
- return Temp;
- }
+ /// The unwind destination index for this handler.
+ unsigned Index;
};
private:
+ friend class EHScopeStack;
+
Handler *getHandlers() {
return reinterpret_cast<Handler*>(this+1);
}
@@ -110,7 +134,8 @@ public:
void setHandler(unsigned I, llvm::Value *Type, llvm::BasicBlock *Block) {
assert(I < getNumHandlers());
- getHandlers()[I] = Handler::make(Type, Block);
+ getHandlers()[I].Type = Type;
+ getHandlers()[I].Block = Block;
}
const Handler &getHandler(unsigned I) const {
@@ -128,21 +153,27 @@ public:
};
/// A cleanup scope which generates the cleanup blocks lazily.
-class EHLazyCleanupScope : public EHScope {
+class EHCleanupScope : public EHScope {
/// Whether this cleanup needs to be run along normal edges.
bool IsNormalCleanup : 1;
/// Whether this cleanup needs to be run along exception edges.
bool IsEHCleanup : 1;
- /// The amount of extra storage needed by the LazyCleanup.
+ /// Whether this cleanup was activated before all normal uses.
+ bool ActivatedBeforeNormalUse : 1;
+
+ /// Whether this cleanup was activated before all EH uses.
+ bool ActivatedBeforeEHUse : 1;
+
+ /// The amount of extra storage needed by the Cleanup.
/// Always a multiple of the scope-stack alignment.
unsigned CleanupSize : 12;
/// The number of fixups required by enclosing scopes (not including
/// this one). If this is the top cleanup scope, all the fixups
/// from this index onwards belong to this scope.
- unsigned FixupDepth : BitsRemaining - 14;
+ unsigned FixupDepth : BitsRemaining - 16;
/// The nearest normal cleanup scope enclosing this one.
EHScopeStack::stable_iterator EnclosingNormal;
@@ -158,27 +189,78 @@ class EHLazyCleanupScope : public EHScope {
/// created if needed before the cleanup is popped.
llvm::BasicBlock *EHBlock;
+ /// An optional i1 variable indicating whether this cleanup has been
+ /// activated yet. This has one of three states:
+ /// - it is null if the cleanup is inactive
+ /// - it is activeSentinel() if the cleanup is active and was not
+ /// required before activation
+ /// - it points to a valid variable
+ llvm::AllocaInst *ActiveVar;
+
+ /// Extra information required for cleanups that have resolved
+ /// branches through them. This has to be allocated on the side
+ /// because everything on the cleanup stack has be trivially
+ /// movable.
+ struct ExtInfo {
+ /// The destinations of normal branch-afters and branch-throughs.
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> Branches;
+
+ /// Normal branch-afters.
+ llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
+ BranchAfters;
+
+ /// The destinations of EH branch-afters and branch-throughs.
+ /// TODO: optimize for the extremely common case of a single
+ /// branch-through.
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> EHBranches;
+
+ /// EH branch-afters.
+ llvm::SmallVector<std::pair<llvm::BasicBlock*,llvm::ConstantInt*>, 4>
+ EHBranchAfters;
+ };
+ mutable struct ExtInfo *ExtInfo;
+
+ struct ExtInfo &getExtInfo() {
+ if (!ExtInfo) ExtInfo = new struct ExtInfo();
+ return *ExtInfo;
+ }
+
+ const struct ExtInfo &getExtInfo() const {
+ if (!ExtInfo) ExtInfo = new struct ExtInfo();
+ return *ExtInfo;
+ }
+
public:
/// Gets the size required for a lazy cleanup scope with the given
/// cleanup-data requirements.
static size_t getSizeForCleanupSize(size_t Size) {
- return sizeof(EHLazyCleanupScope) + Size;
+ return sizeof(EHCleanupScope) + Size;
}
size_t getAllocatedSize() const {
- return sizeof(EHLazyCleanupScope) + CleanupSize;
+ return sizeof(EHCleanupScope) + CleanupSize;
}
- EHLazyCleanupScope(bool IsNormal, bool IsEH, unsigned CleanupSize,
- unsigned FixupDepth,
- EHScopeStack::stable_iterator EnclosingNormal,
- EHScopeStack::stable_iterator EnclosingEH)
- : EHScope(EHScope::LazyCleanup),
+ EHCleanupScope(bool IsNormal, bool IsEH, bool IsActive,
+ unsigned CleanupSize, unsigned FixupDepth,
+ EHScopeStack::stable_iterator EnclosingNormal,
+ EHScopeStack::stable_iterator EnclosingEH)
+ : EHScope(EHScope::Cleanup),
IsNormalCleanup(IsNormal), IsEHCleanup(IsEH),
+ ActivatedBeforeNormalUse(IsActive),
+ ActivatedBeforeEHUse(IsActive),
CleanupSize(CleanupSize), FixupDepth(FixupDepth),
EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH),
- NormalBlock(0), EHBlock(0)
- {}
+ NormalBlock(0), EHBlock(0),
+ ActiveVar(IsActive ? activeSentinel() : 0),
+ ExtInfo(0)
+ {
+ assert(this->CleanupSize == CleanupSize && "cleanup size overflow");
+ }
+
+ ~EHCleanupScope() {
+ delete ExtInfo;
+ }
bool isNormalCleanup() const { return IsNormalCleanup; }
llvm::BasicBlock *getNormalBlock() const { return NormalBlock; }
@@ -188,6 +270,20 @@ public:
llvm::BasicBlock *getEHBlock() const { return EHBlock; }
void setEHBlock(llvm::BasicBlock *BB) { EHBlock = BB; }
+ static llvm::AllocaInst *activeSentinel() {
+ return reinterpret_cast<llvm::AllocaInst*>(1);
+ }
+
+ bool isActive() const { return ActiveVar != 0; }
+ llvm::AllocaInst *getActiveVar() const { return ActiveVar; }
+ void setActiveVar(llvm::AllocaInst *Var) { ActiveVar = Var; }
+
+ bool wasActivatedBeforeNormalUse() const { return ActivatedBeforeNormalUse; }
+ void setActivatedBeforeNormalUse(bool B) { ActivatedBeforeNormalUse = B; }
+
+ bool wasActivatedBeforeEHUse() const { return ActivatedBeforeEHUse; }
+ void setActivatedBeforeEHUse(bool B) { ActivatedBeforeEHUse = B; }
+
unsigned getFixupDepth() const { return FixupDepth; }
EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
return EnclosingNormal;
@@ -199,67 +295,108 @@ public:
size_t getCleanupSize() const { return CleanupSize; }
void *getCleanupBuffer() { return this + 1; }
- EHScopeStack::LazyCleanup *getCleanup() {
- return reinterpret_cast<EHScopeStack::LazyCleanup*>(getCleanupBuffer());
+ EHScopeStack::Cleanup *getCleanup() {
+ return reinterpret_cast<EHScopeStack::Cleanup*>(getCleanupBuffer());
}
- static bool classof(const EHScope *Scope) {
- return (Scope->getKind() == LazyCleanup);
+ /// True if this cleanup scope has any branch-afters or branch-throughs.
+ bool hasBranches() const { return ExtInfo && !ExtInfo->Branches.empty(); }
+
+ /// Add a branch-after to this cleanup scope. A branch-after is a
+ /// branch from a point protected by this (normal) cleanup to a
+ /// point in the normal cleanup scope immediately containing it.
+ /// For example,
+ /// for (;;) { A a; break; }
+ /// contains a branch-after.
+ ///
+ /// Branch-afters each have their own destination out of the
+ /// cleanup, guaranteed distinct from anything else threaded through
+ /// it. Therefore branch-afters usually force a switch after the
+ /// cleanup.
+ void addBranchAfter(llvm::ConstantInt *Index,
+ llvm::BasicBlock *Block) {
+ struct ExtInfo &ExtInfo = getExtInfo();
+ if (ExtInfo.Branches.insert(Block))
+ ExtInfo.BranchAfters.push_back(std::make_pair(Block, Index));
}
-};
-/// A scope which needs to execute some code if we try to unwind ---
-/// either normally, via the EH mechanism, or both --- through it.
-class EHCleanupScope : public EHScope {
- /// The number of fixups required by enclosing scopes (not including
- /// this one). If this is the top cleanup scope, all the fixups
- /// from this index onwards belong to this scope.
- unsigned FixupDepth : BitsRemaining;
+ /// Return the number of unique branch-afters on this scope.
+ unsigned getNumBranchAfters() const {
+ return ExtInfo ? ExtInfo->BranchAfters.size() : 0;
+ }
- /// The nearest normal cleanup scope enclosing this one.
- EHScopeStack::stable_iterator EnclosingNormal;
+ llvm::BasicBlock *getBranchAfterBlock(unsigned I) const {
+ assert(I < getNumBranchAfters());
+ return ExtInfo->BranchAfters[I].first;
+ }
- /// The nearest EH cleanup scope enclosing this one.
- EHScopeStack::stable_iterator EnclosingEH;
+ llvm::ConstantInt *getBranchAfterIndex(unsigned I) const {
+ assert(I < getNumBranchAfters());
+ return ExtInfo->BranchAfters[I].second;
+ }
- llvm::BasicBlock *NormalEntry;
- llvm::BasicBlock *NormalExit;
- llvm::BasicBlock *EHEntry;
- llvm::BasicBlock *EHExit;
+ /// Add a branch-through to this cleanup scope. A branch-through is
+ /// a branch from a scope protected by this (normal) cleanup to an
+ /// enclosing scope other than the immediately-enclosing normal
+ /// cleanup scope.
+ ///
+ /// In the following example, the branch through B's scope is a
+ /// branch-through, while the branch through A's scope is a
+ /// branch-after:
+ /// for (;;) { A a; B b; break; }
+ ///
+ /// All branch-throughs have a common destination out of the
+ /// cleanup, one possibly shared with the fall-through. Therefore
+ /// branch-throughs usually don't force a switch after the cleanup.
+ ///
+ /// \return true if the branch-through was new to this scope
+ bool addBranchThrough(llvm::BasicBlock *Block) {
+ return getExtInfo().Branches.insert(Block);
+ }
-public:
- static size_t getSize() { return sizeof(EHCleanupScope); }
+ /// Determines if this cleanup scope has any branch throughs.
+ bool hasBranchThroughs() const {
+ if (!ExtInfo) return false;
+ return (ExtInfo->BranchAfters.size() != ExtInfo->Branches.size());
+ }
- EHCleanupScope(unsigned FixupDepth,
- EHScopeStack::stable_iterator EnclosingNormal,
- EHScopeStack::stable_iterator EnclosingEH,
- llvm::BasicBlock *NormalEntry, llvm::BasicBlock *NormalExit,
- llvm::BasicBlock *EHEntry, llvm::BasicBlock *EHExit)
- : EHScope(Cleanup), FixupDepth(FixupDepth),
- EnclosingNormal(EnclosingNormal), EnclosingEH(EnclosingEH),
- NormalEntry(NormalEntry), NormalExit(NormalExit),
- EHEntry(EHEntry), EHExit(EHExit) {
- assert((NormalEntry != 0) == (NormalExit != 0));
- assert((EHEntry != 0) == (EHExit != 0));
+ // Same stuff, only for EH branches instead of normal branches.
+ // It's quite possible that we could find a better representation
+ // for this.
+
+ bool hasEHBranches() const { return ExtInfo && !ExtInfo->EHBranches.empty(); }
+ void addEHBranchAfter(llvm::ConstantInt *Index,
+ llvm::BasicBlock *Block) {
+ struct ExtInfo &ExtInfo = getExtInfo();
+ if (ExtInfo.EHBranches.insert(Block))
+ ExtInfo.EHBranchAfters.push_back(std::make_pair(Block, Index));
}
- bool isNormalCleanup() const { return NormalEntry != 0; }
- bool isEHCleanup() const { return EHEntry != 0; }
+ unsigned getNumEHBranchAfters() const {
+ return ExtInfo ? ExtInfo->EHBranchAfters.size() : 0;
+ }
- llvm::BasicBlock *getNormalEntry() const { return NormalEntry; }
- llvm::BasicBlock *getNormalExit() const { return NormalExit; }
- llvm::BasicBlock *getEHEntry() const { return EHEntry; }
- llvm::BasicBlock *getEHExit() const { return EHExit; }
- unsigned getFixupDepth() const { return FixupDepth; }
- EHScopeStack::stable_iterator getEnclosingNormalCleanup() const {
- return EnclosingNormal;
+ llvm::BasicBlock *getEHBranchAfterBlock(unsigned I) const {
+ assert(I < getNumEHBranchAfters());
+ return ExtInfo->EHBranchAfters[I].first;
}
- EHScopeStack::stable_iterator getEnclosingEHCleanup() const {
- return EnclosingEH;
+
+ llvm::ConstantInt *getEHBranchAfterIndex(unsigned I) const {
+ assert(I < getNumEHBranchAfters());
+ return ExtInfo->EHBranchAfters[I].second;
+ }
+
+ bool addEHBranchThrough(llvm::BasicBlock *Block) {
+ return getExtInfo().EHBranches.insert(Block);
+ }
+
+ bool hasEHBranchThroughs() const {
+ if (!ExtInfo) return false;
+ return (ExtInfo->EHBranchAfters.size() != ExtInfo->EHBranches.size());
}
static bool classof(const EHScope *Scope) {
- return Scope->getKind() == Cleanup;
+ return (Scope->getKind() == Cleanup);
}
};
@@ -310,10 +447,13 @@ public:
/// An exceptions scope which calls std::terminate if any exception
/// reaches it.
class EHTerminateScope : public EHScope {
+ unsigned DestIndex : BitsRemaining;
public:
- EHTerminateScope() : EHScope(Terminate) {}
+ EHTerminateScope(unsigned Index) : EHScope(Terminate), DestIndex(Index) {}
static size_t getSize() { return sizeof(EHTerminateScope); }
+ unsigned getDestIndex() const { return DestIndex; }
+
static bool classof(const EHScope *Scope) {
return Scope->getKind() == Terminate;
}
@@ -348,13 +488,9 @@ public:
static_cast<const EHFilterScope*>(get())->getNumFilters());
break;
- case EHScope::LazyCleanup:
- Ptr += static_cast<const EHLazyCleanupScope*>(get())
- ->getAllocatedSize();
- break;
-
case EHScope::Cleanup:
- Ptr += EHCleanupScope::getSize();
+ Ptr += static_cast<const EHCleanupScope*>(get())
+ ->getAllocatedSize();
break;
case EHScope::Terminate:
@@ -377,6 +513,9 @@ public:
return copy;
}
+ bool encloses(iterator other) const { return Ptr >= other.Ptr; }
+ bool strictlyEncloses(iterator other) const { return Ptr > other.Ptr; }
+
bool operator==(iterator other) const { return Ptr == other.Ptr; }
bool operator!=(iterator other) const { return Ptr != other.Ptr; }
};
@@ -396,6 +535,8 @@ inline void EHScopeStack::popCatch() {
StartOfData += EHCatchScope::getSizeForNumHandlers(
cast<EHCatchScope>(*begin()).getNumHandlers());
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
CatchDepth--;
}
@@ -406,6 +547,8 @@ inline void EHScopeStack::popTerminate() {
assert(isa<EHTerminateScope>(*begin()));
StartOfData += EHTerminateScope::getSize();
+ if (empty()) NextEHDestIndex = FirstEHDestIndex;
+
assert(CatchDepth > 0 && "mismatched catch/terminate push/pop");
CatchDepth--;
}
@@ -422,6 +565,28 @@ EHScopeStack::stabilize(iterator ir) const {
return stable_iterator(EndOfBuffer - ir.Ptr);
}
+inline EHScopeStack::stable_iterator
+EHScopeStack::getInnermostActiveNormalCleanup() const {
+ for (EHScopeStack::stable_iterator
+ I = getInnermostNormalCleanup(), E = stable_end(); I != E; ) {
+ EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
+ if (S.isActive()) return I;
+ I = S.getEnclosingNormalCleanup();
+ }
+ return stable_end();
+}
+
+inline EHScopeStack::stable_iterator
+EHScopeStack::getInnermostActiveEHCleanup() const {
+ for (EHScopeStack::stable_iterator
+ I = getInnermostEHCleanup(), E = stable_end(); I != E; ) {
+ EHCleanupScope &S = cast<EHCleanupScope>(*find(I));
+ if (S.isActive()) return I;
+ I = S.getEnclosingEHCleanup();
+ }
+ return stable_end();
+}
+
}
}
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 43bab9fece6e..3750ab80c3fc 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -14,6 +14,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "CGCall.h"
+#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "CGObjCRuntime.h"
#include "clang/AST/ASTContext.h"
@@ -65,22 +66,12 @@ llvm::AllocaInst *CodeGenFunction::CreateMemTemp(QualType Ty,
/// EvaluateExprAsBool - Perform the usual unary conversions on the specified
/// expression and compare the result against zero, returning an Int1Ty value.
llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
- QualType BoolTy = getContext().BoolTy;
- if (E->getType()->isMemberFunctionPointerType()) {
- LValue LV = EmitAggExprToLValue(E);
-
- // Get the pointer.
- llvm::Value *FuncPtr = Builder.CreateStructGEP(LV.getAddress(), 0,
- "src.ptr");
- FuncPtr = Builder.CreateLoad(FuncPtr);
-
- llvm::Value *IsNotNull =
- Builder.CreateICmpNE(FuncPtr,
- llvm::Constant::getNullValue(FuncPtr->getType()),
- "tobool");
-
- return IsNotNull;
+ if (const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>()) {
+ llvm::Value *MemPtr = EmitScalarExpr(E);
+ return CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);
}
+
+ QualType BoolTy = getContext().BoolTy;
if (!E->getType()->isAnyComplexType())
return EmitScalarConversion(EmitScalarExpr(E), E->getType(), BoolTy);
@@ -130,7 +121,7 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
EmitAggExpr(E, Location, IsLocationVolatile, /*Ignore*/ false, IsInit);
else {
RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false));
- LValue LV = LValue::MakeAddr(Location, MakeQualifiers(E->getType()));
+ LValue LV = MakeAddrLValue(Location, E->getType());
EmitStoreThroughLValue(RV, LV, E->getType());
}
}
@@ -142,17 +133,14 @@ struct SubobjectAdjustment {
union {
struct {
- const CXXBaseSpecifierArray *BasePath;
+ const CastExpr *BasePath;
const CXXRecordDecl *DerivedClass;
} DerivedToBase;
- struct {
- FieldDecl *Field;
- unsigned CVRQualifiers;
- } Field;
+ FieldDecl *Field;
};
- SubobjectAdjustment(const CXXBaseSpecifierArray *BasePath,
+ SubobjectAdjustment(const CastExpr *BasePath,
const CXXRecordDecl *DerivedClass)
: Kind(DerivedToBaseAdjustment)
{
@@ -160,11 +148,10 @@ struct SubobjectAdjustment {
DerivedToBase.DerivedClass = DerivedClass;
}
- SubobjectAdjustment(FieldDecl *Field, unsigned CVRQualifiers)
- : Kind(FieldAdjustment)
+ SubobjectAdjustment(FieldDecl *Field)
+ : Kind(FieldAdjustment)
{
- this->Field.Field = Field;
- this->Field.CVRQualifiers = CVRQualifiers;
+ this->Field = Field;
}
};
@@ -174,7 +161,7 @@ CreateReferenceTemporary(CodeGenFunction& CGF, QualType Type,
if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
if (VD->hasGlobalStorage()) {
llvm::SmallString<256> Name;
- CGF.CGM.getMangleContext().mangleReferenceTemporary(VD, Name);
+ CGF.CGM.getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Name);
const llvm::Type *RefTempTy = CGF.ConvertTypeForMem(Type);
@@ -230,18 +217,17 @@ EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
}
if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if ((CE->getCastKind() == CastExpr::CK_DerivedToBase ||
- CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase) &&
+ if ((CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase) &&
E->getType()->isRecordType()) {
E = CE->getSubExpr();
CXXRecordDecl *Derived
= cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
- Adjustments.push_back(SubobjectAdjustment(&CE->getBasePath(),
- Derived));
+ Adjustments.push_back(SubobjectAdjustment(CE, Derived));
continue;
}
- if (CE->getCastKind() == CastExpr::CK_NoOp) {
+ if (CE->getCastKind() == CK_NoOp) {
E = CE->getSubExpr();
continue;
}
@@ -250,8 +236,7 @@ EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
ME->getBase()->getType()->isRecordType()) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
E = ME->getBase();
- Adjustments.push_back(SubobjectAdjustment(Field,
- E->getType().getCVRQualifiers()));
+ Adjustments.push_back(SubobjectAdjustment(Field));
continue;
}
}
@@ -291,14 +276,14 @@ EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
Object =
CGF.GetAddressOfBaseClass(Object,
Adjustment.DerivedToBase.DerivedClass,
- *Adjustment.DerivedToBase.BasePath,
+ Adjustment.DerivedToBase.BasePath->path_begin(),
+ Adjustment.DerivedToBase.BasePath->path_end(),
/*NullCheckValue=*/false);
break;
case SubobjectAdjustment::FieldAdjustment: {
- unsigned CVR = Adjustment.Field.CVRQualifiers;
LValue LV =
- CGF.EmitLValueForField(Object, Adjustment.Field.Field, CVR);
+ CGF.EmitLValueForField(Object, Adjustment.Field, 0);
if (LV.isSimple()) {
Object = LV.getAddress();
break;
@@ -306,11 +291,11 @@ EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
// For non-simple lvalues, we actually have to create a copy of
// the object we're binding to.
- QualType T = Adjustment.Field.Field->getType().getNonReferenceType()
- .getUnqualifiedType();
+ QualType T = Adjustment.Field->getType().getNonReferenceType()
+ .getUnqualifiedType();
Object = CreateReferenceTemporary(CGF, T, InitializedDecl);
- LValue TempLV = LValue::MakeAddr(Object,
- Qualifiers::fromCVRMask(CVR));
+ LValue TempLV = CGF.MakeAddrLValue(Object,
+ Adjustment.Field->getType());
CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV, T), TempLV, T);
break;
}
@@ -330,9 +315,12 @@ EmitExprForReferenceBinding(CodeGenFunction& CGF, const Expr* E,
ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
InitializedDecl);
+
+ unsigned Alignment =
+ CGF.getContext().getTypeAlignInChars(E->getType()).getQuantity();
if (RV.isScalar())
CGF.EmitStoreOfScalar(RV.getScalarVal(), ReferenceTemporary,
- /*Volatile=*/false, E->getType());
+ /*Volatile=*/false, Alignment, E->getType());
else
CGF.StoreComplexToAddr(RV.getComplexVal(), ReferenceTemporary,
/*Volatile=*/false);
@@ -347,7 +335,6 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary,
ReferenceTemporaryDtor,
InitializedDecl);
-
if (!ReferenceTemporaryDtor)
return RValue::get(Value);
@@ -362,16 +349,8 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
return RValue::get(Value);
}
}
-
- CleanupBlock Cleanup(*this, NormalCleanup);
- EmitCXXDestructorCall(ReferenceTemporaryDtor, Dtor_Complete,
- /*ForVirtualBase=*/false, ReferenceTemporary);
-
- if (Exceptions) {
- Cleanup.beginEHCleanup();
- EmitCXXDestructorCall(ReferenceTemporaryDtor, Dtor_Complete,
- /*ForVirtualBase=*/false, ReferenceTemporary);
- }
+
+ PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
return RValue::get(Value);
}
@@ -462,9 +441,12 @@ RValue CodeGenFunction::GetUndefRValue(QualType Ty) {
return RValue::getComplex(std::make_pair(U, U));
}
+ // If this is a use of an undefined aggregate type, the aggregate must have an
+ // identifiable address. Just because the contents of the value are undefined
+ // doesn't mean that the address can't be taken and compared.
if (hasAggregateLLVMType(Ty)) {
- const llvm::Type *LTy = llvm::PointerType::getUnqual(ConvertType(Ty));
- return RValue::getAggregate(llvm::UndefValue::get(LTy));
+ llvm::Value *DestPtr = CreateMemTemp(Ty, "undef.agg.tmp");
+ return RValue::getAggregate(DestPtr);
}
return RValue::get(llvm::UndefValue::get(ConvertType(Ty)));
@@ -480,8 +462,7 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
const char *Name) {
ErrorUnsupported(E, Name);
llvm::Type *Ty = llvm::PointerType::getUnqual(ConvertType(E->getType()));
- return LValue::MakeAddr(llvm::UndefValue::get(Ty),
- MakeQualifiers(E->getType()));
+ return MakeAddrLValue(llvm::UndefValue::get(Ty), E->getType());
}
LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) {
@@ -590,10 +571,12 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
}
llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
- QualType Ty) {
+ unsigned Alignment, QualType Ty) {
llvm::LoadInst *Load = Builder.CreateLoad(Addr, "tmp");
if (Volatile)
Load->setVolatile(true);
+ if (Alignment)
+ Load->setAlignment(Alignment);
// Bool can have different representation in memory than in registers.
llvm::Value *V = Load;
@@ -605,14 +588,18 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
}
void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
- bool Volatile, QualType Ty) {
+ bool Volatile, unsigned Alignment,
+ QualType Ty) {
if (Ty->isBooleanType()) {
// Bool can have different representation in memory than in registers.
const llvm::PointerType *DstPtr = cast<llvm::PointerType>(Addr->getType());
Value = Builder.CreateIntCast(Value, DstPtr->getElementType(), false);
}
- Builder.CreateStore(Value, Addr, Volatile);
+
+ llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
+ if (Alignment)
+ Store->setAlignment(Alignment);
}
/// EmitLoadOfLValue - Given an expression that represents a value lvalue, this
@@ -628,18 +615,15 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) {
if (LV.isSimple()) {
llvm::Value *Ptr = LV.getAddress();
- const llvm::Type *EltTy =
- cast<llvm::PointerType>(Ptr->getType())->getElementType();
- // Simple scalar l-value.
- //
- // FIXME: We shouldn't have to use isSingleValueType here.
- if (EltTy->isSingleValueType())
- return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(),
- ExprType));
+ // Functions are l-values that don't require loading.
+ if (ExprType->isFunctionType())
+ return RValue::get(Ptr);
+
+ // Everything needs a load.
+ return RValue::get(EmitLoadOfScalar(Ptr, LV.isVolatileQualified(),
+ LV.getAlignment(), ExprType));
- assert(ExprType->isFunctionType() && "Unknown scalar value");
- return RValue::get(Ptr);
}
if (LV.isVectorElt()) {
@@ -836,8 +820,10 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset");
CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst,
BytesBetween);
- } else if (Dst.isGlobalObjCRef())
- CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst);
+ } else if (Dst.isGlobalObjCRef()) {
+ CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst,
+ Dst.isThreadLocalRef());
+ }
else
CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
return;
@@ -845,7 +831,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
assert(Src.isScalar() && "Can't emit an agg store with this method");
EmitStoreOfScalar(Src.getScalarVal(), Dst.getAddress(),
- Dst.isVolatileQualified(), Ty);
+ Dst.isVolatileQualified(), Dst.getAlignment(), Ty);
}
void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
@@ -1045,20 +1031,22 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
return;
if (isa<ObjCIvarRefExpr>(E)) {
- LV.SetObjCIvar(LV, true);
+ LV.setObjCIvar(true);
ObjCIvarRefExpr *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr*>(E));
LV.setBaseIvarExp(Exp->getBase());
- LV.SetObjCArray(LV, E->getType()->isArrayType());
+ LV.setObjCArray(E->getType()->isArrayType());
return;
}
if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
- VD->isFileVarDecl())
- LV.SetGlobalObjCRef(LV, true);
+ VD->isFileVarDecl()) {
+ LV.setGlobalObjCRef(true);
+ LV.setThreadLocalRef(VD->isThreadSpecified());
+ }
}
- LV.SetObjCArray(LV, E->getType()->isArrayType());
+ LV.setObjCArray(E->getType()->isArrayType());
return;
}
@@ -1076,7 +1064,7 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
if (ExpTy->isPointerType())
ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
if (ExpTy->isRecordType())
- LV.SetObjCIvar(LV, false);
+ LV.setObjCIvar(false);
}
return;
}
@@ -1095,11 +1083,11 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
if (LV.isObjCIvar() && !LV.isObjCArray())
// Using array syntax to assigning to what an ivar points to is not
// same as assigning to the ivar itself. {id *Names;} Names[i] = 0;
- LV.SetObjCIvar(LV, false);
+ LV.setObjCIvar(false);
else if (LV.isGlobalObjCRef() && !LV.isObjCArray())
// Using array syntax to assigning to what global points to is not
// same as assigning to the global itself. {id *G;} G[i] = 0;
- LV.SetGlobalObjCRef(LV, false);
+ LV.setGlobalObjCRef(false);
return;
}
@@ -1107,7 +1095,7 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
// We don't know if member is an 'ivar', but this flag is looked at
// only in the context of LV.isObjCIvar().
- LV.SetObjCArray(LV, E->getType()->isArrayType());
+ LV.setObjCArray(E->getType()->isArrayType());
return;
}
}
@@ -1120,7 +1108,8 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
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()));
+ unsigned Alignment = CGF.getContext().getDeclAlign(VD).getQuantity();
+ LValue LV = CGF.MakeAddrLValue(V, E->getType(), Alignment);
setObjCGCLValueClass(CGF.getContext(), E, LV);
return LV;
}
@@ -1140,20 +1129,18 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF,
V = CGF.Builder.CreateBitCast(V, CGF.ConvertType(NoProtoType), "tmp");
}
}
- return LValue::MakeAddr(V, CGF.MakeQualifiers(E->getType()));
+ unsigned Alignment = CGF.getContext().getDeclAlign(FD).getQuantity();
+ return CGF.MakeAddrLValue(V, E->getType(), Alignment);
}
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const NamedDecl *ND = E->getDecl();
+ unsigned Alignment = CGF.getContext().getDeclAlign(ND).getQuantity();
if (ND->hasAttr<WeakRefAttr>()) {
const ValueDecl* VD = cast<ValueDecl>(ND);
llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
-
- Qualifiers Quals = MakeQualifiers(E->getType());
- LValue LV = LValue::MakeAddr(Aliasee, Quals);
-
- return LV;
+ return MakeAddrLValue(Aliasee, E->getType(), Alignment);
}
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
@@ -1170,11 +1157,6 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
V = CGM.getStaticLocalDeclAddress(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);
@@ -1183,21 +1165,31 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- LValue LV = LValue::MakeAddr(V, Quals);
- LValue::SetObjCNonGC(LV, NonGCable);
+
+ LValue LV = MakeAddrLValue(V, E->getType(), Alignment);
+ if (NonGCable) {
+ LV.getQuals().removeObjCGCAttr();
+ LV.setNonGC(true);
+ }
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
+ // If we're emitting an instance method as an independent lvalue,
+ // we're actually emitting a member pointer.
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
+ if (MD->isInstance()) {
+ llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(MD);
+ return MakeAddrLValue(V, MD->getType(), Alignment);
+ }
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
return EmitFunctionDeclLValue(*this, E, FD);
- // FIXME: the qualifier check does not seem sufficient here
- if (E->getQualifier()) {
- const FieldDecl *FD = cast<FieldDecl>(ND);
- llvm::Value *V = CGM.EmitPointerToDataMember(FD);
-
- return LValue::MakeAddr(V, MakeQualifiers(FD->getType()));
+ // If we're emitting a field as an independent lvalue, we're
+ // actually emitting a member pointer.
+ if (const FieldDecl *FD = dyn_cast<FieldDecl>(ND)) {
+ llvm::Value *V = CGM.getCXXABI().EmitMemberPointer(FD);
+ return MakeAddrLValue(V, FD->getType(), Alignment);
}
assert(false && "Unhandled DeclRefExpr");
@@ -1208,25 +1200,26 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) {
- return LValue::MakeAddr(GetAddrOfBlockDecl(E), MakeQualifiers(E->getType()));
+ unsigned Alignment =
+ CGF.getContext().getDeclAlign(E->getDecl()).getQuantity();
+ return MakeAddrLValue(GetAddrOfBlockDecl(E), E->getType(), Alignment);
}
LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
// __extension__ doesn't affect lvalue-ness.
- if (E->getOpcode() == UnaryOperator::Extension)
+ if (E->getOpcode() == UO_Extension)
return EmitLValue(E->getSubExpr());
QualType ExprTy = getContext().getCanonicalType(E->getSubExpr()->getType());
switch (E->getOpcode()) {
default: assert(0 && "Unknown unary operator lvalue!");
- case UnaryOperator::Deref: {
+ case UO_Deref: {
QualType T = E->getSubExpr()->getType()->getPointeeType();
assert(!T.isNull() && "CodeGenFunction::EmitUnaryOpLValue: Illegal type");
- Qualifiers Quals = MakeQualifiers(T);
- Quals.setAddressSpace(ExprTy.getAddressSpace());
+ LValue LV = MakeAddrLValue(EmitScalarExpr(E->getSubExpr()), T);
+ LV.getQuals().setAddressSpace(ExprTy.getAddressSpace());
- LValue LV = LValue::MakeAddr(EmitScalarExpr(E->getSubExpr()), Quals);
// We should not generate __weak write barrier on indirect reference
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
@@ -1234,21 +1227,21 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
if (getContext().getLangOptions().ObjC1 &&
getContext().getLangOptions().getGCMode() != LangOptions::NonGC &&
LV.isObjCWeak())
- LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
+ LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
return LV;
}
- case UnaryOperator::Real:
- case UnaryOperator::Imag: {
+ case UO_Real:
+ case UO_Imag: {
LValue LV = EmitLValue(E->getSubExpr());
- unsigned Idx = E->getOpcode() == UnaryOperator::Imag;
- return LValue::MakeAddr(Builder.CreateStructGEP(LV.getAddress(),
+ unsigned Idx = E->getOpcode() == UO_Imag;
+ return MakeAddrLValue(Builder.CreateStructGEP(LV.getAddress(),
Idx, "idx"),
- MakeQualifiers(ExprTy));
+ ExprTy);
}
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec: {
+ case UO_PreInc:
+ case UO_PreDec: {
LValue LV = EmitLValue(E->getSubExpr());
- bool isInc = E->getOpcode() == UnaryOperator::PreInc;
+ bool isInc = E->getOpcode() == UO_PreInc;
if (E->getType()->isAnyComplexType())
EmitComplexPrePostIncDec(E, LV, isInc, true/*isPre*/);
@@ -1260,53 +1253,56 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
}
LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
- return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromLiteral(E),
- Qualifiers());
+ return MakeAddrLValue(CGM.GetAddrOfConstantStringFromLiteral(E),
+ E->getType());
}
LValue CodeGenFunction::EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E) {
- return LValue::MakeAddr(CGM.GetAddrOfConstantStringFromObjCEncode(E),
- Qualifiers());
+ return MakeAddrLValue(CGM.GetAddrOfConstantStringFromObjCEncode(E),
+ E->getType());
}
-LValue CodeGenFunction::EmitPredefinedFunctionName(unsigned Type) {
- std::string GlobalVarName;
+LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
+ switch (E->getIdentType()) {
+ default:
+ return EmitUnsupportedLValue(E, "predefined expression");
- switch (Type) {
- default: assert(0 && "Invalid type");
case PredefinedExpr::Func:
- GlobalVarName = "__func__.";
- break;
case PredefinedExpr::Function:
- GlobalVarName = "__FUNCTION__.";
- break;
- case PredefinedExpr::PrettyFunction:
- GlobalVarName = "__PRETTY_FUNCTION__.";
- break;
- }
+ case PredefinedExpr::PrettyFunction: {
+ unsigned Type = E->getIdentType();
+ std::string GlobalVarName;
+
+ switch (Type) {
+ default: assert(0 && "Invalid type");
+ case PredefinedExpr::Func:
+ GlobalVarName = "__func__.";
+ break;
+ case PredefinedExpr::Function:
+ GlobalVarName = "__FUNCTION__.";
+ break;
+ case PredefinedExpr::PrettyFunction:
+ GlobalVarName = "__PRETTY_FUNCTION__.";
+ break;
+ }
- llvm::StringRef FnName = CurFn->getName();
- if (FnName.startswith("\01"))
- FnName = FnName.substr(1);
- GlobalVarName += FnName;
+ llvm::StringRef FnName = CurFn->getName();
+ if (FnName.startswith("\01"))
+ FnName = FnName.substr(1);
+ GlobalVarName += FnName;
- std::string FunctionName =
- PredefinedExpr::ComputeName((PredefinedExpr::IdentType)Type, CurCodeDecl);
+ const Decl *CurDecl = CurCodeDecl;
+ if (CurDecl == 0)
+ CurDecl = getContext().getTranslationUnitDecl();
- llvm::Constant *C =
- CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
- return LValue::MakeAddr(C, Qualifiers());
-}
+ std::string FunctionName =
+ PredefinedExpr::ComputeName((PredefinedExpr::IdentType)Type, CurDecl);
-LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
- switch (E->getIdentType()) {
- default:
- return EmitUnsupportedLValue(E, "predefined expression");
- case PredefinedExpr::Func:
- case PredefinedExpr::Function:
- case PredefinedExpr::PrettyFunction:
- return EmitPredefinedFunctionName(E->getIdentType());
+ llvm::Constant *C =
+ CGM.GetAddrOfConstantCString(FunctionName, GlobalVarName.c_str());
+ return MakeAddrLValue(C, E->getType());
+ }
}
}
@@ -1315,10 +1311,9 @@ llvm::BasicBlock *CodeGenFunction::getTrapBB() {
// If we are not optimzing, don't collapse all calls to trap in the function
// to the same call, that way, in the debugger they can see which operation
- // did in fact fail. If we are optimizing, we collpase all call to trap down
+ // did in fact fail. If we are optimizing, we collapse all calls to trap down
// to just one per function to save on codesize.
- if (GCO.OptimizationLevel
- && TrapBB)
+ if (GCO.OptimizationLevel && TrapBB)
return TrapBB;
llvm::BasicBlock *Cont = 0;
@@ -1345,7 +1340,7 @@ llvm::BasicBlock *CodeGenFunction::getTrapBB() {
static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
// If this isn't just an array->pointer decay, bail out.
const CastExpr *CE = dyn_cast<CastExpr>(E);
- if (CE == 0 || CE->getCastKind() != CastExpr::CK_ArrayToPointerDecay)
+ if (CE == 0 || CE->getCastKind() != CK_ArrayToPointerDecay)
return 0;
// If this is a decay from variable width array, bail out.
@@ -1382,7 +1377,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
if (CatchUndefined) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E->getBase())){
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
- if (ICE->getCastKind() == CastExpr::CK_ArrayToPointerDecay) {
+ if (ICE->getCastKind() == CK_ArrayToPointerDecay) {
if (const ConstantArrayType *CAT
= getContext().getAsConstantArrayType(DRE->getType())) {
llvm::APInt Size = CAT->getSize();
@@ -1454,13 +1449,12 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
assert(!T.isNull() &&
"CodeGenFunction::EmitArraySubscriptExpr(): Illegal base type");
- Qualifiers Quals = MakeQualifiers(T);
- Quals.setAddressSpace(E->getBase()->getType().getAddressSpace());
+ LValue LV = MakeAddrLValue(Address, T);
+ LV.getQuals().setAddressSpace(E->getBase()->getType().getAddressSpace());
- LValue LV = LValue::MakeAddr(Address, Quals);
if (getContext().getLangOptions().ObjC1 &&
getContext().getLangOptions().getGCMode() != LangOptions::NonGC) {
- LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
+ LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
setObjCGCLValueClass(getContext(), E, LV);
}
return LV;
@@ -1489,9 +1483,8 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
// it.
llvm::Value *Ptr = EmitScalarExpr(E->getBase());
const PointerType *PT = E->getBase()->getType()->getAs<PointerType>();
- Qualifiers Quals = MakeQualifiers(PT->getPointeeType());
- Quals.removeObjCGCAttr();
- Base = LValue::MakeAddr(Ptr, Quals);
+ Base = MakeAddrLValue(Ptr, PT->getPointeeType());
+ Base.getQuals().removeObjCGCAttr();
} else if (E->getBase()->isLvalue(getContext()) == Expr::LV_Valid) {
// Otherwise, if the base is an lvalue ( as in the case of foo.x.x),
// emit the base as an lvalue.
@@ -1506,7 +1499,7 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
// Store the vector to memory (because LValue wants an address).
llvm::Value *VecMem = CreateMemTemp(E->getBase()->getType());
Builder.CreateStore(Vec, VecMem);
- Base = LValue::MakeAddr(VecMem, Qualifiers());
+ Base = MakeAddrLValue(VecMem, E->getBase()->getType());
}
// Encode the element access list into a vector of unsigned indices.
@@ -1566,7 +1559,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
LValue LV = EmitLValueForField(BaseValue, Field,
BaseQuals.getCVRQualifiers());
- LValue::SetObjCNonGC(LV, isNonGC);
+ LV.setNonGC(isNonGC);
setObjCGCLValueClass(getContext(), E, LV);
return LV;
}
@@ -1645,13 +1638,15 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
if (Field->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
- Qualifiers Quals = MakeQualifiers(Field->getType());
- Quals.addCVRQualifiers(CVRQualifiers);
+ unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
+ LValue LV = MakeAddrLValue(V, Field->getType(), Alignment);
+ LV.getQuals().addCVRQualifiers(CVRQualifiers);
+
// __weak attribute on a field is ignored.
- if (Quals.getObjCGCAttr() == Qualifiers::Weak)
- Quals.removeObjCGCAttr();
+ if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak)
+ LV.getQuals().removeObjCGCAttr();
- return LValue::MakeAddr(V, Quals);
+ return LV;
}
LValue
@@ -1670,13 +1665,14 @@ CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value* BaseValue,
assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
- return LValue::MakeAddr(V, MakeQualifiers(FieldType));
+ unsigned Alignment = getContext().getDeclAlign(Field).getQuantity();
+ return MakeAddrLValue(V, FieldType, Alignment);
}
LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr* E){
llvm::Value *DeclPtr = CreateMemTemp(E->getType(), ".compoundliteral");
const Expr* InitExpr = E->getInitializer();
- LValue Result = LValue::MakeAddr(DeclPtr, MakeQualifiers(E->getType()));
+ LValue Result = MakeAddrLValue(DeclPtr, E->getType());
EmitAnyExprToMem(InitExpr, DeclPtr, /*Volatile*/ false);
@@ -1729,7 +1725,7 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
EmitBlock(ContBlock);
Temp = Builder.CreateLoad(Temp, "lv");
- return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
+ return MakeAddrLValue(Temp, E->getType());
}
// ?: here should be an aggregate.
@@ -1749,35 +1745,65 @@ CodeGenFunction::EmitConditionalOperatorLValue(const ConditionalOperator* E) {
/// cast from scalar to union.
LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
switch (E->getCastKind()) {
- default:
+ case CK_ToVoid:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
-
- case CastExpr::CK_Dynamic: {
+
+ case CK_NoOp:
+ if (E->getSubExpr()->Classify(getContext()).getKind()
+ != Expr::Classification::CL_PRValue) {
+ LValue LV = EmitLValue(E->getSubExpr());
+ if (LV.isPropertyRef() || LV.isKVCRef()) {
+ QualType QT = E->getSubExpr()->getType();
+ RValue RV =
+ LV.isPropertyRef() ? EmitLoadOfPropertyRefLValue(LV, QT)
+ : EmitLoadOfKVCRefLValue(LV, QT);
+ assert(!RV.isScalar() && "EmitCastLValue-scalar cast of property ref");
+ llvm::Value *V = RV.getAggregateAddr();
+ return MakeAddrLValue(V, QT);
+ }
+ return LV;
+ }
+ // Fall through to synthesize a temporary.
+
+ case CK_Unknown:
+ case CK_BitCast:
+ case CK_ArrayToPointerDecay:
+ case CK_FunctionToPointerDecay:
+ case CK_NullToMemberPointer:
+ case CK_IntegralToPointer:
+ case CK_PointerToIntegral:
+ case CK_VectorSplat:
+ case CK_IntegralCast:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingCast:
+ case CK_DerivedToBaseMemberPointer:
+ case CK_BaseToDerivedMemberPointer:
+ case CK_MemberPointerToBoolean:
+ case CK_AnyPointerToBlockPointerCast: {
+ // These casts only produce lvalues when we're binding a reference to a
+ // temporary realized from a (converted) pure rvalue. Emit the expression
+ // as a value, copy it into a temporary, and return an lvalue referring to
+ // that temporary.
+ llvm::Value *V = CreateMemTemp(E->getType(), "ref.temp");
+ EmitAnyExprToMem(E, V, false, false);
+ return MakeAddrLValue(V, E->getType());
+ }
+
+ case 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()));
+ return MakeAddrLValue(EmitDynamicCast(V, DCE), E->getType());
}
- case CastExpr::CK_NoOp: {
- LValue LV = EmitLValue(E->getSubExpr());
- if (LV.isPropertyRef()) {
- QualType QT = E->getSubExpr()->getType();
- RValue RV = EmitLoadOfPropertyRefLValue(LV, QT);
- assert(!RV.isScalar() && "EmitCastLValue - scalar cast of property ref");
- llvm::Value *V = RV.getAggregateAddr();
- return LValue::MakeAddr(V, MakeQualifiers(QT));
- }
- return LV;
- }
- case CastExpr::CK_ConstructorConversion:
- case CastExpr::CK_UserDefinedConversion:
- case CastExpr::CK_AnyPointerToObjCPointerCast:
+ case CK_ConstructorConversion:
+ case CK_UserDefinedConversion:
+ case CK_AnyPointerToObjCPointerCast:
return EmitLValue(E->getSubExpr());
- case CastExpr::CK_UncheckedDerivedToBase:
- case CastExpr::CK_DerivedToBase: {
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBase: {
const RecordType *DerivedClassTy =
E->getSubExpr()->getType()->getAs<RecordType>();
CXXRecordDecl *DerivedClassDecl =
@@ -1785,8 +1811,11 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
LValue LV = EmitLValue(E->getSubExpr());
llvm::Value *This;
- if (LV.isPropertyRef()) {
- RValue RV = EmitLoadOfPropertyRefLValue(LV, E->getSubExpr()->getType());
+ if (LV.isPropertyRef() || LV.isKVCRef()) {
+ QualType QT = E->getSubExpr()->getType();
+ RValue RV =
+ LV.isPropertyRef() ? EmitLoadOfPropertyRefLValue(LV, QT)
+ : EmitLoadOfKVCRefLValue(LV, QT);
assert (!RV.isScalar() && "EmitCastLValue");
This = RV.getAggregateAddr();
}
@@ -1796,13 +1825,14 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
// Perform the derived-to-base conversion
llvm::Value *Base =
GetAddressOfBaseClass(This, DerivedClassDecl,
- E->getBasePath(), /*NullCheckValue=*/false);
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
- return LValue::MakeAddr(Base, MakeQualifiers(E->getType()));
+ return MakeAddrLValue(Base, E->getType());
}
- case CastExpr::CK_ToUnion:
+ case CK_ToUnion:
return EmitAggExprToLValue(E);
- case CastExpr::CK_BaseToDerived: {
+ case CK_BaseToDerived: {
const RecordType *DerivedClassTy = E->getType()->getAs<RecordType>();
CXXRecordDecl *DerivedClassDecl =
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
@@ -1812,26 +1842,36 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
// Perform the base-to-derived conversion
llvm::Value *Derived =
GetAddressOfDerivedClass(LV.getAddress(), DerivedClassDecl,
- E->getBasePath(),/*NullCheckValue=*/false);
+ E->path_begin(), E->path_end(),
+ /*NullCheckValue=*/false);
- return LValue::MakeAddr(Derived, MakeQualifiers(E->getType()));
+ return MakeAddrLValue(Derived, E->getType());
}
- case CastExpr::CK_LValueBitCast: {
+ case CK_LValueBitCast: {
// 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()));
+ return MakeAddrLValue(V, E->getType());
}
+ case CK_ObjCObjectLValueCast: {
+ LValue LV = EmitLValue(E->getSubExpr());
+ QualType ToType = getContext().getLValueReferenceType(E->getType());
+ llvm::Value *V = Builder.CreateBitCast(LV.getAddress(),
+ ConvertType(ToType));
+ return MakeAddrLValue(V, E->getType());
}
+ }
+
+ llvm_unreachable("Unhandled lvalue cast kind?");
}
LValue CodeGenFunction::EmitNullInitializationLValue(
const CXXScalarValueInitExpr *E) {
QualType Ty = E->getType();
- LValue LV = LValue::MakeAddr(CreateMemTemp(Ty), MakeQualifiers(Ty));
+ LValue LV = MakeAddrLValue(CreateMemTemp(Ty), Ty);
EmitNullInitialization(LV.getAddress(), Ty);
return LV;
}
@@ -1881,28 +1921,26 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
// Comma expressions just emit their LHS then their RHS as an l-value.
- if (E->getOpcode() == BinaryOperator::Comma) {
+ if (E->getOpcode() == BO_Comma) {
EmitAnyExpr(E->getLHS());
EnsureInsertPoint();
return EmitLValue(E->getRHS());
}
- if (E->getOpcode() == BinaryOperator::PtrMemD ||
- E->getOpcode() == BinaryOperator::PtrMemI)
+ if (E->getOpcode() == BO_PtrMemD ||
+ E->getOpcode() == BO_PtrMemI)
return EmitPointerToDataMemberBinaryExpr(E);
// Can only get l-value for binary operator expressions which are a
// simple assignment of aggregate type.
- if (E->getOpcode() != BinaryOperator::Assign)
+ if (E->getOpcode() != BO_Assign)
return EmitUnsupportedLValue(E, "binary l-value expression");
if (!hasAggregateLLVMType(E->getType())) {
// Emit the LHS as an l-value.
LValue LV = EmitLValue(E->getLHS());
-
- llvm::Value *RHS = EmitScalarExpr(E->getRHS());
- EmitStoreOfScalar(RHS, LV.getAddress(), LV.isVolatileQualified(),
- E->getType());
+ // Store the value through the l-value.
+ EmitStoreThroughLValue(EmitAnyExpr(E->getRHS()), LV, E->getType());
return LV;
}
@@ -1913,13 +1951,13 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) {
RValue RV = EmitCallExpr(E);
if (!RV.isScalar())
- return LValue::MakeAddr(RV.getAggregateAddr(),MakeQualifiers(E->getType()));
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
assert(E->getCallReturnType()->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
- return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
+ return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
@@ -1930,13 +1968,12 @@ LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
llvm::Value *Temp = CreateMemTemp(E->getType(), "tmp");
EmitCXXConstructExpr(Temp, E);
- return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
+ return MakeAddrLValue(Temp, E->getType());
}
LValue
CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
- llvm::Value *Temp = EmitCXXTypeidExpr(E);
- return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
+ return MakeAddrLValue(EmitCXXTypeidExpr(E), E->getType());
}
LValue
@@ -1950,20 +1987,19 @@ LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
RValue RV = EmitObjCMessageExpr(E);
if (!RV.isScalar())
- return LValue::MakeAddr(RV.getAggregateAddr(),
- MakeQualifiers(E->getType()));
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
assert(E->getMethodDecl()->getResultType()->isReferenceType() &&
"Can't have a scalar return unless the return type is a "
"reference type!");
- return LValue::MakeAddr(RV.getScalarVal(), MakeQualifiers(E->getType()));
+ return MakeAddrLValue(RV.getScalarVal(), E->getType());
}
LValue CodeGenFunction::EmitObjCSelectorLValue(const ObjCSelectorExpr *E) {
llvm::Value *V =
CGM.getObjCRuntime().GetSelector(Builder, E->getSelector(), true);
- return LValue::MakeAddr(V, MakeQualifiers(E->getType()));
+ return MakeAddrLValue(V, E->getType());
}
llvm::Value *CodeGenFunction::EmitIvarOffset(const ObjCInterfaceDecl *Interface,
@@ -2025,7 +2061,7 @@ LValue CodeGenFunction::EmitObjCSuperExprLValue(const ObjCSuperExpr *E) {
LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {
// Can only get l-value for message expression returning aggregate type
RValue RV = EmitAnyExprToTemp(E);
- return LValue::MakeAddr(RV.getAggregateAddr(), MakeQualifiers(E->getType()));
+ return MakeAddrLValue(RV.getAggregateAddr(), E->getType());
}
RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
@@ -2054,20 +2090,19 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
LValue CodeGenFunction::
EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) {
llvm::Value *BaseV;
- if (E->getOpcode() == BinaryOperator::PtrMemI)
+ if (E->getOpcode() == BO_PtrMemI)
BaseV = EmitScalarExpr(E->getLHS());
else
BaseV = EmitLValue(E->getLHS()).getAddress();
- const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext());
- BaseV = Builder.CreateBitCast(BaseV, i8Ty);
+
llvm::Value *OffsetV = EmitScalarExpr(E->getRHS());
- llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr");
- QualType Ty = E->getRHS()->getType();
- Ty = Ty->getAs<MemberPointerType>()->getPointeeType();
-
- const llvm::Type *PType = ConvertType(getContext().getPointerType(Ty));
- AddV = Builder.CreateBitCast(AddV, PType);
- return LValue::MakeAddr(AddV, MakeQualifiers(Ty));
+ const MemberPointerType *MPT
+ = E->getRHS()->getType()->getAs<MemberPointerType>();
+
+ llvm::Value *AddV =
+ CGM.getCXXABI().EmitMemberDataPointerAddress(*this, BaseV, OffsetV, MPT);
+
+ return MakeAddrLValue(AddV, MPT->getPointeeType());
}
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 219a5f915329..28c8b3545b38 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -108,7 +108,6 @@ public:
void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);
void VisitBinAssign(const BinaryOperator *E);
void VisitBinComma(const BinaryOperator *E);
- void VisitUnaryAddrOf(const UnaryOperator *E);
void VisitObjCMessageExpr(ObjCMessageExpr *E);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -193,10 +192,18 @@ void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) {
void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) {
assert(Src.isAggregate() && "value must be aggregate value!");
- // If the result is ignored, don't copy from the value.
+ // If DestPtr is null, then we're evaluating an aggregate expression
+ // in a context (like an expression statement) that doesn't care
+ // about the result. C says that an lvalue-to-rvalue conversion is
+ // performed in these cases; C++ says that it is not. In either
+ // case, we don't actually need to do anything unless the value is
+ // volatile.
if (DestPtr == 0) {
- if (!Src.isVolatileQualified() || (IgnoreResult && Ignore))
+ if (!Src.isVolatileQualified() ||
+ CGF.CGM.getLangOptions().CPlusPlus ||
+ (IgnoreResult && Ignore))
return;
+
// If the source is volatile, we must read from it; to do that, we need
// some place to put it.
DestPtr = CGF.CreateMemTemp(E->getType(), "agg.tmp");
@@ -235,7 +242,7 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) {
//===----------------------------------------------------------------------===//
void AggExprEmitter::VisitCastExpr(CastExpr *E) {
- if (!DestPtr && E->getCastKind() != CastExpr::CK_Dynamic) {
+ if (!DestPtr && E->getCastKind() != CK_Dynamic) {
Visit(E->getSubExpr());
return;
}
@@ -243,7 +250,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
switch (E->getCastKind()) {
default: assert(0 && "Unhandled cast kind!");
- case CastExpr::CK_Dynamic: {
+ case CK_Dynamic: {
assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?");
LValue LV = CGF.EmitCheckedLValue(E->getSubExpr());
// FIXME: Do we also need to handle property references here?
@@ -257,105 +264,39 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break;
}
- case CastExpr::CK_ToUnion: {
+ case CK_ToUnion: {
// GCC union extension
- QualType PtrTy =
- CGF.getContext().getPointerType(E->getSubExpr()->getType());
+ QualType Ty = E->getSubExpr()->getType();
+ QualType PtrTy = CGF.getContext().getPointerType(Ty);
llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr,
CGF.ConvertType(PtrTy));
- EmitInitializationToLValue(E->getSubExpr(),
- LValue::MakeAddr(CastPtr, Qualifiers()),
- E->getSubExpr()->getType());
+ EmitInitializationToLValue(E->getSubExpr(), CGF.MakeAddrLValue(CastPtr, Ty),
+ Ty);
break;
}
- case CastExpr::CK_DerivedToBase:
- case CastExpr::CK_BaseToDerived:
- case CastExpr::CK_UncheckedDerivedToBase: {
+ case CK_DerivedToBase:
+ case CK_BaseToDerived:
+ case CK_UncheckedDerivedToBase: {
assert(0 && "cannot perform hierarchy conversion in EmitAggExpr: "
"should have been unpacked before we got here");
break;
}
// FIXME: Remove the CK_Unknown check here.
- case CastExpr::CK_Unknown:
- case CastExpr::CK_NoOp:
- case CastExpr::CK_UserDefinedConversion:
- case CastExpr::CK_ConstructorConversion:
+ case CK_Unknown:
+ case CK_NoOp:
+ case CK_UserDefinedConversion:
+ case CK_ConstructorConversion:
assert(CGF.getContext().hasSameUnqualifiedType(E->getSubExpr()->getType(),
E->getType()) &&
"Implicit cast types must be compatible");
Visit(E->getSubExpr());
break;
- case CastExpr::CK_NullToMemberPointer: {
- // If the subexpression's type is the C++0x nullptr_t, emit the
- // subexpression, which may have side effects.
- if (E->getSubExpr()->getType()->isNullPtrType())
- Visit(E->getSubExpr());
-
- const llvm::Type *PtrDiffTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
-
- llvm::Value *NullValue = llvm::Constant::getNullValue(PtrDiffTy);
- llvm::Value *Ptr = Builder.CreateStructGEP(DestPtr, 0, "ptr");
- Builder.CreateStore(NullValue, Ptr, VolatileDest);
-
- llvm::Value *Adj = Builder.CreateStructGEP(DestPtr, 1, "adj");
- Builder.CreateStore(NullValue, Adj, VolatileDest);
-
- break;
- }
-
- case CastExpr::CK_LValueBitCast:
+ case CK_LValueBitCast:
llvm_unreachable("there are no lvalue bit-casts on aggregates");
break;
-
- case CastExpr::CK_BitCast: {
- // This must be a member function pointer cast.
- Visit(E->getSubExpr());
- break;
- }
-
- case CastExpr::CK_DerivedToBaseMemberPointer:
- case CastExpr::CK_BaseToDerivedMemberPointer: {
- QualType SrcType = E->getSubExpr()->getType();
-
- llvm::Value *Src = CGF.CreateMemTemp(SrcType, "tmp");
- CGF.EmitAggExpr(E->getSubExpr(), Src, SrcType.isVolatileQualified());
-
- llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr");
- SrcPtr = Builder.CreateLoad(SrcPtr);
-
- llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj");
- SrcAdj = Builder.CreateLoad(SrcAdj);
-
- llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr");
- Builder.CreateStore(SrcPtr, DstPtr, VolatileDest);
-
- llvm::Value *DstAdj = Builder.CreateStructGEP(DestPtr, 1, "dst.adj");
-
- // Now See if we need to update the adjustment.
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(SrcType->getAs<MemberPointerType>()->
- getClass()->getAs<RecordType>()->getDecl());
- const CXXRecordDecl *DerivedDecl =
- cast<CXXRecordDecl>(E->getType()->getAs<MemberPointerType>()->
- getClass()->getAs<RecordType>()->getDecl());
- if (E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
- std::swap(DerivedDecl, BaseDecl);
-
- if (llvm::Constant *Adj =
- CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, E->getBasePath())) {
- if (E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
- SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj");
- else
- SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj");
- }
-
- Builder.CreateStore(SrcAdj, DstAdj, VolatileDest);
- break;
- }
}
}
@@ -391,42 +332,12 @@ void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {
/*IgnoreResult=*/false, IsInitializer);
}
-void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {
- // We have a member function pointer.
- const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
- (void) MPT;
- assert(MPT->getPointeeType()->isFunctionProtoType() &&
- "Unexpected member pointer type!");
-
- // The creation of member function pointers has no side effects; if
- // there is no destination pointer, we have nothing to do.
- if (!DestPtr)
- return;
-
- const DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
- const CXXMethodDecl *MD =
- cast<CXXMethodDecl>(DRE->getDecl())->getCanonicalDecl();
-
- const llvm::Type *PtrDiffTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
-
- llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr");
- llvm::Value *FuncPtr = CGF.CGM.GetCXXMemberFunctionPointerValue(MD);
- Builder.CreateStore(FuncPtr, DstPtr, VolatileDest);
-
- llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "dst.adj");
- // The adjustment will always be 0.
- Builder.CreateStore(llvm::ConstantInt::get(PtrDiffTy, 0), AdjPtr,
- VolatileDest);
-}
-
void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {
CGF.EmitCompoundStmt(*E->getSubStmt(), true, DestPtr, VolatileDest);
}
void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
- if (E->getOpcode() == BinaryOperator::PtrMemD ||
- E->getOpcode() == BinaryOperator::PtrMemI)
+ if (E->getOpcode() == BO_PtrMemD || E->getOpcode() == BO_PtrMemI)
VisitPointerToDataMemberBinaryOperator(E);
else
CGF.ErrorUnsupported(E, "aggregate binary expression");
@@ -519,7 +430,7 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
return;
}
- EmitFinalDestCopy(VE, LValue::MakeAddr(ArgPtr, Qualifiers()));
+ EmitFinalDestCopy(VE, CGF.MakeAddrLValue(ArgPtr, VE->getType()));
}
void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
@@ -546,12 +457,6 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) {
if (!Val) // Create a temporary variable.
Val = CGF.CreateMemTemp(E->getType(), "tmp");
- if (E->requiresZeroInitialization())
- EmitNullInitializationToLValue(LValue::MakeAddr(Val,
- // FIXME: Qualifiers()?
- E->getType().getQualifiers()),
- E->getType());
-
CGF.EmitCXXConstructExpr(Val, E);
}
@@ -568,8 +473,8 @@ void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
// Create a temporary variable.
Val = CGF.CreateMemTemp(E->getType(), "tmp");
}
- LValue LV = LValue::MakeAddr(Val, Qualifiers());
- EmitNullInitializationToLValue(LV, E->getType());
+ EmitNullInitializationToLValue(CGF.MakeAddrLValue(Val, E->getType()),
+ E->getType());
}
void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
@@ -579,8 +484,8 @@ void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
// Create a temporary variable.
Val = CGF.CreateMemTemp(E->getType(), "tmp");
}
- LValue LV = LValue::MakeAddr(Val, Qualifiers());
- EmitNullInitializationToLValue(LV, E->getType());
+ EmitNullInitializationToLValue(CGF.MakeAddrLValue(Val, E->getType()),
+ E->getType());
}
void
@@ -625,7 +530,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
llvm::GlobalVariable* GV =
new llvm::GlobalVariable(CGF.CGM.getModule(), C->getType(), true,
llvm::GlobalValue::InternalLinkage, C, "");
- EmitFinalDestCopy(E, LValue::MakeAddr(GV, Qualifiers()));
+ EmitFinalDestCopy(E, CGF.MakeAddrLValue(GV, E->getType()));
return;
}
#endif
@@ -656,17 +561,15 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
// FIXME: were we intentionally ignoring address spaces and GC attributes?
- Qualifiers Quals = CGF.MakeQualifiers(ElementType);
for (uint64_t i = 0; i != NumArrayElements; ++i) {
llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
+ LValue LV = CGF.MakeAddrLValue(NextVal, ElementType);
if (i < NumInitElements)
- EmitInitializationToLValue(E->getInit(i),
- LValue::MakeAddr(NextVal, Quals),
- ElementType);
+ EmitInitializationToLValue(E->getInit(i), LV, ElementType);
+
else
- EmitNullInitializationToLValue(LValue::MakeAddr(NextVal, Quals),
- ElementType);
+ EmitNullInitializationToLValue(LV, ElementType);
}
return;
}
@@ -679,8 +582,17 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// the optimizer, especially with bitfields.
unsigned NumInitElements = E->getNumInits();
RecordDecl *SD = E->getType()->getAs<RecordType>()->getDecl();
- unsigned CurInitVal = 0;
-
+
+ // If we're initializing the whole aggregate, just do it in place.
+ // FIXME: This is a hack around an AST bug (PR6537).
+ if (NumInitElements == 1 && E->getType() == E->getInit(0)->getType()) {
+ EmitInitializationToLValue(E->getInit(0),
+ CGF.MakeAddrLValue(DestPtr, E->getType()),
+ E->getType());
+ return;
+ }
+
+
if (E->getType()->isUnionType()) {
// Only initialize one field of a union. The field itself is
// specified by the initializer list.
@@ -712,19 +624,10 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
return;
}
-
- // If we're initializing the whole aggregate, just do it in place.
- // FIXME: This is a hack around an AST bug (PR6537).
- if (NumInitElements == 1 && E->getType() == E->getInit(0)->getType()) {
- EmitInitializationToLValue(E->getInit(0),
- LValue::MakeAddr(DestPtr, Qualifiers()),
- E->getType());
- return;
- }
-
// Here we iterate over the fields; this makes it simpler to both
// default-initialize fields and skip over unnamed fields.
+ unsigned CurInitVal = 0;
for (RecordDecl::field_iterator Field = SD->field_begin(),
FieldEnd = SD->field_end();
Field != FieldEnd; ++Field) {
@@ -738,7 +641,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// FIXME: volatility
LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestPtr, *Field, 0);
// We never generate write-barries for initialized fields.
- LValue::SetObjCNonGC(FieldLoc, true);
+ FieldLoc.setNonGC(true);
if (CurInitVal < NumInitElements) {
// Store the initializer into the field.
EmitInitializationToLValue(E->getInit(CurInitVal++), FieldLoc,
@@ -776,10 +679,10 @@ void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr,
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!");
- Qualifiers Q = MakeQualifiers(E->getType());
llvm::Value *Temp = CreateMemTemp(E->getType());
- EmitAggExpr(E, Temp, Q.hasVolatile());
- return LValue::MakeAddr(Temp, Q);
+ LValue LV = MakeAddrLValue(Temp, E->getType());
+ EmitAggExpr(E, Temp, LV.isVolatileQualified());
+ return LV;
}
void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 69e5f0ef4be8..9a98281771fa 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -12,7 +12,9 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
+#include "llvm/Intrinsics.h"
using namespace clang;
using namespace CodeGen;
@@ -91,14 +93,9 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
return EmitCall(getContext().getPointerType(MD->getType()), Callee,
ReturnValue, CE->arg_begin(), CE->arg_end());
}
-
- const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
- const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
- FPT->isVariadic());
+ // Compute the object pointer.
llvm::Value *This;
-
if (ME->isArrow())
This = EmitScalarExpr(ME->getBase());
else {
@@ -106,7 +103,10 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
This = BaseLV.getAddress();
}
- if (MD->isCopyAssignment() && MD->isTrivial()) {
+ if (MD->isTrivial()) {
+ if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
+
+ assert(MD->isCopyAssignment() && "unknown trivial member function");
// We don't like to generate the trivial copy assignment operator when
// it isn't necessary; just produce the proper effect here.
llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
@@ -114,25 +114,34 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
return RValue::get(This);
}
+ // Compute the function type we're calling.
+ const CGFunctionInfo &FInfo =
+ (isa<CXXDestructorDecl>(MD)
+ ? CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD),
+ Dtor_Complete)
+ : CGM.getTypes().getFunctionInfo(MD));
+
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty
+ = CGM.getTypes().GetFunctionType(FInfo, FPT->isVariadic());
+
// C++ [class.virtual]p12:
// Explicit qualification with the scope operator (5.1) suppresses the
// virtual call mechanism.
//
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
+ bool UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
+ && !canDevirtualizeMemberFunctionCalls(ME->getBase());
+
llvm::Value *Callee;
- if (const CXXDestructorDecl *Destructor
- = dyn_cast<CXXDestructorDecl>(MD)) {
- if (Destructor->isTrivial())
- return RValue::get(0);
- if (MD->isVirtual() && !ME->hasQualifier() &&
- !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
- Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty);
+ if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
+ if (UseVirtualCall) {
+ Callee = BuildVirtualCall(Dtor, Dtor_Complete, This, Ty);
} else {
- Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty);
+ Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
}
- } else if (MD->isVirtual() && !ME->hasQualifier() &&
- !canDevirtualizeMemberFunctionCalls(ME->getBase())) {
+ } else if (UseVirtualCall) {
Callee = BuildVirtualCall(MD, This, Ty);
} else {
Callee = CGM.GetAddrOfFunction(MD, Ty);
@@ -152,89 +161,27 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
const MemberPointerType *MPT =
MemFnExpr->getType()->getAs<MemberPointerType>();
+
const FunctionProtoType *FPT =
MPT->getPointeeType()->getAs<FunctionProtoType>();
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
- const llvm::FunctionType *FTy =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
- FPT->isVariadic());
-
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-
// Get the member function pointer.
- llvm::Value *MemFnPtr = CreateMemTemp(MemFnExpr->getType(), "mem.fn");
- EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false);
+ llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr);
// Emit the 'this' pointer.
llvm::Value *This;
- if (BO->getOpcode() == BinaryOperator::PtrMemI)
+ if (BO->getOpcode() == BO_PtrMemI)
This = EmitScalarExpr(BaseExpr);
else
This = EmitLValue(BaseExpr).getAddress();
-
- // Adjust it.
- llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1);
- Adj = Builder.CreateLoad(Adj, "mem.fn.adj");
-
- llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr");
- Ptr = Builder.CreateGEP(Ptr, Adj, "adj");
-
- This = Builder.CreateBitCast(Ptr, This->getType(), "this");
-
- llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr");
-
- const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
- llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn");
-
- // If the LSB in the function pointer is 1, the function pointer points to
- // a virtual function.
- llvm::Value *IsVirtual
- = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1),
- "and");
-
- IsVirtual = Builder.CreateTrunc(IsVirtual,
- llvm::Type::getInt1Ty(VMContext));
+ // Ask the ABI to load the callee. Note that This is modified.
+ llvm::Value *Callee =
+ CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(CGF, This, MemFnPtr, MPT);
- llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual");
- llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual");
- llvm::BasicBlock *FnEnd = createBasicBlock("fn.end");
-
- Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
- EmitBlock(FnVirtual);
-
- const llvm::Type *VTableTy =
- FTy->getPointerTo()->getPointerTo();
-
- llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
- VTable = Builder.CreateLoad(VTable);
-
- VTable = Builder.CreateBitCast(VTable, Int8PtrTy);
- llvm::Value *VTableOffset =
- Builder.CreateSub(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1));
-
- VTable = Builder.CreateGEP(VTable, VTableOffset, "fn");
- VTable = Builder.CreateBitCast(VTable, VTableTy);
-
- llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
-
- EmitBranch(FnEnd);
- EmitBlock(FnNonVirtual);
-
- // If the function is not virtual, just load the pointer.
- llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn");
- NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo());
-
- EmitBlock(FnEnd);
-
- llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
- Callee->reserveOperandSpace(2);
- Callee->addIncoming(VirtualFn, FnVirtual);
- Callee->addIncoming(NonVirtualFn, FnNonVirtual);
-
CallArgList Args;
QualType ThisType =
@@ -263,11 +210,17 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
"EmitCXXOperatorMemberCallExpr - user declared copy assignment");
LValue LV = EmitLValue(E->getArg(0));
llvm::Value *This;
- if (LV.isPropertyRef()) {
+ if (LV.isPropertyRef() || LV.isKVCRef()) {
llvm::Value *AggLoc = CreateMemTemp(E->getArg(1)->getType());
EmitAggExpr(E->getArg(1), AggLoc, false /*VolatileDest*/);
- EmitObjCPropertySet(LV.getPropertyRefExpr(),
- RValue::getAggregate(AggLoc, false /*VolatileDest*/));
+ if (LV.isPropertyRef())
+ EmitObjCPropertySet(LV.getPropertyRefExpr(),
+ RValue::getAggregate(AggLoc,
+ false /*VolatileDest*/));
+ else
+ EmitObjCPropertySet(LV.getKVCRefExpr(),
+ RValue::getAggregate(AggLoc,
+ false /*VolatileDest*/));
return RValue::getAggregate(0, false);
}
else
@@ -286,8 +239,11 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
FPT->isVariadic());
LValue LV = EmitLValue(E->getArg(0));
llvm::Value *This;
- if (LV.isPropertyRef()) {
- RValue RV = EmitLoadOfPropertyRefLValue(LV, E->getArg(0)->getType());
+ if (LV.isPropertyRef() || LV.isKVCRef()) {
+ QualType QT = E->getArg(0)->getType();
+ RValue RV =
+ LV.isPropertyRef() ? EmitLoadOfPropertyRefLValue(LV, QT)
+ : EmitLoadOfKVCRefLValue(LV, QT);
assert (!RV.isScalar() && "EmitCXXOperatorMemberCallExpr");
This = RV.getAggregateAddr();
}
@@ -309,19 +265,18 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
const CXXConstructExpr *E) {
assert(Dest && "Must have a destination!");
const CXXConstructorDecl *CD = E->getConstructor();
- const ConstantArrayType *Array =
- getContext().getAsConstantArrayType(E->getType());
- // For a copy constructor, even if it is trivial, must fall thru so
- // its argument is code-gen'ed.
- if (!CD->isCopyConstructor()) {
- QualType InitType = E->getType();
- if (Array)
- InitType = getContext().getBaseElementType(Array);
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(InitType->getAs<RecordType>()->getDecl());
- if (RD->hasTrivialConstructor())
- return;
- }
+
+ // If we require zero initialization before (or instead of) calling the
+ // constructor, as can be the case with a non-user-provided default
+ // constructor, emit the zero initialization now.
+ if (E->requiresZeroInitialization())
+ EmitNullInitialization(Dest, E->getType());
+
+
+ // If this is a call to a trivial default constructor, do nothing.
+ if (CD->isTrivial() && CD->isDefaultConstructor())
+ return;
+
// Code gen optimization to eliminate copy constructor and return
// its first argument instead, if in fact that argument is a temporary
// object.
@@ -331,6 +286,9 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
return;
}
}
+
+ const ConstantArrayType *Array
+ = getContext().getAsConstantArrayType(E->getType());
if (Array) {
QualType BaseElementTy = getContext().getBaseElementType(Array);
const llvm::Type *BasePtr = ConvertType(BaseElementTy);
@@ -354,131 +312,205 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,
}
}
-static CharUnits CalculateCookiePadding(ASTContext &Ctx, QualType ElementType) {
- const RecordType *RT = ElementType->getAs<RecordType>();
- if (!RT)
- return CharUnits::Zero();
-
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
- return CharUnits::Zero();
-
- // Check if the class has a trivial destructor.
- if (RD->hasTrivialDestructor()) {
- // Check if the usual deallocation function takes two arguments.
- const CXXMethodDecl *UsualDeallocationFunction = 0;
-
- DeclarationName OpName =
- Ctx.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
- DeclContext::lookup_const_iterator Op, OpEnd;
- for (llvm::tie(Op, OpEnd) = RD->lookup(OpName);
- Op != OpEnd; ++Op) {
- const CXXMethodDecl *Delete = cast<CXXMethodDecl>(*Op);
-
- if (Delete->isUsualDeallocationFunction()) {
- UsualDeallocationFunction = Delete;
- break;
- }
- }
-
- // No usual deallocation function, we don't need a cookie.
- if (!UsualDeallocationFunction)
- return CharUnits::Zero();
-
- // The usual deallocation function doesn't take a size_t argument, so we
- // don't need a cookie.
- if (UsualDeallocationFunction->getNumParams() == 1)
- return CharUnits::Zero();
-
- assert(UsualDeallocationFunction->getNumParams() == 2 &&
- "Unexpected deallocation function type!");
- }
-
- // Padding is the maximum of sizeof(size_t) and alignof(ElementType)
- return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
- Ctx.getTypeAlignInChars(ElementType));
+/// Check whether the given operator new[] is the global placement
+/// operator new[].
+static bool IsPlacementOperatorNewArray(ASTContext &Ctx,
+ const FunctionDecl *Fn) {
+ // Must be in global scope. Note that allocation functions can't be
+ // declared in namespaces.
+ if (!Fn->getDeclContext()->getRedeclContext()->isFileContext())
+ return false;
+
+ // Signature must be void *operator new[](size_t, void*).
+ // The size_t is common to all operator new[]s.
+ if (Fn->getNumParams() != 2)
+ return false;
+
+ CanQualType ParamType = Ctx.getCanonicalType(Fn->getParamDecl(1)->getType());
+ return (ParamType == Ctx.VoidPtrTy);
}
-static CharUnits CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
+static CharUnits CalculateCookiePadding(CodeGenFunction &CGF,
+ const CXXNewExpr *E) {
if (!E->isArray())
return CharUnits::Zero();
// No cookie is required if the new operator being used is
// ::operator new[](size_t, void*).
const FunctionDecl *OperatorNew = E->getOperatorNew();
- if (OperatorNew->getDeclContext()->getLookupContext()->isFileContext()) {
- if (OperatorNew->getNumParams() == 2) {
- CanQualType ParamType =
- Ctx.getCanonicalType(OperatorNew->getParamDecl(1)->getType());
-
- if (ParamType == Ctx.VoidPtrTy)
- return CharUnits::Zero();
- }
- }
-
- return CalculateCookiePadding(Ctx, E->getAllocatedType());
+ if (IsPlacementOperatorNewArray(CGF.getContext(), OperatorNew))
+ return CharUnits::Zero();
+
+ return CGF.CGM.getCXXABI().GetArrayCookieSize(E->getAllocatedType());
}
static llvm::Value *EmitCXXNewAllocSize(ASTContext &Context,
- CodeGenFunction &CGF,
+ CodeGenFunction &CGF,
const CXXNewExpr *E,
- llvm::Value *& NumElements) {
- QualType Type = E->getAllocatedType();
- CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(Type);
- const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
-
- if (!E->isArray())
- return llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+ llvm::Value *&NumElements,
+ llvm::Value *&SizeWithoutCookie) {
+ QualType ElemType = E->getAllocatedType();
- CharUnits CookiePadding = CalculateCookiePadding(CGF.getContext(), E);
+ const llvm::IntegerType *SizeTy =
+ cast<llvm::IntegerType>(CGF.ConvertType(CGF.getContext().getSizeType()));
- Expr::EvalResult Result;
- if (E->getArraySize()->Evaluate(Result, CGF.getContext()) &&
- !Result.HasSideEffects && Result.Val.isInt()) {
+ CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(ElemType);
- CharUnits AllocSize =
- Result.Val.getInt().getZExtValue() * TypeSize + CookiePadding;
-
- NumElements =
- llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue());
- while (const ArrayType *AType = Context.getAsArrayType(Type)) {
- const llvm::ArrayType *llvmAType =
- cast<llvm::ArrayType>(CGF.ConvertType(Type));
- NumElements =
- CGF.Builder.CreateMul(NumElements,
- llvm::ConstantInt::get(
- SizeTy, llvmAType->getNumElements()));
- Type = AType->getElementType();
- }
-
- return llvm::ConstantInt::get(SizeTy, AllocSize.getQuantity());
+ if (!E->isArray()) {
+ SizeWithoutCookie = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+ return SizeWithoutCookie;
}
-
+
+ // Figure out the cookie size.
+ CharUnits CookieSize = CalculateCookiePadding(CGF, E);
+
// Emit the array size expression.
+ // We multiply the size of all dimensions for NumElements.
+ // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.
NumElements = CGF.EmitScalarExpr(E->getArraySize());
-
- // Multiply with the type size.
- llvm::Value *V =
- CGF.Builder.CreateMul(NumElements,
- llvm::ConstantInt::get(SizeTy,
- TypeSize.getQuantity()));
-
- while (const ArrayType *AType = Context.getAsArrayType(Type)) {
- const llvm::ArrayType *llvmAType =
- cast<llvm::ArrayType>(CGF.ConvertType(Type));
- NumElements =
- CGF.Builder.CreateMul(NumElements,
- llvm::ConstantInt::get(
- SizeTy, llvmAType->getNumElements()));
- Type = AType->getElementType();
+ assert(NumElements->getType() == SizeTy && "element count not a size_t");
+
+ uint64_t ArraySizeMultiplier = 1;
+ while (const ConstantArrayType *CAT
+ = CGF.getContext().getAsConstantArrayType(ElemType)) {
+ ElemType = CAT->getElementType();
+ ArraySizeMultiplier *= CAT->getSize().getZExtValue();
}
- // And add the cookie padding if necessary.
- if (!CookiePadding.isZero())
- V = CGF.Builder.CreateAdd(V,
- llvm::ConstantInt::get(SizeTy, CookiePadding.getQuantity()));
-
- return V;
+ llvm::Value *Size;
+
+ // If someone is doing 'new int[42]' there is no need to do a dynamic check.
+ // Don't bloat the -O0 code.
+ if (llvm::ConstantInt *NumElementsC =
+ dyn_cast<llvm::ConstantInt>(NumElements)) {
+ llvm::APInt NEC = NumElementsC->getValue();
+ unsigned SizeWidth = NEC.getBitWidth();
+
+ // Determine if there is an overflow here by doing an extended multiply.
+ NEC.zext(SizeWidth*2);
+ llvm::APInt SC(SizeWidth*2, TypeSize.getQuantity());
+ SC *= NEC;
+
+ if (!CookieSize.isZero()) {
+ // Save the current size without a cookie. We don't care if an
+ // overflow's already happened because SizeWithoutCookie isn't
+ // used if the allocator returns null or throws, as it should
+ // always do on an overflow.
+ llvm::APInt SWC = SC;
+ SWC.trunc(SizeWidth);
+ SizeWithoutCookie = llvm::ConstantInt::get(SizeTy, SWC);
+
+ // Add the cookie size.
+ SC += llvm::APInt(SizeWidth*2, CookieSize.getQuantity());
+ }
+
+ if (SC.countLeadingZeros() >= SizeWidth) {
+ SC.trunc(SizeWidth);
+ Size = llvm::ConstantInt::get(SizeTy, SC);
+ } else {
+ // On overflow, produce a -1 so operator new throws.
+ Size = llvm::Constant::getAllOnesValue(SizeTy);
+ }
+
+ // Scale NumElements while we're at it.
+ uint64_t N = NEC.getZExtValue() * ArraySizeMultiplier;
+ NumElements = llvm::ConstantInt::get(SizeTy, N);
+
+ // Otherwise, we don't need to do an overflow-checked multiplication if
+ // we're multiplying by one.
+ } else if (TypeSize.isOne()) {
+ assert(ArraySizeMultiplier == 1);
+
+ Size = NumElements;
+
+ // If we need a cookie, add its size in with an overflow check.
+ // This is maybe a little paranoid.
+ if (!CookieSize.isZero()) {
+ SizeWithoutCookie = Size;
+
+ llvm::Value *CookieSizeV
+ = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
+
+ const llvm::Type *Types[] = { SizeTy };
+ llvm::Value *UAddF
+ = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, Types, 1);
+ llvm::Value *AddRes
+ = CGF.Builder.CreateCall2(UAddF, Size, CookieSizeV);
+
+ Size = CGF.Builder.CreateExtractValue(AddRes, 0);
+ llvm::Value *DidOverflow = CGF.Builder.CreateExtractValue(AddRes, 1);
+ Size = CGF.Builder.CreateSelect(DidOverflow,
+ llvm::ConstantInt::get(SizeTy, -1),
+ Size);
+ }
+
+ // Otherwise use the int.umul.with.overflow intrinsic.
+ } else {
+ llvm::Value *OutermostElementSize
+ = llvm::ConstantInt::get(SizeTy, TypeSize.getQuantity());
+
+ llvm::Value *NumOutermostElements = NumElements;
+
+ // Scale NumElements by the array size multiplier. This might
+ // overflow, but only if the multiplication below also overflows,
+ // in which case this multiplication isn't used.
+ if (ArraySizeMultiplier != 1)
+ NumElements = CGF.Builder.CreateMul(NumElements,
+ llvm::ConstantInt::get(SizeTy, ArraySizeMultiplier));
+
+ // The requested size of the outermost array is non-constant.
+ // Multiply that by the static size of the elements of that array;
+ // on unsigned overflow, set the size to -1 to trigger an
+ // exception from the allocation routine. This is sufficient to
+ // prevent buffer overruns from the allocator returning a
+ // seemingly valid pointer to insufficient space. This idea comes
+ // originally from MSVC, and GCC has an open bug requesting
+ // similar behavior:
+ // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19351
+ //
+ // This will not be sufficient for C++0x, which requires a
+ // specific exception class (std::bad_array_new_length).
+ // That will require ABI support that has not yet been specified.
+ const llvm::Type *Types[] = { SizeTy };
+ llvm::Value *UMulF
+ = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, Types, 1);
+ llvm::Value *MulRes = CGF.Builder.CreateCall2(UMulF, NumOutermostElements,
+ OutermostElementSize);
+
+ // The overflow bit.
+ llvm::Value *DidOverflow = CGF.Builder.CreateExtractValue(MulRes, 1);
+
+ // The result of the multiplication.
+ Size = CGF.Builder.CreateExtractValue(MulRes, 0);
+
+ // If we have a cookie, we need to add that size in, too.
+ if (!CookieSize.isZero()) {
+ SizeWithoutCookie = Size;
+
+ llvm::Value *CookieSizeV
+ = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
+ llvm::Value *UAddF
+ = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, Types, 1);
+ llvm::Value *AddRes
+ = CGF.Builder.CreateCall2(UAddF, SizeWithoutCookie, CookieSizeV);
+
+ Size = CGF.Builder.CreateExtractValue(AddRes, 0);
+
+ llvm::Value *AddDidOverflow = CGF.Builder.CreateExtractValue(AddRes, 1);
+ DidOverflow = CGF.Builder.CreateAnd(DidOverflow, AddDidOverflow);
+ }
+
+ Size = CGF.Builder.CreateSelect(DidOverflow,
+ llvm::ConstantInt::get(SizeTy, -1),
+ Size);
+ }
+
+ if (CookieSize.isZero())
+ SizeWithoutCookie = Size;
+ else
+ assert(SizeWithoutCookie && "didn't set SizeWithoutCookie?");
+
+ return Size;
}
static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
@@ -489,10 +521,13 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
const Expr *Init = E->getConstructorArg(0);
QualType AllocType = E->getAllocatedType();
-
+
+ unsigned Alignment =
+ CGF.getContext().getTypeAlignInChars(AllocType).getQuantity();
if (!CGF.hasAggregateLLVMType(AllocType))
CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
- AllocType.isVolatileQualified(), AllocType);
+ AllocType.isVolatileQualified(), Alignment,
+ AllocType);
else if (AllocType->isAnyComplexType())
CGF.EmitComplexExprIntoAddr(Init, NewPtr,
AllocType.isVolatileQualified());
@@ -554,18 +589,59 @@ CodeGenFunction::EmitNewArrayInitializer(const CXXNewExpr *E,
EmitBlock(AfterFor, true);
}
+static void EmitZeroMemSet(CodeGenFunction &CGF, QualType T,
+ llvm::Value *NewPtr, llvm::Value *Size) {
+ llvm::LLVMContext &VMContext = CGF.CGM.getLLVMContext();
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
+ if (NewPtr->getType() != BP)
+ NewPtr = CGF.Builder.CreateBitCast(NewPtr, BP, "tmp");
+
+ CGF.Builder.CreateCall5(CGF.CGM.getMemSetFn(BP, CGF.IntPtrTy), NewPtr,
+ llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)),
+ Size,
+ llvm::ConstantInt::get(CGF.Int32Ty,
+ CGF.getContext().getTypeAlign(T)/8),
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext),
+ 0));
+}
+
static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
llvm::Value *NewPtr,
- llvm::Value *NumElements) {
+ llvm::Value *NumElements,
+ llvm::Value *AllocSizeWithoutCookie) {
if (E->isArray()) {
if (CXXConstructorDecl *Ctor = E->getConstructor()) {
- if (!Ctor->getParent()->hasTrivialConstructor())
- CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
- E->constructor_arg_begin(),
- E->constructor_arg_end());
+ bool RequiresZeroInitialization = false;
+ if (Ctor->getParent()->hasTrivialConstructor()) {
+ // If new expression did not specify value-initialization, then there
+ // is no initialization.
+ if (!E->hasInitializer() || Ctor->getParent()->isEmpty())
+ return;
+
+ if (CGF.CGM.getTypes().isZeroInitializable(E->getAllocatedType())) {
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+ EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,
+ AllocSizeWithoutCookie);
+ return;
+ }
+
+ RequiresZeroInitialization = true;
+ }
+
+ CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
+ E->constructor_arg_begin(),
+ E->constructor_arg_end(),
+ RequiresZeroInitialization);
return;
- }
- else {
+ } else if (E->getNumConstructorArgs() == 1 &&
+ isa<ImplicitValueInitExpr>(E->getConstructorArg(0))) {
+ // Optimization: since zero initialization will just set the memory
+ // to all zeroes, generate a single memset to do it in one shot.
+ EmitZeroMemSet(CGF, E->getAllocatedType(), NewPtr,
+ AllocSizeWithoutCookie);
+ return;
+ } else {
CGF.EmitNewArrayInitializer(E, NewPtr, NumElements);
return;
}
@@ -595,6 +671,10 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
QualType AllocType = E->getAllocatedType();
+ if (AllocType->isArrayType())
+ while (const ArrayType *AType = getContext().getAsArrayType(AllocType))
+ AllocType = AType->getElementType();
+
FunctionDecl *NewFD = E->getOperatorNew();
const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();
@@ -604,8 +684,10 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
QualType SizeTy = getContext().getSizeType();
llvm::Value *NumElements = 0;
+ llvm::Value *AllocSizeWithoutCookie = 0;
llvm::Value *AllocSize = EmitCXXNewAllocSize(getContext(),
- *this, E, NumElements);
+ *this, E, NumElements,
+ AllocSizeWithoutCookie);
NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
@@ -654,112 +736,69 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
!(AllocType->isPODType() && !E->hasInitializer());
- llvm::BasicBlock *NewNull = 0;
+ llvm::BasicBlock *NullCheckSource = 0;
llvm::BasicBlock *NewNotNull = 0;
llvm::BasicBlock *NewEnd = 0;
llvm::Value *NewPtr = RV.getScalarVal();
+ unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
if (NullCheckResult) {
- NewNull = createBasicBlock("new.null");
+ NullCheckSource = Builder.GetInsertBlock();
NewNotNull = createBasicBlock("new.notnull");
NewEnd = createBasicBlock("new.end");
- llvm::Value *IsNull =
- Builder.CreateICmpEQ(NewPtr,
- llvm::Constant::getNullValue(NewPtr->getType()),
- "isnull");
-
- Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
+ llvm::Value *IsNull = Builder.CreateIsNull(NewPtr, "new.isnull");
+ Builder.CreateCondBr(IsNull, NewEnd, NewNotNull);
EmitBlock(NewNotNull);
}
- CharUnits CookiePadding = CalculateCookiePadding(getContext(), E);
- if (!CookiePadding.isZero()) {
- CharUnits CookieOffset =
- CookiePadding - getContext().getTypeSizeInChars(SizeTy);
-
- llvm::Value *NumElementsPtr =
- Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset.getQuantity());
-
- NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
- ConvertType(SizeTy)->getPointerTo());
- Builder.CreateStore(NumElements, NumElementsPtr);
-
- // Now add the padding to the new ptr.
- NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr,
- CookiePadding.getQuantity());
+ assert((AllocSize == AllocSizeWithoutCookie) ==
+ CalculateCookiePadding(*this, E).isZero());
+ if (AllocSize != AllocSizeWithoutCookie) {
+ assert(E->isArray());
+ NewPtr = CGM.getCXXABI().InitializeArrayCookie(CGF, NewPtr, NumElements,
+ AllocType);
}
-
- if (AllocType->isArrayType()) {
- while (const ArrayType *AType = getContext().getAsArrayType(AllocType))
- AllocType = AType->getElementType();
- NewPtr =
- Builder.CreateBitCast(NewPtr,
- ConvertType(getContext().getPointerType(AllocType)));
- EmitNewInitializer(*this, E, NewPtr, NumElements);
- NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
- }
- else {
- NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
- EmitNewInitializer(*this, E, NewPtr, NumElements);
+
+ const llvm::Type *ElementPtrTy
+ = ConvertTypeForMem(AllocType)->getPointerTo(AS);
+ NewPtr = Builder.CreateBitCast(NewPtr, ElementPtrTy);
+ if (E->isArray()) {
+ EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie);
+
+ // NewPtr is a pointer to the base element type. If we're
+ // allocating an array of arrays, we'll need to cast back to the
+ // array pointer type.
+ const llvm::Type *ResultTy = ConvertTypeForMem(E->getType());
+ if (NewPtr->getType() != ResultTy)
+ NewPtr = Builder.CreateBitCast(NewPtr, ResultTy);
+ } else {
+ EmitNewInitializer(*this, E, NewPtr, NumElements, AllocSizeWithoutCookie);
}
if (NullCheckResult) {
Builder.CreateBr(NewEnd);
- NewNotNull = Builder.GetInsertBlock();
- EmitBlock(NewNull);
- Builder.CreateBr(NewEnd);
+ llvm::BasicBlock *NotNullSource = Builder.GetInsertBlock();
EmitBlock(NewEnd);
llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
PHI->reserveOperandSpace(2);
- PHI->addIncoming(NewPtr, NewNotNull);
- PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull);
+ PHI->addIncoming(NewPtr, NotNullSource);
+ PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()),
+ NullCheckSource);
NewPtr = PHI;
}
-
- return NewPtr;
-}
-
-static std::pair<llvm::Value *, llvm::Value *>
-GetAllocatedObjectPtrAndNumElements(CodeGenFunction &CGF,
- llvm::Value *Ptr, QualType DeleteTy) {
- QualType SizeTy = CGF.getContext().getSizeType();
- const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
-
- CharUnits DeleteTypeAlign = CGF.getContext().getTypeAlignInChars(DeleteTy);
- CharUnits CookiePadding =
- std::max(CGF.getContext().getTypeSizeInChars(SizeTy),
- DeleteTypeAlign);
- assert(!CookiePadding.isZero() && "CookiePadding should not be 0.");
-
- const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
- CharUnits CookieOffset =
- CookiePadding - CGF.getContext().getTypeSizeInChars(SizeTy);
-
- llvm::Value *AllocatedObjectPtr = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
- AllocatedObjectPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
- -CookiePadding.getQuantity());
-
- llvm::Value *NumElementsPtr =
- CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
- CookieOffset.getQuantity());
- NumElementsPtr =
- CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo());
-
- llvm::Value *NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
- NumElements =
- CGF.Builder.CreateIntCast(NumElements, SizeLTy, /*isSigned=*/false);
- return std::make_pair(AllocatedObjectPtr, NumElements);
+ return NewPtr;
}
void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
llvm::Value *Ptr,
QualType DeleteTy) {
+ assert(DeleteFD->getOverloadedOperator() == OO_Delete);
+
const FunctionProtoType *DeleteFTy =
DeleteFD->getType()->getAs<FunctionProtoType>();
@@ -775,21 +814,6 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
DeleteTypeSize.getQuantity());
}
- if (DeleteFD->getOverloadedOperator() == OO_Array_Delete &&
- !CalculateCookiePadding(getContext(), DeleteTy).isZero()) {
- // We need to get the number of elements in the array from the cookie.
- llvm::Value *AllocatedObjectPtr;
- llvm::Value *NumElements;
- llvm::tie(AllocatedObjectPtr, NumElements) =
- GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy);
-
- // Multiply the size with the number of elements.
- if (Size)
- Size = Builder.CreateMul(NumElements, Size);
-
- Ptr = AllocatedObjectPtr;
- }
-
QualType ArgTy = DeleteFTy->getArgType(0);
llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
@@ -803,20 +827,169 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
DeleteArgs, DeleteFD);
}
+namespace {
+ /// Calls the given 'operator delete' on a single object.
+ struct CallObjectDelete : EHScopeStack::Cleanup {
+ llvm::Value *Ptr;
+ const FunctionDecl *OperatorDelete;
+ QualType ElementType;
+
+ CallObjectDelete(llvm::Value *Ptr,
+ const FunctionDecl *OperatorDelete,
+ QualType ElementType)
+ : Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);
+ }
+ };
+}
+
+/// Emit the code for deleting a single object.
+static void EmitObjectDelete(CodeGenFunction &CGF,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr,
+ QualType ElementType) {
+ // Find the destructor for the type, if applicable. If the
+ // destructor is virtual, we'll just emit the vcall and return.
+ const CXXDestructorDecl *Dtor = 0;
+ if (const RecordType *RT = ElementType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (!RD->hasTrivialDestructor()) {
+ Dtor = RD->getDestructor();
+
+ if (Dtor->isVirtual()) {
+ const llvm::Type *Ty =
+ CGF.getTypes().GetFunctionType(CGF.getTypes().getFunctionInfo(Dtor,
+ Dtor_Complete),
+ /*isVariadic=*/false);
+
+ llvm::Value *Callee
+ = CGF.BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
+ CGF.EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,
+ 0, 0);
+
+ // The dtor took care of deleting the object.
+ return;
+ }
+ }
+ }
+
+ // Make sure that we call delete even if the dtor throws.
+ CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup,
+ Ptr, OperatorDelete, ElementType);
+
+ if (Dtor)
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false, Ptr);
+
+ CGF.PopCleanupBlock();
+}
+
+namespace {
+ /// Calls the given 'operator delete' on an array of objects.
+ struct CallArrayDelete : EHScopeStack::Cleanup {
+ llvm::Value *Ptr;
+ const FunctionDecl *OperatorDelete;
+ llvm::Value *NumElements;
+ QualType ElementType;
+ CharUnits CookieSize;
+
+ CallArrayDelete(llvm::Value *Ptr,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *NumElements,
+ QualType ElementType,
+ CharUnits CookieSize)
+ : Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),
+ ElementType(ElementType), CookieSize(CookieSize) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ const FunctionProtoType *DeleteFTy =
+ OperatorDelete->getType()->getAs<FunctionProtoType>();
+ assert(DeleteFTy->getNumArgs() == 1 || DeleteFTy->getNumArgs() == 2);
+
+ CallArgList Args;
+
+ // Pass the pointer as the first argument.
+ QualType VoidPtrTy = DeleteFTy->getArgType(0);
+ llvm::Value *DeletePtr
+ = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy));
+ Args.push_back(std::make_pair(RValue::get(DeletePtr), VoidPtrTy));
+
+ // Pass the original requested size as the second argument.
+ if (DeleteFTy->getNumArgs() == 2) {
+ QualType size_t = DeleteFTy->getArgType(1);
+ const llvm::IntegerType *SizeTy
+ = cast<llvm::IntegerType>(CGF.ConvertType(size_t));
+
+ CharUnits ElementTypeSize =
+ CGF.CGM.getContext().getTypeSizeInChars(ElementType);
+
+ // The size of an element, multiplied by the number of elements.
+ llvm::Value *Size
+ = llvm::ConstantInt::get(SizeTy, ElementTypeSize.getQuantity());
+ Size = CGF.Builder.CreateMul(Size, NumElements);
+
+ // Plus the size of the cookie if applicable.
+ if (!CookieSize.isZero()) {
+ llvm::Value *CookieSizeV
+ = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());
+ Size = CGF.Builder.CreateAdd(Size, CookieSizeV);
+ }
+
+ Args.push_back(std::make_pair(RValue::get(Size), size_t));
+ }
+
+ // Emit the call to delete.
+ CGF.EmitCall(CGF.getTypes().getFunctionInfo(Args, DeleteFTy),
+ CGF.CGM.GetAddrOfFunction(OperatorDelete),
+ ReturnValueSlot(), Args, OperatorDelete);
+ }
+ };
+}
+
+/// Emit the code for deleting an array of objects.
+static void EmitArrayDelete(CodeGenFunction &CGF,
+ const FunctionDecl *OperatorDelete,
+ llvm::Value *Ptr,
+ QualType ElementType) {
+ llvm::Value *NumElements = 0;
+ llvm::Value *AllocatedPtr = 0;
+ CharUnits CookieSize;
+ CGF.CGM.getCXXABI().ReadArrayCookie(CGF, Ptr, ElementType,
+ NumElements, AllocatedPtr, CookieSize);
+
+ assert(AllocatedPtr && "ReadArrayCookie didn't set AllocatedPtr");
+
+ // Make sure that we call delete even if one of the dtors throws.
+ CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup,
+ AllocatedPtr, OperatorDelete,
+ NumElements, ElementType,
+ CookieSize);
+
+ if (const CXXRecordDecl *RD = ElementType->getAsCXXRecordDecl()) {
+ if (!RD->hasTrivialDestructor()) {
+ assert(NumElements && "ReadArrayCookie didn't find element count"
+ " for a class with destructor");
+ CGF.EmitCXXAggrDestructorCall(RD->getDestructor(), NumElements, Ptr);
+ }
+ }
+
+ CGF.PopCleanupBlock();
+}
+
void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
// Get at the argument before we performed the implicit conversion
// to void*.
const Expr *Arg = E->getArgument();
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
- if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion &&
+ if (ICE->getCastKind() != CK_UserDefinedConversion &&
ICE->getType()->isVoidPointerType())
Arg = ICE->getSubExpr();
else
break;
}
-
- QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
llvm::Value *Ptr = EmitScalarExpr(Arg);
@@ -830,41 +1003,38 @@ 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();
- if (E->isArrayForm()) {
- llvm::Value *AllocatedObjectPtr;
- llvm::Value *NumElements;
- llvm::tie(AllocatedObjectPtr, NumElements) =
- GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy);
-
- EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
- } else if (Dtor->isVirtual()) {
- const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
- /*isVariadic=*/false);
-
- llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
- EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,
- 0, 0);
-
- // The dtor took care of deleting the object.
- ShouldCallDelete = false;
- } else
- EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- Ptr);
- }
+
+ // We might be deleting a pointer to array. If so, GEP down to the
+ // first non-array element.
+ // (this assumes that A(*)[3][7] is converted to [3 x [7 x %A]]*)
+ QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
+ if (DeleteTy->isConstantArrayType()) {
+ llvm::Value *Zero = Builder.getInt32(0);
+ llvm::SmallVector<llvm::Value*,8> GEP;
+
+ GEP.push_back(Zero); // point at the outermost array
+
+ // For each layer of array type we're pointing at:
+ while (const ConstantArrayType *Arr
+ = getContext().getAsConstantArrayType(DeleteTy)) {
+ // 1. Unpeel the array type.
+ DeleteTy = Arr->getElementType();
+
+ // 2. GEP to the first element of the array.
+ GEP.push_back(Zero);
}
+
+ Ptr = Builder.CreateInBoundsGEP(Ptr, GEP.begin(), GEP.end(), "del.first");
}
- if (ShouldCallDelete)
- EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy);
+ assert(ConvertTypeForMem(DeleteTy) ==
+ cast<llvm::PointerType>(Ptr->getType())->getElementType());
+
+ if (E->isArrayForm()) {
+ EmitArrayDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy);
+ } else {
+ EmitObjectDelete(*this, E->getOperatorDelete(), Ptr, DeleteTy);
+ }
EmitBlock(DeleteEnd);
}
@@ -895,7 +1065,7 @@ llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
// FIXME: PointerType->hasAttr<NonNullAttr>()
bool CanBeZero = false;
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
- if (UO->getOpcode() == UnaryOperator::Deref)
+ if (UO->getOpcode() == UO_Deref)
CanBeZero = true;
if (CanBeZero) {
llvm::BasicBlock *NonZeroBlock = createBasicBlock();
diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp
index 0927319db776..79e9dd42ee28 100644
--- a/lib/CodeGen/CGExprComplex.cpp
+++ b/lib/CodeGen/CGExprComplex.cpp
@@ -347,7 +347,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
// FIXME: We should be looking at all of the cast kinds here, not
// cherry-picking the ones we have test cases for.
- if (CK == CastExpr::CK_LValueBitCast) {
+ if (CK == CK_LValueBitCast) {
llvm::Value *V = CGF.EmitLValue(Op).getAddress();
V = Builder.CreateBitCast(V,
CGF.ConvertType(CGF.getContext().getPointerType(DestTy)));
@@ -532,7 +532,7 @@ EmitCompoundAssign(const CompoundAssignOperator *E,
// improve codegen a little. It is possible for the RHS to be complex or
// scalar.
OpInfo.Ty = E->getComputationResultType();
- OpInfo.RHS = EmitCast(CastExpr::CK_Unknown, E->getRHS(), OpInfo.Ty);
+ OpInfo.RHS = EmitCast(CK_Unknown, E->getRHS(), OpInfo.Ty);
LValue LHS = CGF.EmitLValue(E->getLHS());
// We know the LHS is a complex lvalue.
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index bbd256c4f1fa..9c31c2a3d538 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "clang/AST/APValue.h"
@@ -81,10 +82,6 @@ AppendField(const FieldDecl *Field, uint64_t FieldOffset,
assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
&& "Field offset mismatch!");
- // Emit the field.
- if (!InitCst)
- return false;
-
unsigned FieldAlignment = getAlignment(InitCst);
// Round up the field offset to the alignment of the field type.
@@ -360,6 +357,9 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
Field->getType(), CGF);
else
EltInit = CGM.EmitNullConstant(Field->getType());
+
+ if (!EltInit)
+ return false;
if (!Field->isBitField()) {
// Handle non-bitfield members.
@@ -455,37 +455,15 @@ public:
return Visit(E->getInitializer());
}
- llvm::Constant *EmitMemberFunctionPointer(CXXMethodDecl *MD) {
- assert(MD->isInstance() && "Member function must not be static!");
-
- MD = MD->getCanonicalDecl();
-
- const llvm::Type *PtrDiffTy =
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
-
- llvm::Constant *Values[2];
-
- Values[0] = CGM.GetCXXMemberFunctionPointerValue(MD);
-
- // The adjustment will always be 0.
- Values[1] = llvm::ConstantInt::get(PtrDiffTy, 0);
-
- return llvm::ConstantStruct::get(CGM.getLLVMContext(),
- Values, 2, /*Packed=*/false);
- }
-
llvm::Constant *VisitUnaryAddrOf(UnaryOperator *E) {
if (const MemberPointerType *MPT =
- E->getType()->getAs<MemberPointerType>()) {
- QualType T = MPT->getPointeeType();
+ E->getType()->getAs<MemberPointerType>()) {
DeclRefExpr *DRE = cast<DeclRefExpr>(E->getSubExpr());
-
NamedDecl *ND = DRE->getDecl();
- if (T->isFunctionProtoType())
- return EmitMemberFunctionPointer(cast<CXXMethodDecl>(ND));
-
- // We have a pointer to data member.
- return CGM.EmitPointerToDataMember(cast<FieldDecl>(ND));
+ if (MPT->isMemberFunctionPointer())
+ return CGM.getCXXABI().EmitMemberPointer(cast<CXXMethodDecl>(ND));
+ else
+ return CGM.getCXXABI().EmitMemberPointer(cast<FieldDecl>(ND));
}
return 0;
@@ -514,7 +492,7 @@ public:
llvm::Constant *VisitCastExpr(CastExpr* E) {
switch (E->getCastKind()) {
- case CastExpr::CK_ToUnion: {
+ case CK_ToUnion: {
// GCC cast to union extension
assert(E->getType()->isUnionType() &&
"Destination type is not union type!");
@@ -549,44 +527,21 @@ public:
llvm::StructType::get(C->getType()->getContext(), Types, false);
return llvm::ConstantStruct::get(STy, Elts);
}
- case CastExpr::CK_NullToMemberPointer:
- return CGM.EmitNullConstant(E->getType());
+ case CK_NullToMemberPointer: {
+ const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ return CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ }
- case CastExpr::CK_BaseToDerivedMemberPointer: {
+ case CK_BaseToDerivedMemberPointer: {
Expr *SubExpr = E->getSubExpr();
+ llvm::Constant *C =
+ CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
+ if (!C) return 0;
- const MemberPointerType *SrcTy =
- SubExpr->getType()->getAs<MemberPointerType>();
- const MemberPointerType *DestTy =
- E->getType()->getAs<MemberPointerType>();
-
- const CXXRecordDecl *DerivedClass =
- cast<CXXRecordDecl>(cast<RecordType>(DestTy->getClass())->getDecl());
-
- if (SrcTy->getPointeeType()->isFunctionProtoType()) {
- llvm::Constant *C =
- CGM.EmitConstantExpr(SubExpr, SubExpr->getType(), CGF);
- if (!C)
- return 0;
-
- llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
-
- // Check if we need to update the adjustment.
- if (llvm::Constant *Offset =
- CGM.GetNonVirtualBaseClassOffset(DerivedClass, E->getBasePath())) {
- llvm::Constant *Values[2];
-
- Values[0] = CS->getOperand(0);
- Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
- return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
- /*Packed=*/false);
- }
-
- return CS;
- }
+ return CGM.getCXXABI().EmitMemberPointerConversion(C, E);
}
- case CastExpr::CK_BitCast:
+ case CK_BitCast:
// This must be a member function pointer cast.
return Visit(E->getSubExpr());
@@ -792,7 +747,7 @@ public:
case Expr::DeclRefExprClass: {
ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
if (Decl->hasAttr<WeakRefAttr>())
- return CGM.GetWeakRefReference(Decl);
+ return CGM.GetWeakRefReference(Decl);
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
return CGM.GetAddrOfFunction(FD);
if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
@@ -821,7 +776,7 @@ public:
case Expr::PredefinedExprClass: {
unsigned Type = cast<PredefinedExpr>(E)->getIdentType();
if (CGF) {
- LValue Res = CGF->EmitPredefinedFunctionName(Type);
+ LValue Res = CGF->EmitPredefinedLValue(cast<PredefinedExpr>(E));
return cast<llvm::Constant>(Res.getAddress());
} else if (Type == PredefinedExpr::PrettyFunction) {
return CGM.GetAddrOfConstantCString("top level", ".tmp");
@@ -989,7 +944,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
uint64_t StartOffset) {
assert(StartOffset % 8 == 0 && "StartOffset not byte aligned!");
- if (!CGM.getTypes().ContainsPointerToDataMember(T))
+ if (CGM.getTypes().isZeroInitializable(T))
return;
if (const ConstantArrayType *CAT =
@@ -1022,7 +977,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
continue;
// Ignore bases that don't have any pointer to data members.
- if (!CGM.getTypes().ContainsPointerToDataMember(BaseDecl))
+ if (CGM.getTypes().isZeroInitializable(BaseDecl))
continue;
uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl);
@@ -1036,7 +991,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
E = RD->field_end(); I != E; ++I, ++FieldNo) {
QualType FieldType = I->getType();
- if (!CGM.getTypes().ContainsPointerToDataMember(FieldType))
+ if (CGM.getTypes().isZeroInitializable(FieldType))
continue;
uint64_t FieldOffset = StartOffset + Layout.getFieldOffset(FieldNo);
@@ -1061,7 +1016,7 @@ FillInNullDataMemberPointers(CodeGenModule &CGM, QualType T,
}
llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
- if (!getTypes().ContainsPointerToDataMember(T))
+ if (getTypes().isZeroInitializable(T))
return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));
if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
@@ -1105,7 +1060,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
continue;
// Ignore bases that don't have any pointer to data members.
- if (!getTypes().ContainsPointerToDataMember(BaseDecl))
+ if (getTypes().isZeroInitializable(BaseDecl))
continue;
// Currently, all bases are arrays of i8. Figure out how many elements
@@ -1165,29 +1120,3 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
return llvm::ConstantInt::get(getTypes().ConvertTypeForMem(T), -1ULL,
/*isSigned=*/true);
}
-
-llvm::Constant *
-CodeGenModule::EmitPointerToDataMember(const FieldDecl *FD) {
-
- // Itanium C++ ABI 2.3:
- // A pointer to data member is an offset from the base address of the class
- // object containing it, represented as a ptrdiff_t
-
- const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(FD->getParent());
- QualType ClassType =
- getContext().getTypeDeclType(const_cast<CXXRecordDecl *>(ClassDecl));
-
- const llvm::StructType *ClassLTy =
- cast<llvm::StructType>(getTypes().ConvertType(ClassType));
-
- const CGRecordLayout &RL =
- getTypes().getCGRecordLayout(FD->getParent());
- unsigned FieldNo = RL.getLLVMFieldNo(FD);
- uint64_t Offset =
- getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo);
-
- const llvm::Type *PtrDiffTy =
- getTypes().ConvertType(getContext().getPointerDiffType());
-
- return llvm::ConstantInt::get(PtrDiffTy, Offset);
-}
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index ef38209e1eaf..2318cc4e9aeb 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
@@ -137,7 +138,7 @@ public:
CGF.getContext().typesAreCompatible(
E->getArgType1(), E->getArgType2()));
}
- Value *VisitOffsetOfExpr(const OffsetOfExpr *E);
+ Value *VisitOffsetOfExpr(OffsetOfExpr *E);
Value *VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E);
Value *VisitAddrLabelExpr(const AddrLabelExpr *E) {
llvm::Value *V = CGF.GetAddrOfLabel(E->getLabel());
@@ -149,7 +150,10 @@ public:
Expr::EvalResult Result;
if (E->Evaluate(Result, CGF.getContext()) && Result.Val.isInt()) {
assert(!Result.HasSideEffects && "Constant declref with side-effect?!");
- return llvm::ConstantInt::get(VMContext, Result.Val.getInt());
+ llvm::ConstantInt *CI
+ = llvm::ConstantInt::get(VMContext, Result.Val.getInt());
+ CGF.EmitDeclRefExprDbgValue(E, CI);
+ return CI;
}
return EmitLoadOfLValue(E);
}
@@ -235,6 +239,9 @@ public:
Value *VisitUnaryAddrOf(const UnaryOperator *E) {
+ // If the sub-expression is an instance member reference,
+ // EmitDeclRefLValue will magically emit it with the appropriate
+ // value as the "address".
return EmitLValue(E->getSubExpr()).getAddress();
}
Value *VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
@@ -251,7 +258,6 @@ public:
Value *VisitUnaryExtension(const UnaryOperator *E) {
return Visit(E->getSubExpr());
}
- Value *VisitUnaryOffsetOf(const UnaryOperator *E);
// C++
Value *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
@@ -297,7 +303,7 @@ public:
// Binary Operators.
Value *EmitMul(const BinOpInfo &Ops) {
- if (Ops.Ty->isSignedIntegerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined:
return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
@@ -409,11 +415,8 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
return Builder.CreateFCmpUNE(Src, Zero, "tobool");
}
- if (SrcType->isMemberPointerType()) {
- // Compare against -1.
- llvm::Value *NegativeOne = llvm::Constant::getAllOnesValue(Src->getType());
- return Builder.CreateICmpNE(Src, NegativeOne, "tobool");
- }
+ if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType))
+ return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT);
assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) &&
"Unknown scalar type to convert");
@@ -562,17 +565,10 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,
}
Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
- const llvm::Type *LTy = ConvertType(Ty);
-
- if (!Ty->isMemberPointerType())
- return llvm::Constant::getNullValue(LTy);
-
- assert(!Ty->isMemberFunctionPointerType() &&
- "member function pointers are not scalar!");
+ if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>())
+ return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
- // Itanium C++ ABI 2.3:
- // A NULL pointer is represented as -1.
- return llvm::ConstantInt::get(LTy, -1ULL, /*isSigned=*/true);
+ return llvm::Constant::getNullValue(ConvertType(Ty));
}
//===----------------------------------------------------------------------===//
@@ -888,7 +884,7 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
const Expr *E = CE->getSubExpr();
- if (CE->getCastKind() == CastExpr::CK_UncheckedDerivedToBase)
+ if (CE->getCastKind() == CK_UncheckedDerivedToBase)
return false;
if (isa<CXXThisExpr>(E)) {
@@ -897,8 +893,8 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
}
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(CE)) {
- // And that lvalue casts are never null.
- if (ICE->isLvalueCast())
+ // And that glvalue casts are never null.
+ if (ICE->getValueKind() != VK_RValue)
return false;
}
@@ -911,7 +907,7 @@ static bool ShouldNullCheckClassCastValue(const CastExpr *CE) {
Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
Expr *E = CE->getSubExpr();
QualType DestTy = CE->getType();
- CastExpr::CastKind Kind = CE->getCastKind();
+ CastKind Kind = CE->getCastKind();
if (!DestTy->isVoidType())
TestAndClearIgnoreResultAssign();
@@ -920,59 +916,58 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
// a default case, so the compiler will warn on a missing case. The cases
// are in the same order as in the CastKind enum.
switch (Kind) {
- case CastExpr::CK_Unknown:
+ case CK_Unknown:
// FIXME: All casts should have a known kind!
//assert(0 && "Unknown cast kind!");
break;
- case CastExpr::CK_LValueBitCast: {
+ case CK_LValueBitCast:
+ case CK_ObjCObjectLValueCast: {
Value *V = EmitLValue(E).getAddress();
V = Builder.CreateBitCast(V,
ConvertType(CGF.getContext().getPointerType(DestTy)));
- // FIXME: Are the qualifiers correct here?
- return EmitLoadOfLValue(LValue::MakeAddr(V, CGF.MakeQualifiers(DestTy)),
- DestTy);
+ return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), DestTy);
}
- case CastExpr::CK_AnyPointerToObjCPointerCast:
- case CastExpr::CK_AnyPointerToBlockPointerCast:
- case CastExpr::CK_BitCast: {
+ case CK_AnyPointerToObjCPointerCast:
+ case CK_AnyPointerToBlockPointerCast:
+ case CK_BitCast: {
Value *Src = Visit(const_cast<Expr*>(E));
return Builder.CreateBitCast(Src, ConvertType(DestTy));
}
- case CastExpr::CK_NoOp:
- case CastExpr::CK_UserDefinedConversion:
+ case CK_NoOp:
+ case CK_UserDefinedConversion:
return Visit(const_cast<Expr*>(E));
- case CastExpr::CK_BaseToDerived: {
+ case CK_BaseToDerived: {
const CXXRecordDecl *DerivedClassDecl =
DestTy->getCXXRecordDeclForPointerType();
return CGF.GetAddressOfDerivedClass(Visit(E), DerivedClassDecl,
- CE->getBasePath(),
+ CE->path_begin(), CE->path_end(),
ShouldNullCheckClassCastValue(CE));
}
- case CastExpr::CK_UncheckedDerivedToBase:
- case CastExpr::CK_DerivedToBase: {
+ case CK_UncheckedDerivedToBase:
+ case CK_DerivedToBase: {
const RecordType *DerivedClassTy =
E->getType()->getAs<PointerType>()->getPointeeType()->getAs<RecordType>();
CXXRecordDecl *DerivedClassDecl =
cast<CXXRecordDecl>(DerivedClassTy->getDecl());
return CGF.GetAddressOfBaseClass(Visit(E), DerivedClassDecl,
- CE->getBasePath(),
+ CE->path_begin(), CE->path_end(),
ShouldNullCheckClassCastValue(CE));
}
- case CastExpr::CK_Dynamic: {
+ case CK_Dynamic: {
Value *V = Visit(const_cast<Expr*>(E));
const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
return CGF.EmitDynamicCast(V, DCE);
}
- case CastExpr::CK_ToUnion:
+ case CK_ToUnion:
assert(0 && "Should be unreachable!");
break;
- case CastExpr::CK_ArrayToPointerDecay: {
+ case CK_ArrayToPointerDecay: {
assert(E->getType()->isArrayType() &&
"Array to pointer decay must have array source type!");
@@ -990,62 +985,66 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
return V;
}
- case CastExpr::CK_FunctionToPointerDecay:
+ case CK_FunctionToPointerDecay:
return EmitLValue(E).getAddress();
- case CastExpr::CK_NullToMemberPointer:
- return CGF.CGM.EmitNullConstant(DestTy);
+ case CK_NullToMemberPointer: {
+ // If the subexpression's type is the C++0x nullptr_t, emit the
+ // subexpression, which may have side effects.
+ if (E->getType()->isNullPtrType())
+ (void) Visit(E);
- case CastExpr::CK_BaseToDerivedMemberPointer:
- case CastExpr::CK_DerivedToBaseMemberPointer: {
- Value *Src = Visit(E);
+ const MemberPointerType *MPT = CE->getType()->getAs<MemberPointerType>();
+ return CGF.CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ }
- // See if we need to adjust the pointer.
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(E->getType()->getAs<MemberPointerType>()->
- getClass()->getAs<RecordType>()->getDecl());
- const CXXRecordDecl *DerivedDecl =
- cast<CXXRecordDecl>(CE->getType()->getAs<MemberPointerType>()->
- getClass()->getAs<RecordType>()->getDecl());
- if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
- std::swap(DerivedDecl, BaseDecl);
-
- if (llvm::Constant *Adj =
- CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, CE->getBasePath())){
- if (CE->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer)
- Src = Builder.CreateNSWSub(Src, Adj, "adj");
- else
- Src = Builder.CreateNSWAdd(Src, Adj, "adj");
- }
+ case CK_BaseToDerivedMemberPointer:
+ case CK_DerivedToBaseMemberPointer: {
+ Value *Src = Visit(E);
- return Src;
+ // Note that the AST doesn't distinguish between checked and
+ // unchecked member pointer conversions, so we always have to
+ // implement checked conversions here. This is inefficient when
+ // actual control flow may be required in order to perform the
+ // check, which it is for data member pointers (but not member
+ // function pointers on Itanium and ARM).
+ return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src);
}
+
- case CastExpr::CK_ConstructorConversion:
+ case CK_ConstructorConversion:
assert(0 && "Should be unreachable!");
break;
- case CastExpr::CK_IntegralToPointer: {
+ case CK_IntegralToPointer: {
Value *Src = Visit(const_cast<Expr*>(E));
-
+
// First, convert to the correct width so that we control the kind of
// extension.
const llvm::Type *MiddleTy = CGF.IntPtrTy;
bool InputSigned = E->getType()->isSignedIntegerType();
llvm::Value* IntResult =
Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv");
-
+
return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));
}
- case CastExpr::CK_PointerToIntegral: {
+ case CK_PointerToIntegral: {
Value *Src = Visit(const_cast<Expr*>(E));
+
+ // Handle conversion to bool correctly.
+ if (DestTy->isBooleanType())
+ return EmitScalarConversion(Src, E->getType(), DestTy);
+
return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
}
- case CastExpr::CK_ToVoid: {
- CGF.EmitAnyExpr(E, 0, false, true);
+ case CK_ToVoid: {
+ if (E->Classify(CGF.getContext()).isGLValue())
+ CGF.EmitLValue(E);
+ else
+ CGF.EmitAnyExpr(E, 0, false, true);
return 0;
}
- case CastExpr::CK_VectorSplat: {
+ case CK_VectorSplat: {
const llvm::Type *DstTy = ConvertType(DestTy);
Value *Elt = Visit(const_cast<Expr*>(E));
@@ -1064,16 +1063,19 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
return Yay;
}
- case CastExpr::CK_IntegralCast:
- case CastExpr::CK_IntegralToFloating:
- case CastExpr::CK_FloatingToIntegral:
- case CastExpr::CK_FloatingCast:
+ case CK_IntegralCast:
+ case CK_IntegralToFloating:
+ case CK_FloatingToIntegral:
+ case CK_FloatingCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy);
- case CastExpr::CK_MemberPointerToBoolean:
- return CGF.EvaluateExprAsBool(E);
+ case CK_MemberPointerToBoolean: {
+ llvm::Value *MemPtr = Visit(E);
+ const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
+ return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);
}
-
+ }
+
// Handle cases where the source is an non-complex type.
if (!CGF.hasAggregateLLVMType(E->getType())) {
@@ -1116,7 +1118,7 @@ Value *ScalarExprEmitter::VisitBlockDeclRefExpr(const BlockDeclRefExpr *E) {
llvm::Value *V = CGF.GetAddrOfBlockDecl(E);
if (E->getType().isObjCGCWeak())
return CGF.CGM.getObjCRuntime().EmitObjCWeakRead(CGF, V);
- return Builder.CreateLoad(V, "tmp");
+ return CGF.EmitLoadOfScalar(V, false, 0, E->getType());
}
//===----------------------------------------------------------------------===//
@@ -1156,7 +1158,7 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
NextVal = Builder.CreateGEP(InVal, Inc, "add.ptr");
llvm::Value *lhs = LV.getAddress();
lhs = Builder.CreateBitCast(lhs, llvm::PointerType::getUnqual(i8Ty));
- LV = LValue::MakeAddr(lhs, CGF.MakeQualifiers(ValTy));
+ LV = CGF.MakeAddrLValue(lhs, ValTy);
} else
NextVal = Builder.CreateInBoundsGEP(InVal, Inc, "ptrincdec");
} else {
@@ -1191,9 +1193,10 @@ EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
BinOp.LHS = InVal;
BinOp.RHS = NextVal;
BinOp.Ty = E->getType();
- BinOp.Opcode = BinaryOperator::Add;
+ BinOp.Opcode = BO_Add;
BinOp.E = E;
- return EmitOverflowCheckedBinOp(BinOp);
+ NextVal = EmitOverflowCheckedBinOp(BinOp);
+ break;
}
}
} else {
@@ -1240,7 +1243,7 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
else
BinOp.LHS = llvm::Constant::getNullValue(BinOp.RHS->getType());
BinOp.Ty = E->getType();
- BinOp.Opcode = BinaryOperator::Sub;
+ BinOp.Opcode = BO_Sub;
BinOp.E = E;
return EmitSub(BinOp);
}
@@ -1264,19 +1267,94 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
return Builder.CreateZExt(BoolVal, ConvertType(E->getType()), "lnot.ext");
}
-Value *ScalarExprEmitter::VisitOffsetOfExpr(const OffsetOfExpr *E) {
- Expr::EvalResult Result;
- if(E->Evaluate(Result, CGF.getContext()))
- return llvm::ConstantInt::get(VMContext, Result.Val.getInt());
-
- // FIXME: Cannot support code generation for non-constant offsetof.
- unsigned DiagID = CGF.CGM.getDiags().getCustomDiagID(Diagnostic::Error,
- "cannot compile non-constant __builtin_offsetof");
- CGF.CGM.getDiags().Report(CGF.getContext().getFullLoc(E->getLocStart()),
- DiagID)
- << E->getSourceRange();
-
- return llvm::Constant::getNullValue(ConvertType(E->getType()));
+Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ // Try folding the offsetof to a constant.
+ Expr::EvalResult EvalResult;
+ if (E->Evaluate(EvalResult, CGF.getContext()))
+ return llvm::ConstantInt::get(VMContext, EvalResult.Val.getInt());
+
+ // Loop over the components of the offsetof to compute the value.
+ unsigned n = E->getNumComponents();
+ const llvm::Type* ResultType = ConvertType(E->getType());
+ llvm::Value* Result = llvm::Constant::getNullValue(ResultType);
+ QualType CurrentType = E->getTypeSourceInfo()->getType();
+ for (unsigned i = 0; i != n; ++i) {
+ OffsetOfExpr::OffsetOfNode ON = E->getComponent(i);
+ llvm::Value *Offset = 0;
+ switch (ON.getKind()) {
+ case OffsetOfExpr::OffsetOfNode::Array: {
+ // Compute the index
+ Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex());
+ llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr);
+ bool IdxSigned = IdxExpr->getType()->isSignedIntegerType();
+ Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv");
+
+ // Save the element type
+ CurrentType =
+ CGF.getContext().getAsArrayType(CurrentType)->getElementType();
+
+ // Compute the element size
+ llvm::Value* ElemSize = llvm::ConstantInt::get(ResultType,
+ CGF.getContext().getTypeSizeInChars(CurrentType).getQuantity());
+
+ // Multiply out to compute the result
+ Offset = Builder.CreateMul(Idx, ElemSize);
+ break;
+ }
+
+ case OffsetOfExpr::OffsetOfNode::Field: {
+ FieldDecl *MemberDecl = ON.getField();
+ RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
+
+ // Compute the index of the field in its parent.
+ unsigned i = 0;
+ // FIXME: It would be nice if we didn't have to loop here!
+ for (RecordDecl::field_iterator Field = RD->field_begin(),
+ FieldEnd = RD->field_end();
+ Field != FieldEnd; (void)++Field, ++i) {
+ if (*Field == MemberDecl)
+ break;
+ }
+ assert(i < RL.getFieldCount() && "offsetof field in wrong type");
+
+ // Compute the offset to the field
+ int64_t OffsetInt = RL.getFieldOffset(i) /
+ CGF.getContext().getCharWidth();
+ Offset = llvm::ConstantInt::get(ResultType, OffsetInt);
+
+ // Save the element type.
+ CurrentType = MemberDecl->getType();
+ break;
+ }
+
+ case OffsetOfExpr::OffsetOfNode::Identifier:
+ llvm_unreachable("dependent __builtin_offsetof");
+
+ case OffsetOfExpr::OffsetOfNode::Base: {
+ if (ON.getBase()->isVirtual()) {
+ CGF.ErrorUnsupported(E, "virtual base in offsetof");
+ continue;
+ }
+
+ RecordDecl *RD = CurrentType->getAs<RecordType>()->getDecl();
+ const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD);
+
+ // Save the element type.
+ CurrentType = ON.getBase()->getType();
+
+ // Compute the offset to the base.
+ const RecordType *BaseRT = CurrentType->getAs<RecordType>();
+ CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl());
+ int64_t OffsetInt = RL.getBaseClassOffset(BaseRD) /
+ CGF.getContext().getCharWidth();
+ Offset = llvm::ConstantInt::get(ResultType, OffsetInt);
+ break;
+ }
+ }
+ Result = Builder.CreateAdd(Result, Offset);
+ }
+ return Result;
}
/// VisitSizeOfAlignOfExpr - Return the size or alignment of the type of
@@ -1327,12 +1405,6 @@ Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) {
return llvm::Constant::getNullValue(ConvertType(E->getType()));
}
-Value *ScalarExprEmitter::VisitUnaryOffsetOf(const UnaryOperator *E) {
- Value* ResultAsPtr = EmitLValue(E->getSubExpr()).getAddress();
- const llvm::Type* ResultType = ConvertType(E->getType());
- return Builder.CreatePtrToInt(ResultAsPtr, ResultType, "offsetof");
-}
-
//===----------------------------------------------------------------------===//
// Binary Operators
//===----------------------------------------------------------------------===//
@@ -1422,7 +1494,7 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
if (Ops.LHS->getType()->isFPOrFPVectorTy())
return Builder.CreateFDiv(Ops.LHS, Ops.RHS, "div");
- else if (Ops.Ty->isUnsignedIntegerType())
+ else if (Ops.Ty->hasUnsignedIntegerRepresentation())
return Builder.CreateUDiv(Ops.LHS, Ops.RHS, "div");
else
return Builder.CreateSDiv(Ops.LHS, Ops.RHS, "div");
@@ -1441,18 +1513,18 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
unsigned OpID = 0;
switch (Ops.Opcode) {
- case BinaryOperator::Add:
- case BinaryOperator::AddAssign:
+ case BO_Add:
+ case BO_AddAssign:
OpID = 1;
IID = llvm::Intrinsic::sadd_with_overflow;
break;
- case BinaryOperator::Sub:
- case BinaryOperator::SubAssign:
+ case BO_Sub:
+ case BO_SubAssign:
OpID = 2;
IID = llvm::Intrinsic::ssub_with_overflow;
break;
- case BinaryOperator::Mul:
- case BinaryOperator::MulAssign:
+ case BO_Mul:
+ case BO_MulAssign:
OpID = 3;
IID = llvm::Intrinsic::smul_with_overflow;
break;
@@ -1472,58 +1544,26 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
Value *overflow = Builder.CreateExtractValue(resultAndOverflow, 1);
// Branch in case of overflow.
- llvm::BasicBlock *initialBB = Builder.GetInsertBlock();
- llvm::BasicBlock *overflowBB =
- CGF.createBasicBlock("overflow", CGF.CurFn);
- llvm::BasicBlock *continueBB =
- CGF.createBasicBlock("overflow.continue", CGF.CurFn);
+ llvm::BasicBlock *overflowBB = CGF.createBasicBlock("overflow", CGF.CurFn);
+ llvm::BasicBlock *continueBB = CGF.createBasicBlock("nooverflow", CGF.CurFn);
Builder.CreateCondBr(overflow, overflowBB, continueBB);
- // Handle overflow
-
+ // Handle overflow with llvm.trap.
+ // TODO: it would be better to generate one of these blocks per function.
Builder.SetInsertPoint(overflowBB);
-
- // Handler is:
- // long long *__overflow_handler)(long long a, long long b, char op,
- // char width)
- std::vector<const llvm::Type*> handerArgTypes;
- handerArgTypes.push_back(CGF.Int64Ty);
- handerArgTypes.push_back(CGF.Int64Ty);
- handerArgTypes.push_back(llvm::Type::getInt8Ty(VMContext));
- handerArgTypes.push_back(llvm::Type::getInt8Ty(VMContext));
- llvm::FunctionType *handlerTy =
- llvm::FunctionType::get(CGF.Int64Ty, handerArgTypes, false);
- llvm::Value *handlerFunction =
- CGF.CGM.getModule().getOrInsertGlobal("__overflow_handler",
- llvm::PointerType::getUnqual(handlerTy));
- handlerFunction = Builder.CreateLoad(handlerFunction);
-
- llvm::Value *handlerResult = Builder.CreateCall4(handlerFunction,
- Builder.CreateSExt(Ops.LHS, CGF.Int64Ty),
- Builder.CreateSExt(Ops.RHS, CGF.Int64Ty),
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), OpID),
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext),
- cast<llvm::IntegerType>(opTy)->getBitWidth()));
-
- handlerResult = Builder.CreateTrunc(handlerResult, opTy);
-
- Builder.CreateBr(continueBB);
-
- // Set up the continuation
+ llvm::Function *Trap = CGF.CGM.getIntrinsic(llvm::Intrinsic::trap);
+ Builder.CreateCall(Trap);
+ Builder.CreateUnreachable();
+
+ // Continue on.
Builder.SetInsertPoint(continueBB);
- // Get the correct result
- llvm::PHINode *phi = Builder.CreatePHI(opTy);
- phi->reserveOperandSpace(2);
- phi->addIncoming(result, initialBB);
- phi->addIncoming(handlerResult, overflowBB);
-
- return phi;
+ return result;
}
Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
if (!Ops.Ty->isAnyPointerType()) {
- if (Ops.Ty->isSignedIntegerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined:
return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add");
@@ -1606,7 +1646,7 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
if (!isa<llvm::PointerType>(Ops.LHS->getType())) {
- if (Ops.Ty->isSignedIntegerType()) {
+ if (Ops.Ty->hasSignedIntegerRepresentation()) {
switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
case LangOptions::SOB_Undefined:
return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub");
@@ -1747,7 +1787,7 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
CGF.EmitBlock(Cont);
}
- if (Ops.Ty->isUnsignedIntegerType())
+ if (Ops.Ty->hasUnsignedIntegerRepresentation())
return Builder.CreateLShr(Ops.LHS, RHS, "shr");
return Builder.CreateAShr(Ops.LHS, RHS, "shr");
}
@@ -1757,33 +1797,13 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
TestAndClearIgnoreResultAssign();
Value *Result;
QualType LHSTy = E->getLHS()->getType();
- if (LHSTy->isMemberFunctionPointerType()) {
- Value *LHSPtr = CGF.EmitAnyExprToTemp(E->getLHS()).getAggregateAddr();
- Value *RHSPtr = CGF.EmitAnyExprToTemp(E->getRHS()).getAggregateAddr();
- llvm::Value *LHSFunc = Builder.CreateStructGEP(LHSPtr, 0);
- LHSFunc = Builder.CreateLoad(LHSFunc);
- llvm::Value *RHSFunc = Builder.CreateStructGEP(RHSPtr, 0);
- RHSFunc = Builder.CreateLoad(RHSFunc);
- Value *ResultF = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHSFunc, RHSFunc, "cmp.func");
- Value *NullPtr = llvm::Constant::getNullValue(LHSFunc->getType());
- Value *ResultNull = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHSFunc, NullPtr, "cmp.null");
- llvm::Value *LHSAdj = Builder.CreateStructGEP(LHSPtr, 1);
- LHSAdj = Builder.CreateLoad(LHSAdj);
- llvm::Value *RHSAdj = Builder.CreateStructGEP(RHSPtr, 1);
- RHSAdj = Builder.CreateLoad(RHSAdj);
- Value *ResultA = Builder.CreateICmp((llvm::ICmpInst::Predicate)UICmpOpc,
- LHSAdj, RHSAdj, "cmp.adj");
- if (E->getOpcode() == BinaryOperator::EQ) {
- Result = Builder.CreateOr(ResultNull, ResultA, "or.na");
- Result = Builder.CreateAnd(Result, ResultF, "and.f");
- } else {
- assert(E->getOpcode() == BinaryOperator::NE &&
- "Member pointer comparison other than == or != ?");
- Result = Builder.CreateAnd(ResultNull, ResultA, "and.na");
- Result = Builder.CreateOr(Result, ResultF, "or.f");
- }
+ if (const MemberPointerType *MPT = LHSTy->getAs<MemberPointerType>()) {
+ assert(E->getOpcode() == BO_EQ ||
+ E->getOpcode() == BO_NE);
+ Value *LHS = CGF.EmitScalarExpr(E->getLHS());
+ Value *RHS = CGF.EmitScalarExpr(E->getRHS());
+ Result = CGF.CGM.getCXXABI().EmitMemberPointerComparison(
+ CGF, LHS, RHS, MPT, E->getOpcode() == BO_NE);
} else if (!LHSTy->isAnyComplexType()) {
Value *LHS = Visit(E->getLHS());
Value *RHS = Visit(E->getRHS());
@@ -1791,7 +1811,7 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
if (LHS->getType()->isFPOrFPVectorTy()) {
Result = Builder.CreateFCmp((llvm::CmpInst::Predicate)FCmpOpc,
LHS, RHS, "cmp");
- } else if (LHSTy->isSignedIntegerType()) {
+ } else if (LHSTy->hasSignedIntegerRepresentation()) {
Result = Builder.CreateICmp((llvm::ICmpInst::Predicate)SICmpOpc,
LHS, RHS, "cmp");
} else {
@@ -1827,10 +1847,10 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
LHS.second, RHS.second, "cmp.i");
}
- if (E->getOpcode() == BinaryOperator::EQ) {
+ if (E->getOpcode() == BO_EQ) {
Result = Builder.CreateAnd(ResultR, ResultI, "and.ri");
} else {
- assert(E->getOpcode() == BinaryOperator::NE &&
+ assert(E->getOpcode() == BO_NE &&
"Complex comparison other than == or != ?");
Result = Builder.CreateOr(ResultR, ResultI, "or.ri");
}
@@ -2044,7 +2064,12 @@ VisitConditionalOperator(const ConditionalOperator *E) {
return Builder.CreateSelect(CondV, LHS, RHS, "cond");
}
-
+ if (!E->getLHS() && CGF.getContext().getLangOptions().CPlusPlus) {
+ // Does not support GNU missing condition extension in C++ yet (see #7726)
+ CGF.ErrorUnsupported(E, "conditional operator with missing LHS");
+ return llvm::UndefValue::get(ConvertType(E->getType()));
+ }
+
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
@@ -2188,21 +2213,19 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) {
V = CreateTempAlloca(ClassPtrTy, "resval");
llvm::Value *Src = EmitScalarExpr(BaseExpr);
Builder.CreateStore(Src, V);
- LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- V = ScalarExprEmitter(*this).EmitLoadOfLValue(LV, E->getType());
- }
- else {
- if (E->isArrow())
- V = ScalarExprEmitter(*this).EmitLoadOfLValue(BaseExpr);
- else
- V = EmitLValue(BaseExpr).getAddress();
+ V = ScalarExprEmitter(*this).EmitLoadOfLValue(
+ MakeAddrLValue(V, E->getType()), E->getType());
+ } else {
+ if (E->isArrow())
+ V = ScalarExprEmitter(*this).EmitLoadOfLValue(BaseExpr);
+ else
+ V = EmitLValue(BaseExpr).getAddress();
}
// build Class* type
ClassPtrTy = ClassPtrTy->getPointerTo();
V = Builder.CreateBitCast(V, ClassPtrTy);
- LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType()));
- return LV;
+ return MakeAddrLValue(V, E->getType());
}
@@ -2212,7 +2235,7 @@ LValue CodeGenFunction::EmitCompoundAssignOperatorLValue(
Value *Result = 0;
switch (E->getOpcode()) {
#define COMPOUND_OP(Op) \
- case BinaryOperator::Op##Assign: \
+ case BO_##Op##Assign: \
return Scalar.EmitCompoundAssignLValue(E, &ScalarExprEmitter::Emit##Op, \
Result)
COMPOUND_OP(Mul);
@@ -2227,28 +2250,28 @@ LValue CodeGenFunction::EmitCompoundAssignOperatorLValue(
COMPOUND_OP(Or);
#undef COMPOUND_OP
- case BinaryOperator::PtrMemD:
- case BinaryOperator::PtrMemI:
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
- case BinaryOperator::Rem:
- case BinaryOperator::Add:
- case BinaryOperator::Sub:
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
- case BinaryOperator::And:
- case BinaryOperator::Xor:
- case BinaryOperator::Or:
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr:
- case BinaryOperator::Assign:
- case BinaryOperator::Comma:
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_Assign:
+ case BO_Comma:
assert(false && "Not valid compound assignment operators");
break;
}
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index e735a617546c..6a6d63df8f52 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -403,13 +403,14 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP,
// Objective-C pointer types, we can always bit cast the RHS in these cases.
if (getContext().getCanonicalType(Ivar->getType()) !=
getContext().getCanonicalType(ArgDecl->getType())) {
- ImplicitCastExpr ArgCasted(Ivar->getType(), CastExpr::CK_BitCast, &Arg,
- CXXBaseSpecifierArray(), false);
- BinaryOperator Assign(&IvarRef, &ArgCasted, BinaryOperator::Assign,
+ ImplicitCastExpr ArgCasted(ImplicitCastExpr::OnStack,
+ Ivar->getType(), CK_BitCast, &Arg,
+ VK_RValue);
+ BinaryOperator Assign(&IvarRef, &ArgCasted, BO_Assign,
Ivar->getType(), Loc);
EmitStmt(&Assign);
} else {
- BinaryOperator Assign(&IvarRef, &Arg, BinaryOperator::Assign,
+ BinaryOperator Assign(&IvarRef, &Arg, BO_Assign,
Ivar->getType(), Loc);
EmitStmt(&Assign);
}
@@ -571,7 +572,7 @@ void CodeGenFunction::EmitObjCSuperPropertySet(const Expr *Exp,
Args.push_back(std::make_pair(Src, Exp->getType()));
CGM.getObjCRuntime().GenerateMessageSendSuper(*this,
ReturnValueSlot(),
- Exp->getType(),
+ getContext().VoidTy,
S,
OMD->getClassInterface(),
isCategoryImpl,
@@ -792,7 +793,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
BreakContinueStack.pop_back();
- EmitBlock(AfterBody.Block);
+ EmitBlock(AfterBody.getBlock());
llvm::BasicBlock *FetchMore = createBasicBlock("fetchmore");
@@ -828,7 +829,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
LV.getAddress());
}
- EmitBlock(LoopEnd.Block);
+ EmitBlock(LoopEnd.getBlock());
}
void CodeGenFunction::EmitObjCAtTryStmt(const ObjCAtTryStmt &S) {
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index f3c80bcf08e3..d7960beb1d1d 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -167,6 +167,7 @@ public:
bool lval = false);
virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
*Method);
+ virtual llvm::Constant *GetEHType(QualType T);
virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD);
@@ -192,7 +193,8 @@ public:
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dst);
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest);
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal=false);
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest,
llvm::Value *ivarOffset);
@@ -210,6 +212,10 @@ public:
virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
const ObjCInterfaceDecl *Interface,
const ObjCIvarDecl *Ivar);
+ virtual llvm::Constant *GCBlockLayout(CodeGen::CodeGenFunction &CGF,
+ const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &) {
+ return NULLPtr;
+ }
};
} // end anonymous namespace
@@ -402,6 +408,11 @@ llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
return Builder.CreateLoad(Sel);
}
+llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
+ llvm_unreachable("asking for catch type for ObjC type in GNU runtime");
+ return 0;
+}
+
llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
const std::string &Name) {
llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
@@ -438,7 +449,7 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
/// Generate an NSConstantString object.
llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
- std::string Str(SL->getStrData(), SL->getByteLength());
+ std::string Str = SL->getString().str();
// Look for an existing one
llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
@@ -691,7 +702,7 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Params.push_back(SelectorTy);
llvm::Value *self;
- if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) {
+ if (isa<ObjCMethodDecl>(CGF.CurCodeDecl)) {
self = CGF.LoadObjCSelf();
} else {
self = llvm::ConstantPointerNull::get(IdTy);
@@ -721,8 +732,8 @@ CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
// The lookup function may have changed the receiver, so make sure we use
// the new one.
- ActualArgs[0] =
- std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy);
+ ActualArgs[0] = std::make_pair(RValue::get(
+ Builder.CreateLoad(ReceiverPtr, true)), ASTIdTy);
} else {
std::vector<const llvm::Type*> Params;
Params.push_back(Receiver->getType());
@@ -1854,6 +1865,19 @@ llvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
}
+namespace {
+ struct CallSyncExit : EHScopeStack::Cleanup {
+ llvm::Value *SyncExitFn;
+ llvm::Value *SyncArg;
+ CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
+ : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ }
+ };
+}
+
void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtSynchronizedStmt &S) {
std::vector<const llvm::Type*> Args(1, IdTy);
@@ -1870,13 +1894,8 @@ void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
CGF.Builder.CreateCall(SyncEnter, SyncArg);
// Register an all-paths cleanup to release the lock.
- {
- CodeGenFunction::CleanupBlock ReleaseScope(CGF, NormalAndEHCleanup);
-
- llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
- SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
- CGF.Builder.CreateCall(SyncExit, SyncArg);
- }
+ llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
+ CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, SyncExit, SyncArg);
// Emit the body of the statement.
CGF.EmitStmt(S.getSynchBody());
@@ -2007,13 +2026,11 @@ void CGObjCGNU::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
if (S.getFinallyStmt())
CGF.ExitFinallyBlock(FinallyInfo);
- if (Cont.Block) {
- if (Cont.Block->use_empty())
- delete Cont.Block;
- else {
- CGF.EmitBranch(Cont.Block);
- CGF.EmitBlock(Cont.Block);
- }
+ if (Cont.isValid()) {
+ if (Cont.getBlock()->use_empty())
+ delete Cont.getBlock();
+ else
+ CGF.EmitBlock(Cont.getBlock());
}
}
@@ -2075,11 +2092,16 @@ void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
}
void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, llvm::Value *dst,
+ bool threadlocal) {
CGBuilderTy B = CGF.Builder;
src = EnforceType(B, src, IdTy);
dst = EnforceType(B, dst, PtrToIdTy);
- B.CreateCall2(GlobalAssignFn, src, dst);
+ if (!threadlocal)
+ B.CreateCall2(GlobalAssignFn, src, dst);
+ else
+ // FIXME. Add threadloca assign API
+ assert(false && "EmitObjCGlobalAssign - Threal Local API NYI");
}
void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 01ead9efe876..54d0ff21ea44 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -25,7 +25,8 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/Intrinsics.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/IntrinsicInst.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/ADT/DenseSet.h"
@@ -106,17 +107,33 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
- Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
- Quals.addCVRQualifiers(CVRQualifiers);
-
- if (!Ivar->isBitField())
- return LValue::MakeAddr(V, Quals);
+ if (!Ivar->isBitField()) {
+ LValue LV = CGF.MakeAddrLValue(V, IvarTy);
+ LV.getQuals().addCVRQualifiers(CVRQualifiers);
+ return LV;
+ }
- // We need to compute the bit offset for the bit-field, the offset is to the
- // byte. Note, there is a subtle invariant here: we can only call this routine
- // on non-synthesized ivars but we may be called for synthesized ivars.
- // However, a synthesized ivar can never be a bit-field, so this is safe.
- uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8;
+ // We need to compute an access strategy for this bit-field. We are given the
+ // offset to the first byte in the bit-field, the sub-byte offset is taken
+ // from the original layout. We reuse the normal bit-field access strategy by
+ // treating this as an access to a struct where the bit-field is in byte 0,
+ // and adjust the containing type size as appropriate.
+ //
+ // FIXME: Note that currently we make a very conservative estimate of the
+ // alignment of the bit-field, because (a) it is not clear what guarantees the
+ // runtime makes us, and (b) we don't have a way to specify that the struct is
+ // at an alignment plus offset.
+ //
+ // Note, there is a subtle invariant here: we can only call this routine on
+ // non-synthesized ivars but we may be called for synthesized ivars. However,
+ // a synthesized ivar can never be a bit-field, so this is safe.
+ const ASTRecordLayout &RL =
+ CGF.CGM.getContext().getASTObjCInterfaceLayout(OID);
+ uint64_t TypeSizeInBits = RL.getSize();
+ uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar);
+ uint64_t BitOffset = FieldBitOffset % 8;
+ uint64_t ContainingTypeAlign = 8;
+ uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset);
uint64_t BitFieldSize =
Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
@@ -126,24 +143,12 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
// layout object. However, this is blocked on other cleanups to the
// Objective-C code, so for now we just live with allocating a bunch of these
// objects.
+ CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo(
+ CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize,
+ ContainingTypeSize, ContainingTypeAlign));
- // We always construct a single, possibly unaligned, access for this case.
- CGBitFieldInfo::AccessInfo AI;
- AI.FieldIndex = 0;
- AI.FieldByteOffset = 0;
- AI.FieldBitStart = BitOffset;
- AI.AccessWidth = CGF.CGM.getContext().getTypeSize(IvarTy);
- AI.AccessAlignment = 0;
- AI.TargetBitOffset = 0;
- AI.TargetBitWidth = BitFieldSize;
-
- CGBitFieldInfo *Info =
- new (CGF.CGM.getContext()) CGBitFieldInfo(BitFieldSize, 1, &AI,
- IvarTy->isSignedIntegerType());
-
- // FIXME: We need to set a very conservative alignment on this, or make sure
- // that the runtime is doing the right thing.
- return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers());
+ return LValue::MakeBitfield(V, *Info,
+ IvarTy.getCVRQualifiers() | CVRQualifiers);
}
///
@@ -402,6 +407,16 @@ public:
return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
}
+ /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
+ llvm::Constant *getGcAssignThreadLocalFn() {
+ // id objc_assign_threadlocal(id src, id * dest)
+ std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
+ Args.push_back(ObjectPtrTy->getPointerTo());
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(ObjectPtrTy, Args, false);
+ return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
+ }
+
/// GcAssignIvarFn -- LLVM objc_assign_ivar function.
llvm::Constant *getGcAssignIvarFn() {
// id objc_assign_ivar(id, id *, ptrdiff_t)
@@ -425,7 +440,7 @@ public:
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
llvm::Constant *getGcAssignStrongCastFn() {
- // id objc_assign_global(id, id *)
+ // id objc_assign_strongCast(id, id *)
std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
Args.push_back(ObjectPtrTy->getPointerTo());
llvm::FunctionType *FTy =
@@ -719,25 +734,6 @@ public:
"objc_msgSend_stret_fixup");
}
- llvm::Constant *getMessageSendIdFixupFn() {
- // id objc_msgSendId_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendId_fixup");
- }
-
- llvm::Constant *getMessageSendIdStretFixupFn() {
- // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendId_stret_fixup");
- }
llvm::Constant *getMessageSendSuper2FixupFn() {
// id objc_msgSendSuper2_fixup (struct objc_super *,
// struct _super_message_ref_t*, ...)
@@ -760,28 +756,6 @@ public:
"objc_msgSendSuper2_stret_fixup");
}
-
-
- /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
- /// exception personality function.
- llvm::Value *getEHPersonalityPtr() {
- llvm::Constant *Personality =
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
- true),
- "__objc_personality_v0");
- return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
- }
-
- llvm::Constant *getUnwindResumeOrRethrowFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(Int8PtrTy);
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, false),
- (CGM.getLangOptions().SjLjExceptions ? "_Unwind_SjLj_Resume" :
- "_Unwind_Resume_or_Rethrow"));
- }
-
llvm::Constant *getObjCEndCatchFn() {
return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
false),
@@ -905,7 +879,6 @@ protected:
/// selector's name. The return value has type char *.
llvm::Constant *GetMethodVarName(Selector Sel);
llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
- llvm::Constant *GetMethodVarName(const std::string &Name);
/// GetMethodVarType - Return a unique constant for the given
/// selector's name. The return value has type char *.
@@ -926,11 +899,15 @@ protected:
/// name. The return value has type char *.
llvm::Constant *GetClassName(IdentifierInfo *Ident);
+ llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
+
/// BuildIvarLayout - Builds ivar layout bitmap for the class
/// implementation for the __strong or __weak case.
///
llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
bool ForStrongLayout);
+
+ llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
void BuildAggrIvarRecordLayout(const RecordType *RT,
unsigned int BytePos, bool ForStrongLayout,
@@ -1022,6 +999,9 @@ public:
/// forward references will be filled in with empty bodies if no
/// definition is seen. The return value has type ProtocolPtrTy.
virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
+ virtual llvm::Constant *GCBlockLayout(CodeGen::CodeGenFunction &CGF,
+ const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &);
+
};
class CGObjCMac : public CGObjCCommonMac {
@@ -1053,15 +1033,6 @@ private:
/// EmitSuperClassRef - Emits reference to class's main metadata class.
llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
- CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Arg0,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs);
-
/// EmitIvarList - Emit the ivar list for the given
/// implementation. If ForClass is true the list of class ivars
/// (i.e. metaclass ivars) is emitted, otherwise the list of
@@ -1174,6 +1145,8 @@ public:
virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
const ObjCMethodDecl *Method);
+ virtual llvm::Constant *GetEHType(QualType T);
+
virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
@@ -1198,7 +1171,8 @@ public:
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dst);
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest);
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal = false);
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest,
llvm::Value *ivarOffset);
@@ -1343,7 +1317,7 @@ private:
/// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
/// interface. The return value has type EHTypePtrTy.
- llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
+ llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
bool ForDefinition);
const char *getMetaclassSymbolPrefix() const {
@@ -1418,6 +1392,8 @@ public:
virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD);
+ virtual llvm::Constant *GetEHType(QualType T);
+
virtual llvm::Constant *GetPropertyGetFunction() {
return ObjCTypes.getGetPropertyFn();
}
@@ -1444,7 +1420,8 @@ public:
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dst);
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest);
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal = false);
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest,
llvm::Value *ivarOffset);
@@ -1515,6 +1492,11 @@ llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
return EmitSelector(Builder, Method->getSelector());
}
+llvm::Constant *CGObjCMac::GetEHType(QualType T) {
+ llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
+ return 0;
+}
+
/// Generate a constant CFString object.
/*
struct __builtin_CFString {
@@ -1664,6 +1646,90 @@ CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
}
+static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
+ if (FQT.isObjCGCStrong())
+ return Qualifiers::Strong;
+
+ if (FQT.isObjCGCWeak())
+ return Qualifiers::Weak;
+
+ if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
+ return Qualifiers::Strong;
+
+ if (const PointerType *PT = FQT->getAs<PointerType>())
+ return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
+
+ return Qualifiers::GCNone;
+}
+
+llvm::Constant *CGObjCCommonMac::GCBlockLayout(CodeGen::CodeGenFunction &CGF,
+ const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &DeclRefs) {
+ llvm::Constant *NullPtr =
+ llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
+ if ((CGM.getLangOptions().getGCMode() == LangOptions::NonGC) ||
+ DeclRefs.empty())
+ return NullPtr;
+ bool hasUnion = false;
+ SkipIvars.clear();
+ IvarsInfo.clear();
+ unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
+ unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
+
+ for (size_t i = 0; i < DeclRefs.size(); ++i) {
+ const BlockDeclRefExpr *BDRE = DeclRefs[i];
+ const ValueDecl *VD = BDRE->getDecl();
+ CharUnits Offset = CGF.BlockDecls[VD];
+ uint64_t FieldOffset = Offset.getQuantity();
+ QualType Ty = VD->getType();
+ assert(!Ty->isArrayType() &&
+ "Array block variable should have been caught");
+ if ((Ty->isRecordType() || Ty->isUnionType()) && !BDRE->isByRef()) {
+ BuildAggrIvarRecordLayout(Ty->getAs<RecordType>(),
+ FieldOffset,
+ true,
+ hasUnion);
+ continue;
+ }
+
+ Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), Ty);
+ unsigned FieldSize = CGM.getContext().getTypeSize(Ty);
+ // __block variables are passed by their descriptior address. So, size
+ // must reflect this.
+ if (BDRE->isByRef())
+ FieldSize = WordSizeInBits;
+ if (GCAttr == Qualifiers::Strong || BDRE->isByRef())
+ IvarsInfo.push_back(GC_IVAR(FieldOffset,
+ FieldSize / WordSizeInBits));
+ else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
+ SkipIvars.push_back(GC_IVAR(FieldOffset,
+ FieldSize / ByteSizeInBits));
+ }
+
+ if (IvarsInfo.empty())
+ return NullPtr;
+ // Sort on byte position in case we encounterred a union nested in
+ // block variable type's aggregate type.
+ if (hasUnion && !IvarsInfo.empty())
+ std::sort(IvarsInfo.begin(), IvarsInfo.end());
+ if (hasUnion && !SkipIvars.empty())
+ std::sort(SkipIvars.begin(), SkipIvars.end());
+
+ std::string BitMap;
+ llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
+ if (CGM.getLangOptions().ObjCGCBitmapPrint) {
+ printf("\n block variable layout for block: ");
+ const unsigned char *s = (unsigned char*)BitMap.c_str();
+ for (unsigned i = 0; i < BitMap.size(); i++)
+ if (!(s[i] & 0xf0))
+ printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
+ else
+ printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
+ printf("\n");
+ }
+
+ return C;
+}
+
llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
const ObjCProtocolDecl *PD) {
// FIXME: I don't understand why gcc generates this, or where it is
@@ -1927,8 +1993,9 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Prop));
}
if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
- E = OID->protocol_end(); P != E; ++P)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = OID->all_referenced_protocol_begin(),
+ E = OID->all_referenced_protocol_end(); P != E; ++P)
PushProtocolProperties(PropertySet, Properties, Container, (*P),
ObjCTypes);
}
@@ -2116,8 +2183,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
llvm::Constant *Protocols =
EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
- Interface->protocol_begin(),
- Interface->protocol_end());
+ Interface->all_referenced_protocol_begin(),
+ Interface->all_referenced_protocol_end());
unsigned Flags = eClassFlags_Factory;
if (ID->getNumIvarInitializers())
Flags |= eClassFlags_HasCXXStructors;
@@ -2427,8 +2494,7 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
/// given method if it has been defined. The result is null if the
/// method has not been defined. The return value has type MethodPtrTy.
llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
- // FIXME: Use DenseMap::lookup
- llvm::Function *Fn = MethodDefinitions[MD];
+ llvm::Function *Fn = GetMethodDefinition(MD);
if (!Fn)
return 0;
@@ -2529,6 +2595,214 @@ void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
return EmitTryOrSynchronizedStmt(CGF, S);
}
+namespace {
+ struct PerformFragileFinally : EHScopeStack::Cleanup {
+ const Stmt &S;
+ llvm::Value *SyncArgSlot;
+ llvm::Value *CallTryExitVar;
+ llvm::Value *ExceptionData;
+ ObjCTypesHelper &ObjCTypes;
+ PerformFragileFinally(const Stmt *S,
+ llvm::Value *SyncArgSlot,
+ llvm::Value *CallTryExitVar,
+ llvm::Value *ExceptionData,
+ ObjCTypesHelper *ObjCTypes)
+ : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
+ ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ // Check whether we need to call objc_exception_try_exit.
+ // In optimized code, this branch will always be folded.
+ llvm::BasicBlock *FinallyCallExit =
+ CGF.createBasicBlock("finally.call_exit");
+ llvm::BasicBlock *FinallyNoCallExit =
+ CGF.createBasicBlock("finally.no_call_exit");
+ CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
+ FinallyCallExit, FinallyNoCallExit);
+
+ CGF.EmitBlock(FinallyCallExit);
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
+ ->setDoesNotThrow();
+
+ CGF.EmitBlock(FinallyNoCallExit);
+
+ if (isa<ObjCAtTryStmt>(S)) {
+ if (const ObjCAtFinallyStmt* FinallyStmt =
+ cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
+ // Save the current cleanup destination in case there's
+ // control flow inside the finally statement.
+ llvm::Value *CurCleanupDest =
+ CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
+
+ CGF.EmitStmt(FinallyStmt->getFinallyBody());
+
+ if (CGF.HaveInsertPoint()) {
+ CGF.Builder.CreateStore(CurCleanupDest,
+ CGF.getNormalCleanupDestSlot());
+ } else {
+ // Currently, the end of the cleanup must always exist.
+ CGF.EnsureInsertPoint();
+ }
+ }
+ } else {
+ // Emit objc_sync_exit(expr); as finally's sole statement for
+ // @synchronized.
+ llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
+ CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
+ ->setDoesNotThrow();
+ }
+ }
+ };
+
+ class FragileHazards {
+ CodeGenFunction &CGF;
+ llvm::SmallVector<llvm::Value*, 20> Locals;
+ llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
+
+ llvm::InlineAsm *ReadHazard;
+ llvm::InlineAsm *WriteHazard;
+
+ llvm::FunctionType *GetAsmFnType();
+
+ void collectLocals();
+ void emitReadHazard(CGBuilderTy &Builder);
+
+ public:
+ FragileHazards(CodeGenFunction &CGF);
+
+ void emitWriteHazard();
+ void emitHazardsInNewBlocks();
+ };
+}
+
+/// Create the fragile-ABI read and write hazards based on the current
+/// state of the function, which is presumed to be immediately prior
+/// to a @try block. These hazards are used to maintain correct
+/// semantics in the face of optimization and the fragile ABI's
+/// cavalier use of setjmp/longjmp.
+FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
+ collectLocals();
+
+ if (Locals.empty()) return;
+
+ // Collect all the blocks in the function.
+ for (llvm::Function::iterator
+ I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
+ BlocksBeforeTry.insert(&*I);
+
+ llvm::FunctionType *AsmFnTy = GetAsmFnType();
+
+ // Create a read hazard for the allocas. This inhibits dead-store
+ // optimizations and forces the values to memory. This hazard is
+ // inserted before any 'throwing' calls in the protected scope to
+ // reflect the possibility that the variables might be read from the
+ // catch block if the call throws.
+ {
+ std::string Constraint;
+ for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
+ if (I) Constraint += ',';
+ Constraint += "*m";
+ }
+
+ ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
+ }
+
+ // Create a write hazard for the allocas. This inhibits folding
+ // loads across the hazard. This hazard is inserted at the
+ // beginning of the catch path to reflect the possibility that the
+ // variables might have been written within the protected scope.
+ {
+ std::string Constraint;
+ for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
+ if (I) Constraint += ',';
+ Constraint += "=*m";
+ }
+
+ WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
+ }
+}
+
+/// Emit a write hazard at the current location.
+void FragileHazards::emitWriteHazard() {
+ if (Locals.empty()) return;
+
+ CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
+ ->setDoesNotThrow();
+}
+
+void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
+ assert(!Locals.empty());
+ Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
+ ->setDoesNotThrow();
+}
+
+/// Emit read hazards in all the protected blocks, i.e. all the blocks
+/// which have been inserted since the beginning of the try.
+void FragileHazards::emitHazardsInNewBlocks() {
+ if (Locals.empty()) return;
+
+ CGBuilderTy Builder(CGF.getLLVMContext());
+
+ // Iterate through all blocks, skipping those prior to the try.
+ for (llvm::Function::iterator
+ FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
+ llvm::BasicBlock &BB = *FI;
+ if (BlocksBeforeTry.count(&BB)) continue;
+
+ // Walk through all the calls in the block.
+ for (llvm::BasicBlock::iterator
+ BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
+ llvm::Instruction &I = *BI;
+
+ // Ignore instructions that aren't non-intrinsic calls.
+ // These are the only calls that can possibly call longjmp.
+ if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
+ if (isa<llvm::IntrinsicInst>(I))
+ continue;
+
+ // Ignore call sites marked nounwind. This may be questionable,
+ // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
+ llvm::CallSite CS(&I);
+ if (CS.doesNotThrow()) continue;
+
+ // Insert a read hazard before the call. This will ensure that
+ // any writes to the locals are performed before making the
+ // call. If the call throws, then this is sufficient to
+ // guarantee correctness as long as it doesn't also write to any
+ // locals.
+ Builder.SetInsertPoint(&BB, BI);
+ emitReadHazard(Builder);
+ }
+ }
+}
+
+static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
+ if (V) S.insert(V);
+}
+
+void FragileHazards::collectLocals() {
+ // Compute a set of allocas to ignore.
+ llvm::DenseSet<llvm::Value*> AllocasToIgnore;
+ addIfPresent(AllocasToIgnore, CGF.ReturnValue);
+ addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
+ addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
+
+ // Collect all the allocas currently in the function. This is
+ // probably way too aggressive.
+ llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
+ for (llvm::BasicBlock::iterator
+ I = Entry.begin(), E = Entry.end(); I != E; ++I)
+ if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
+ Locals.push_back(&*I);
+}
+
+llvm::FunctionType *FragileHazards::GetAsmFnType() {
+ std::vector<const llvm::Type *> Tys(Locals.size());
+ for (unsigned I = 0, E = Locals.size(); I != E; ++I)
+ Tys[I] = Locals[I]->getType();
+ return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
+}
+
/*
Objective-C setjmp-longjmp (sjlj) Exception Handling
@@ -2657,66 +2931,49 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// For @synchronized, call objc_sync_enter(sync.expr). The
// evaluation of the expression must occur before we enter the
- // @synchronized. We can safely avoid a temp here because jumps into
- // @synchronized are illegal & this will dominate uses.
- llvm::Value *SyncArg = 0;
+ // @synchronized. We can't avoid a temp here because we need the
+ // value to be preserved. If the backend ever does liveness
+ // correctly after setjmp, this will be unnecessary.
+ llvm::Value *SyncArgSlot = 0;
if (!isTry) {
- SyncArg =
+ llvm::Value *SyncArg =
CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
->setDoesNotThrow();
+
+ SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
+ CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
}
- // Allocate memory for the exception data and rethrow pointer.
+ // Allocate memory for the setjmp buffer. This needs to be kept
+ // live throughout the try and catch blocks.
llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
"exceptiondata.ptr");
- llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
- "_rethrow");
+
+ // Create the fragile hazards. Note that this will not capture any
+ // of the allocas required for exception processing, but will
+ // capture the current basic block (which extends all the way to the
+ // setjmp call) as "before the @try".
+ FragileHazards Hazards(CGF);
// Create a flag indicating whether the cleanup needs to call
// objc_exception_try_exit. This is true except when
// - no catches match and we're branching through the cleanup
// just to rethrow the exception, or
// - a catch matched and we're falling out of the catch handler.
+ // The setjmp-safety rule here is that we should always store to this
+ // variable in a place that dominates the branch through the cleanup
+ // without passing through any setjmps.
llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
"_call_try_exit");
- CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext),
- CallTryExitVar);
// Push a normal cleanup to leave the try scope.
- {
- CodeGenFunction::CleanupBlock FinallyScope(CGF, NormalCleanup);
-
- // Check whether we need to call objc_exception_try_exit.
- // In optimized code, this branch will always be folded.
- llvm::BasicBlock *FinallyCallExit =
- CGF.createBasicBlock("finally.call_exit");
- llvm::BasicBlock *FinallyNoCallExit =
- CGF.createBasicBlock("finally.no_call_exit");
- CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
- FinallyCallExit, FinallyNoCallExit);
-
- CGF.EmitBlock(FinallyCallExit);
- CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
- ->setDoesNotThrow();
-
- CGF.EmitBlock(FinallyNoCallExit);
-
- if (isTry) {
- if (const ObjCAtFinallyStmt* FinallyStmt =
- cast<ObjCAtTryStmt>(S).getFinallyStmt())
- CGF.EmitStmt(FinallyStmt->getFinallyBody());
-
- // ~CleanupBlock requires there to be an exit block.
- CGF.EnsureInsertPoint();
- } else {
- // Emit objc_sync_exit(expr); as finally's sole statement for
- // @synchronized.
- CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
- ->setDoesNotThrow();
- }
- }
+ CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
+ SyncArgSlot,
+ CallTryExitVar,
+ ExceptionData,
+ &ObjCTypes);
// Enter a try block:
// - Call objc_exception_try_enter to push ExceptionData on top of
@@ -2738,68 +2995,71 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
llvm::Value *DidCatch =
- CGF.Builder.CreateIsNull(SetJmpResult, "did_catch_exception");
- CGF.Builder.CreateCondBr(DidCatch, TryBlock, TryHandler);
+ CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
+ CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
// Emit the protected block.
CGF.EmitBlock(TryBlock);
+ CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
: cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
- CGF.EmitBranchThroughCleanup(FinallyEnd);
+
+ CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
// Emit the exception handler block.
CGF.EmitBlock(TryHandler);
- // Retrieve the exception object. We may emit multiple blocks but
- // nothing can cross this so the value is already in SSA form.
- llvm::CallInst *Caught =
- CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData, "caught");
- Caught->setDoesNotThrow();
-
- // Remember the exception to rethrow.
- CGF.Builder.CreateStore(Caught, RethrowPtr);
-
- // Note: at this point, objc_exception_throw already popped the
- // catch handler, so anything that branches to the cleanup needs
- // to set CallTryExitVar to false.
+ // Don't optimize loads of the in-scope locals across this point.
+ Hazards.emitWriteHazard();
// For a @synchronized (or a @try with no catches), just branch
// through the cleanup to the rethrow block.
if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
// Tell the cleanup not to re-pop the exit.
- CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
- CallTryExitVar);
-
+ CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
CGF.EmitBranchThroughCleanup(FinallyRethrow);
// Otherwise, we have to match against the caught exceptions.
} else {
+ // Retrieve the exception object. We may emit multiple blocks but
+ // nothing can cross this so the value is already in SSA form.
+ llvm::CallInst *Caught =
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
+ ExceptionData, "caught");
+ Caught->setDoesNotThrow();
+
// Push the exception to rethrow onto the EH value stack for the
// benefit of any @throws in the handlers.
CGF.ObjCEHValueStack.push_back(Caught);
const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
-
- // Enter a new exception try block (in case a @catch block throws
- // an exception). Now CallTryExitVar (currently true) is back in
- // synch with reality.
- CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
- ->setDoesNotThrow();
- llvm::CallInst *SetJmpResult =
- CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
- "setjmp.result");
- SetJmpResult->setDoesNotThrow();
+ bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
- llvm::Value *Threw =
- CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
+ llvm::BasicBlock *CatchBlock = 0;
+ llvm::BasicBlock *CatchHandler = 0;
+ if (HasFinally) {
+ // Enter a new exception try block (in case a @catch block
+ // throws an exception).
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
+ ->setDoesNotThrow();
+
+ llvm::CallInst *SetJmpResult =
+ CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
+ "setjmp.result");
+ SetJmpResult->setDoesNotThrow();
+
+ llvm::Value *Threw =
+ CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
- llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
- llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch_for_catch");
- CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
+ CatchBlock = CGF.createBasicBlock("catch");
+ CatchHandler = CGF.createBasicBlock("catch_for_catch");
+ CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
+
+ CGF.EmitBlock(CatchBlock);
+ }
- CGF.EmitBlock(CatchBlock);
+ CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
// Handle catch list. As a special case we check if everything is
// matched and avoid generating code for falling off the end if
@@ -2872,7 +3132,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
// Collect any cleanups for the catch variable. The scope lasts until
// the end of the catch body.
- CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
+ CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
CGF.EmitLocalBlockVarDecl(*CatchParam);
assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
@@ -2896,43 +3156,55 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
CGF.ObjCEHValueStack.pop_back();
- if (!AllMatched) {
- // None of the handlers caught the exception, so store it to be
- // rethrown at the end of the @finally block.
- CGF.Builder.CreateStore(Caught, RethrowPtr);
+ // If nothing wanted anything to do with the caught exception,
+ // kill the extract call.
+ if (Caught->use_empty())
+ Caught->eraseFromParent();
+
+ if (!AllMatched)
CGF.EmitBranchThroughCleanup(FinallyRethrow);
- }
- // Emit the exception handler for the @catch blocks.
- CGF.EmitBlock(CatchHandler);
+ if (HasFinally) {
+ // Emit the exception handler for the @catch blocks.
+ CGF.EmitBlock(CatchHandler);
- // Rethrow the new exception, not the old one.
- Caught = CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData);
- Caught->setDoesNotThrow();
- CGF.Builder.CreateStore(Caught, RethrowPtr);
+ // In theory we might now need a write hazard, but actually it's
+ // unnecessary because there's no local-accessing code between
+ // the try's write hazard and here.
+ //Hazards.emitWriteHazard();
- // Don't pop the catch handler; the throw already did.
- CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext),
- CallTryExitVar);
- CGF.EmitBranchThroughCleanup(FinallyRethrow);
+ // Don't pop the catch handler; the throw already did.
+ CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
+ CGF.EmitBranchThroughCleanup(FinallyRethrow);
+ }
}
+ // Insert read hazards as required in the new blocks.
+ Hazards.emitHazardsInNewBlocks();
+
// Pop the cleanup.
+ CGF.Builder.restoreIP(TryFallthroughIP);
+ if (CGF.HaveInsertPoint())
+ CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
CGF.PopCleanupBlock();
- CGF.EmitBlock(FinallyEnd.Block);
+ CGF.EmitBlock(FinallyEnd.getBlock(), true);
// Emit the rethrow block.
- CGF.Builder.ClearInsertionPoint();
- CGF.EmitBlock(FinallyRethrow.Block, true);
+ CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
+ CGF.EmitBlock(FinallyRethrow.getBlock(), true);
if (CGF.HaveInsertPoint()) {
- CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(),
- CGF.Builder.CreateLoad(RethrowPtr))
+ // Just look in the buffer for the exception to throw.
+ llvm::CallInst *Caught =
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
+ ExceptionData);
+ Caught->setDoesNotThrow();
+
+ CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), Caught)
->setDoesNotThrow();
CGF.Builder.CreateUnreachable();
}
- CGF.Builder.SetInsertPoint(FinallyEnd.Block);
+ CGF.Builder.restoreIP(SavedIP);
}
void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
@@ -2996,7 +3268,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
/// objc_assign_global (id src, id *dst)
///
void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, llvm::Value *dst,
+ bool threadlocal) {
const llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
@@ -3007,8 +3280,12 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
- src, dst, "globalassign");
+ if (!threadlocal)
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
+ src, dst, "globalassign");
+ else
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
+ src, dst, "threadlocalassign");
return;
}
@@ -3260,6 +3537,22 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
return getConstantGEP(VMContext, Entry, 0, 0);
}
+llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
+ llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
+ I = MethodDefinitions.find(MD);
+ if (I != MethodDefinitions.end())
+ return I->second;
+
+ if (MD->hasBody() && MD->getPCHLevel() > 0) {
+ // MD isn't emitted yet because it comes from PCH.
+ CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
+ assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
+ return MethodDefinitions[MD];
+ }
+
+ return NULL;
+}
+
/// GetIvarLayoutName - Returns a unique constant for the given
/// ivar layout bitmap.
llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
@@ -3267,22 +3560,6 @@ llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
}
-static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
- if (FQT.isObjCGCStrong())
- return Qualifiers::Strong;
-
- if (FQT.isObjCGCWeak())
- return Qualifiers::Weak;
-
- if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
- return Qualifiers::Strong;
-
- if (const PointerType *PT = FQT->getAs<PointerType>())
- return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
-
- return Qualifiers::GCNone;
-}
-
void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
unsigned int BytePos,
bool ForStrongLayout,
@@ -3446,63 +3723,19 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
MaxSkippedUnionIvarSize));
}
-/// BuildIvarLayout - Builds ivar layout bitmap for the class
-/// implementation for the __strong or __weak case.
-/// The layout map displays which words in ivar list must be skipped
-/// and which must be scanned by GC (see below). String is built of bytes.
-/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
-/// of words to skip and right nibble is count of words to scan. So, each
-/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
-/// represented by a 0x00 byte which also ends the string.
-/// 1. when ForStrongLayout is true, following ivars are scanned:
-/// - id, Class
-/// - object *
-/// - __strong anything
-///
-/// 2. When ForStrongLayout is false, following ivars are scanned:
-/// - __weak anything
-///
-llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
- const ObjCImplementationDecl *OMD,
- bool ForStrongLayout) {
- bool hasUnion = false;
-
+/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
+/// the computations and returning the layout bitmap (for ivar or blocks) in
+/// the given argument BitMap string container. Routine reads
+/// two containers, IvarsInfo and SkipIvars which are assumed to be
+/// filled already by the caller.
+llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
unsigned int WordsToScan, WordsToSkip;
const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
- if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
- return llvm::Constant::getNullValue(PtrTy);
-
- llvm::SmallVector<FieldDecl*, 32> RecFields;
- const ObjCInterfaceDecl *OI = OMD->getClassInterface();
- CGM.getContext().CollectObjCIvars(OI, RecFields);
-
- // Add this implementations synthesized ivars.
- llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
- CGM.getContext().CollectNonClassIvars(OI, Ivars);
- for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
- RecFields.push_back(cast<FieldDecl>(Ivars[k]));
-
- if (RecFields.empty())
- return llvm::Constant::getNullValue(PtrTy);
-
- SkipIvars.clear();
- IvarsInfo.clear();
-
- BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
- if (IvarsInfo.empty())
- return llvm::Constant::getNullValue(PtrTy);
-
- // Sort on byte position in case we encounterred a union nested in
- // the ivar list.
- if (hasUnion && !IvarsInfo.empty())
- std::sort(IvarsInfo.begin(), IvarsInfo.end());
- if (hasUnion && !SkipIvars.empty())
- std::sort(SkipIvars.begin(), SkipIvars.end());
-
+
// Build the string of skip/scan nibbles
llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
unsigned int WordSize =
- CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
+ CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
if (IvarsInfo[0].ivar_bytepos == 0) {
WordsToSkip = 0;
WordsToScan = IvarsInfo[0].ivar_size;
@@ -3512,7 +3745,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
}
for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
unsigned int TailPrevGCObjC =
- IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
+ IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
// consecutive 'scanned' object pointers.
WordsToScan += IvarsInfo[i].ivar_size;
@@ -3526,7 +3759,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
SkScan.skip = WordsToSkip;
SkScan.scan = WordsToScan;
SkipScanIvars.push_back(SkScan);
-
+
// Skip the hole.
SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
SkScan.scan = 0;
@@ -3541,15 +3774,15 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
SkScan.scan = WordsToScan;
SkipScanIvars.push_back(SkScan);
}
-
+
if (!SkipIvars.empty()) {
unsigned int LastIndex = SkipIvars.size()-1;
int LastByteSkipped =
- SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
+ SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
LastIndex = IvarsInfo.size()-1;
int LastByteScanned =
- IvarsInfo[LastIndex].ivar_bytepos +
- IvarsInfo[LastIndex].ivar_size * WordSize;
+ IvarsInfo[LastIndex].ivar_bytepos +
+ IvarsInfo[LastIndex].ivar_size * WordSize;
// Compute number of bytes to skip at the tail end of the last ivar scanned.
if (LastByteSkipped > LastByteScanned) {
unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
@@ -3572,20 +3805,19 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
--SkipScan;
}
}
-
+
// Generate the string.
- std::string BitMap;
for (int i = 0; i <= SkipScan; i++) {
unsigned char byte;
unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
-
+
// first skip big.
for (unsigned int ix = 0; ix < skip_big; ix++)
BitMap += (unsigned char)(0xf0);
-
+
// next (skip small, scan)
if (skip_small) {
byte = skip_small << 4;
@@ -3610,11 +3842,71 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
// null terminate string.
unsigned char zero = 0;
BitMap += zero;
+
+ llvm::GlobalVariable * Entry =
+ CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
+ llvm::ConstantArray::get(VMContext, BitMap.c_str()),
+ "__TEXT,__cstring,cstring_literals",
+ 1, true);
+ return getConstantGEP(VMContext, Entry, 0, 0);
+}
- if (CGM.getLangOptions().ObjCGCBitmapPrint) {
+/// BuildIvarLayout - Builds ivar layout bitmap for the class
+/// implementation for the __strong or __weak case.
+/// The layout map displays which words in ivar list must be skipped
+/// and which must be scanned by GC (see below). String is built of bytes.
+/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
+/// of words to skip and right nibble is count of words to scan. So, each
+/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
+/// represented by a 0x00 byte which also ends the string.
+/// 1. when ForStrongLayout is true, following ivars are scanned:
+/// - id, Class
+/// - object *
+/// - __strong anything
+///
+/// 2. When ForStrongLayout is false, following ivars are scanned:
+/// - __weak anything
+///
+llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
+ const ObjCImplementationDecl *OMD,
+ bool ForStrongLayout) {
+ bool hasUnion = false;
+
+ const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
+ if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+ return llvm::Constant::getNullValue(PtrTy);
+
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ const ObjCInterfaceDecl *OI = OMD->getClassInterface();
+ CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
+
+ llvm::SmallVector<FieldDecl*, 32> RecFields;
+ for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
+ RecFields.push_back(cast<FieldDecl>(Ivars[k]));
+
+ if (RecFields.empty())
+ return llvm::Constant::getNullValue(PtrTy);
+
+ SkipIvars.clear();
+ IvarsInfo.clear();
+
+ BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
+ if (IvarsInfo.empty())
+ return llvm::Constant::getNullValue(PtrTy);
+ // Sort on byte position in case we encounterred a union nested in
+ // the ivar list.
+ if (hasUnion && !IvarsInfo.empty())
+ std::sort(IvarsInfo.begin(), IvarsInfo.end());
+ if (hasUnion && !SkipIvars.empty())
+ std::sort(SkipIvars.begin(), SkipIvars.end());
+
+ std::string BitMap;
+ llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
+
+ if (CGM.getLangOptions().ObjCGCBitmapPrint) {
printf("\n%s ivar layout for class '%s': ",
ForStrongLayout ? "strong" : "weak",
- OMD->getClassInterface()->getNameAsCString());
+ OMD->getClassInterface()->getName().data());
const unsigned char *s = (unsigned char*)BitMap.c_str();
for (unsigned i = 0; i < BitMap.size(); i++)
if (!(s[i] & 0xf0))
@@ -3623,12 +3915,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
printf("\n");
}
- llvm::GlobalVariable * Entry =
- CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
- llvm::ConstantArray::get(VMContext, BitMap.c_str()),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
- return getConstantGEP(VMContext, Entry, 0, 0);
+ return C;
}
llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
@@ -3649,11 +3936,6 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
}
-// FIXME: Merge into a single cstring creation function.
-llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
- return GetMethodVarName(&CGM.getContext().Idents.get(Name));
-}
-
llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
std::string TypeStr;
CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
@@ -4526,8 +4808,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
+ OID->getName(),
- OID->protocol_begin(),
- OID->protocol_end());
+ OID->all_referenced_protocol_begin(),
+ OID->all_referenced_protocol_end());
if (flags & CLS_META)
Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
@@ -4741,7 +5023,7 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
ObjCTypes.ExternalProtocolPtrTy);
std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
- ProtocolName += PD->getNameAsCString();
+ ProtocolName += PD->getName();
llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
if (PTGV)
@@ -4855,8 +5137,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
/// method has not been defined. The return value has type MethodPtrTy.
llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
const ObjCMethodDecl *MD) {
- // FIXME: Use DenseMap::lookup
- llvm::Function *Fn = MethodDefinitions[MD];
+ llvm::Function *Fn = GetMethodDefinition(MD);
if (!Fn)
return 0;
@@ -5284,40 +5565,24 @@ CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
llvm::Constant *Fn = 0;
std::string Name("\01l_");
if (CGM.ReturnTypeUsesSRet(FnInfo)) {
-#if 0
- // unlike what is documented. gcc never generates this API!!
- if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
- Fn = ObjCTypes.getMessageSendIdStretFixupFn();
- // FIXME. Is there a better way of getting these names.
- // They are available in RuntimeFunctions vector pair.
- Name += "objc_msgSendId_stret_fixup";
- } else
-#endif
- if (IsSuper) {
- Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
- Name += "objc_msgSendSuper2_stret_fixup";
- } else {
- Fn = ObjCTypes.getMessageSendStretFixupFn();
- Name += "objc_msgSend_stret_fixup";
- }
+ if (IsSuper) {
+ Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
+ Name += "objc_msgSendSuper2_stret_fixup";
+ } else {
+ Fn = ObjCTypes.getMessageSendStretFixupFn();
+ Name += "objc_msgSend_stret_fixup";
+ }
} else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) {
Fn = ObjCTypes.getMessageSendFpretFixupFn();
Name += "objc_msgSend_fpret_fixup";
} else {
-#if 0
-// unlike what is documented. gcc never generates this API!!
- if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
- Fn = ObjCTypes.getMessageSendIdFixupFn();
- Name += "objc_msgSendId_fixup";
- } else
-#endif
- if (IsSuper) {
- Fn = ObjCTypes.getMessageSendSuper2FixupFn();
- Name += "objc_msgSendSuper2_fixup";
- } else {
- Fn = ObjCTypes.getMessageSendFixupFn();
- Name += "objc_msgSend_fixup";
- }
+ if (IsSuper) {
+ Fn = ObjCTypes.getMessageSendSuper2FixupFn();
+ Name += "objc_msgSendSuper2_fixup";
+ } else {
+ Fn = ObjCTypes.getMessageSendFixupFn();
+ Name += "objc_msgSend_fixup";
+ }
}
assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
Name += '_';
@@ -5647,7 +5912,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
/// objc_assign_global (id src, id *dst)
///
void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
+ llvm::Value *src, llvm::Value *dst,
+ bool threadlocal) {
const llvm::Type * SrcTy = src->getType();
if (!isa<llvm::PointerType>(SrcTy)) {
unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
@@ -5658,11 +5924,28 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
}
src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
- src, dst, "globalassign");
+ if (!threadlocal)
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
+ src, dst, "globalassign");
+ else
+ CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
+ src, dst, "threadlocalassign");
return;
}
+namespace {
+ struct CallSyncExit : EHScopeStack::Cleanup {
+ llvm::Value *SyncExitFn;
+ llvm::Value *SyncArg;
+ CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
+ : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
+ CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
+ }
+ };
+}
+
void
CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtSynchronizedStmt &S) {
@@ -5675,12 +5958,9 @@ CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
->setDoesNotThrow();
// Register an all-paths cleanup to release the lock.
- {
- CodeGenFunction::CleanupBlock ReleaseScope(CGF, NormalAndEHCleanup);
-
- CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
- ->setDoesNotThrow();
- }
+ CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup,
+ ObjCTypes.getSyncExitFn(),
+ SyncArg);
// Emit the body of the statement.
CGF.EmitStmt(S.getSynchBody());
@@ -5697,7 +5977,7 @@ namespace {
llvm::Value *TypeInfo;
};
- struct CallObjCEndCatch : EHScopeStack::LazyCleanup {
+ struct CallObjCEndCatch : EHScopeStack::Cleanup {
CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
MightThrow(MightThrow), Fn(Fn) {}
bool MightThrow;
@@ -5714,6 +5994,31 @@ namespace {
};
}
+llvm::Constant *
+CGObjCNonFragileABIMac::GetEHType(QualType T) {
+ // There's a particular fixed type info for 'id'.
+ if (T->isObjCIdType() ||
+ T->isObjCQualifiedIdType()) {
+ llvm::Constant *IDEHType =
+ CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
+ if (!IDEHType)
+ IDEHType =
+ new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
+ false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0, "OBJC_EHTYPE_id");
+ return IDEHType;
+ }
+
+ // All other types should be Objective-C interface pointer types.
+ const ObjCObjectPointerType *PT =
+ T->getAs<ObjCObjectPointerType>();
+ assert(PT && "Invalid @catch type.");
+ const ObjCInterfaceType *IT = PT->getInterfaceType();
+ assert(IT && "Invalid @catch type.");
+ return GetInterfaceEHType(IT->getDecl(), false);
+}
+
void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtTryStmt &S) {
// Jump destination for falling out of catch bodies.
@@ -5749,27 +6054,7 @@ void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
break;
}
- // There's a particular fixed type info for 'id'.
- if (CatchDecl->getType()->isObjCIdType() ||
- CatchDecl->getType()->isObjCQualifiedIdType()) {
- llvm::Value *IDEHType =
- CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
- if (!IDEHType)
- IDEHType =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0, "OBJC_EHTYPE_id");
- Handler.TypeInfo = IDEHType;
- } else {
- // All other types should be Objective-C interface pointer types.
- const ObjCObjectPointerType *PT =
- CatchDecl->getType()->getAs<ObjCObjectPointerType>();
- assert(PT && "Invalid @catch type.");
- const ObjCInterfaceType *IT = PT->getInterfaceType();
- assert(IT && "Invalid @catch type.");
- Handler.TypeInfo = GetInterfaceEHType(IT->getDecl(), false);
- }
+ Handler.TypeInfo = GetEHType(CatchDecl->getType());
}
EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
@@ -5802,9 +6087,9 @@ void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
// Add a cleanup to leave the catch.
bool EndCatchMightThrow = (Handler.Variable == 0);
- CGF.EHStack.pushLazyCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
- EndCatchMightThrow,
- ObjCTypes.getObjCEndCatchFn());
+ CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
+ EndCatchMightThrow,
+ ObjCTypes.getObjCEndCatchFn());
// Bind the catch parameter if it exists.
if (const VarDecl *CatchParam = Handler.Variable) {
@@ -5832,8 +6117,8 @@ void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
if (S.getFinallyStmt())
CGF.ExitFinallyBlock(FinallyInfo);
- if (Cont.Block)
- CGF.EmitBlock(Cont.Block);
+ if (Cont.isValid())
+ CGF.EmitBlock(Cont.getBlock());
}
/// EmitThrowStmt - Generate code for a throw statement.
@@ -5868,7 +6153,7 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
CGF.Builder.ClearInsertionPoint();
}
-llvm::Value *
+llvm::Constant *
CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
bool ForDefinition) {
llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h
index eb79f09de13f..584760f6f343 100644
--- a/lib/CodeGen/CGObjCRuntime.h
+++ b/lib/CodeGen/CGObjCRuntime.h
@@ -52,6 +52,7 @@ namespace CodeGen {
class Selector;
class ObjCIvarDecl;
class ObjCStringLiteral;
+ class BlockDeclRefExpr;
namespace CodeGen {
class CodeGenModule;
@@ -103,6 +104,12 @@ public:
virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
const ObjCMethodDecl *Method) = 0;
+ /// Get the type constant to catch for the given ObjC pointer type.
+ /// This is used externally to implement catching ObjC types in C++.
+ /// Runtimes which don't support this should add the appropriate
+ /// error to Sema.
+ virtual llvm::Constant *GetEHType(QualType T) = 0;
+
/// Generate a constant string object.
virtual llvm::Constant *GenerateConstantString(const StringLiteral *) = 0;
@@ -192,7 +199,8 @@ public:
virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest) = 0;
virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest) = 0;
+ llvm::Value *src, llvm::Value *dest,
+ bool threadlocal=false) = 0;
virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
llvm::Value *src, llvm::Value *dest,
llvm::Value *ivarOffset) = 0;
@@ -211,6 +219,9 @@ public:
llvm::Value *DestPtr,
llvm::Value *SrcPtr,
llvm::Value *Size) = 0;
+ virtual llvm::Constant *GCBlockLayout(CodeGen::CodeGenFunction &CGF,
+ const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &) = 0;
+
};
/// Creates an instance of an Objective-C runtime class.
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 1cca97702ddd..60df613f65e8 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -11,9 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/AST/Type.h"
-#include "clang/AST/RecordLayout.h"
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
using namespace clang;
using namespace CodeGen;
@@ -45,7 +48,11 @@ class RTTIBuilder {
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
/// for pointer types.
- void BuildPointerTypeInfo(const PointerType *Ty);
+ void BuildPointerTypeInfo(QualType PointeeTy);
+
+ /// BuildObjCObjectTypeInfo - Build the appropriate kind of
+ /// type_info for an object type.
+ void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
/// struct, used for member pointer types.
@@ -59,7 +66,7 @@ public:
llvm::Constant *BuildName(QualType Ty, bool Hidden,
llvm::GlobalVariable::LinkageTypes Linkage) {
llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXRTTIName(Ty, OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, OutName);
llvm::StringRef Name = OutName.str();
llvm::GlobalVariable *OGV = CGM.getModule().getNamedGlobal(Name);
@@ -158,7 +165,7 @@ public:
llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
// Mangle the RTTI name.
llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName);
llvm::StringRef Name = OutName.str();
// Look for an existing global.
@@ -244,11 +251,9 @@ static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
return TypeInfoIsInStandardLibrary(BuiltinTy);
}
-/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
-/// the given type exists somewhere else, and that we should not emit the type
-/// information in this translation unit.
-static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
- QualType Ty) {
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
// Type info for builtin types is defined in the standard library.
if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
return TypeInfoIsInStandardLibrary(BuiltinTy);
@@ -258,6 +263,15 @@ static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
return TypeInfoIsInStandardLibrary(PointerTy);
+ return false;
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the type
+/// information in this translation unit. Assumes that it is not a
+/// standard-library type.
+static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
+ QualType Ty) {
// If RTTI is disabled, don't consider key functions.
if (!Context.getLangOptions().RTTI) return false;
@@ -270,7 +284,7 @@ static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context,
return false;
// Get the key function.
- const CXXMethodDecl *KeyFunction = RD->getASTContext().getKeyFunction(RD);
+ const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD);
if (KeyFunction && !KeyFunction->hasBody()) {
// The class has a key function, but it is not defined in this translation
// unit, so we should use the external descriptor for it.
@@ -383,21 +397,45 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
}
void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
- const char *VTableName;
+ // abi::__class_type_info.
+ static const char * const ClassTypeInfo =
+ "_ZTVN10__cxxabiv117__class_type_infoE";
+ // abi::__si_class_type_info.
+ static const char * const SIClassTypeInfo =
+ "_ZTVN10__cxxabiv120__si_class_type_infoE";
+ // abi::__vmi_class_type_info.
+ static const char * const VMIClassTypeInfo =
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+
+ const char *VTableName = 0;
switch (Ty->getTypeClass()) {
- default: assert(0 && "Unhandled type!");
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Non-canonical and dependent types shouldn't get here");
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ assert(false && "References shouldn't get here");
case Type::Builtin:
- // GCC treats vector types as fundamental types.
+ // GCC treats vector and complex types as fundamental types.
case Type::Vector:
case Type::ExtVector:
+ case Type::Complex:
+ // FIXME: GCC treats block pointers as fundamental types?!
+ case Type::BlockPointer:
// abi::__fundamental_type_info.
VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
break;
case Type::ConstantArray:
case Type::IncompleteArray:
+ case Type::VariableArray:
// abi::__array_type_info.
VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
break;
@@ -412,25 +450,44 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
// abi::__enum_type_info.
VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
break;
-
+
case Type::Record: {
const CXXRecordDecl *RD =
cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
if (!RD->hasDefinition() || !RD->getNumBases()) {
- // abi::__class_type_info.
- VTableName = "_ZTVN10__cxxabiv117__class_type_infoE";
+ VTableName = ClassTypeInfo;
} else if (CanUseSingleInheritance(RD)) {
- // abi::__si_class_type_info.
- VTableName = "_ZTVN10__cxxabiv120__si_class_type_infoE";
+ VTableName = SIClassTypeInfo;
} else {
- // abi::__vmi_class_type_info.
- VTableName = "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+ VTableName = VMIClassTypeInfo;
}
break;
}
+ case Type::ObjCObject:
+ // Ignore protocol qualifiers.
+ Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(Ty)) {
+ VTableName = ClassTypeInfo;
+ break;
+ }
+
+ assert(isa<ObjCInterfaceType>(Ty));
+ // Fall through.
+
+ case Type::ObjCInterface:
+ if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = ClassTypeInfo;
+ }
+ break;
+
+ case Type::ObjCObjectPointer:
case Type::Pointer:
// abi::__pointer_type_info.
VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
@@ -456,45 +513,64 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
Fields.push_back(VTable);
}
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty,
- bool Force) {
+llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
// We want to operate on the canonical type.
Ty = CGM.getContext().getCanonicalType(Ty);
// Check if we've already emitted an RTTI descriptor for this type.
llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXRTTI(Ty, OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName);
llvm::StringRef Name = OutName.str();
llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
if (OldGV && !OldGV->isDeclaration())
return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy);
-
+
// Check if there is already an external RTTI descriptor for this type.
- if (!Force && ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty))
+ bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
+ if (!Force &&
+ (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty)))
return GetAddrOfExternalRTTIDescriptor(Ty);
- llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(Ty);
+ // Emit the standard library with external linkage.
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ if (IsStdLib)
+ Linkage = llvm::GlobalValue::ExternalLinkage;
+ else
+ Linkage = getTypeInfoLinkage(Ty);
// Add the vtable pointer.
BuildVTablePointer(cast<Type>(Ty));
// And the name.
Fields.push_back(BuildName(Ty, DecideHidden(Ty), Linkage));
-
+
switch (Ty->getTypeClass()) {
- default: assert(false && "Unhandled type class!");
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ assert(false && "Non-canonical and dependent types shouldn't get here");
// GCC treats vector types as fundamental types.
case Type::Builtin:
case Type::Vector:
case Type::ExtVector:
+ case Type::Complex:
+ case Type::BlockPointer:
// Itanium C++ ABI 2.9.5p4:
// abi::__fundamental_type_info adds no data members to std::type_info.
break;
-
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ assert(false && "References shouldn't get here");
+
case Type::ConstantArray:
case Type::IncompleteArray:
+ case Type::VariableArray:
// Itanium C++ ABI 2.9.5p5:
// abi::__array_type_info adds no data members to std::type_info.
break;
@@ -525,11 +601,20 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty,
break;
}
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
+ break;
+
+ case Type::ObjCObjectPointer:
+ BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ break;
case Type::Pointer:
- BuildPointerTypeInfo(cast<PointerType>(Ty));
+ BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
break;
-
+
case Type::MemberPointer:
BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
break;
@@ -551,7 +636,18 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty,
OldGV->replaceAllUsesWith(NewPtr);
OldGV->eraseFromParent();
}
-
+
+ // GCC only relies on the uniqueness of the type names, not the
+ // type_infos themselves, so we can emit these as hidden symbols.
+ // But don't do this if we're worried about strict visibility
+ // compatibility.
+ if (const RecordType *RT = dyn_cast<RecordType>(Ty))
+ CGM.setTypeVisibility(GV, cast<CXXRecordDecl>(RT->getDecl()),
+ /*ForRTTI*/ true);
+ else if (CGM.getCodeGenOpts().HiddenWeakVTables &&
+ Linkage == llvm::GlobalValue::WeakODRLinkage)
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+
return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy);
}
@@ -570,6 +666,30 @@ static unsigned ComputeQualifierFlags(Qualifiers Quals) {
return Flags;
}
+/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
+/// for the given Objective-C object type.
+void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
+ // Drop qualifiers.
+ const Type *T = OT->getBaseType().getTypePtr();
+ assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
+
+ // The builtin types are abi::__class_type_infos and don't require
+ // extra fields.
+ if (isa<BuiltinType>(T)) return;
+
+ ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
+ ObjCInterfaceDecl *Super = Class->getSuperClass();
+
+ // Root classes are also __class_type_info.
+ if (!Super) return;
+
+ QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
+
+ // Everything else is single inheritance.
+ llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
+ Fields.push_back(BaseTypeInfo);
+}
+
/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
@@ -677,7 +797,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// direct proper base. Each description is of the type:
//
// struct abi::__base_class_type_info {
- // public:
+ // public:
// const __class_type_info *__base_type;
// long __offset_flags;
//
@@ -725,9 +845,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
/// used for pointer types.
-void RTTIBuilder::BuildPointerTypeInfo(const PointerType *Ty) {
- QualType PointeeTy = Ty->getPointeeType();
-
+void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
Qualifiers Quals;
QualType UnqualifiedPointeeTy =
CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
diff --git a/lib/CodeGen/CGRecordLayout.h b/lib/CodeGen/CGRecordLayout.h
index e95591e5cc01..9b4e9f86c6da 100644
--- a/lib/CodeGen/CGRecordLayout.h
+++ b/lib/CodeGen/CGRecordLayout.h
@@ -144,6 +144,21 @@ public:
void print(llvm::raw_ostream &OS) const;
void dump() const;
+
+ /// \brief Given a bit-field decl, build an appropriate helper object for
+ /// accessing that field (which is expected to have the given offset and
+ /// size).
+ static CGBitFieldInfo MakeInfo(class CodeGenTypes &Types, const FieldDecl *FD,
+ uint64_t FieldOffset, uint64_t FieldSize);
+
+ /// \brief Given a bit-field decl, build an appropriate helper object for
+ /// accessing that field (which is expected to have the given offset and
+ /// size). The field decl should be known to be contained within a type of at
+ /// least the given size and with the given alignment.
+ static CGBitFieldInfo MakeInfo(CodeGenTypes &Types, const FieldDecl *FD,
+ uint64_t FieldOffset, uint64_t FieldSize,
+ uint64_t ContainingTypeSizeInBits,
+ unsigned ContainingTypeAlign);
};
/// CGRecordLayout - This class handles struct and union layout info while
@@ -174,20 +189,21 @@ private:
/// Whether one of the fields in this record layout is a pointer to data
/// member, or a struct that contains pointer to data member.
- bool ContainsPointerToDataMember : 1;
+ bool IsZeroInitializable : 1;
public:
- CGRecordLayout(const llvm::Type *T, bool ContainsPointerToDataMember)
- : LLVMType(T), ContainsPointerToDataMember(ContainsPointerToDataMember) {}
+ CGRecordLayout(const llvm::Type *T, bool IsZeroInitializable)
+ : LLVMType(T), IsZeroInitializable(IsZeroInitializable) {}
/// \brief Return the LLVM type associated with this record.
const llvm::Type *getLLVMType() const {
return LLVMType;
}
- /// \brief Check whether this struct contains pointers to data members.
- bool containsPointerToDataMember() const {
- return ContainsPointerToDataMember;
+ /// \brief Check whether this struct can be C++ zero-initialized
+ /// with a zeroinitializer.
+ bool isZeroInitializable() const {
+ return IsZeroInitializable;
}
/// \brief Return llvm::StructType element number that corresponds to the
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 9f1687577c3e..77a319fa3ab1 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "CodeGenTypes.h"
+#include "CGCXXABI.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Type.h"
#include "llvm/Support/Debug.h"
@@ -45,10 +46,9 @@ public:
typedef std::pair<const CXXRecordDecl *, unsigned> LLVMBaseInfo;
llvm::SmallVector<LLVMBaseInfo, 16> LLVMNonVirtualBases;
- /// ContainsPointerToDataMember - Whether one of the fields in this record
- /// layout is a pointer to data member, or a struct that contains pointer to
- /// data member.
- bool ContainsPointerToDataMember;
+ /// IsZeroInitializable - Whether this struct can be C++
+ /// zero-initialized with an LLVM zeroinitializer.
+ bool IsZeroInitializable;
/// Packed - Whether the resulting LLVM struct will be packed or not.
bool Packed;
@@ -115,14 +115,14 @@ private:
unsigned getTypeAlignment(const llvm::Type *Ty) const;
- /// CheckForPointerToDataMember - Check if the given type contains a pointer
+ /// CheckZeroInitializable - Check if the given type contains a pointer
/// to data member.
- void CheckForPointerToDataMember(QualType T);
- void CheckForPointerToDataMember(const CXXRecordDecl *RD);
+ void CheckZeroInitializable(QualType T);
+ void CheckZeroInitializable(const CXXRecordDecl *RD);
public:
CGRecordLayoutBuilder(CodeGenTypes &Types)
- : ContainsPointerToDataMember(false), Packed(false), Types(Types),
+ : IsZeroInitializable(true), Packed(false), Types(Types),
Alignment(0), AlignmentAsLLVMStruct(1),
BitsAvailableInLastField(0), NextFieldOffsetInBytes(0) { }
@@ -157,15 +157,12 @@ void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
LayoutFields(D);
}
-static CGBitFieldInfo ComputeBitFieldInfo(CodeGenTypes &Types,
- const FieldDecl *FD,
- uint64_t FieldOffset,
- uint64_t FieldSize) {
- const RecordDecl *RD = FD->getParent();
- const ASTRecordLayout &RL = Types.getContext().getASTRecordLayout(RD);
- uint64_t ContainingTypeSizeInBits = RL.getSize();
- unsigned ContainingTypeAlign = RL.getAlignment();
-
+CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
+ const FieldDecl *FD,
+ uint64_t FieldOffset,
+ uint64_t FieldSize,
+ uint64_t ContainingTypeSizeInBits,
+ unsigned ContainingTypeAlign) {
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(FD->getType());
uint64_t TypeSizeInBytes = Types.getTargetData().getTypeAllocSize(Ty);
uint64_t TypeSizeInBits = TypeSizeInBytes * 8;
@@ -255,6 +252,19 @@ static CGBitFieldInfo ComputeBitFieldInfo(CodeGenTypes &Types,
return CGBitFieldInfo(FieldSize, NumComponents, Components, IsSigned);
}
+CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
+ const FieldDecl *FD,
+ uint64_t FieldOffset,
+ uint64_t FieldSize) {
+ const RecordDecl *RD = FD->getParent();
+ const ASTRecordLayout &RL = Types.getContext().getASTRecordLayout(RD);
+ uint64_t ContainingTypeSizeInBits = RL.getSize();
+ unsigned ContainingTypeAlign = RL.getAlignment();
+
+ return MakeInfo(Types, FD, FieldOffset, FieldSize, ContainingTypeSizeInBits,
+ ContainingTypeAlign);
+}
+
void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
uint64_t FieldOffset) {
uint64_t FieldSize =
@@ -287,7 +297,8 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
// Add the bit field info.
LLVMBitFields.push_back(
- LLVMBitFieldInfo(D, ComputeBitFieldInfo(Types, D, FieldOffset, FieldSize)));
+ LLVMBitFieldInfo(D, CGBitFieldInfo::MakeInfo(Types, D, FieldOffset,
+ FieldSize)));
AppendBytes(NumBytesToAppend);
@@ -311,8 +322,7 @@ bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
return true;
}
- // Check if we have a pointer to data member in this field.
- CheckForPointerToDataMember(D->getType());
+ CheckZeroInitializable(D->getType());
assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
uint64_t FieldOffsetInBytes = FieldOffset / 8;
@@ -380,7 +390,8 @@ CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field,
// Add the bit field info.
LLVMBitFields.push_back(
- LLVMBitFieldInfo(Field, ComputeBitFieldInfo(Types, Field, 0, FieldSize)));
+ LLVMBitFieldInfo(Field, CGBitFieldInfo::MakeInfo(Types, Field,
+ 0, FieldSize)));
return FieldTy;
}
@@ -458,7 +469,7 @@ void CGRecordLayoutBuilder::LayoutNonVirtualBase(const CXXRecordDecl *BaseDecl,
return;
}
- CheckForPointerToDataMember(BaseDecl);
+ CheckZeroInitializable(BaseDecl);
// FIXME: Actually use a better type than [sizeof(BaseDecl) x i8] when we can.
AppendPadding(BaseOffset / 8, 1);
@@ -603,9 +614,9 @@ unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {
return Types.getTargetData().getABITypeAlignment(Ty);
}
-void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) {
+void CGRecordLayoutBuilder::CheckZeroInitializable(QualType T) {
// This record already contains a member pointer.
- if (ContainsPointerToDataMember)
+ if (!IsZeroInitializable)
return;
// Can only have member pointers if we're compiling C++.
@@ -615,21 +626,17 @@ void CGRecordLayoutBuilder::CheckForPointerToDataMember(QualType T) {
T = Types.getContext().getBaseElementType(T);
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>()) {
- if (!MPT->getPointeeType()->isFunctionType()) {
- // We have a pointer to data member.
- ContainsPointerToDataMember = true;
- }
+ if (!Types.getCXXABI().isZeroInitializable(MPT))
+ IsZeroInitializable = false;
} else if (const RecordType *RT = T->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-
- return CheckForPointerToDataMember(RD);
+ CheckZeroInitializable(RD);
}
}
-void
-CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) {
+void CGRecordLayoutBuilder::CheckZeroInitializable(const CXXRecordDecl *RD) {
// This record already contains a member pointer.
- if (ContainsPointerToDataMember)
+ if (!IsZeroInitializable)
return;
// FIXME: It would be better if there was a way to explicitly compute the
@@ -638,8 +645,8 @@ CGRecordLayoutBuilder::CheckForPointerToDataMember(const CXXRecordDecl *RD) {
const CGRecordLayout &Layout = Types.getCGRecordLayout(RD);
- if (Layout.containsPointerToDataMember())
- ContainsPointerToDataMember = true;
+ if (!Layout.isZeroInitializable())
+ IsZeroInitializable = false;
}
CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
@@ -652,7 +659,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
Builder.Packed);
CGRecordLayout *RL =
- new CGRecordLayout(Ty, Builder.ContainsPointerToDataMember);
+ new CGRecordLayout(Ty, Builder.IsZeroInitializable);
// Add all the non-virtual base field numbers.
RL->NonVirtualBaseFields.insert(Builder.LLVMNonVirtualBases.begin(),
@@ -723,7 +730,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) {
void CGRecordLayout::print(llvm::raw_ostream &OS) const {
OS << "<CGRecordLayout\n";
OS << " LLVMType:" << *LLVMType << "\n";
- OS << " ContainsPointerToDataMember:" << ContainsPointerToDataMember << "\n";
+ OS << " IsZeroInitializable:" << IsZeroInitializable << "\n";
OS << " BitFields:[\n";
// Print bit-field infos in declaration order.
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp
index b72725edca7e..16145f766af2 100644
--- a/lib/CodeGen/CGStmt.cpp
+++ b/lib/CodeGen/CGStmt.cpp
@@ -34,7 +34,8 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) {
DI->setLocation(S->getLocEnd());
else
DI->setLocation(S->getLocStart());
- DI->EmitStopPoint(CurFn, Builder);
+ DI->UpdateLineDirectiveRegion(Builder);
+ DI->EmitStopPoint(Builder);
}
}
@@ -152,7 +153,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
CGDebugInfo *DI = getDebugInfo();
if (DI) {
DI->setLocation(S.getLBracLoc());
- DI->EmitRegionStart(CurFn, Builder);
+ DI->EmitRegionStart(Builder);
}
// Keep track of the current cleanup stack depth.
@@ -164,7 +165,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
if (DI) {
DI->setLocation(S.getRBracLoc());
- DI->EmitRegionEnd(CurFn, Builder);
+ DI->EmitRegionEnd(Builder);
}
RValue RV;
@@ -247,32 +248,35 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
CodeGenFunction::JumpDest
CodeGenFunction::getJumpDestForLabel(const LabelStmt *S) {
JumpDest &Dest = LabelMap[S];
- if (Dest.Block) return Dest;
+ if (Dest.isValid()) return Dest;
// Create, but don't insert, the new block.
- Dest.Block = createBasicBlock(S->getName());
- Dest.ScopeDepth = EHScopeStack::stable_iterator::invalid();
+ Dest = JumpDest(createBasicBlock(S->getName()),
+ EHScopeStack::stable_iterator::invalid(),
+ NextCleanupDestIndex++);
return Dest;
}
void CodeGenFunction::EmitLabel(const LabelStmt &S) {
JumpDest &Dest = LabelMap[&S];
- // If we didn't needed a forward reference to this label, just go
+ // If we didn't need a forward reference to this label, just go
// ahead and create a destination at the current scope.
- if (!Dest.Block) {
+ if (!Dest.isValid()) {
Dest = getJumpDestInCurrentScope(S.getName());
// Otherwise, we need to give this label a target depth and remove
// it from the branch-fixups list.
} else {
- assert(!Dest.ScopeDepth.isValid() && "already emitted label!");
- Dest.ScopeDepth = EHStack.stable_begin();
+ assert(!Dest.getScopeDepth().isValid() && "already emitted label!");
+ Dest = JumpDest(Dest.getBlock(),
+ EHStack.stable_begin(),
+ Dest.getDestIndex());
- EHStack.resolveBranchFixups(Dest.Block);
+ ResolveBranchFixups(Dest.getBlock());
}
- EmitBlock(Dest.Block);
+ EmitBlock(Dest.getBlock());
}
@@ -372,7 +376,7 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
// Emit the header for the loop, which will also become
// the continue target.
JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
- EmitBlock(LoopHeader.Block);
+ EmitBlock(LoopHeader.getBlock());
// Create an exit block for when the condition fails, which will
// also become the break target.
@@ -408,13 +412,13 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
// As long as the condition is true, go to the loop body.
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
if (EmitBoolCondBranch) {
- llvm::BasicBlock *ExitBlock = LoopExit.Block;
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (ConditionScope.requiresCleanups())
ExitBlock = createBasicBlock("while.exit");
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
- if (ExitBlock != LoopExit.Block) {
+ if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
@@ -434,15 +438,15 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
ConditionScope.ForceCleanup();
// Branch to the loop header again.
- EmitBranch(LoopHeader.Block);
+ EmitBranch(LoopHeader.getBlock());
// Emit the exit block.
- EmitBlock(LoopExit.Block, true);
+ EmitBlock(LoopExit.getBlock(), true);
// The LoopHeader typically is just a branch if we skipped emitting
// a branch, try to erase it.
if (!EmitBoolCondBranch)
- SimplifyForwardingBlocks(LoopHeader.Block);
+ SimplifyForwardingBlocks(LoopHeader.getBlock());
}
void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
@@ -462,7 +466,7 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
BreakContinueStack.pop_back();
- EmitBlock(LoopCond.Block);
+ EmitBlock(LoopCond.getBlock());
// C99 6.8.5.2: "The evaluation of the controlling expression takes place
// after each execution of the loop body."
@@ -481,15 +485,15 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch)
- Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.Block);
+ Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock());
// Emit the exit block.
- EmitBlock(LoopExit.Block);
+ EmitBlock(LoopExit.getBlock());
// The DoCond block typically is just a branch if we skipped
// emitting a branch, try to erase it.
if (!EmitBoolCondBranch)
- SimplifyForwardingBlocks(LoopCond.Block);
+ SimplifyForwardingBlocks(LoopCond.getBlock());
}
void CodeGenFunction::EmitForStmt(const ForStmt &S) {
@@ -497,6 +501,12 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
RunCleanupsScope ForScope(*this);
+ CGDebugInfo *DI = getDebugInfo();
+ if (DI) {
+ DI->setLocation(S.getSourceRange().getBegin());
+ DI->EmitRegionStart(Builder);
+ }
+
// Evaluate the first part before the loop.
if (S.getInit())
EmitStmt(S.getInit());
@@ -505,7 +515,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// If there's an increment, the continue scope will be overwritten
// later.
JumpDest Continue = getJumpDestInCurrentScope("for.cond");
- llvm::BasicBlock *CondBlock = Continue.Block;
+ llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
// Create a cleanup scope for the condition variable cleanups.
@@ -515,7 +525,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
if (S.getCond()) {
// If the for statement has a condition scope, emit the local variable
// declaration.
- llvm::BasicBlock *ExitBlock = LoopExit.Block;
+ llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
if (S.getConditionVariable()) {
EmitLocalBlockVarDecl(*S.getConditionVariable());
}
@@ -533,7 +543,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
BoolCondVal = EvaluateExprAsBool(S.getCond());
Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock);
- if (ExitBlock != LoopExit.Block) {
+ if (ExitBlock != LoopExit.getBlock()) {
EmitBlock(ExitBlock);
EmitBranchThroughCleanup(LoopExit);
}
@@ -554,12 +564,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// Store the blocks to use for break and continue.
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
- CGDebugInfo *DI = getDebugInfo();
- if (DI) {
- DI->setLocation(S.getSourceRange().getBegin());
- DI->EmitRegionStart(CurFn, Builder);
- }
-
{
// Create a separate cleanup scope for the body, in case it is not
// a compound statement.
@@ -569,7 +573,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// If there is an increment, emit it next.
if (S.getInc()) {
- EmitBlock(Continue.Block);
+ EmitBlock(Continue.getBlock());
EmitStmt(S.getInc());
}
@@ -582,11 +586,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
if (DI) {
DI->setLocation(S.getSourceRange().getEnd());
- DI->EmitRegionEnd(CurFn, Builder);
+ DI->EmitRegionEnd(Builder);
}
// Emit the fall-through block.
- EmitBlock(LoopExit.Block, true);
+ EmitBlock(LoopExit.getBlock(), true);
}
void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
@@ -839,13 +843,15 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
// Otherwise, just forward the default block to the switch end.
} else {
- DefaultBlock->replaceAllUsesWith(SwitchExit.Block);
+ DefaultBlock->replaceAllUsesWith(SwitchExit.getBlock());
delete DefaultBlock;
}
}
+ ConditionScope.ForceCleanup();
+
// Emit continuation.
- EmitBlock(SwitchExit.Block, true);
+ EmitBlock(SwitchExit.getBlock(), true);
SwitchInsn = SavedSwitchInsn;
CaseRangeBlock = SavedCRBlock;
@@ -855,16 +861,24 @@ static std::string
SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
llvm::SmallVectorImpl<TargetInfo::ConstraintInfo> *OutCons=0) {
std::string Result;
+ std::string tmp;
while (*Constraint) {
switch (*Constraint) {
default:
- Result += Target.convertConstraint(*Constraint);
+ tmp = Target.convertConstraint(*Constraint);
+ if (Result.find(tmp) == std::string::npos) // Combine unique constraints
+ Result += tmp;
break;
// Ignore these
case '*':
case '?':
case '!':
+ case '=': // Will see this and the following in mult-alt constraints.
+ case '+':
+ break;
+ case ',': // FIXME - Until the back-end properly supports
+ return Result; // multiple alternative constraints, we stop here.
break;
case 'g':
Result += "imr";
@@ -888,40 +902,50 @@ SimplifyConstraint(const char *Constraint, const TargetInfo &Target,
return Result;
}
-llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S,
- const TargetInfo::ConstraintInfo &Info,
- const Expr *InputExpr,
- std::string &ConstraintStr) {
+llvm::Value*
+CodeGenFunction::EmitAsmInputLValue(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ LValue InputValue, QualType InputType,
+ std::string &ConstraintStr) {
llvm::Value *Arg;
if (Info.allowsRegister() || !Info.allowsMemory()) {
- if (!CodeGenFunction::hasAggregateLLVMType(InputExpr->getType())) {
- Arg = EmitScalarExpr(InputExpr);
+ if (!CodeGenFunction::hasAggregateLLVMType(InputType)) {
+ Arg = EmitLoadOfLValue(InputValue, InputType).getScalarVal();
} else {
- InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
- LValue Dest = EmitLValue(InputExpr);
-
- const llvm::Type *Ty = ConvertType(InputExpr->getType());
+ const llvm::Type *Ty = ConvertType(InputType);
uint64_t Size = CGM.getTargetData().getTypeSizeInBits(Ty);
if (Size <= 64 && llvm::isPowerOf2_64(Size)) {
Ty = llvm::IntegerType::get(VMContext, Size);
Ty = llvm::PointerType::getUnqual(Ty);
- Arg = Builder.CreateLoad(Builder.CreateBitCast(Dest.getAddress(), Ty));
+ Arg = Builder.CreateLoad(Builder.CreateBitCast(InputValue.getAddress(),
+ Ty));
} else {
- Arg = Dest.getAddress();
+ Arg = InputValue.getAddress();
ConstraintStr += '*';
}
}
} else {
- InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
- LValue Dest = EmitLValue(InputExpr);
- Arg = Dest.getAddress();
+ Arg = InputValue.getAddress();
ConstraintStr += '*';
}
return Arg;
}
+llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ const Expr *InputExpr,
+ std::string &ConstraintStr) {
+ if (Info.allowsRegister() || !Info.allowsMemory())
+ if (!CodeGenFunction::hasAggregateLLVMType(InputExpr->getType()))
+ return EmitScalarExpr(InputExpr);
+
+ InputExpr = InputExpr->IgnoreParenNoopCasts(getContext());
+ LValue Dest = EmitLValue(InputExpr);
+ return EmitAsmInputLValue(S, Info, Dest, InputExpr->getType(), ConstraintStr);
+}
+
void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
// Analyze the asm string to decompose it into its pieces. We know that Sema
// has already done this, so it is guaranteed to be successful.
@@ -1031,7 +1055,8 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
InOutConstraints += ',';
const Expr *InputExpr = S.getOutputExpr(i);
- llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, InOutConstraints);
+ llvm::Value *Arg = EmitAsmInputLValue(S, Info, Dest, InputExpr->getType(),
+ InOutConstraints);
if (Info.allowsRegister())
InOutConstraints += llvm::utostr(i);
diff --git a/lib/CodeGen/CGTemporaries.cpp b/lib/CodeGen/CGTemporaries.cpp
index fd7c616b1162..dfb8dc63c5c5 100644
--- a/lib/CodeGen/CGTemporaries.cpp
+++ b/lib/CodeGen/CGTemporaries.cpp
@@ -15,34 +15,43 @@
using namespace clang;
using namespace CodeGen;
-static void EmitTemporaryCleanup(CodeGenFunction &CGF,
- const CXXTemporary *Temporary,
- llvm::Value *Addr,
- llvm::Value *CondPtr) {
- llvm::BasicBlock *CondEnd = 0;
+namespace {
+ struct DestroyTemporary : EHScopeStack::Cleanup {
+ const CXXTemporary *Temporary;
+ llvm::Value *Addr;
+ llvm::Value *CondPtr;
+
+ DestroyTemporary(const CXXTemporary *Temporary, llvm::Value *Addr,
+ llvm::Value *CondPtr)
+ : Temporary(Temporary), Addr(Addr), CondPtr(CondPtr) {}
+
+ void Emit(CodeGenFunction &CGF, bool IsForEH) {
+ llvm::BasicBlock *CondEnd = 0;
- // If this is a conditional temporary, we need to check the condition
- // boolean and only call the destructor if it's true.
- if (CondPtr) {
- llvm::BasicBlock *CondBlock = CGF.createBasicBlock("temp.cond-dtor.call");
- CondEnd = CGF.createBasicBlock("temp.cond-dtor.cont");
+ // If this is a conditional temporary, we need to check the condition
+ // boolean and only call the destructor if it's true.
+ if (CondPtr) {
+ llvm::BasicBlock *CondBlock =
+ CGF.createBasicBlock("temp.cond-dtor.call");
+ CondEnd = CGF.createBasicBlock("temp.cond-dtor.cont");
- llvm::Value *Cond = CGF.Builder.CreateLoad(CondPtr);
- CGF.Builder.CreateCondBr(Cond, CondBlock, CondEnd);
- CGF.EmitBlock(CondBlock);
- }
+ llvm::Value *Cond = CGF.Builder.CreateLoad(CondPtr);
+ CGF.Builder.CreateCondBr(Cond, CondBlock, CondEnd);
+ CGF.EmitBlock(CondBlock);
+ }
- CGF.EmitCXXDestructorCall(Temporary->getDestructor(),
- Dtor_Complete, /*ForVirtualBase=*/false,
- Addr);
+ CGF.EmitCXXDestructorCall(Temporary->getDestructor(),
+ Dtor_Complete, /*ForVirtualBase=*/false,
+ Addr);
- if (CondPtr) {
- // Reset the condition to false.
- CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()),
- CondPtr);
- CGF.EmitBlock(CondEnd);
- }
-}
+ if (CondPtr) {
+ // Reset the condition to false.
+ CGF.Builder.CreateStore(CGF.Builder.getFalse(), CondPtr);
+ CGF.EmitBlock(CondEnd);
+ }
+ }
+ };
+}
/// Emits all the code to cause the given temporary to be cleaned up.
void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
@@ -59,16 +68,11 @@ void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary,
InitTempAlloca(CondPtr, llvm::ConstantInt::getFalse(VMContext));
// Now set it to true.
- Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
+ Builder.CreateStore(Builder.getTrue(), CondPtr);
}
- CleanupBlock Cleanup(*this, NormalCleanup);
- EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr);
-
- if (Exceptions) {
- Cleanup.beginEHCleanup();
- EmitTemporaryCleanup(*this, Temporary, Ptr, CondPtr);
- }
+ EHStack.pushCleanup<DestroyTemporary>(NormalAndEHCleanup,
+ Temporary, Ptr, CondPtr);
}
RValue
@@ -76,23 +80,13 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
llvm::Value *AggLoc,
bool IsAggLocVolatile,
bool IsInitializer) {
- RValue RV;
- {
- RunCleanupsScope Scope(*this);
-
- RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
+ RunCleanupsScope Scope(*this);
+ return EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
/*IgnoreResult=*/false, IsInitializer);
- }
- return RV;
}
LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
const CXXExprWithTemporaries *E) {
- LValue LV;
- {
- RunCleanupsScope Scope(*this);
-
- LV = EmitLValue(E->getSubExpr());
- }
- return LV;
+ RunCleanupsScope Scope(*this);
+ return EmitLValue(E->getSubExpr());
}
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 61c74230e118..56acfc84802e 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
#include "clang/AST/RecordLayout.h"
using namespace clang;
using namespace CodeGen;
@@ -373,7 +374,7 @@ CodeGenVTables::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
return 0;
llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXVTT(RD, OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXVTT(RD, OutName);
llvm::StringRef Name = OutName.str();
D1(printf("vtt %s\n", RD->getNameAsCString()));
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index 6abac2609f5f..bed4670f7f95 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -13,8 +13,10 @@
#include "CodeGenModule.h"
#include "CodeGenFunction.h"
+#include "CGCXXABI.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/Compiler.h"
@@ -2408,12 +2410,12 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
// Compute the mangled name.
llvm::SmallString<256> Name;
if (const CXXDestructorDecl* DD = dyn_cast<CXXDestructorDecl>(MD))
- getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(), Thunk.This,
- Name);
+ getCXXABI().getMangleContext().mangleCXXDtorThunk(DD, GD.getDtorType(),
+ Thunk.This, Name);
else
- getMangleContext().mangleThunk(MD, Thunk, Name);
+ getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Name);
- const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(MD);
+ const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
return GetOrCreateLLVMFunction(Name, Ty, GD);
}
@@ -2460,6 +2462,54 @@ static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF,
return CGF.Builder.CreateBitCast(V, Ptr->getType());
}
+static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk, llvm::Function *Fn) {
+ CGM.setGlobalVisibility(Fn, MD);
+
+ if (!CGM.getCodeGenOpts().HiddenWeakVTables)
+ return;
+
+ // If the thunk has weak/linkonce linkage, but the function must be
+ // emitted in every translation unit that references it, then we can
+ // emit its thunks with hidden visibility, since its thunks must be
+ // emitted when the function is.
+
+ // This follows CodeGenModule::setTypeVisibility; see the comments
+ // there for explanation.
+
+ if ((Fn->getLinkage() != llvm::GlobalVariable::LinkOnceODRLinkage &&
+ Fn->getLinkage() != llvm::GlobalVariable::WeakODRLinkage) ||
+ Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
+ return;
+
+ if (MD->hasAttr<VisibilityAttr>())
+ return;
+
+ switch (MD->getTemplateSpecializationKind()) {
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitInstantiationDeclaration:
+ return;
+
+ case TSK_Undeclared:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ if (!CGM.getCodeGenOpts().HiddenWeakTemplateVTables)
+ return;
+ break;
+ }
+
+ // If there's an explicit definition, and that definition is
+ // out-of-line, then we can't assume that all users will have a
+ // definition to emit.
+ const FunctionDecl *Def = 0;
+ if (MD->hasBody(Def) && Def->isOutOfLine())
+ return;
+
+ Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
+}
+
void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
const ThunkInfo &Thunk) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@@ -2473,13 +2523,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
// CodeGenFunction::GenerateCode.
// Create the implicit 'this' parameter declaration.
- CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
- MD->getLocation(),
- &getContext().Idents.get("this"),
- ThisType);
-
- // Add the 'this' parameter.
- FunctionArgs.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
+ CurGD = GD;
+ CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResultType, FunctionArgs);
// Add the rest of the parameters.
for (FunctionDecl::param_const_iterator I = MD->param_begin(),
@@ -2491,6 +2536,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
StartFunction(GlobalDecl(), ResultType, Fn, FunctionArgs, SourceLocation());
+ CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
+
// Adjust the 'this' pointer if necessary.
llvm::Value *AdjustedThisPtr =
PerformTypeAdjustment(*this, LoadCXXThis(),
@@ -2514,7 +2561,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
// Get our callee.
const llvm::Type *Ty =
- CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(GD),
FPT->isVariadic());
llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty);
@@ -2574,24 +2621,20 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
}
if (!ResultType->isVoidType() && Slot.isNull())
- EmitReturnOfRValue(RV, ResultType);
+ CGM.getCXXABI().EmitReturnFromThunk(CGF, RV, ResultType);
FinishFunction();
- // Destroy the 'this' declaration.
- CXXThisDecl->Destroy(getContext());
-
// Set the right linkage.
CGM.setFunctionLinkage(MD, Fn);
// Set the right visibility.
- CGM.setGlobalVisibility(Fn, MD);
+ setThunkVisibility(CGM, MD, Thunk, Fn);
}
void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
{
llvm::Constant *Entry = CGM.GetAddrOfThunk(GD, Thunk);
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
// Strip off a bitcast if we got one back.
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
@@ -2602,7 +2645,7 @@ void CodeGenVTables::EmitThunk(GlobalDecl GD, const ThunkInfo &Thunk)
// There's already a declaration with the same name, check if it has the same
// type or if we need to replace it.
if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() !=
- CGM.getTypes().GetFunctionTypeForVTable(MD)) {
+ CGM.getTypes().GetFunctionTypeForVTable(GD)) {
llvm::GlobalValue *OldThunkFn = cast<llvm::GlobalValue>(Entry);
// If the types mismatch then we have to rewrite the definition.
@@ -2821,8 +2864,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
NextVTableThunkIndex++;
} else {
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(MD);
+ const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
Init = CGM.GetAddrOfFunction(GD, Ty);
}
@@ -2889,7 +2931,7 @@ GetGlobalVariable(llvm::Module &Module, llvm::StringRef Name,
llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXVTable(RD, OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXVTable(RD, OutName);
llvm::StringRef Name = OutName.str();
ComputeVTableRelatedInformation(RD, true);
@@ -2928,7 +2970,7 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
VTable->setLinkage(Linkage);
// Set the right visibility.
- CGM.setGlobalVisibility(VTable, RD);
+ CGM.setTypeVisibility(VTable, RD, /*ForRTTI*/ false);
}
llvm::GlobalVariable *
@@ -2949,8 +2991,8 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
// Get the mangled construction vtable name.
llvm::SmallString<256> OutName;
- CGM.getMangleContext().mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8,
- Base.getBase(), OutName);
+ CGM.getCXXABI().getMangleContext().
+ mangleCXXCtorVTable(RD, Base.getBaseOffset() / 8, Base.getBase(), OutName);
llvm::StringRef Name = OutName.str();
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index 92ef9dc4a11f..f57ecd245f09 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -15,6 +15,7 @@
#ifndef CLANG_CODEGEN_CGVALUE_H
#define CLANG_CODEGEN_CGVALUE_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
namespace llvm {
@@ -136,6 +137,9 @@ class LValue {
// 'const' is unused here
Qualifiers Quals;
+ /// The alignment to use when accessing this lvalue.
+ unsigned short Alignment;
+
// objective-c's ivar
bool Ivar:1;
@@ -148,15 +152,20 @@ class LValue {
// Lvalue is a global reference of an objective-c object
bool GlobalObjCRef : 1;
+
+ // Lvalue is a thread local reference
+ bool ThreadLocalRef : 1;
Expr *BaseIvarExp;
private:
- void SetQualifiers(Qualifiers Quals) {
+ void Initialize(Qualifiers Quals, unsigned Alignment = 0) {
this->Quals = Quals;
-
- // FIXME: Convenient place to set objc flags to 0. This should really be
- // done in a user-defined constructor instead.
+ this->Alignment = Alignment;
+ assert(this->Alignment == Alignment && "Alignment exceeds allowed max!");
+
+ // Initialize Objective-C flags.
this->Ivar = this->ObjIsArray = this->NonGC = this->GlobalObjCRef = false;
+ this->ThreadLocalRef = false;
this->BaseIvarExp = 0;
}
@@ -175,30 +184,36 @@ public:
}
bool isObjCIvar() const { return Ivar; }
+ void setObjCIvar(bool Value) { Ivar = Value; }
+
bool isObjCArray() const { return ObjIsArray; }
+ void setObjCArray(bool Value) { ObjIsArray = Value; }
+
bool isNonGC () const { return NonGC; }
+ void setNonGC(bool Value) { NonGC = Value; }
+
bool isGlobalObjCRef() const { return GlobalObjCRef; }
- bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; }
- bool isObjCStrong() const { return Quals.getObjCGCAttr() == Qualifiers::Strong; }
+ void setGlobalObjCRef(bool Value) { GlobalObjCRef = Value; }
+
+ bool isThreadLocalRef() const { return ThreadLocalRef; }
+ void setThreadLocalRef(bool Value) { ThreadLocalRef = Value;}
+
+ bool isObjCWeak() const {
+ return Quals.getObjCGCAttr() == Qualifiers::Weak;
+ }
+ bool isObjCStrong() const {
+ return Quals.getObjCGCAttr() == Qualifiers::Strong;
+ }
Expr *getBaseIvarExp() const { return BaseIvarExp; }
void setBaseIvarExp(Expr *V) { BaseIvarExp = V; }
- unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
+ const Qualifiers &getQuals() const { return Quals; }
+ Qualifiers &getQuals() { return Quals; }
- static void SetObjCIvar(LValue& R, bool iValue) {
- R.Ivar = iValue;
- }
- static void SetObjCArray(LValue& R, bool iValue) {
- R.ObjIsArray = iValue;
- }
- static void SetGlobalObjCRef(LValue& R, bool iValue) {
- R.GlobalObjCRef = iValue;
- }
+ unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
- static void SetObjCNonGC(LValue& R, bool iValue) {
- R.NonGC = iValue;
- }
+ unsigned getAlignment() const { return Alignment; }
// simple lvalue
llvm::Value *getAddress() const { assert(isSimple()); return V; }
@@ -236,11 +251,15 @@ public:
return KVCRefExpr;
}
- static LValue MakeAddr(llvm::Value *V, Qualifiers Quals) {
+ static LValue MakeAddr(llvm::Value *V, QualType T, unsigned Alignment,
+ ASTContext &Context) {
+ Qualifiers Quals = Context.getCanonicalType(T).getQualifiers();
+ Quals.setObjCGCAttr(Context.getObjCGCAttrKind(T));
+
LValue R;
R.LVType = Simple;
R.V = V;
- R.SetQualifiers(Quals);
+ R.Initialize(Quals, Alignment);
return R;
}
@@ -250,7 +269,7 @@ public:
R.LVType = VectorElt;
R.V = Vec;
R.VectorIdx = Idx;
- R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
return R;
}
@@ -260,7 +279,7 @@ public:
R.LVType = ExtVectorElt;
R.V = Vec;
R.VectorElts = Elts;
- R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
return R;
}
@@ -276,7 +295,7 @@ public:
R.LVType = BitField;
R.V = BaseValue;
R.BitFieldInfo = &Info;
- R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
return R;
}
@@ -288,7 +307,7 @@ public:
LValue R;
R.LVType = PropertyRef;
R.PropertyRefExpr = E;
- R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
return R;
}
@@ -297,7 +316,7 @@ public:
LValue R;
R.LVType = KVCRef;
R.KVCRefExpr = E;
- R.SetQualifiers(Qualifiers::fromCVRMask(CVR));
+ R.Initialize(Qualifiers::fromCVRMask(CVR));
return R;
}
};
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index eb6c4361be89..51d084e1d301 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -13,6 +13,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGException.h"
#include "clang/Basic/TargetInfo.h"
@@ -31,8 +32,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
: BlockFunction(cgm, *this, Builder), CGM(cgm),
Target(CGM.getContext().Target),
Builder(cgm.getModule().getContext()),
+ NormalCleanupDest(0), EHCleanupDest(0), NextCleanupDestIndex(1),
ExceptionSlot(0), DebugInfo(0), IndirectBranch(0),
- SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0),
+ SwitchInsn(0), CaseRangeBlock(0),
DidCallStackSave(false), UnreachableBlock(0),
CXXThisDecl(0), CXXThisValue(0), CXXVTTDecl(0), CXXVTTValue(0),
ConditionalBranchLevel(0), TerminateLandingPad(0), TerminateHandler(0),
@@ -47,7 +49,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
Exceptions = getContext().getLangOptions().Exceptions;
CatchUndefined = getContext().getLangOptions().CatchUndefined;
- CGM.getMangleContext().startNewFunction();
+ CGM.getCXXABI().getMangleContext().startNewFunction();
}
ASTContext &CodeGenFunction::getContext() const {
@@ -55,17 +57,6 @@ ASTContext &CodeGenFunction::getContext() const {
}
-llvm::Value *CodeGenFunction::GetAddrOfLocalVar(const VarDecl *VD) {
- llvm::Value *Res = LocalDeclMap[VD];
- assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
- return Res;
-}
-
-llvm::Constant *
-CodeGenFunction::GetAddrOfStaticLocalVar(const VarDecl *BVD) {
- return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
-}
-
const llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
return CGM.getTypes().ConvertTypeForMem(T);
}
@@ -76,7 +67,7 @@ const llvm::Type *CodeGenFunction::ConvertType(QualType T) {
bool CodeGenFunction::hasAggregateLLVMType(QualType T) {
return T->isRecordType() || T->isArrayType() || T->isAnyComplexType() ||
- T->isMemberFunctionPointerType();
+ T->isObjCObjectType();
}
void CodeGenFunction::EmitReturnBlock() {
@@ -89,26 +80,26 @@ void CodeGenFunction::EmitReturnBlock() {
// We have a valid insert point, reuse it if it is empty or there are no
// explicit jumps to the return block.
- if (CurBB->empty() || ReturnBlock.Block->use_empty()) {
- ReturnBlock.Block->replaceAllUsesWith(CurBB);
- delete ReturnBlock.Block;
+ if (CurBB->empty() || ReturnBlock.getBlock()->use_empty()) {
+ ReturnBlock.getBlock()->replaceAllUsesWith(CurBB);
+ delete ReturnBlock.getBlock();
} else
- EmitBlock(ReturnBlock.Block);
+ EmitBlock(ReturnBlock.getBlock());
return;
}
// Otherwise, if the return block is the target of a single direct
// branch then we can just put the code in that block instead. This
// cleans up functions which started with a unified return block.
- if (ReturnBlock.Block->hasOneUse()) {
+ if (ReturnBlock.getBlock()->hasOneUse()) {
llvm::BranchInst *BI =
- dyn_cast<llvm::BranchInst>(*ReturnBlock.Block->use_begin());
+ dyn_cast<llvm::BranchInst>(*ReturnBlock.getBlock()->use_begin());
if (BI && BI->isUnconditional() &&
- BI->getSuccessor(0) == ReturnBlock.Block) {
+ BI->getSuccessor(0) == ReturnBlock.getBlock()) {
// Reset insertion point and delete the branch.
Builder.SetInsertPoint(BI->getParent());
BI->eraseFromParent();
- delete ReturnBlock.Block;
+ delete ReturnBlock.getBlock();
return;
}
}
@@ -117,7 +108,7 @@ void CodeGenFunction::EmitReturnBlock() {
// unless it has uses. However, we still need a place to put the debug
// region.end for now.
- EmitBlock(ReturnBlock.Block);
+ EmitBlock(ReturnBlock.getBlock());
}
static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) {
@@ -139,7 +130,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
// Emit debug descriptor for function end.
if (CGDebugInfo *DI = getDebugInfo()) {
DI->setLocation(EndLoc);
- DI->EmitRegionEnd(CurFn, Builder);
+ DI->EmitFunctionEnd(Builder);
}
EmitFunctionEpilog(*CurFnInfo);
@@ -170,6 +161,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
}
}
+ EmitIfUsed(*this, RethrowBlock.getBlock());
EmitIfUsed(*this, TerminateLandingPad);
EmitIfUsed(*this, TerminateHandler);
EmitIfUsed(*this, UnreachableBlock);
@@ -287,10 +279,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
EmitStartEHSpec(CurCodeDecl);
EmitFunctionProlog(*CurFnInfo, CurFn, Args);
- if (CXXThisDecl)
- CXXThisValue = Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this");
- if (CXXVTTDecl)
- CXXVTTValue = Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
+ if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+ CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
// If any of the arguments have a variably modified type, make sure to
// emit the type size.
@@ -309,6 +299,23 @@ void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args) {
EmitStmt(FD->getBody());
}
+/// Tries to mark the given function nounwind based on the
+/// non-existence of any throwing calls within it. We believe this is
+/// lightweight enough to do at -O0.
+static void TryMarkNoThrow(llvm::Function *F) {
+ // LLVM treats 'nounwind' on a function as part of the type, so we
+ // can't do this on functions that can be overwritten.
+ if (F->mayBeOverridden()) return;
+
+ for (llvm::Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
+ for (llvm::BasicBlock::iterator
+ BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
+ if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(&*BI))
+ if (!Call->doesNotThrow())
+ return;
+ F->setDoesNotThrow(true);
+}
+
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -317,30 +324,11 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
DebugInfo = CGM.getDebugInfo();
FunctionArgList Args;
+ QualType ResTy = FD->getResultType();
CurGD = GD;
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- if (MD->isInstance()) {
- // Create the implicit 'this' decl.
- // FIXME: I'm not entirely sure I like using a fake decl just for code
- // generation. Maybe we can come up with a better way?
- CXXThisDecl = ImplicitParamDecl::Create(getContext(), 0,
- FD->getLocation(),
- &getContext().Idents.get("this"),
- MD->getThisType(getContext()));
- Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
-
- // Check if we need a VTT parameter as well.
- if (CodeGenVTables::needsVTTParameter(GD)) {
- // FIXME: The comment about using a fake decl above applies here too.
- QualType T = getContext().getPointerType(getContext().VoidPtrTy);
- CXXVTTDecl =
- ImplicitParamDecl::Create(getContext(), 0, FD->getLocation(),
- &getContext().Idents.get("vtt"), T);
- Args.push_back(std::make_pair(CXXVTTDecl, CXXVTTDecl->getType()));
- }
- }
- }
+ if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
+ CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
if (FD->getNumParams()) {
const FunctionProtoType* FProto = FD->getType()->getAs<FunctionProtoType>();
@@ -355,7 +343,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
// Emit the standard function prologue.
- StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
+ StartFunction(GD, ResTy, Fn, Args, BodyRange.getBegin());
// Generate the body of the function.
if (isa<CXXDestructorDecl>(FD))
@@ -368,13 +356,10 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
// Emit the standard function epilogue.
FinishFunction(BodyRange.getEnd());
- // Destroy the 'this' declaration.
- if (CXXThisDecl)
- CXXThisDecl->Destroy(getContext());
-
- // Destroy the VTT declaration.
- if (CXXVTTDecl)
- CXXVTTDecl->Destroy(getContext());
+ // If we haven't marked the function nothrow through other means, do
+ // a quick pass now to see if we can.
+ if (!CurFn->doesNotThrow())
+ TryMarkNoThrow(CurFn);
}
/// ContainsLabel - Return true if the statement contains a label in it. If
@@ -439,7 +424,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
// Handle X && Y in a condition.
- if (CondBOp->getOpcode() == BinaryOperator::LAnd) {
+ if (CondBOp->getOpcode() == BO_LAnd) {
// If we have "1 && X", simplify the code. "0 && X" would have constant
// folded if the case was simple enough.
if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == 1) {
@@ -466,7 +451,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
EndConditionalBranch();
return;
- } else if (CondBOp->getOpcode() == BinaryOperator::LOr) {
+ } else if (CondBOp->getOpcode() == BO_LOr) {
// If we have "0 || X", simplify the code. "1 || X" would have constant
// folded if the case was simple enough.
if (ConstantFoldsToSimpleInteger(CondBOp->getLHS()) == -1) {
@@ -498,7 +483,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(Cond)) {
// br(!x, t, f) -> br(x, f, t)
- if (CondUOp->getOpcode() == UnaryOperator::LNot)
+ if (CondUOp->getOpcode() == UO_LNot)
return EmitBranchOnBoolExpr(CondUOp->getSubExpr(), FalseBlock, TrueBlock);
}
@@ -533,21 +518,6 @@ void CodeGenFunction::ErrorUnsupported(const Stmt *S, const char *Type,
void
CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
- // If the type contains a pointer to data member we can't memset it to zero.
- // Instead, create a null constant and copy it to the destination.
- if (CGM.getTypes().ContainsPointerToDataMember(Ty)) {
- llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
-
- llvm::GlobalVariable *NullVariable =
- new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
- /*isConstant=*/true,
- llvm::GlobalVariable::PrivateLinkage,
- NullConstant, llvm::Twine());
- EmitAggregateCopy(DestPtr, NullVariable, Ty, /*isVolatile=*/false);
- return;
- }
-
-
// Ignore empty classes in C++.
if (getContext().getLangOptions().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -555,29 +525,58 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
return;
}
}
-
- // Otherwise, just memset the whole thing to zero. This is legal
- // because in LLVM, all default initializers (other than the ones we just
- // handled above) are guaranteed to have a bit pattern of all zeros.
- const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
+
+ // Cast the dest ptr to the appropriate i8 pointer type.
+ unsigned DestAS =
+ cast<llvm::PointerType>(DestPtr->getType())->getAddressSpace();
+ const llvm::Type *BP =
+ llvm::Type::getInt8PtrTy(VMContext, DestAS);
if (DestPtr->getType() != BP)
DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp");
// Get size and alignment info for this aggregate.
std::pair<uint64_t, unsigned> TypeInfo = getContext().getTypeInfo(Ty);
+ uint64_t Size = TypeInfo.first;
+ unsigned Align = TypeInfo.second;
// Don't bother emitting a zero-byte memset.
- if (TypeInfo.first == 0)
+ if (Size == 0)
return;
+ llvm::ConstantInt *SizeVal = llvm::ConstantInt::get(IntPtrTy, Size / 8);
+ llvm::ConstantInt *AlignVal = Builder.getInt32(Align / 8);
+
+ // If the type contains a pointer to data member we can't memset it to zero.
+ // Instead, create a null constant and copy it to the destination.
+ if (!CGM.getTypes().isZeroInitializable(Ty)) {
+ llvm::Constant *NullConstant = CGM.EmitNullConstant(Ty);
+
+ llvm::GlobalVariable *NullVariable =
+ new llvm::GlobalVariable(CGM.getModule(), NullConstant->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalVariable::PrivateLinkage,
+ NullConstant, llvm::Twine());
+ llvm::Value *SrcPtr =
+ Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy());
+
+ // FIXME: variable-size types?
+
+ // Get and call the appropriate llvm.memcpy overload.
+ llvm::Constant *Memcpy =
+ CGM.getMemCpyFn(DestPtr->getType(), SrcPtr->getType(), IntPtrTy);
+ Builder.CreateCall5(Memcpy, DestPtr, SrcPtr, SizeVal, AlignVal,
+ /*volatile*/ Builder.getFalse());
+ return;
+ }
+
+ // Otherwise, just memset the whole thing to zero. This is legal
+ // because in LLVM, all default initializers (other than the ones we just
+ // handled above) are guaranteed to have a bit pattern of all zeros.
+
// FIXME: Handle variable sized types.
Builder.CreateCall5(CGM.getMemSetFn(BP, IntPtrTy), DestPtr,
- llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)),
- // TypeInfo.first describes size in bits.
- llvm::ConstantInt::get(IntPtrTy, TypeInfo.first/8),
- llvm::ConstantInt::get(Int32Ty, TypeInfo.second/8),
- llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext),
- 0));
+ Builder.getInt8(0),
+ SizeVal, AlignVal, /*volatile*/ Builder.getFalse());
}
llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
@@ -585,7 +584,7 @@ llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
if (IndirectBranch == 0)
GetIndirectGotoBlock();
- llvm::BasicBlock *BB = getJumpDestForLabel(L).Block;
+ llvm::BasicBlock *BB = getJumpDestForLabel(L).getBlock();
// Make sure the indirect branch includes all of the address-taken blocks.
IndirectBranch->addDestination(BB);
@@ -666,70 +665,75 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
void CodeGenFunction::PopCleanupBlocks(EHScopeStack::stable_iterator Old) {
assert(Old.isValid());
- EHScopeStack::iterator E = EHStack.find(Old);
- while (EHStack.begin() != E)
- PopCleanupBlock();
-}
+ while (EHStack.stable_begin() != Old) {
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
+
+ // As long as Old strictly encloses the scope's enclosing normal
+ // cleanup, we're going to emit another normal cleanup which
+ // fallthrough can propagate through.
+ bool FallThroughIsBranchThrough =
+ Old.strictlyEncloses(Scope.getEnclosingNormalCleanup());
-/// Destroys a cleanup if it was unused.
-static void DestroyCleanup(CodeGenFunction &CGF,
- llvm::BasicBlock *Entry,
- llvm::BasicBlock *Exit) {
- assert(Entry->use_empty() && "destroying cleanup with uses!");
- assert(Exit->getTerminator() == 0 &&
- "exit has terminator but entry has no predecessors!");
-
- // This doesn't always remove the entire cleanup, but it's much
- // safer as long as we don't know what blocks belong to the cleanup.
- // A *much* better approach if we care about this inefficiency would
- // be to lazily emit the cleanup.
-
- // If the exit block is distinct from the entry, give it a branch to
- // an unreachable destination. This preserves the well-formedness
- // of the IR.
- if (Entry != Exit)
- llvm::BranchInst::Create(CGF.getUnreachableBlock(), Exit);
-
- assert(!Entry->getParent() && "cleanup entry already positioned?");
- // We can't just delete the entry; we have to kill any references to
- // its instructions in other blocks.
- for (llvm::BasicBlock::iterator I = Entry->begin(), E = Entry->end();
- I != E; ++I)
- if (!I->use_empty())
- I->replaceAllUsesWith(llvm::UndefValue::get(I->getType()));
- delete Entry;
+ PopCleanupBlock(FallThroughIsBranchThrough);
+ }
}
-/// Creates a switch instruction to thread branches out of the given
-/// block (which is the exit block of a cleanup).
-static void CreateCleanupSwitch(CodeGenFunction &CGF,
- llvm::BasicBlock *Block) {
- if (Block->getTerminator()) {
- assert(isa<llvm::SwitchInst>(Block->getTerminator()) &&
- "cleanup block already has a terminator, but it isn't a switch");
- return;
+static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF,
+ EHCleanupScope &Scope) {
+ assert(Scope.isNormalCleanup());
+ llvm::BasicBlock *Entry = Scope.getNormalBlock();
+ if (!Entry) {
+ Entry = CGF.createBasicBlock("cleanup");
+ Scope.setNormalBlock(Entry);
}
+ return Entry;
+}
- llvm::Value *DestCodePtr
- = CGF.CreateTempAlloca(CGF.Builder.getInt32Ty(), "cleanup.dst");
- CGBuilderTy Builder(Block);
- llvm::Value *DestCode = Builder.CreateLoad(DestCodePtr, "tmp");
+static llvm::BasicBlock *CreateEHEntry(CodeGenFunction &CGF,
+ EHCleanupScope &Scope) {
+ assert(Scope.isEHCleanup());
+ llvm::BasicBlock *Entry = Scope.getEHBlock();
+ if (!Entry) {
+ Entry = CGF.createBasicBlock("eh.cleanup");
+ Scope.setEHBlock(Entry);
+ }
+ return Entry;
+}
- // Create a switch instruction to determine where to jump next.
- Builder.CreateSwitch(DestCode, CGF.getUnreachableBlock());
+/// Transitions the terminator of the given exit-block of a cleanup to
+/// be a cleanup switch.
+static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF,
+ llvm::BasicBlock *Block) {
+ // If it's a branch, turn it into a switch whose default
+ // destination is its original target.
+ llvm::TerminatorInst *Term = Block->getTerminator();
+ assert(Term && "can't transition block without terminator");
+
+ if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) {
+ assert(Br->isUnconditional());
+ llvm::LoadInst *Load =
+ new llvm::LoadInst(CGF.getNormalCleanupDestSlot(), "cleanup.dest", Term);
+ llvm::SwitchInst *Switch =
+ llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block);
+ Br->eraseFromParent();
+ return Switch;
+ } else {
+ return cast<llvm::SwitchInst>(Term);
+ }
}
/// Attempts to reduce a cleanup's entry block to a fallthrough. This
/// is basically llvm::MergeBlockIntoPredecessor, except
-/// simplified/optimized for the tighter constraints on cleanup
-/// blocks.
-static void SimplifyCleanupEntry(CodeGenFunction &CGF,
- llvm::BasicBlock *Entry) {
+/// simplified/optimized for the tighter constraints on cleanup blocks.
+///
+/// Returns the new block, whatever it is.
+static llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF,
+ llvm::BasicBlock *Entry) {
llvm::BasicBlock *Pred = Entry->getSinglePredecessor();
- if (!Pred) return;
+ if (!Pred) return Entry;
llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Pred->getTerminator());
- if (!Br || Br->isConditional()) return;
+ if (!Br || Br->isConditional()) return Entry;
assert(Br->getSuccessor(0) == Entry);
// If we were previously inserting at the end of the cleanup entry
@@ -749,145 +753,44 @@ static void SimplifyCleanupEntry(CodeGenFunction &CGF,
if (WasInsertBlock)
CGF.Builder.SetInsertPoint(Pred);
-}
-
-/// Attempts to reduce an cleanup's exit switch to an unconditional
-/// branch.
-static void SimplifyCleanupExit(llvm::BasicBlock *Exit) {
- llvm::TerminatorInst *Terminator = Exit->getTerminator();
- assert(Terminator && "completed cleanup exit has no terminator");
-
- llvm::SwitchInst *Switch = dyn_cast<llvm::SwitchInst>(Terminator);
- if (!Switch) return;
- if (Switch->getNumCases() != 2) return; // default + 1
- llvm::LoadInst *Cond = cast<llvm::LoadInst>(Switch->getCondition());
- llvm::AllocaInst *CondVar = cast<llvm::AllocaInst>(Cond->getPointerOperand());
-
- // Replace the switch instruction with an unconditional branch.
- llvm::BasicBlock *Dest = Switch->getSuccessor(1); // default is 0
- Switch->eraseFromParent();
- llvm::BranchInst::Create(Dest, Exit);
-
- // Delete all uses of the condition variable.
- Cond->eraseFromParent();
- while (!CondVar->use_empty())
- cast<llvm::StoreInst>(*CondVar->use_begin())->eraseFromParent();
-
- // Delete the condition variable itself.
- CondVar->eraseFromParent();
+ return Pred;
}
-/// Threads a branch fixup through a cleanup block.
-static void ThreadFixupThroughCleanup(CodeGenFunction &CGF,
- BranchFixup &Fixup,
- llvm::BasicBlock *Entry,
- llvm::BasicBlock *Exit) {
- if (!Exit->getTerminator())
- CreateCleanupSwitch(CGF, Exit);
-
- // Find the switch and its destination index alloca.
- llvm::SwitchInst *Switch = cast<llvm::SwitchInst>(Exit->getTerminator());
- llvm::Value *DestCodePtr =
- cast<llvm::LoadInst>(Switch->getCondition())->getPointerOperand();
-
- // Compute the index of the new case we're adding to the switch.
- unsigned Index = Switch->getNumCases();
-
- const llvm::IntegerType *i32 = llvm::Type::getInt32Ty(CGF.getLLVMContext());
- llvm::ConstantInt *IndexV = llvm::ConstantInt::get(i32, Index);
-
- // Set the index in the origin block.
- new llvm::StoreInst(IndexV, DestCodePtr, Fixup.Origin);
-
- // Add a case to the switch.
- Switch->addCase(IndexV, Fixup.Destination);
-
- // Change the last branch to point to the cleanup entry block.
- Fixup.LatestBranch->setSuccessor(Fixup.LatestBranchIndex, Entry);
-
- // And finally, update the fixup.
- Fixup.LatestBranch = Switch;
- Fixup.LatestBranchIndex = Index;
-}
-
-/// Try to simplify both the entry and exit edges of a cleanup.
-static void SimplifyCleanupEdges(CodeGenFunction &CGF,
- llvm::BasicBlock *Entry,
- llvm::BasicBlock *Exit) {
-
- // Given their current implementations, it's important to run these
- // in this order: SimplifyCleanupEntry will delete Entry if it can
- // be merged into its predecessor, which will then break
- // SimplifyCleanupExit if (as is common) Entry == Exit.
-
- SimplifyCleanupExit(Exit);
- SimplifyCleanupEntry(CGF, Entry);
-}
-
-static void EmitLazyCleanup(CodeGenFunction &CGF,
- EHScopeStack::LazyCleanup *Fn,
- bool ForEH) {
+static void EmitCleanup(CodeGenFunction &CGF,
+ EHScopeStack::Cleanup *Fn,
+ bool ForEH) {
if (ForEH) CGF.EHStack.pushTerminate();
Fn->Emit(CGF, ForEH);
if (ForEH) CGF.EHStack.popTerminate();
assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?");
}
-static void SplitAndEmitLazyCleanup(CodeGenFunction &CGF,
- EHScopeStack::LazyCleanup *Fn,
- bool ForEH,
- llvm::BasicBlock *Entry) {
- assert(Entry && "no entry block for cleanup");
-
- // Remove the switch and load from the end of the entry block.
- llvm::Instruction *Switch = &Entry->getInstList().back();
- Entry->getInstList().remove(Switch);
- assert(isa<llvm::SwitchInst>(Switch));
- llvm::Instruction *Load = &Entry->getInstList().back();
- Entry->getInstList().remove(Load);
- assert(isa<llvm::LoadInst>(Load));
-
- assert(Entry->getInstList().empty() &&
- "lazy cleanup block not empty after removing load/switch pair?");
-
- // Emit the actual cleanup at the end of the entry block.
- CGF.Builder.SetInsertPoint(Entry);
- EmitLazyCleanup(CGF, Fn, ForEH);
-
- // Put the load and switch at the end of the exit block.
- llvm::BasicBlock *Exit = CGF.Builder.GetInsertBlock();
- Exit->getInstList().push_back(Load);
- Exit->getInstList().push_back(Switch);
-
- // Clean up the edges if possible.
- SimplifyCleanupEdges(CGF, Entry, Exit);
-
- CGF.Builder.ClearInsertionPoint();
-}
-
-static void PopLazyCleanupBlock(CodeGenFunction &CGF) {
- assert(isa<EHLazyCleanupScope>(*CGF.EHStack.begin()) && "top not a cleanup!");
- EHLazyCleanupScope &Scope = cast<EHLazyCleanupScope>(*CGF.EHStack.begin());
- assert(Scope.getFixupDepth() <= CGF.EHStack.getNumBranchFixups());
+/// Pops a cleanup block. If the block includes a normal cleanup, the
+/// current insertion point is threaded through the cleanup, as are
+/// any branch fixups on the cleanup.
+void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
+ assert(!EHStack.empty() && "cleanup stack is empty!");
+ assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!");
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
+ assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups());
+ assert(Scope.isActive() && "cleanup was still inactive when popped!");
// Check whether we need an EH cleanup. This is only true if we've
// generated a lazy EH cleanup block.
- llvm::BasicBlock *EHEntry = Scope.getEHBlock();
- bool RequiresEHCleanup = (EHEntry != 0);
+ bool RequiresEHCleanup = Scope.hasEHBranches();
// Check the three conditions which might require a normal cleanup:
// - whether there are branch fix-ups through this cleanup
unsigned FixupDepth = Scope.getFixupDepth();
- bool HasFixups = CGF.EHStack.getNumBranchFixups() != FixupDepth;
+ bool HasFixups = EHStack.getNumBranchFixups() != FixupDepth;
- // - whether control has already been threaded through this cleanup
- llvm::BasicBlock *NormalEntry = Scope.getNormalBlock();
- bool HasExistingBranches = (NormalEntry != 0);
+ // - whether there are branch-throughs or branch-afters
+ bool HasExistingBranches = Scope.hasBranches();
// - whether there's a fallthrough
- llvm::BasicBlock *FallthroughSource = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock();
bool HasFallthrough = (FallthroughSource != 0);
bool RequiresNormalCleanup = false;
@@ -898,9 +801,9 @@ static void PopLazyCleanupBlock(CodeGenFunction &CGF) {
// If we don't need the cleanup at all, we're done.
if (!RequiresNormalCleanup && !RequiresEHCleanup) {
- CGF.EHStack.popCleanup();
- assert(CGF.EHStack.getNumBranchFixups() == 0 ||
- CGF.EHStack.hasNormalCleanups());
+ EHStack.popCleanup(); // safe because there are no fixups
+ assert(EHStack.getNumBranchFixups() == 0 ||
+ EHStack.hasNormalCleanups());
return;
}
@@ -912,319 +815,527 @@ static void PopLazyCleanupBlock(CodeGenFunction &CGF) {
memcpy(CleanupBuffer.data(),
Scope.getCleanupBuffer(), Scope.getCleanupSize());
CleanupBuffer.set_size(Scope.getCleanupSize());
- EHScopeStack::LazyCleanup *Fn =
- reinterpret_cast<EHScopeStack::LazyCleanup*>(CleanupBuffer.data());
+ EHScopeStack::Cleanup *Fn =
+ reinterpret_cast<EHScopeStack::Cleanup*>(CleanupBuffer.data());
+
+ // We want to emit the EH cleanup after the normal cleanup, but go
+ // ahead and do the setup for the EH cleanup while the scope is still
+ // alive.
+ llvm::BasicBlock *EHEntry = 0;
+ llvm::SmallVector<llvm::Instruction*, 2> EHInstsToAppend;
+ if (RequiresEHCleanup) {
+ EHEntry = CreateEHEntry(*this, Scope);
+
+ // Figure out the branch-through dest if necessary.
+ llvm::BasicBlock *EHBranchThroughDest = 0;
+ if (Scope.hasEHBranchThroughs()) {
+ assert(Scope.getEnclosingEHCleanup() != EHStack.stable_end());
+ EHScope &S = *EHStack.find(Scope.getEnclosingEHCleanup());
+ EHBranchThroughDest = CreateEHEntry(*this, cast<EHCleanupScope>(S));
+ }
- // We're done with the scope; pop it off so we can emit the cleanups.
- CGF.EHStack.popCleanup();
+ // If we have exactly one branch-after and no branch-throughs, we
+ // can dispatch it without a switch.
+ if (!Scope.hasEHBranchThroughs() &&
+ Scope.getNumEHBranchAfters() == 1) {
+ assert(!EHBranchThroughDest);
+
+ // TODO: remove the spurious eh.cleanup.dest stores if this edge
+ // never went through any switches.
+ llvm::BasicBlock *BranchAfterDest = Scope.getEHBranchAfterBlock(0);
+ EHInstsToAppend.push_back(llvm::BranchInst::Create(BranchAfterDest));
+
+ // Otherwise, if we have any branch-afters, we need a switch.
+ } else if (Scope.getNumEHBranchAfters()) {
+ // The default of the switch belongs to the branch-throughs if
+ // they exist.
+ llvm::BasicBlock *Default =
+ (EHBranchThroughDest ? EHBranchThroughDest : getUnreachableBlock());
+
+ const unsigned SwitchCapacity = Scope.getNumEHBranchAfters();
+
+ llvm::LoadInst *Load =
+ new llvm::LoadInst(getEHCleanupDestSlot(), "cleanup.dest");
+ llvm::SwitchInst *Switch =
+ llvm::SwitchInst::Create(Load, Default, SwitchCapacity);
+
+ EHInstsToAppend.push_back(Load);
+ EHInstsToAppend.push_back(Switch);
+
+ for (unsigned I = 0, E = Scope.getNumEHBranchAfters(); I != E; ++I)
+ Switch->addCase(Scope.getEHBranchAfterIndex(I),
+ Scope.getEHBranchAfterBlock(I));
+
+ // Otherwise, we have only branch-throughs; jump to the next EH
+ // cleanup.
+ } else {
+ assert(EHBranchThroughDest);
+ EHInstsToAppend.push_back(llvm::BranchInst::Create(EHBranchThroughDest));
+ }
+ }
+
+ if (!RequiresNormalCleanup) {
+ EHStack.popCleanup();
+ } else {
+ // As a kindof crazy internal case, branch-through fall-throughs
+ // leave the insertion point set to the end of the last cleanup.
+ bool HasPrebranchedFallthrough =
+ (HasFallthrough && FallthroughSource->getTerminator());
+ assert(!HasPrebranchedFallthrough ||
+ FallthroughSource->getTerminator()->getSuccessor(0)
+ == Scope.getNormalBlock());
- if (RequiresNormalCleanup) {
// If we have a fallthrough and no other need for the cleanup,
// emit it directly.
- if (HasFallthrough && !HasFixups && !HasExistingBranches) {
- EmitLazyCleanup(CGF, Fn, /*ForEH*/ false);
+ if (HasFallthrough && !HasPrebranchedFallthrough &&
+ !HasFixups && !HasExistingBranches) {
+
+ // Fixups can cause us to optimistically create a normal block,
+ // only to later have no real uses for it. Just delete it in
+ // this case.
+ // TODO: we can potentially simplify all the uses after this.
+ if (Scope.getNormalBlock()) {
+ Scope.getNormalBlock()->replaceAllUsesWith(getUnreachableBlock());
+ delete Scope.getNormalBlock();
+ }
+
+ EHStack.popCleanup();
+
+ EmitCleanup(*this, Fn, /*ForEH*/ false);
// Otherwise, the best approach is to thread everything through
// the cleanup block and then try to clean up after ourselves.
} else {
// Force the entry block to exist.
- if (!HasExistingBranches) {
- NormalEntry = CGF.createBasicBlock("cleanup");
- CreateCleanupSwitch(CGF, NormalEntry);
+ llvm::BasicBlock *NormalEntry = CreateNormalEntry(*this, Scope);
+
+ // If there's a fallthrough, we need to store the cleanup
+ // destination index. For fall-throughs this is always zero.
+ if (HasFallthrough && !HasPrebranchedFallthrough)
+ Builder.CreateStore(Builder.getInt32(0), getNormalCleanupDestSlot());
+
+ // Emit the entry block. This implicitly branches to it if we
+ // have fallthrough. All the fixups and existing branches should
+ // already be branched to it.
+ EmitBlock(NormalEntry);
+
+ bool HasEnclosingCleanups =
+ (Scope.getEnclosingNormalCleanup() != EHStack.stable_end());
+
+ // Compute the branch-through dest if we need it:
+ // - if there are branch-throughs threaded through the scope
+ // - if fall-through is a branch-through
+ // - if there are fixups that will be optimistically forwarded
+ // to the enclosing cleanup
+ llvm::BasicBlock *BranchThroughDest = 0;
+ if (Scope.hasBranchThroughs() ||
+ (HasFallthrough && FallthroughIsBranchThrough) ||
+ (HasFixups && HasEnclosingCleanups)) {
+ assert(HasEnclosingCleanups);
+ EHScope &S = *EHStack.find(Scope.getEnclosingNormalCleanup());
+ BranchThroughDest = CreateNormalEntry(*this, cast<EHCleanupScope>(S));
}
- CGF.EmitBlock(NormalEntry);
-
- // Thread the fallthrough edge through the (momentarily trivial)
- // cleanup.
- llvm::BasicBlock *FallthroughDestination = 0;
- if (HasFallthrough) {
- assert(isa<llvm::BranchInst>(FallthroughSource->getTerminator()));
- FallthroughDestination = CGF.createBasicBlock("cleanup.cont");
-
- BranchFixup Fix;
- Fix.Destination = FallthroughDestination;
- Fix.LatestBranch = FallthroughSource->getTerminator();
- Fix.LatestBranchIndex = 0;
- Fix.Origin = Fix.LatestBranch;
+ llvm::BasicBlock *FallthroughDest = 0;
+ llvm::SmallVector<llvm::Instruction*, 2> InstsToAppend;
+
+ // If there's exactly one branch-after and no other threads,
+ // we can route it without a switch.
+ if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough &&
+ Scope.getNumBranchAfters() == 1) {
+ assert(!BranchThroughDest);
+
+ // TODO: clean up the possibly dead stores to the cleanup dest slot.
+ llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0);
+ InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter));
+
+ // Build a switch-out if we need it:
+ // - if there are branch-afters threaded through the scope
+ // - if fall-through is a branch-after
+ // - if there are fixups that have nowhere left to go and
+ // so must be immediately resolved
+ } else if (Scope.getNumBranchAfters() ||
+ (HasFallthrough && !FallthroughIsBranchThrough) ||
+ (HasFixups && !HasEnclosingCleanups)) {
+
+ llvm::BasicBlock *Default =
+ (BranchThroughDest ? BranchThroughDest : getUnreachableBlock());
+
+ // TODO: base this on the number of branch-afters and fixups
+ const unsigned SwitchCapacity = 10;
+
+ llvm::LoadInst *Load =
+ new llvm::LoadInst(getNormalCleanupDestSlot(), "cleanup.dest");
+ llvm::SwitchInst *Switch =
+ llvm::SwitchInst::Create(Load, Default, SwitchCapacity);
+
+ InstsToAppend.push_back(Load);
+ InstsToAppend.push_back(Switch);
+
+ // Branch-after fallthrough.
+ if (HasFallthrough && !FallthroughIsBranchThrough) {
+ FallthroughDest = createBasicBlock("cleanup.cont");
+ Switch->addCase(Builder.getInt32(0), FallthroughDest);
+ }
- // Restore fixup invariant. EmitBlock added a branch to the
- // cleanup which we need to redirect to the destination.
- cast<llvm::BranchInst>(Fix.LatestBranch)
- ->setSuccessor(0, Fix.Destination);
+ for (unsigned I = 0, E = Scope.getNumBranchAfters(); I != E; ++I) {
+ Switch->addCase(Scope.getBranchAfterIndex(I),
+ Scope.getBranchAfterBlock(I));
+ }
- ThreadFixupThroughCleanup(CGF, Fix, NormalEntry, NormalEntry);
+ if (HasFixups && !HasEnclosingCleanups)
+ ResolveAllBranchFixups(Switch);
+ } else {
+ // We should always have a branch-through destination in this case.
+ assert(BranchThroughDest);
+ InstsToAppend.push_back(llvm::BranchInst::Create(BranchThroughDest));
}
- // Thread any "real" fixups we need to thread.
- for (unsigned I = FixupDepth, E = CGF.EHStack.getNumBranchFixups();
- I != E; ++I)
- if (CGF.EHStack.getBranchFixup(I).Destination)
- ThreadFixupThroughCleanup(CGF, CGF.EHStack.getBranchFixup(I),
- NormalEntry, NormalEntry);
-
- SplitAndEmitLazyCleanup(CGF, Fn, /*ForEH*/ false, NormalEntry);
-
- if (HasFallthrough)
- CGF.EmitBlock(FallthroughDestination);
+ // We're finally ready to pop the cleanup.
+ EHStack.popCleanup();
+ assert(EHStack.hasNormalCleanups() == HasEnclosingCleanups);
+
+ EmitCleanup(*this, Fn, /*ForEH*/ false);
+
+ // Append the prepared cleanup prologue from above.
+ llvm::BasicBlock *NormalExit = Builder.GetInsertBlock();
+ for (unsigned I = 0, E = InstsToAppend.size(); I != E; ++I)
+ NormalExit->getInstList().push_back(InstsToAppend[I]);
+
+ // Optimistically hope that any fixups will continue falling through.
+ for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups();
+ I < E; ++I) {
+ BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I);
+ if (!Fixup.Destination) continue;
+ if (!Fixup.OptimisticBranchBlock) {
+ new llvm::StoreInst(Builder.getInt32(Fixup.DestinationIndex),
+ getNormalCleanupDestSlot(),
+ Fixup.InitialBranch);
+ Fixup.InitialBranch->setSuccessor(0, NormalEntry);
+ }
+ Fixup.OptimisticBranchBlock = NormalExit;
+ }
+
+ if (FallthroughDest)
+ EmitBlock(FallthroughDest);
+ else if (!HasFallthrough)
+ Builder.ClearInsertionPoint();
+
+ // Check whether we can merge NormalEntry into a single predecessor.
+ // This might invalidate (non-IR) pointers to NormalEntry.
+ llvm::BasicBlock *NewNormalEntry =
+ SimplifyCleanupEntry(*this, NormalEntry);
+
+ // If it did invalidate those pointers, and NormalEntry was the same
+ // as NormalExit, go back and patch up the fixups.
+ if (NewNormalEntry != NormalEntry && NormalEntry == NormalExit)
+ for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups();
+ I < E; ++I)
+ CGF.EHStack.getBranchFixup(I).OptimisticBranchBlock = NewNormalEntry;
}
}
+ assert(EHStack.hasNormalCleanups() || EHStack.getNumBranchFixups() == 0);
+
// Emit the EH cleanup if required.
if (RequiresEHCleanup) {
- CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
- CGF.EmitBlock(EHEntry);
- SplitAndEmitLazyCleanup(CGF, Fn, /*ForEH*/ true, EHEntry);
- CGF.Builder.restoreIP(SavedIP);
- }
-}
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
-/// Pops a cleanup block. If the block includes a normal cleanup, the
-/// current insertion point is threaded through the cleanup, as are
-/// any branch fixups on the cleanup.
-void CodeGenFunction::PopCleanupBlock() {
- assert(!EHStack.empty() && "cleanup stack is empty!");
- if (isa<EHLazyCleanupScope>(*EHStack.begin()))
- return PopLazyCleanupBlock(*this);
+ EmitBlock(EHEntry);
+ EmitCleanup(*this, Fn, /*ForEH*/ true);
- assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!");
- EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin());
- assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups());
+ // Append the prepared cleanup prologue from above.
+ llvm::BasicBlock *EHExit = Builder.GetInsertBlock();
+ for (unsigned I = 0, E = EHInstsToAppend.size(); I != E; ++I)
+ EHExit->getInstList().push_back(EHInstsToAppend[I]);
- // Handle the EH cleanup if (1) there is one and (2) it's different
- // from the normal cleanup.
- if (Scope.isEHCleanup() &&
- Scope.getEHEntry() != Scope.getNormalEntry()) {
- llvm::BasicBlock *EHEntry = Scope.getEHEntry();
- llvm::BasicBlock *EHExit = Scope.getEHExit();
-
- if (EHEntry->use_empty()) {
- DestroyCleanup(*this, EHEntry, EHExit);
- } else {
- // TODO: this isn't really the ideal location to put this EH
- // cleanup, but lazy emission is a better solution than trying
- // to pick a better spot.
- CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
- EmitBlock(EHEntry);
- Builder.restoreIP(SavedIP);
-
- SimplifyCleanupEdges(*this, EHEntry, EHExit);
- }
- }
+ Builder.restoreIP(SavedIP);
- // If we only have an EH cleanup, we don't really need to do much
- // here. Branch fixups just naturally drop down to the enclosing
- // cleanup scope.
- if (!Scope.isNormalCleanup()) {
- EHStack.popCleanup();
- assert(EHStack.getNumBranchFixups() == 0 || EHStack.hasNormalCleanups());
- return;
+ SimplifyCleanupEntry(*this, EHEntry);
}
+}
- // Check whether the scope has any fixups that need to be threaded.
- unsigned FixupDepth = Scope.getFixupDepth();
- bool HasFixups = EHStack.getNumBranchFixups() != FixupDepth;
+/// Terminate the current block by emitting a branch which might leave
+/// the current cleanup-protected scope. The target scope may not yet
+/// be known, in which case this will require a fixup.
+///
+/// As a side-effect, this method clears the insertion point.
+void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
+ assert(Dest.getScopeDepth().encloses(EHStack.getInnermostNormalCleanup())
+ && "stale jump destination");
- // Grab the entry and exit blocks.
- llvm::BasicBlock *Entry = Scope.getNormalEntry();
- llvm::BasicBlock *Exit = Scope.getNormalExit();
+ if (!HaveInsertPoint())
+ return;
- // Check whether anything's been threaded through the cleanup already.
- assert((Exit->getTerminator() == 0) == Entry->use_empty() &&
- "cleanup entry/exit mismatch");
- bool HasExistingBranches = !Entry->use_empty();
+ // Create the branch.
+ llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock());
- // Check whether we need to emit a "fallthrough" branch through the
- // cleanup for the current insertion point.
- llvm::BasicBlock *FallThrough = Builder.GetInsertBlock();
- if (FallThrough && FallThrough->getTerminator())
- FallThrough = 0;
+ // Calculate the innermost active normal cleanup.
+ EHScopeStack::stable_iterator
+ TopCleanup = EHStack.getInnermostActiveNormalCleanup();
- // If *nothing* is using the cleanup, kill it.
- if (!FallThrough && !HasFixups && !HasExistingBranches) {
- EHStack.popCleanup();
- DestroyCleanup(*this, Entry, Exit);
+ // If we're not in an active normal cleanup scope, or if the
+ // destination scope is within the innermost active normal cleanup
+ // scope, we don't need to worry about fixups.
+ if (TopCleanup == EHStack.stable_end() ||
+ TopCleanup.encloses(Dest.getScopeDepth())) { // works for invalid
+ Builder.ClearInsertionPoint();
return;
}
- // Otherwise, add the block to the function.
- EmitBlock(Entry);
+ // If we can't resolve the destination cleanup scope, just add this
+ // to the current cleanup scope as a branch fixup.
+ if (!Dest.getScopeDepth().isValid()) {
+ BranchFixup &Fixup = EHStack.addBranchFixup();
+ Fixup.Destination = Dest.getBlock();
+ Fixup.DestinationIndex = Dest.getDestIndex();
+ Fixup.InitialBranch = BI;
+ Fixup.OptimisticBranchBlock = 0;
- if (FallThrough)
- Builder.SetInsertPoint(Exit);
- else
Builder.ClearInsertionPoint();
-
- // Fast case: if we don't have to add any fixups, and either
- // we don't have a fallthrough or the cleanup wasn't previously
- // used, then the setup above is sufficient.
- if (!HasFixups) {
- if (!FallThrough) {
- assert(HasExistingBranches && "no reason for cleanup but didn't kill before");
- EHStack.popCleanup();
- SimplifyCleanupEdges(*this, Entry, Exit);
- return;
- } else if (!HasExistingBranches) {
- assert(FallThrough && "no reason for cleanup but didn't kill before");
- // We can't simplify the exit edge in this case because we're
- // already inserting at the end of the exit block.
- EHStack.popCleanup();
- SimplifyCleanupEntry(*this, Entry);
- return;
- }
+ return;
}
- // Otherwise we're going to have to thread things through the cleanup.
- llvm::SmallVector<BranchFixup*, 8> Fixups;
-
- // Synthesize a fixup for the current insertion point.
- BranchFixup Cur;
- if (FallThrough) {
- Cur.Destination = createBasicBlock("cleanup.cont");
- Cur.LatestBranch = FallThrough->getTerminator();
- Cur.LatestBranchIndex = 0;
- Cur.Origin = Cur.LatestBranch;
-
- // Restore fixup invariant. EmitBlock added a branch to the cleanup
- // which we need to redirect to the destination.
- cast<llvm::BranchInst>(Cur.LatestBranch)->setSuccessor(0, Cur.Destination);
+ // Otherwise, thread through all the normal cleanups in scope.
- Fixups.push_back(&Cur);
- } else {
- Cur.Destination = 0;
- }
+ // Store the index at the start.
+ llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
+ new llvm::StoreInst(Index, getNormalCleanupDestSlot(), BI);
- // Collect any "real" fixups we need to thread.
- for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups();
- I != E; ++I)
- if (EHStack.getBranchFixup(I).Destination)
- Fixups.push_back(&EHStack.getBranchFixup(I));
-
- assert(!Fixups.empty() && "no fixups, invariants broken!");
-
- // If there's only a single fixup to thread through, do so with
- // unconditional branches. This only happens if there's a single
- // branch and no fallthrough.
- if (Fixups.size() == 1 && !HasExistingBranches) {
- Fixups[0]->LatestBranch->setSuccessor(Fixups[0]->LatestBranchIndex, Entry);
- llvm::BranchInst *Br =
- llvm::BranchInst::Create(Fixups[0]->Destination, Exit);
- Fixups[0]->LatestBranch = Br;
- Fixups[0]->LatestBranchIndex = 0;
-
- // Otherwise, force a switch statement and thread everything through
- // the switch.
- } else {
- CreateCleanupSwitch(*this, Exit);
- for (unsigned I = 0, E = Fixups.size(); I != E; ++I)
- ThreadFixupThroughCleanup(*this, *Fixups[I], Entry, Exit);
+ // Adjust BI to point to the first cleanup block.
+ {
+ EHCleanupScope &Scope =
+ cast<EHCleanupScope>(*EHStack.find(TopCleanup));
+ BI->setSuccessor(0, CreateNormalEntry(*this, Scope));
}
- // Emit the fallthrough destination block if necessary.
- if (Cur.Destination)
- EmitBlock(Cur.Destination);
+ // Add this destination to all the scopes involved.
+ EHScopeStack::stable_iterator I = TopCleanup;
+ EHScopeStack::stable_iterator E = Dest.getScopeDepth();
+ if (E.strictlyEncloses(I)) {
+ while (true) {
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I));
+ assert(Scope.isNormalCleanup());
+ I = Scope.getEnclosingNormalCleanup();
+
+ // If this is the last cleanup we're propagating through, tell it
+ // that there's a resolved jump moving through it.
+ if (!E.strictlyEncloses(I)) {
+ Scope.addBranchAfter(Index, Dest.getBlock());
+ break;
+ }
- // We're finally done with the cleanup.
- EHStack.popCleanup();
+ // Otherwise, tell the scope that there's a jump propoagating
+ // through it. If this isn't new information, all the rest of
+ // the work has been done before.
+ if (!Scope.addBranchThrough(Dest.getBlock()))
+ break;
+ }
+ }
+
+ Builder.ClearInsertionPoint();
}
-void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
+void CodeGenFunction::EmitBranchThroughEHCleanup(UnwindDest Dest) {
+ // We should never get invalid scope depths for an UnwindDest; that
+ // implies that the destination wasn't set up correctly.
+ assert(Dest.getScopeDepth().isValid() && "invalid scope depth on EH dest?");
+
if (!HaveInsertPoint())
return;
// Create the branch.
- llvm::BranchInst *BI = Builder.CreateBr(Dest.Block);
+ llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock());
- // If we're not in a cleanup scope, we don't need to worry about
- // fixups.
- if (!EHStack.hasNormalCleanups()) {
+ // Calculate the innermost active cleanup.
+ EHScopeStack::stable_iterator
+ InnermostCleanup = EHStack.getInnermostActiveEHCleanup();
+
+ // If the destination is in the same EH cleanup scope as us, we
+ // don't need to thread through anything.
+ if (InnermostCleanup.encloses(Dest.getScopeDepth())) {
Builder.ClearInsertionPoint();
return;
}
+ assert(InnermostCleanup != EHStack.stable_end());
- // Initialize a fixup.
- BranchFixup Fixup;
- Fixup.Destination = Dest.Block;
- Fixup.Origin = BI;
- Fixup.LatestBranch = BI;
- Fixup.LatestBranchIndex = 0;
+ // Store the index at the start.
+ llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
+ new llvm::StoreInst(Index, getEHCleanupDestSlot(), BI);
- // If we can't resolve the destination cleanup scope, just add this
- // to the current cleanup scope.
- if (!Dest.ScopeDepth.isValid()) {
- EHStack.addBranchFixup() = Fixup;
- Builder.ClearInsertionPoint();
- return;
+ // Adjust BI to point to the first cleanup block.
+ {
+ EHCleanupScope &Scope =
+ cast<EHCleanupScope>(*EHStack.find(InnermostCleanup));
+ BI->setSuccessor(0, CreateEHEntry(*this, Scope));
}
-
- for (EHScopeStack::iterator I = EHStack.begin(),
- E = EHStack.find(Dest.ScopeDepth); I != E; ++I) {
- if (isa<EHCleanupScope>(*I)) {
- EHCleanupScope &Scope = cast<EHCleanupScope>(*I);
- if (Scope.isNormalCleanup())
- ThreadFixupThroughCleanup(*this, Fixup, Scope.getNormalEntry(),
- Scope.getNormalExit());
- } else if (isa<EHLazyCleanupScope>(*I)) {
- EHLazyCleanupScope &Scope = cast<EHLazyCleanupScope>(*I);
- if (Scope.isNormalCleanup()) {
- llvm::BasicBlock *Block = Scope.getNormalBlock();
- if (!Block) {
- Block = createBasicBlock("cleanup");
- Scope.setNormalBlock(Block);
- }
- ThreadFixupThroughCleanup(*this, Fixup, Block, Block);
- }
+
+ // Add this destination to all the scopes involved.
+ for (EHScopeStack::stable_iterator
+ I = InnermostCleanup, E = Dest.getScopeDepth(); ; ) {
+ assert(E.strictlyEncloses(I));
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I));
+ assert(Scope.isEHCleanup());
+ I = Scope.getEnclosingEHCleanup();
+
+ // If this is the last cleanup we're propagating through, add this
+ // as a branch-after.
+ if (I == E) {
+ Scope.addEHBranchAfter(Index, Dest.getBlock());
+ break;
}
+
+ // Otherwise, add it as a branch-through. If this isn't new
+ // information, all the rest of the work has been done before.
+ if (!Scope.addEHBranchThrough(Dest.getBlock()))
+ break;
}
Builder.ClearInsertionPoint();
}
-void CodeGenFunction::EmitBranchThroughEHCleanup(JumpDest Dest) {
- if (!HaveInsertPoint())
- return;
+/// All the branch fixups on the EH stack have propagated out past the
+/// outermost normal cleanup; resolve them all by adding cases to the
+/// given switch instruction.
+void CodeGenFunction::ResolveAllBranchFixups(llvm::SwitchInst *Switch) {
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> CasesAdded;
+
+ for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) {
+ // Skip this fixup if its destination isn't set or if we've
+ // already treated it.
+ BranchFixup &Fixup = EHStack.getBranchFixup(I);
+ if (Fixup.Destination == 0) continue;
+ if (!CasesAdded.insert(Fixup.Destination)) continue;
+
+ Switch->addCase(Builder.getInt32(Fixup.DestinationIndex),
+ Fixup.Destination);
+ }
- // Create the branch.
- llvm::BranchInst *BI = Builder.CreateBr(Dest.Block);
+ EHStack.clearFixups();
+}
- // If we're not in a cleanup scope, we don't need to worry about
- // fixups.
- if (!EHStack.hasEHCleanups()) {
- Builder.ClearInsertionPoint();
- return;
+void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) {
+ assert(Block && "resolving a null target block");
+ if (!EHStack.getNumBranchFixups()) return;
+
+ assert(EHStack.hasNormalCleanups() &&
+ "branch fixups exist with no normal cleanups on stack");
+
+ llvm::SmallPtrSet<llvm::BasicBlock*, 4> ModifiedOptimisticBlocks;
+ bool ResolvedAny = false;
+
+ for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) {
+ // Skip this fixup if its destination doesn't match.
+ BranchFixup &Fixup = EHStack.getBranchFixup(I);
+ if (Fixup.Destination != Block) continue;
+
+ Fixup.Destination = 0;
+ ResolvedAny = true;
+
+ // If it doesn't have an optimistic branch block, LatestBranch is
+ // already pointing to the right place.
+ llvm::BasicBlock *BranchBB = Fixup.OptimisticBranchBlock;
+ if (!BranchBB)
+ continue;
+
+ // Don't process the same optimistic branch block twice.
+ if (!ModifiedOptimisticBlocks.insert(BranchBB))
+ continue;
+
+ llvm::SwitchInst *Switch = TransitionToCleanupSwitch(*this, BranchBB);
+
+ // Add a case to the switch.
+ Switch->addCase(Builder.getInt32(Fixup.DestinationIndex), Block);
}
- // Initialize a fixup.
- BranchFixup Fixup;
- Fixup.Destination = Dest.Block;
- Fixup.Origin = BI;
- Fixup.LatestBranch = BI;
- Fixup.LatestBranchIndex = 0;
-
- // We should never get invalid scope depths for these: invalid scope
- // depths only arise for as-yet-unemitted labels, and we can't do an
- // EH-unwind to one of those.
- assert(Dest.ScopeDepth.isValid() && "invalid scope depth on EH dest?");
-
- for (EHScopeStack::iterator I = EHStack.begin(),
- E = EHStack.find(Dest.ScopeDepth); I != E; ++I) {
- if (isa<EHCleanupScope>(*I)) {
- EHCleanupScope &Scope = cast<EHCleanupScope>(*I);
- if (Scope.isEHCleanup())
- ThreadFixupThroughCleanup(*this, Fixup, Scope.getEHEntry(),
- Scope.getEHExit());
- } else if (isa<EHLazyCleanupScope>(*I)) {
- EHLazyCleanupScope &Scope = cast<EHLazyCleanupScope>(*I);
- if (Scope.isEHCleanup()) {
- llvm::BasicBlock *Block = Scope.getEHBlock();
- if (!Block) {
- Block = createBasicBlock("eh.cleanup");
- Scope.setEHBlock(Block);
+ if (ResolvedAny)
+ EHStack.popNullFixups();
+}
+
+/// Activate a cleanup that was created in an inactivated state.
+void CodeGenFunction::ActivateCleanup(EHScopeStack::stable_iterator C) {
+ assert(C != EHStack.stable_end() && "activating bottom of stack?");
+ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C));
+ assert(!Scope.isActive() && "double activation");
+
+ // Calculate whether the cleanup was used:
+ bool Used = false;
+
+ // - as a normal cleanup
+ if (Scope.isNormalCleanup()) {
+ bool NormalUsed = false;
+ if (Scope.getNormalBlock()) {
+ NormalUsed = true;
+ } else {
+ // Check whether any enclosed cleanups were needed.
+ for (EHScopeStack::stable_iterator
+ I = EHStack.getInnermostNormalCleanup(); I != C; ) {
+ assert(C.strictlyEncloses(I));
+ EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I));
+ if (S.getNormalBlock()) {
+ NormalUsed = true;
+ break;
}
- ThreadFixupThroughCleanup(*this, Fixup, Block, Block);
+ I = S.getEnclosingNormalCleanup();
}
}
+
+ if (NormalUsed)
+ Used = true;
+ else
+ Scope.setActivatedBeforeNormalUse(true);
+ }
+
+ // - as an EH cleanup
+ if (Scope.isEHCleanup()) {
+ bool EHUsed = false;
+ if (Scope.getEHBlock()) {
+ EHUsed = true;
+ } else {
+ // Check whether any enclosed cleanups were needed.
+ for (EHScopeStack::stable_iterator
+ I = EHStack.getInnermostEHCleanup(); I != C; ) {
+ assert(C.strictlyEncloses(I));
+ EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I));
+ if (S.getEHBlock()) {
+ EHUsed = true;
+ break;
+ }
+ I = S.getEnclosingEHCleanup();
+ }
+ }
+
+ if (EHUsed)
+ Used = true;
+ else
+ Scope.setActivatedBeforeEHUse(true);
}
- Builder.ClearInsertionPoint();
+ llvm::AllocaInst *Var = EHCleanupScope::activeSentinel();
+ if (Used) {
+ Var = CreateTempAlloca(Builder.getInt1Ty());
+ InitTempAlloca(Var, Builder.getFalse());
+ }
+ Scope.setActiveVar(Var);
+}
+
+llvm::Value *CodeGenFunction::getNormalCleanupDestSlot() {
+ if (!NormalCleanupDest)
+ NormalCleanupDest =
+ CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
+ return NormalCleanupDest;
+}
+
+llvm::Value *CodeGenFunction::getEHCleanupDestSlot() {
+ if (!EHCleanupDest)
+ EHCleanupDest =
+ CreateTempAlloca(Builder.getInt32Ty(), "eh.cleanup.dest.slot");
+ return EHCleanupDest;
+}
+
+void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
+ llvm::ConstantInt *Init) {
+ assert (Init && "Invalid DeclRefExpr initializer!");
+ if (CGDebugInfo *Dbg = getDebugInfo())
+ Dbg->EmitGlobalVariable(E->getDecl(), Init, Builder);
}
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 5ee3db08eea0..4f0420536ad2 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -41,6 +41,7 @@ namespace llvm {
}
namespace clang {
+ class APValue;
class ASTContext;
class CXXDestructorDecl;
class CXXTryStmt;
@@ -69,6 +70,7 @@ namespace CodeGen {
class CGFunctionInfo;
class CGRecordLayout;
class CGBlockInfo;
+ class CGCXXABI;
/// A branch fixup. These are required when emitting a goto to a
/// label which hasn't been emitted yet. The goto is optimistically
@@ -77,25 +79,34 @@ namespace CodeGen {
/// the innermost cleanup. When a (normal) cleanup is popped, any
/// unresolved fixups in that scope are threaded through the cleanup.
struct BranchFixup {
- /// The origin of the branch. Any switch-index stores required by
- /// cleanup threading are added before this instruction.
- llvm::Instruction *Origin;
+ /// The block containing the terminator which needs to be modified
+ /// into a switch if this fixup is resolved into the current scope.
+ /// If null, LatestBranch points directly to the destination.
+ llvm::BasicBlock *OptimisticBranchBlock;
- /// The destination of the branch.
+ /// The ultimate destination of the branch.
///
/// This can be set to null to indicate that this fixup was
/// successfully resolved.
llvm::BasicBlock *Destination;
- /// The last branch of the fixup. It is an invariant that
- /// LatestBranch->getSuccessor(LatestBranchIndex) == Destination.
- ///
- /// The branch is always either a BranchInst or a SwitchInst.
- llvm::TerminatorInst *LatestBranch;
- unsigned LatestBranchIndex;
+ /// The destination index value.
+ unsigned DestinationIndex;
+
+ /// The initial branch of the fixup.
+ llvm::BranchInst *InitialBranch;
};
-enum CleanupKind { NormalAndEHCleanup, EHCleanup, NormalCleanup };
+enum CleanupKind {
+ EHCleanup = 0x1,
+ NormalCleanup = 0x2,
+ NormalAndEHCleanup = EHCleanup | NormalCleanup,
+
+ InactiveCleanup = 0x4,
+ InactiveEHCleanup = EHCleanup | InactiveCleanup,
+ InactiveNormalCleanup = NormalCleanup | InactiveCleanup,
+ InactiveNormalAndEHCleanup = NormalAndEHCleanup | InactiveCleanup
+};
/// A stack of scopes which respond to exceptions, including cleanups
/// and catch blocks.
@@ -117,6 +128,17 @@ public:
bool isValid() const { return Size >= 0; }
+ /// Returns true if this scope encloses I.
+ /// Returns false if I is invalid.
+ /// This scope must be valid.
+ bool encloses(stable_iterator I) const { return Size <= I.Size; }
+
+ /// Returns true if this scope strictly encloses I: that is,
+ /// if it encloses I and is not I.
+ /// Returns false is I is invalid.
+ /// This scope must be valid.
+ bool strictlyEncloses(stable_iterator I) const { return Size < I.Size; }
+
friend bool operator==(stable_iterator A, stable_iterator B) {
return A.Size == B.Size;
}
@@ -125,13 +147,14 @@ public:
}
};
- /// A lazy cleanup. Subclasses must be POD-like: cleanups will
- /// not be destructed, and they will be allocated on the cleanup
- /// stack and freely copied and moved around.
+ /// Information for lazily generating a cleanup. Subclasses must be
+ /// POD-like: cleanups will not be destructed, and they will be
+ /// allocated on the cleanup stack and freely copied and moved
+ /// around.
///
- /// LazyCleanup implementations should generally be declared in an
+ /// Cleanup implementations should generally be declared in an
/// anonymous namespace.
- class LazyCleanup {
+ class Cleanup {
public:
// Anchor the construction vtable. We use the destructor because
// gcc gives an obnoxious warning if there are virtual methods
@@ -140,7 +163,7 @@ public:
// doesn't seem to be any other way around this warning.
//
// This destructor will never be called.
- virtual ~LazyCleanup();
+ virtual ~Cleanup();
/// Emit the cleanup. For normal cleanups, this is run in the
/// same EH context as when the cleanup was pushed, i.e. the
@@ -177,6 +200,11 @@ private:
/// The number of catches on the stack.
unsigned CatchDepth;
+ /// The current EH destination index. Reset to FirstCatchIndex
+ /// whenever the last EH cleanup is popped.
+ unsigned NextEHDestIndex;
+ enum { FirstEHDestIndex = 1 };
+
/// The current set of branch fixups. A branch fixup is a jump to
/// an as-yet unemitted label, i.e. a label for which we don't yet
/// know the EH stack depth. Whenever we pop a cleanup, we have
@@ -198,64 +226,64 @@ private:
char *allocate(size_t Size);
- void popNullFixups();
-
- void *pushLazyCleanup(CleanupKind K, size_t DataSize);
+ void *pushCleanup(CleanupKind K, size_t DataSize);
public:
EHScopeStack() : StartOfBuffer(0), EndOfBuffer(0), StartOfData(0),
InnermostNormalCleanup(stable_end()),
InnermostEHCleanup(stable_end()),
- CatchDepth(0) {}
+ CatchDepth(0), NextEHDestIndex(FirstEHDestIndex) {}
~EHScopeStack() { delete[] StartOfBuffer; }
// Variadic templates would make this not terrible.
/// Push a lazily-created cleanup on the stack.
template <class T>
- void pushLazyCleanup(CleanupKind Kind) {
- void *Buffer = pushLazyCleanup(Kind, sizeof(T));
- LazyCleanup *Obj = new(Buffer) T();
+ void pushCleanup(CleanupKind Kind) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T();
(void) Obj;
}
/// Push a lazily-created cleanup on the stack.
template <class T, class A0>
- void pushLazyCleanup(CleanupKind Kind, A0 a0) {
- void *Buffer = pushLazyCleanup(Kind, sizeof(T));
- LazyCleanup *Obj = new(Buffer) T(a0);
+ void pushCleanup(CleanupKind Kind, A0 a0) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0);
(void) Obj;
}
/// Push a lazily-created cleanup on the stack.
template <class T, class A0, class A1>
- void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1) {
- void *Buffer = pushLazyCleanup(Kind, sizeof(T));
- LazyCleanup *Obj = new(Buffer) T(a0, a1);
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1);
(void) Obj;
}
/// Push a lazily-created cleanup on the stack.
template <class T, class A0, class A1, class A2>
- void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
- void *Buffer = pushLazyCleanup(Kind, sizeof(T));
- LazyCleanup *Obj = new(Buffer) T(a0, a1, a2);
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2);
(void) Obj;
}
/// Push a lazily-created cleanup on the stack.
template <class T, class A0, class A1, class A2, class A3>
- void pushLazyCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
- void *Buffer = pushLazyCleanup(Kind, sizeof(T));
- LazyCleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3);
(void) Obj;
}
- /// Push a cleanup on the stack.
- void pushCleanup(llvm::BasicBlock *NormalEntry,
- llvm::BasicBlock *NormalExit,
- llvm::BasicBlock *EHEntry,
- llvm::BasicBlock *EHExit);
+ /// Push a lazily-created cleanup on the stack.
+ template <class T, class A0, class A1, class A2, class A3, class A4>
+ void pushCleanup(CleanupKind Kind, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) {
+ void *Buffer = pushCleanup(Kind, sizeof(T));
+ Cleanup *Obj = new(Buffer) T(a0, a1, a2, a3, a4);
+ (void) Obj;
+ }
/// Pops a cleanup scope off the stack. This should only be called
/// by CodeGenFunction::PopCleanupBlock.
@@ -298,6 +326,7 @@ public:
stable_iterator getInnermostNormalCleanup() const {
return InnermostNormalCleanup;
}
+ stable_iterator getInnermostActiveNormalCleanup() const; // CGException.h
/// Determines whether there are any EH cleanups on the stack.
bool hasEHCleanups() const {
@@ -309,6 +338,7 @@ public:
stable_iterator getInnermostEHCleanup() const {
return InnermostEHCleanup;
}
+ stable_iterator getInnermostActiveEHCleanup() const; // CGException.h
/// An unstable reference to a scope-stack depth. Invalidated by
/// pushes but not pops.
@@ -359,8 +389,17 @@ public:
return BranchFixups[I];
}
- /// Mark any branch fixups leading to the given block as resolved.
- void resolveBranchFixups(llvm::BasicBlock *Dest);
+ /// Pops lazily-removed fixups from the end of the list. This
+ /// should only be called by procedures which have just popped a
+ /// cleanup or resolved one or more fixups.
+ void popNullFixups();
+
+ /// Clears the branch-fixups list. This should only be called by
+ /// CodeGenFunction::ResolveAllBranchFixups.
+ void clearFixups() { BranchFixups.clear(); }
+
+ /// Gets the next EH destination index.
+ unsigned getNextEHDestIndex() { return NextEHDestIndex++; }
};
/// CodeGenFunction - This class organizes the per-function state that is used
@@ -368,17 +407,47 @@ public:
class CodeGenFunction : public BlockFunction {
CodeGenFunction(const CodeGenFunction&); // DO NOT IMPLEMENT
void operator=(const CodeGenFunction&); // DO NOT IMPLEMENT
+
+ friend class CGCXXABI;
public:
- /// A jump destination is a pair of a basic block and a cleanup
- /// depth. They are used to implement direct jumps across cleanup
- /// scopes, e.g. goto, break, continue, and return.
+ /// A jump destination is an abstract label, branching to which may
+ /// require a jump out through normal cleanups.
struct JumpDest {
- JumpDest() : Block(0), ScopeDepth() {}
- JumpDest(llvm::BasicBlock *Block, EHScopeStack::stable_iterator Depth)
- : Block(Block), ScopeDepth(Depth) {}
+ JumpDest() : Block(0), ScopeDepth(), Index(0) {}
+ JumpDest(llvm::BasicBlock *Block,
+ EHScopeStack::stable_iterator Depth,
+ unsigned Index)
+ : Block(Block), ScopeDepth(Depth), Index(Index) {}
+
+ bool isValid() const { return Block != 0; }
+ llvm::BasicBlock *getBlock() const { return Block; }
+ EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }
+ unsigned getDestIndex() const { return Index; }
+ private:
+ llvm::BasicBlock *Block;
+ EHScopeStack::stable_iterator ScopeDepth;
+ unsigned Index;
+ };
+
+ /// An unwind destination is an abstract label, branching to which
+ /// may require a jump out through EH cleanups.
+ struct UnwindDest {
+ UnwindDest() : Block(0), ScopeDepth(), Index(0) {}
+ UnwindDest(llvm::BasicBlock *Block,
+ EHScopeStack::stable_iterator Depth,
+ unsigned Index)
+ : Block(Block), ScopeDepth(Depth), Index(Index) {}
+
+ bool isValid() const { return Block != 0; }
+ llvm::BasicBlock *getBlock() const { return Block; }
+ EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; }
+ unsigned getDestIndex() const { return Index; }
+
+ private:
llvm::BasicBlock *Block;
EHScopeStack::stable_iterator ScopeDepth;
+ unsigned Index;
};
CodeGenModule &CGM; // Per-module state.
@@ -406,6 +475,9 @@ public:
/// iff the function has no return value.
llvm::Value *ReturnValue;
+ /// RethrowBlock - Unified rethrow block.
+ UnwindDest RethrowBlock;
+
/// AllocaInsertPoint - This is an instruction in the entry block before which
/// we prefer to insert allocas.
llvm::AssertingVH<llvm::Instruction> AllocaInsertPt;
@@ -423,6 +495,12 @@ public:
EHScopeStack EHStack;
+ /// i32s containing the indexes of the cleanup destinations.
+ llvm::AllocaInst *NormalCleanupDest;
+ llvm::AllocaInst *EHCleanupDest;
+
+ unsigned NextCleanupDestIndex;
+
/// The exception slot. All landing pads write the current
/// exception pointer into this alloca.
llvm::Value *ExceptionSlot;
@@ -454,30 +532,17 @@ public:
/// non-trivial destructor.
void PushDestructorCleanup(QualType T, llvm::Value *Addr);
+ /// PushDestructorCleanup - Push a cleanup to call the
+ /// complete-object variant of the given destructor on the object at
+ /// the given address.
+ void PushDestructorCleanup(const CXXDestructorDecl *Dtor,
+ llvm::Value *Addr);
+
/// PopCleanupBlock - Will pop the cleanup entry on the stack and
/// process all branch fixups.
- void PopCleanupBlock();
-
- /// CleanupBlock - RAII object that will create a cleanup block and
- /// set the insert point to that block. When destructed, it sets the
- /// insert point to the previous block and pushes a new cleanup
- /// entry on the stack.
- class CleanupBlock {
- CodeGenFunction &CGF;
- CGBuilderTy::InsertPoint SavedIP;
- llvm::BasicBlock *NormalCleanupEntryBB;
- llvm::BasicBlock *NormalCleanupExitBB;
- llvm::BasicBlock *EHCleanupEntryBB;
-
- public:
- CleanupBlock(CodeGenFunction &CGF, CleanupKind Kind);
+ void PopCleanupBlock(bool FallThroughIsBranchThrough = false);
- /// If we're currently writing a normal cleanup, tie that off and
- /// start writing an EH cleanup.
- void beginEHCleanup();
-
- ~CleanupBlock();
- };
+ void ActivateCleanup(EHScopeStack::stable_iterator Cleanup);
/// \brief Enters a new scope for capturing cleanups, all of which
/// will be executed once the scope is exited.
@@ -528,18 +593,23 @@ public:
/// the cleanup blocks that have been added.
void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize);
+ void ResolveAllBranchFixups(llvm::SwitchInst *Switch);
+ void ResolveBranchFixups(llvm::BasicBlock *Target);
+
/// The given basic block lies in the current EH scope, but may be a
/// target of a potentially scope-crossing jump; get a stable handle
/// to which we can perform this jump later.
- JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target) const {
- return JumpDest(Target, EHStack.stable_begin());
+ JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target) {
+ return JumpDest(Target,
+ EHStack.getInnermostNormalCleanup(),
+ NextCleanupDestIndex++);
}
/// The given basic block lies in the current EH scope, but may be a
/// target of a potentially scope-crossing jump; get a stable handle
/// to which we can perform this jump later.
JumpDest getJumpDestInCurrentScope(const char *Name = 0) {
- return JumpDest(createBasicBlock(Name), EHStack.stable_begin());
+ return getJumpDestInCurrentScope(createBasicBlock(Name));
}
/// EmitBranchThroughCleanup - Emit a branch from the current insert
@@ -550,7 +620,11 @@ public:
/// EmitBranchThroughEHCleanup - Emit a branch from the current
/// insert block through the EH cleanup handling code (if any) and
/// then on to \arg Dest.
- void EmitBranchThroughEHCleanup(JumpDest Dest);
+ void EmitBranchThroughEHCleanup(UnwindDest Dest);
+
+ /// getRethrowDest - Returns the unified outermost-scope rethrow
+ /// destination.
+ UnwindDest getRethrowDest();
/// BeginConditionalBranch - Should be called before a conditional part of an
/// expression is emitted. For example, before the RHS of the expression below
@@ -608,10 +682,6 @@ private:
/// statement range in current switch instruction.
llvm::BasicBlock *CaseRangeBlock;
- /// InvokeDest - This is the nearest exception target for calls
- /// which can unwind, when exceptions are being used.
- llvm::BasicBlock *InvokeDest;
-
// VLASizeMap - This keeps track of the associated size for each VLA type.
// We track this by the size expression rather than the type itself because
// in certain situations, like a const qualifier applied to an VLA typedef,
@@ -661,6 +731,7 @@ private:
public:
CodeGenFunction(CodeGenModule &cgm);
+ CodeGenTypes &getTypes() const { return CGM.getTypes(); }
ASTContext &getContext() const;
CGDebugInfo *getDebugInfo() { return DebugInfo; }
@@ -668,6 +739,9 @@ public:
/// is assigned in every landing pad.
llvm::Value *getExceptionSlot();
+ llvm::Value *getNormalCleanupDestSlot();
+ llvm::Value *getEHCleanupDestSlot();
+
llvm::BasicBlock *getUnreachableBlock() {
if (!UnreachableBlock) {
UnreachableBlock = createBasicBlock("unreachable");
@@ -711,15 +785,16 @@ public:
llvm::Value *BuildBlockLiteralTmp(const BlockExpr *);
llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
- bool BlockHasCopyDispose,
- CharUnits Size,
+ const CGBlockInfo &Info,
const llvm::StructType *,
+ llvm::Constant *BlockVarLayout,
std::vector<HelperInfo> *);
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
const BlockExpr *BExpr,
CGBlockInfo &Info,
const Decl *OuterFuncDecl,
+ llvm::Constant *& BlockVarLayout,
llvm::DenseMap<const Decl*, llvm::Value*> ldm);
llvm::Value *LoadBlockStruct();
@@ -777,11 +852,11 @@ public:
void InitializeVTablePointers(const CXXRecordDecl *ClassDecl);
- /// EmitDtorEpilogue - Emit all code that comes at the end of class's
- /// destructor. This is to call destructors on members and base classes in
- /// reverse order of their construction.
- void EmitDtorEpilogue(const CXXDestructorDecl *Dtor,
- CXXDtorType Type);
+ /// EnterDtorCleanups - Enter the cleanups necessary to complete the
+ /// given phase of destruction for a destructor. The end result
+ /// should call destructors on members and base classes in reverse
+ /// order of their construction.
+ void EnterDtorCleanups(const CXXDestructorDecl *Dtor, CXXDtorType Type);
/// ShouldInstrumentFunction - Return true if the current function should be
/// instrumented with __cyg_profile_func_* calls
@@ -898,10 +973,8 @@ public:
// Helpers
//===--------------------------------------------------------------------===//
- Qualifiers MakeQualifiers(QualType T) {
- Qualifiers Quals = getContext().getCanonicalType(T).getQualifiers();
- Quals.setObjCGCAttr(getContext().getObjCGCAttrKind(T));
- return Quals;
+ LValue MakeAddrLValue(llvm::Value *V, QualType T, unsigned Alignment = 0) {
+ return LValue::MakeAddr(V, T, Alignment, getContext());
}
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
@@ -965,10 +1038,16 @@ public:
void StartBlock(const char *N);
/// GetAddrOfStaticLocalVar - Return the address of a static local variable.
- llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD);
+ llvm::Constant *GetAddrOfStaticLocalVar(const VarDecl *BVD) {
+ return cast<llvm::Constant>(GetAddrOfLocalVar(BVD));
+ }
/// GetAddrOfLocalVar - Return the address of a local variable.
- llvm::Value *GetAddrOfLocalVar(const VarDecl *VD);
+ llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
+ llvm::Value *Res = LocalDeclMap[VD];
+ assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
+ return Res;
+ }
/// getAccessedFieldNo - Given an encoded value and a result number, return
/// the input field number being accessed.
@@ -1025,12 +1104,14 @@ public:
/// load of 'this' and returns address of the base class.
llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
const CXXRecordDecl *Derived,
- const CXXBaseSpecifierArray &BasePath,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
bool NullCheckValue);
llvm::Value *GetVirtualBaseClassOffset(llvm::Value *This,
@@ -1049,13 +1130,15 @@ public:
const ConstantArrayType *ArrayTy,
llvm::Value *ArrayPtr,
CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd);
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization = false);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *NumElements,
llvm::Value *ArrayPtr,
CallExpr::const_arg_iterator ArgBeg,
- CallExpr::const_arg_iterator ArgEnd);
+ CallExpr::const_arg_iterator ArgEnd,
+ bool ZeroInitialization = false);
void EmitCXXAggrDestructorCall(const CXXDestructorDecl *D,
const ArrayType *Array,
@@ -1224,13 +1307,13 @@ public:
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.
llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
- QualType Ty);
+ unsigned Alignment, QualType Ty);
/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.
void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
- bool Volatile, QualType Ty);
+ bool Volatile, unsigned Alignment, QualType Ty);
/// EmitLoadOfLValue - Given an expression that represents a value lvalue,
/// this method emits the address of the lvalue, then loads the result as an
@@ -1270,7 +1353,6 @@ public:
LValue EmitDeclRefLValue(const DeclRefExpr *E);
LValue EmitStringLiteralLValue(const StringLiteral *E);
LValue EmitObjCEncodeExprLValue(const ObjCEncodeExpr *E);
- LValue EmitPredefinedFunctionName(unsigned Type);
LValue EmitPredefinedLValue(const PredefinedExpr *E);
LValue EmitUnaryOpLValue(const UnaryOperator *E);
LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E);
@@ -1319,7 +1401,7 @@ public:
LValue EmitStmtExprLValue(const StmtExpr *E);
LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
-
+ void EmitDeclRefExprDbgValue(const DeclRefExpr *E, llvm::ConstantInt *Init);
//===--------------------------------------------------------------------===//
// Scalar Expression Emission
//===--------------------------------------------------------------------===//
@@ -1386,7 +1468,8 @@ public:
llvm::SmallVectorImpl<llvm::Value*> &O,
const char *name, bool splat = false,
unsigned shift = 0, bool rightshift = false);
- llvm::Value *EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx);
+ llvm::Value *EmitNeonSplat(llvm::Value *V, llvm::Constant *Idx,
+ bool widen = false);
llvm::Value *EmitNeonShiftVector(llvm::Value *V, const llvm::Type *Ty,
bool negateForRightShift);
@@ -1542,7 +1625,7 @@ public:
/// getTrapBB - Create a basic block that will call the trap intrinsic. We'll
/// generate a branch around the created basic block as necessary.
- llvm::BasicBlock* getTrapBB();
+ llvm::BasicBlock *getTrapBB();
/// EmitCallArg - Emit a single call argument.
RValue EmitCallArg(const Expr *E, QualType ArgType);
@@ -1575,6 +1658,11 @@ private:
const TargetInfo::ConstraintInfo &Info,
const Expr *InputExpr, std::string &ConstraintStr);
+ llvm::Value* EmitAsmInputLValue(const AsmStmt &S,
+ const TargetInfo::ConstraintInfo &Info,
+ LValue InputValue, QualType InputType,
+ std::string &ConstraintStr);
+
/// EmitCallArgs - Emit call arguments for a function.
/// The CallArgTypeInfo parameter is used for iterating over the known
/// argument types of the function being called.
@@ -1622,7 +1710,36 @@ private:
void EmitDeclMetadata();
};
-
+/// CGBlockInfo - Information to generate a block literal.
+class CGBlockInfo {
+public:
+ /// Name - The name of the block, kindof.
+ const char *Name;
+
+ /// DeclRefs - Variables from parent scopes that have been
+ /// imported into this block.
+ llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
+
+ /// InnerBlocks - This block and the blocks it encloses.
+ llvm::SmallPtrSet<const DeclContext *, 4> InnerBlocks;
+
+ /// CXXThisRef - Non-null if 'this' was required somewhere, in
+ /// which case this is that expression.
+ const CXXThisExpr *CXXThisRef;
+
+ /// NeedsObjCSelf - True if something in this block has an implicit
+ /// reference to 'self'.
+ bool NeedsObjCSelf;
+
+ /// These are initialized by GenerateBlockFunction.
+ bool BlockHasCopyDispose;
+ CharUnits BlockSize;
+ CharUnits BlockAlign;
+ llvm::SmallVector<const Expr*, 8> BlockLayout;
+
+ CGBlockInfo(const char *Name);
+};
+
} // end namespace CodeGen
} // end namespace clang
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index bf606a616582..d125b370a07a 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -15,6 +15,7 @@
#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "CGCall.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "Mangle.h"
#include "TargetInfo.h"
@@ -41,6 +42,17 @@
using namespace clang;
using namespace CodeGen;
+static CGCXXABI &createCXXABI(CodeGenModule &CGM) {
+ switch (CGM.getContext().Target.getCXXABI()) {
+ case CXXABI_ARM: return *CreateARMCXXABI(CGM);
+ case CXXABI_Itanium: return *CreateItaniumCXXABI(CGM);
+ case CXXABI_Microsoft: return *CreateMicrosoftCXXABI(CGM);
+ }
+
+ llvm_unreachable("invalid C++ ABI kind");
+ return *CreateItaniumCXXABI(CGM);
+}
+
CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
llvm::Module &M, const llvm::TargetData &TD,
@@ -48,11 +60,15 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
: BlockModule(C, M, TD, Types, *this), Context(C),
Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags),
- Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()),
- VTables(*this), Runtime(0), ABI(0),
- CFConstantStringClassRef(0),
- NSConstantStringClassRef(0),
- VMContext(M.getContext()) {
+ ABI(createCXXABI(*this)),
+ Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI),
+ VTables(*this), Runtime(0),
+ CFConstantStringClassRef(0), NSConstantStringClassRef(0),
+ VMContext(M.getContext()),
+ NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0),
+ NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),
+ BlockObjectAssignDecl(0), BlockObjectDisposeDecl(0),
+ BlockObjectAssign(0), BlockObjectDispose(0){
if (!Features.ObjC1)
Runtime = 0;
@@ -63,17 +79,13 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
else
Runtime = CreateMacObjCRuntime(*this);
- if (!Features.CPlusPlus)
- ABI = 0;
- else createCXXABI();
-
// If debug info generation is enabled, create the CGDebugInfo object.
DebugInfo = CodeGenOpts.DebugInfo ? new CGDebugInfo(*this) : 0;
}
CodeGenModule::~CodeGenModule() {
delete Runtime;
- delete ABI;
+ delete &ABI;
delete DebugInfo;
}
@@ -86,13 +98,6 @@ void CodeGenModule::createObjCRuntime() {
Runtime = CreateMacObjCRuntime(*this);
}
-void CodeGenModule::createCXXABI() {
- if (Context.Target.getCXXABI() == "microsoft")
- ABI = CreateMicrosoftCXXABI(*this);
- else
- ABI = CreateItaniumCXXABI(*this);
-}
-
void CodeGenModule::Release() {
EmitDeferred();
EmitCXXGlobalInitFunc();
@@ -141,17 +146,17 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
LangOptions::VisibilityMode
CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
- if (VD->getStorageClass() == VarDecl::PrivateExtern)
+ if (VD->getStorageClass() == SC_PrivateExtern)
return LangOptions::Hidden;
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
switch (attr->getVisibility()) {
default: assert(0 && "Unknown visibility!");
- case VisibilityAttr::DefaultVisibility:
+ case VisibilityAttr::Default:
return LangOptions::Default;
- case VisibilityAttr::HiddenVisibility:
+ case VisibilityAttr::Hidden:
return LangOptions::Hidden;
- case VisibilityAttr::ProtectedVisibility:
+ case VisibilityAttr::Protected:
return LangOptions::Protected;
}
}
@@ -187,9 +192,11 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
return LangOptions::Hidden;
}
- // This decl should have the same visibility as its parent.
+ // If this decl is contained in a class, it should have the same visibility
+ // as the parent class.
if (const DeclContext *DC = D->getDeclContext())
- return getDeclVisibilityMode(cast<Decl>(DC));
+ if (DC->isRecord())
+ return getDeclVisibilityMode(cast<Decl>(DC));
return getLangOptions().getVisibilityMode();
}
@@ -213,6 +220,67 @@ void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
}
}
+/// Set the symbol visibility of type information (vtable and RTTI)
+/// associated with the given type.
+void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
+ const CXXRecordDecl *RD,
+ bool IsForRTTI) const {
+ setGlobalVisibility(GV, RD);
+
+ if (!CodeGenOpts.HiddenWeakVTables)
+ return;
+
+ // We want to drop the visibility to hidden for weak type symbols.
+ // This isn't possible if there might be unresolved references
+ // elsewhere that rely on this symbol being visible.
+
+ // This should be kept roughly in sync with setThunkVisibility
+ // in CGVTables.cpp.
+
+ // Preconditions.
+ if (GV->getLinkage() != llvm::GlobalVariable::WeakODRLinkage ||
+ GV->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
+ return;
+
+ // Don't override an explicit visibility attribute.
+ if (RD->hasAttr<VisibilityAttr>())
+ return;
+
+ switch (RD->getTemplateSpecializationKind()) {
+ // We have to disable the optimization if this is an EI definition
+ // because there might be EI declarations in other shared objects.
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitInstantiationDeclaration:
+ return;
+
+ // Every use of a non-template class's type information has to emit it.
+ case TSK_Undeclared:
+ break;
+
+ // In theory, implicit instantiations can ignore the possibility of
+ // an explicit instantiation declaration because there necessarily
+ // must be an EI definition somewhere with default visibility. In
+ // practice, it's possible to have an explicit instantiation for
+ // an arbitrary template class, and linkers aren't necessarily able
+ // to deal with mixed-visibility symbols.
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ if (!CodeGenOpts.HiddenWeakTemplateVTables)
+ return;
+ break;
+ }
+
+ // If there's a key function, there may be translation units
+ // that don't have the key function's definition. But ignore
+ // this if we're emitting RTTI under -fno-rtti.
+ if (!IsForRTTI || Features.RTTI)
+ if (Context.getKeyFunction(RD))
+ return;
+
+ // Otherwise, drop the visibility to hidden.
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+}
+
llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
@@ -220,7 +288,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
if (!Str.empty())
return Str;
- if (!getMangleContext().shouldMangleDeclName(ND)) {
+ if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
IdentifierInfo *II = ND->getIdentifier();
assert(II && "Attempt to mangle unnamed decl.");
@@ -230,13 +298,13 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
llvm::SmallString<256> Buffer;
if (const CXXConstructorDecl *D = dyn_cast<CXXConstructorDecl>(ND))
- getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer);
+ getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Buffer);
else if (const CXXDestructorDecl *D = dyn_cast<CXXDestructorDecl>(ND))
- getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer);
+ getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer);
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND))
- getMangleContext().mangleBlock(GD, BD, Buffer);
+ getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer);
else
- getMangleContext().mangleName(ND, Buffer);
+ getCXXABI().getMangleContext().mangleName(ND, Buffer);
// Allocate space for the mangled name.
size_t Length = Buffer.size();
@@ -250,7 +318,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
void CodeGenModule::getMangledName(GlobalDecl GD, MangleBuffer &Buffer,
const BlockDecl *BD) {
- getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer());
+ getCXXABI().getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer());
}
llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) {
@@ -319,68 +387,9 @@ void CodeGenModule::EmitAnnotations() {
gv->setSection("llvm.metadata");
}
-static CodeGenModule::GVALinkage
-GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
- const LangOptions &Features) {
- CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
-
- Linkage L = FD->getLinkage();
- if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
- FD->getType()->getLinkage() == UniqueExternalLinkage)
- L = UniqueExternalLinkage;
-
- switch (L) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
- return CodeGenModule::GVA_Internal;
-
- case ExternalLinkage:
- switch (FD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- External = CodeGenModule::GVA_StrongExternal;
- break;
-
- case TSK_ExplicitInstantiationDefinition:
- return CodeGenModule::GVA_ExplicitTemplateInstantiation;
-
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ImplicitInstantiation:
- External = CodeGenModule::GVA_TemplateInstantiation;
- break;
- }
- }
-
- if (!FD->isInlined())
- return External;
-
- if (!Features.CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
- // GNU or C99 inline semantics. Determine whether this symbol should be
- // externally visible.
- if (FD->isInlineDefinitionExternallyVisible())
- return External;
-
- // C99 inline semantics, where the symbol is not externally visible.
- return CodeGenModule::GVA_C99Inline;
- }
-
- // C++0x [temp.explicit]p9:
- // [ Note: The intent is that an inline function that is the subject of
- // an explicit instantiation declaration will still be implicitly
- // instantiated when used so that the body can be considered for
- // inlining, but that no out-of-line copy of the inline function would be
- // generated in the translation unit. -- end note ]
- if (FD->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDeclaration)
- return CodeGenModule::GVA_C99Inline;
-
- return CodeGenModule::GVA_CXXInline;
-}
-
llvm::GlobalValue::LinkageTypes
CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
- GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
+ GVALinkage Linkage = getContext().GetGVALinkageForFunction(D);
if (Linkage == GVA_Internal)
return llvm::Function::InternalLinkage;
@@ -454,12 +463,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
else if (Features.getStackProtectorMode() == LangOptions::SSPReq)
F->addFnAttr(llvm::Attribute::StackProtectReq);
- if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) {
- unsigned width = Context.Target.getCharWidth();
- F->setAlignment(AA->getAlignment() / width);
- while ((AA = AA->getNext<AlignedAttr>()))
- F->setAlignment(std::max(F->getAlignment(), AA->getAlignment() / width));
- }
+ unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();
+ if (alignment)
+ F->setAlignment(alignment);
+
// C++ ABI requires 2-byte alignment for member functions.
if (F->getAlignment() < 2 && isa<CXXMethodDecl>(D))
F->setAlignment(2);
@@ -638,102 +645,12 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
return llvm::ConstantStruct::get(VMContext, Fields, 4, false);
}
-static CodeGenModule::GVALinkage
-GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
- // If this is a static data member, compute the kind of template
- // specialization. Otherwise, this variable is not part of a
- // template.
- TemplateSpecializationKind TSK = TSK_Undeclared;
- if (VD->isStaticDataMember())
- TSK = VD->getTemplateSpecializationKind();
-
- Linkage L = VD->getLinkage();
- if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
- VD->getType()->getLinkage() == UniqueExternalLinkage)
- L = UniqueExternalLinkage;
-
- switch (L) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
- return CodeGenModule::GVA_Internal;
-
- case ExternalLinkage:
- switch (TSK) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- return CodeGenModule::GVA_StrongExternal;
-
- case TSK_ExplicitInstantiationDeclaration:
- llvm_unreachable("Variable should not be instantiated");
- // Fall through to treat this like any other instantiation.
-
- case TSK_ExplicitInstantiationDefinition:
- return CodeGenModule::GVA_ExplicitTemplateInstantiation;
-
- case TSK_ImplicitInstantiation:
- return CodeGenModule::GVA_TemplateInstantiation;
- }
- }
-
- return CodeGenModule::GVA_StrongExternal;
-}
-
bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
- // Never defer when EmitAllDecls is specified or the decl has
- // attribute used.
- if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>())
- return false;
-
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
- // Constructors and destructors should never be deferred.
- if (FD->hasAttr<ConstructorAttr>() ||
- FD->hasAttr<DestructorAttr>())
- return false;
-
- // The key function for a class must never be deferred.
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Global)) {
- const CXXRecordDecl *RD = MD->getParent();
- if (MD->isOutOfLine() && RD->isDynamicClass()) {
- const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD);
- if (KeyFunction &&
- KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl())
- return false;
- }
- }
-
- GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
-
- // static, static inline, always_inline, and extern inline functions can
- // always be deferred. Normal inline functions can be deferred in C99/C++.
- // Implicit template instantiations can also be deferred in C++.
- if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
- Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
- return true;
+ // Never defer when EmitAllDecls is specified.
+ if (Features.EmitAllDecls)
return false;
- }
- const VarDecl *VD = cast<VarDecl>(Global);
- assert(VD->isFileVarDecl() && "Invalid decl");
-
- // We never want to defer structs that have non-trivial constructors or
- // destructors.
-
- // FIXME: Handle references.
- if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
- if (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor())
- return false;
- }
- }
-
- GVALinkage L = GetLinkageForVariable(getContext(), VD);
- if (L == GVA_Internal || L == GVA_TemplateInstantiation) {
- if (!(VD->getInit() && VD->getInit()->HasSideEffects(Context)))
- return true;
- }
-
- return false;
+ return !getContext().DeclMustBeEmitted(Global);
}
llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
@@ -774,6 +691,15 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// Ignore declarations, they will be emitted on their first use.
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
+ if (FD->getIdentifier()) {
+ llvm::StringRef Name = FD->getName();
+ if (Name == "_Block_object_assign") {
+ BlockObjectAssignDecl = FD;
+ } else if (Name == "_Block_object_dispose") {
+ BlockObjectDisposeDecl = FD;
+ }
+ }
+
// Forward declarations are emitted lazily on first use.
if (!FD->isThisDeclarationADefinition())
return;
@@ -781,6 +707,16 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
const VarDecl *VD = cast<VarDecl>(Global);
assert(VD->isFileVarDecl() && "Cannot emit local var decl as global.");
+ if (VD->getIdentifier()) {
+ llvm::StringRef Name = VD->getName();
+ if (Name == "_NSConcreteGlobalBlock") {
+ NSConcreteGlobalBlockDecl = VD;
+ } else if (Name == "_NSConcreteStackBlock") {
+ NSConcreteStackBlockDecl = VD;
+ }
+ }
+
+
if (VD->isThisDeclarationADefinition() != VarDecl::Definition)
return;
}
@@ -792,6 +728,14 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
EmitGlobalDefinition(GD);
return;
}
+
+ // If we're deferring emission of a C++ variable with an
+ // initializer, remember the order in which it appeared in the file.
+ if (getLangOptions().CPlusPlus && isa<VarDecl>(Global) &&
+ cast<VarDecl>(Global)->hasInit()) {
+ DelayedCXXInitPosition[Global] = CXXGlobalInits.size();
+ CXXGlobalInits.push_back(0);
+ }
// If the value has already been used, add it directly to the
// DeferredDeclsToEmit list.
@@ -816,7 +760,8 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// At -O0, don't generate IR for functions with available_externally
// linkage.
- if (CodeGenOpts.OptimizationLevel == 0 &&
+ if (CodeGenOpts.OptimizationLevel == 0 &&
+ !Function->hasAttr<AlwaysInlineAttr>() &&
getFunctionLinkage(Function)
== llvm::Function::AvailableExternallyLinkage)
return;
@@ -1021,7 +966,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
GV->setConstant(DeclIsConstantGlobal(Context, D));
// FIXME: Merge with other attribute handling code.
- if (D->getStorageClass() == VarDecl::PrivateExtern)
+ if (D->getStorageClass() == SC_PrivateExtern)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
if (D->hasAttr<WeakAttr>() ||
@@ -1174,6 +1119,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
ErrorUnsupported(D, "static initializer");
Init = llvm::UndefValue::get(getTypes().ConvertType(T));
}
+ } else {
+ // We don't need an initializer, so remove the entry for the delayed
+ // initializer position (just in case this entry was delayed).
+ if (getLangOptions().CPlusPlus)
+ DelayedCXXInitPosition.erase(D);
}
}
@@ -1235,7 +1185,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
// Set the llvm linkage type as appropriate.
- GVALinkage Linkage = GetLinkageForVariable(getContext(), D);
+ GVALinkage Linkage = getContext().GetGVALinkageForVariable(D);
if (Linkage == GVA_Internal)
GV->setLinkage(llvm::Function::InternalLinkage);
else if (D->hasAttr<DLLImportAttr>())
@@ -1254,7 +1204,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage);
else if (!getLangOptions().CPlusPlus && !CodeGenOpts.NoCommon &&
!D->hasExternalStorage() && !D->getInit() &&
- !D->getAttr<SectionAttr>()) {
+ !D->getAttr<SectionAttr>() && !D->isThreadSpecified()) {
+ // Thread local vars aren't considered common linkage.
GV->setLinkage(llvm::GlobalVariable::CommonLinkage);
// common vars aren't constant even if declared const.
GV->setConstant(false);
@@ -1293,6 +1244,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
// TODO: Do invokes ever occur in C code? If so, we should handle them too.
llvm::Value::use_iterator I = UI++; // Increment before the CI is erased.
llvm::CallInst *CI = dyn_cast<llvm::CallInst>(*I);
+ if (!CI) continue; // FIXME: when we allow Invoke, just do CallSite CS(*I)
llvm::CallSite CS(CI);
if (!CI || !CS.isCallee(I)) continue;
@@ -1343,7 +1295,7 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
const FunctionDecl *D = cast<FunctionDecl>(GD.getDecl());
const llvm::FunctionType *Ty = getTypes().GetFunctionType(GD);
- getMangleContext().mangleInitDiscriminator();
+ getCXXABI().getMangleContext().mangleInitDiscriminator();
// Get or create the prototype for the function.
llvm::Constant *Entry = GetAddrOfFunction(GD, Ty);
@@ -1528,18 +1480,18 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
bool TargetIsLSB,
bool &IsUTF16,
unsigned &StringLength) {
- unsigned NumBytes = Literal->getByteLength();
+ llvm::StringRef String = Literal->getString();
+ unsigned NumBytes = String.size();
// Check for simple case.
if (!Literal->containsNonAsciiOrNull()) {
StringLength = NumBytes;
- return Map.GetOrCreateValue(llvm::StringRef(Literal->getStrData(),
- StringLength));
+ return Map.GetOrCreateValue(String);
}
// Otherwise, convert the UTF8 literals into a byte string.
llvm::SmallVector<UTF16, 128> ToBuf(NumBytes);
- const UTF8 *FromPtr = (UTF8 *)Literal->getStrData();
+ const UTF8 *FromPtr = (UTF8 *)String.data();
UTF16 *ToPtr = &ToBuf[0];
ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes,
@@ -1552,8 +1504,7 @@ GetConstantCFStringEntry(llvm::StringMap<llvm::Constant*> &Map,
// this duplicate code.
assert(Result == sourceIllegal && "UTF-8 to UTF-16 conversion failed");
StringLength = NumBytes;
- return Map.GetOrCreateValue(llvm::StringRef(Literal->getStrData(),
- StringLength));
+ return Map.GetOrCreateValue(String);
}
// ConvertUTF8toUTF16 returns the length in ToPtr.
@@ -1753,20 +1704,17 @@ CodeGenModule::GetAddrOfConstantNSString(const StringLiteral *Literal) {
/// GetStringForStringLiteral - Return the appropriate bytes for a
/// string literal, properly padded to match the literal type.
std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) {
- const char *StrData = E->getStrData();
- unsigned Len = E->getByteLength();
-
const ConstantArrayType *CAT =
getContext().getAsConstantArrayType(E->getType());
assert(CAT && "String isn't pointer or array!");
// Resize the string to the right size.
- std::string Str(StrData, StrData+Len);
uint64_t RealLen = CAT->getSize().getZExtValue();
if (E->isWide())
RealLen *= getContext().Target.getWCharWidth()/8;
+ std::string Str = E->getString().str();
Str.resize(RealLen, '\0');
return Str;
@@ -1894,7 +1842,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
D->getLocation(),
D->getLocation(), cxxSelector,
getContext().VoidTy, 0,
- DC, true, false, true,
+ DC, true, false, true, false,
ObjCMethodDecl::Required);
D->addInstanceMethod(DTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
@@ -1906,7 +1854,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
D->getLocation(),
D->getLocation(), cxxSelector,
getContext().getObjCIdType(), 0,
- DC, true, false, true,
+ DC, true, false, true, false,
ObjCMethodDecl::Required);
D->addInstanceMethod(CTORMethod);
CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
@@ -1993,9 +1941,16 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// Forward declarations, no (immediate) code generation.
case Decl::ObjCClass:
case Decl::ObjCForwardProtocol:
- case Decl::ObjCCategory:
case Decl::ObjCInterface:
break;
+
+ case Decl::ObjCCategory: {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
+ if (CD->IsClassExtension() && CD->hasSynthBitfield())
+ Context.ResetObjCLayout(CD->getClassInterface());
+ break;
+ }
+
case Decl::ObjCProtocol:
Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
@@ -2009,6 +1964,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::ObjCImplementation: {
ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
+ if (Features.ObjCNonFragileABI2 && OMD->hasSynthBitfield())
+ Context.ResetObjCLayout(OMD->getClassInterface());
EmitObjCPropertyImplementations(OMD);
EmitObjCIvarInitializations(OMD);
Runtime->GenerateClass(OMD);
@@ -2118,3 +2075,88 @@ void CodeGenFunction::EmitDeclMetadata() {
}
}
}
+
+///@name Custom Runtime Function Interfaces
+///@{
+//
+// FIXME: These can be eliminated once we can have clients just get the required
+// AST nodes from the builtin tables.
+
+llvm::Constant *CodeGenModule::getBlockObjectDispose() {
+ if (BlockObjectDispose)
+ return BlockObjectDispose;
+
+ // If we saw an explicit decl, use that.
+ if (BlockObjectDisposeDecl) {
+ return BlockObjectDispose = GetAddrOfFunction(
+ BlockObjectDisposeDecl,
+ getTypes().GetFunctionType(BlockObjectDisposeDecl));
+ }
+
+ // Otherwise construct the function by hand.
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(llvm::Type::getInt32Ty(VMContext));
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ return BlockObjectDispose =
+ CreateRuntimeFunction(FTy, "_Block_object_dispose");
+}
+
+llvm::Constant *CodeGenModule::getBlockObjectAssign() {
+ if (BlockObjectAssign)
+ return BlockObjectAssign;
+
+ // If we saw an explicit decl, use that.
+ if (BlockObjectAssignDecl) {
+ return BlockObjectAssign = GetAddrOfFunction(
+ BlockObjectAssignDecl,
+ getTypes().GetFunctionType(BlockObjectAssignDecl));
+ }
+
+ // Otherwise construct the function by hand.
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(llvm::Type::getInt32Ty(VMContext));
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ return BlockObjectAssign =
+ CreateRuntimeFunction(FTy, "_Block_object_assign");
+}
+
+llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
+ if (NSConcreteGlobalBlock)
+ return NSConcreteGlobalBlock;
+
+ // If we saw an explicit decl, use that.
+ if (NSConcreteGlobalBlockDecl) {
+ return NSConcreteGlobalBlock = GetAddrOfGlobalVar(
+ NSConcreteGlobalBlockDecl,
+ getTypes().ConvertType(NSConcreteGlobalBlockDecl->getType()));
+ }
+
+ // Otherwise construct the variable by hand.
+ return NSConcreteGlobalBlock = CreateRuntimeVariable(
+ PtrToInt8Ty, "_NSConcreteGlobalBlock");
+}
+
+llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
+ if (NSConcreteStackBlock)
+ return NSConcreteStackBlock;
+
+ // If we saw an explicit decl, use that.
+ if (NSConcreteStackBlockDecl) {
+ return NSConcreteStackBlock = GetAddrOfGlobalVar(
+ NSConcreteStackBlockDecl,
+ getTypes().ConvertType(NSConcreteStackBlockDecl->getType()));
+ }
+
+ // Otherwise construct the variable by hand.
+ return NSConcreteStackBlock = CreateRuntimeVariable(
+ PtrToInt8Ty, "_NSConcreteStackBlock");
+}
+
+///@}
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 27f15fc018cd..cabff9e1cad5 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -22,7 +22,6 @@
#include "CGCall.h"
#include "CGCXX.h"
#include "CGVTables.h"
-#include "CGCXXABI.h"
#include "CodeGenTypes.h"
#include "GlobalDecl.h"
#include "Mangle.h"
@@ -71,6 +70,7 @@ namespace clang {
namespace CodeGen {
class CodeGenFunction;
+ class CGCXXABI;
class CGDebugInfo;
class CGObjCRuntime;
class MangleBuffer;
@@ -109,6 +109,7 @@ class CodeGenModule : public BlockModule {
const llvm::TargetData &TheTargetData;
mutable const TargetCodeGenInfo *TheTargetCodeGenInfo;
Diagnostic &Diags;
+ CGCXXABI &ABI;
CodeGenTypes Types;
/// VTables - Holds information about C++ vtables.
@@ -116,7 +117,6 @@ class CodeGenModule : public BlockModule {
friend class CodeGenVTables;
CGObjCRuntime* Runtime;
- CXXABI* ABI;
CGDebugInfo* DebugInfo;
// WeakRefReferences - A set of references that have only been seen via
@@ -162,6 +162,12 @@ class CodeGenModule : public BlockModule {
/// CXXGlobalInits - Global variables with initializers that need to run
/// before main.
std::vector<llvm::Constant*> CXXGlobalInits;
+
+ /// When a C++ decl with an initializer is deferred, null is
+ /// appended to CXXGlobalInits, and the index of that null is placed
+ /// here so that the initializer will be performed in the correct
+ /// order.
+ llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
/// - Global variables with initializers whose order of initialization
/// is set by init_priority attribute.
@@ -183,10 +189,23 @@ class CodeGenModule : public BlockModule {
/// Lazily create the Objective-C runtime
void createObjCRuntime();
- /// Lazily create the C++ ABI
- void createCXXABI();
llvm::LLVMContext &VMContext;
+
+ /// @name Cache for Blocks Runtime Globals
+ /// @{
+
+ const VarDecl *NSConcreteGlobalBlockDecl;
+ const VarDecl *NSConcreteStackBlockDecl;
+ llvm::Constant *NSConcreteGlobalBlock;
+ llvm::Constant *NSConcreteStackBlock;
+
+ const FunctionDecl *BlockObjectAssignDecl;
+ const FunctionDecl *BlockObjectDisposeDecl;
+ llvm::Constant *BlockObjectAssign;
+ llvm::Constant *BlockObjectDispose;
+
+ /// @}
public:
CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts,
llvm::Module &M, const llvm::TargetData &TD, Diagnostic &Diags);
@@ -207,15 +226,8 @@ public:
/// been configured.
bool hasObjCRuntime() { return !!Runtime; }
- /// getCXXABI() - Return a reference to the configured
- /// C++ ABI.
- CXXABI &getCXXABI() {
- if (!ABI) createCXXABI();
- return *ABI;
- }
-
- /// hasCXXABI() - Return true iff a C++ ABI has been configured.
- bool hasCXXABI() { return !!ABI; }
+ /// getCXXABI() - Return a reference to the configured C++ ABI.
+ CGCXXABI &getCXXABI() { return ABI; }
llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) {
return StaticLocalDeclMap[VD];
@@ -231,15 +243,11 @@ public:
const LangOptions &getLangOptions() const { return Features; }
llvm::Module &getModule() const { return TheModule; }
CodeGenTypes &getTypes() { return Types; }
- MangleContext &getMangleContext() {
- if (!ABI) createCXXABI();
- return ABI->getMangleContext();
- }
CodeGenVTables &getVTables() { return VTables; }
Diagnostic &getDiags() const { return Diags; }
const llvm::TargetData &getTargetData() const { return TheTargetData; }
llvm::LLVMContext &getLLVMContext() { return VMContext; }
- const TargetCodeGenInfo &getTargetCodeGenInfo() const;
+ const TargetCodeGenInfo &getTargetCodeGenInfo();
bool isTargetDarwin() const;
/// getDeclVisibilityMode - Compute the visibility of the decl \arg D.
@@ -249,6 +257,11 @@ public:
/// GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const;
+ /// setTypeVisibility - Set the visibility for the given global
+ /// value which holds information about a type.
+ void setTypeVisibility(llvm::GlobalValue *GV, const CXXRecordDecl *D,
+ bool IsForRTTI) const;
+
llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
if (isa<CXXConstructorDecl>(GD.getDecl()))
return GetAddrOfCXXConstructor(cast<CXXConstructorDecl>(GD.getDecl()),
@@ -289,7 +302,8 @@ public:
/// a class. Returns null if the offset is 0.
llvm::Constant *
GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
- const CXXBaseSpecifierArray &BasePath);
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd);
/// GetStringForStringLiteral - Return the appropriate bytes for a string
/// literal, properly padded to match the literal type. If only the address of
@@ -344,10 +358,6 @@ public:
llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
CXXDtorType Type);
- // GetCXXMemberFunctionPointerValue - Given a method declaration, return the
- // integer used in a member function pointer to refer to that value.
- llvm::Constant *GetCXXMemberFunctionPointerValue(const CXXMethodDecl *MD);
-
/// getBuiltinLibFunction - Given a builtin id for a function like
/// "__builtin_fabsf", return a Function* for "fabsf".
llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,
@@ -392,6 +402,16 @@ public:
llvm::Constant *CreateRuntimeVariable(const llvm::Type *Ty,
llvm::StringRef Name);
+ ///@name Custom Blocks Runtime Interfaces
+ ///@{
+
+ llvm::Constant *getNSConcreteGlobalBlock();
+ llvm::Constant *getNSConcreteStackBlock();
+ llvm::Constant *getBlockObjectAssign();
+ llvm::Constant *getBlockObjectDispose();
+
+ ///@}
+
void UpdateCompletedType(const TagDecl *TD) {
// Make sure that this type is translated.
Types.UpdateCompletedType(TD);
@@ -411,8 +431,6 @@ public:
llvm::Constant *EmitAnnotateAttr(llvm::GlobalValue *GV,
const AnnotateAttr *AA, unsigned LineNo);
- llvm::Constant *EmitPointerToDataMember(const FieldDecl *FD);
-
/// ErrorUnsupported - Print out an error that codegen doesn't support the
/// specified stmt yet.
/// \param OmitOnError - If true, then this error should only be emitted if no
@@ -473,15 +491,6 @@ public:
void EmitVTable(CXXRecordDecl *Class, bool DefinitionRequired);
- enum GVALinkage {
- GVA_Internal,
- GVA_C99Inline,
- GVA_CXXInline,
- GVA_StrongExternal,
- GVA_TemplateInstantiation,
- GVA_ExplicitTemplateInstantiation
- };
-
llvm::GlobalVariable::LinkageTypes
getFunctionLinkage(const FunctionDecl *FD);
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index d469b906fca1..5ab65c5779b6 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -13,6 +13,7 @@
#include "CodeGenTypes.h"
#include "CGCall.h"
+#include "CGCXXABI.h"
#include "CGRecordLayout.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -26,9 +27,10 @@ using namespace clang;
using namespace CodeGen;
CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
- const llvm::TargetData &TD, const ABIInfo &Info)
+ const llvm::TargetData &TD, const ABIInfo &Info,
+ CGCXXABI &CXXABI)
: Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD),
- TheABIInfo(Info) {
+ TheABIInfo(Info), TheCXXABI(CXXABI) {
}
CodeGenTypes::~CodeGenTypes() {
@@ -400,17 +402,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
}
case Type::MemberPointer: {
- // FIXME: This is ABI dependent. We use the Itanium C++ ABI.
- // http://www.codesourcery.com/public/cxx-abi/abi.html#member-pointers
- // If we ever want to support other ABIs this needs to be abstracted.
-
- QualType ETy = cast<MemberPointerType>(Ty).getPointeeType();
- const llvm::Type *PtrDiffTy =
- ConvertTypeRecursive(Context.getPointerDiffType());
- if (ETy->isFunctionType())
- return llvm::StructType::get(TheModule.getContext(), PtrDiffTy, PtrDiffTy,
- NULL);
- return PtrDiffTy;
+ return getCXXABI().ConvertMemberPointerType(cast<MemberPointerType>(&Ty));
}
}
@@ -491,31 +483,34 @@ CodeGenTypes::getCGRecordLayout(const RecordDecl *TD) const {
return *Layout;
}
-bool CodeGenTypes::ContainsPointerToDataMember(QualType T) {
+bool CodeGenTypes::isZeroInitializable(QualType T) {
// No need to check for member pointers when not compiling C++.
if (!Context.getLangOptions().CPlusPlus)
- return false;
+ return true;
T = Context.getBaseElementType(T);
+ // Records are non-zero-initializable if they contain any
+ // non-zero-initializable subobjects.
if (const RecordType *RT = T->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-
- return ContainsPointerToDataMember(RD);
+ return isZeroInitializable(RD);
}
-
+
+ // We have to ask the ABI about member pointers.
if (const MemberPointerType *MPT = T->getAs<MemberPointerType>())
- return !MPT->getPointeeType()->isFunctionType();
+ return getCXXABI().isZeroInitializable(MPT);
- return false;
+ // Everything else is okay.
+ return true;
}
-bool CodeGenTypes::ContainsPointerToDataMember(const CXXRecordDecl *RD) {
+bool CodeGenTypes::isZeroInitializable(const CXXRecordDecl *RD) {
// FIXME: It would be better if there was a way to explicitly compute the
// record layout instead of converting to a type.
ConvertTagDeclType(RD);
const CGRecordLayout &Layout = getCGRecordLayout(RD);
- return Layout.containsPointerToDataMember();
+ return Layout.isZeroInitializable();
}
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index c7f48e6c9dd4..1fc2153fcadb 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -14,13 +14,12 @@
#ifndef CLANG_CODEGEN_CODEGENTYPES_H
#define CLANG_CODEGEN_CODEGENTYPES_H
+#include "CGCall.h"
+#include "GlobalDecl.h"
#include "llvm/Module.h"
#include "llvm/ADT/DenseMap.h"
#include <vector>
-#include "CGCall.h"
-#include "GlobalDecl.h"
-
namespace llvm {
class FunctionType;
class Module;
@@ -51,6 +50,7 @@ namespace clang {
typedef CanQual<Type> CanQualType;
namespace CodeGen {
+ class CGCXXABI;
class CGRecordLayout;
/// CodeGenTypes - This class organizes the cross-module state that is used
@@ -61,6 +61,7 @@ class CodeGenTypes {
llvm::Module& TheModule;
const llvm::TargetData& TheTargetData;
const ABIInfo& TheABIInfo;
+ CGCXXABI &TheCXXABI;
llvm::SmallVector<std::pair<QualType,
llvm::OpaqueType *>, 8> PointersToResolve;
@@ -102,13 +103,14 @@ private:
public:
CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
- const ABIInfo &Info);
+ const ABIInfo &Info, CGCXXABI &CXXABI);
~CodeGenTypes();
const llvm::TargetData &getTargetData() const { return TheTargetData; }
const TargetInfo &getTarget() const { return Target; }
ASTContext &getContext() const { return Context; }
const ABIInfo &getABIInfo() const { return TheABIInfo; }
+ CGCXXABI &getCXXABI() const { return TheCXXABI; }
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
/// ConvertType - Convert type T into a llvm::Type.
@@ -139,7 +141,7 @@ public:
/// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
/// given a CXXMethodDecl. If the method to has an incomplete return type,
/// and/or incomplete argument types, this will return the opaque type.
- const llvm::Type *GetFunctionTypeForVTable(const CXXMethodDecl *MD);
+ const llvm::Type *GetFunctionTypeForVTable(GlobalDecl GD);
const CGRecordLayout &getCGRecordLayout(const RecordDecl*) const;
@@ -169,7 +171,9 @@ public:
const CGFunctionInfo &getFunctionInfo(CanQual<FunctionNoProtoType> Ty,
bool IsRecursive = false);
- // getFunctionInfo - Get the function info for a member function.
+ /// getFunctionInfo - Get the function info for a member function of
+ /// the given type. This is used for calls through member function
+ /// pointers.
const CGFunctionInfo &getFunctionInfo(const CXXRecordDecl *RD,
const FunctionProtoType *FTP);
@@ -205,13 +209,13 @@ public: // These are internal details of CGT that shouldn't be used externally.
void GetExpandedTypes(QualType Ty, std::vector<const llvm::Type*> &ArgTys,
bool IsRecursive);
- /// ContainsPointerToDataMember - Return whether the given type contains a
- /// pointer to a data member.
- bool ContainsPointerToDataMember(QualType T);
+ /// IsZeroInitializable - Return whether a type can be
+ /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
+ bool isZeroInitializable(QualType T);
- /// ContainsPointerToDataMember - Return whether the record decl contains a
- /// pointer to a data member.
- bool ContainsPointerToDataMember(const CXXRecordDecl *RD);
+ /// IsZeroInitializable - Return whether a record type can be
+ /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
+ bool isZeroInitializable(const CXXRecordDecl *RD);
};
} // end namespace CodeGen
diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp
index 98db75ea2b46..eefc530ccf18 100644
--- a/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/lib/CodeGen/ItaniumCXXABI.cpp
@@ -12,28 +12,1012 @@
// documented at:
// http://www.codesourcery.com/public/cxx-abi/abi.html
// http://www.codesourcery.com/public/cxx-abi/abi-eh.html
+//
+// It also supports the closely-related ARM ABI, documented at:
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
+//
//===----------------------------------------------------------------------===//
#include "CGCXXABI.h"
+#include "CGRecordLayout.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "Mangle.h"
+#include <clang/AST/Type.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Value.h>
using namespace clang;
+using namespace CodeGen;
namespace {
-class ItaniumCXXABI : public CodeGen::CXXABI {
+class ItaniumCXXABI : public CodeGen::CGCXXABI {
+private:
+ const llvm::IntegerType *PtrDiffTy;
+protected:
CodeGen::MangleContext MangleCtx;
+ bool IsARM;
+
+ // It's a little silly for us to cache this.
+ const llvm::IntegerType *getPtrDiffTy() {
+ if (!PtrDiffTy) {
+ QualType T = getContext().getPointerDiffType();
+ const llvm::Type *Ty = CGM.getTypes().ConvertTypeRecursive(T);
+ PtrDiffTy = cast<llvm::IntegerType>(Ty);
+ }
+ return PtrDiffTy;
+ }
+
+ bool NeedsArrayCookie(QualType ElementType);
+
public:
- ItaniumCXXABI(CodeGen::CodeGenModule &CGM) :
- MangleCtx(CGM.getContext(), CGM.getDiags()) { }
+ ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) :
+ CGCXXABI(CGM), PtrDiffTy(0), MangleCtx(getContext(), CGM.getDiags()),
+ IsARM(IsARM) { }
CodeGen::MangleContext &getMangleContext() {
return MangleCtx;
}
+
+ bool isZeroInitializable(const MemberPointerType *MPT);
+
+ const llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT);
+
+ llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT);
+
+ llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT);
+
+ llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src);
+
+ llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C,
+ const CastExpr *E);
+
+ llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
+
+ llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD);
+ llvm::Constant *EmitMemberPointer(const FieldDecl *FD);
+
+ llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality);
+
+ llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *Addr,
+ const MemberPointerType *MPT);
+
+ void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params);
+
+ void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+
+ CharUnits GetArrayCookieSize(QualType ElementType);
+ llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ QualType ElementType);
+ void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+};
+
+class ARMCXXABI : public ItaniumCXXABI {
+public:
+ ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}
+
+ void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType T,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys);
+
+ void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params);
+
+ void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
+
+ void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);
+
+ CharUnits GetArrayCookieSize(QualType ElementType);
+ llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ QualType ElementType);
+ void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
+private:
+ /// \brief Returns true if the given instance method is one of the
+ /// kinds that the ARM ABI says returns 'this'.
+ static bool HasThisReturn(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) ||
+ (isa<CXXConstructorDecl>(MD)));
+ }
};
}
-CodeGen::CXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
+CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
return new ItaniumCXXABI(CGM);
}
+CodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) {
+ return new ARMCXXABI(CGM);
+}
+
+const llvm::Type *
+ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
+ if (MPT->isMemberDataPointer())
+ return getPtrDiffTy();
+ else
+ return llvm::StructType::get(CGM.getLLVMContext(),
+ getPtrDiffTy(), getPtrDiffTy(), NULL);
+}
+
+/// In the Itanium and ARM ABIs, method pointers have the form:
+/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr;
+///
+/// In the Itanium ABI:
+/// - method pointers are virtual if (memptr.ptr & 1) is nonzero
+/// - the this-adjustment is (memptr.adj)
+/// - the virtual offset is (memptr.ptr - 1)
+///
+/// In the ARM ABI:
+/// - method pointers are virtual if (memptr.adj & 1) is nonzero
+/// - the this-adjustment is (memptr.adj >> 1)
+/// - the virtual offset is (memptr.ptr)
+/// ARM uses 'adj' for the virtual flag because Thumb functions
+/// may be only single-byte aligned.
+///
+/// If the member is virtual, the adjusted 'this' pointer points
+/// to a vtable pointer from which the virtual offset is applied.
+///
+/// If the member is non-virtual, memptr.ptr is the address of
+/// the function to call.
+llvm::Value *
+ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
+ llvm::Value *&This,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ const FunctionProtoType *FPT =
+ MPT->getPointeeType()->getAs<FunctionProtoType>();
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
+
+ const llvm::FunctionType *FTy =
+ CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
+ FPT->isVariadic());
+
+ const llvm::IntegerType *ptrdiff = getPtrDiffTy();
+ llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1);
+
+ llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual");
+ llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual");
+ llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end");
+
+ // Extract memptr.adj, which is in the second field.
+ llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj");
+
+ // Compute the true adjustment.
+ llvm::Value *Adj = RawAdj;
+ if (IsARM)
+ Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted");
+
+ // Apply the adjustment and cast back to the original struct type
+ // for consistency.
+ llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy());
+ Ptr = Builder.CreateInBoundsGEP(Ptr, Adj);
+ This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted");
+
+ // Load the function pointer.
+ llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr");
+
+ // If the LSB in the function pointer is 1, the function pointer points to
+ // a virtual function.
+ llvm::Value *IsVirtual;
+ if (IsARM)
+ IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1);
+ else
+ IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1);
+ IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual");
+ Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
+
+ // In the virtual path, the adjustment left 'This' pointing to the
+ // vtable of the correct base subobject. The "function pointer" is an
+ // offset within the vtable (+1 for the virtual flag on non-ARM).
+ CGF.EmitBlock(FnVirtual);
+
+ // Cast the adjusted this to a pointer to vtable pointer and load.
+ const llvm::Type *VTableTy = Builder.getInt8PtrTy();
+ llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo());
+ VTable = Builder.CreateLoad(VTable, "memptr.vtable");
+
+ // Apply the offset.
+ llvm::Value *VTableOffset = FnAsInt;
+ if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1);
+ VTable = Builder.CreateGEP(VTable, VTableOffset);
+
+ // Load the virtual function to call.
+ VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo());
+ llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn");
+ CGF.EmitBranch(FnEnd);
+
+ // In the non-virtual path, the function pointer is actually a
+ // function pointer.
+ CGF.EmitBlock(FnNonVirtual);
+ llvm::Value *NonVirtualFn =
+ Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn");
+
+ // We're done.
+ CGF.EmitBlock(FnEnd);
+ llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo());
+ Callee->reserveOperandSpace(2);
+ Callee->addIncoming(VirtualFn, FnVirtual);
+ Callee->addIncoming(NonVirtualFn, FnNonVirtual);
+ return Callee;
+}
+
+/// Compute an l-value by applying the given pointer-to-member to a
+/// base object.
+llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF,
+ llvm::Value *Base,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ assert(MemPtr->getType() == getPtrDiffTy());
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace();
+
+ // Cast to char*.
+ Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS));
+
+ // Apply the offset, which we assume is non-null.
+ llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset");
+
+ // Cast the address to the appropriate pointer type, adopting the
+ // address space of the base pointer.
+ const llvm::Type *PType
+ = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS);
+ return Builder.CreateBitCast(Addr, PType);
+}
+
+/// Perform a derived-to-base or base-to-derived member pointer conversion.
+///
+/// Obligatory offset/adjustment diagram:
+/// <-- offset --> <-- adjustment -->
+/// |--------------------------|----------------------|--------------------|
+/// ^Derived address point ^Base address point ^Member address point
+///
+/// So when converting a base member pointer to a derived member pointer,
+/// we add the offset to the adjustment because the address point has
+/// decreased; and conversely, when converting a derived MP to a base MP
+/// we subtract the offset from the adjustment because the address point
+/// has increased.
+///
+/// The standard forbids (at compile time) conversion to and from
+/// virtual bases, which is why we don't have to consider them here.
+///
+/// The standard forbids (at run time) casting a derived MP to a base
+/// MP when the derived MP does not point to a member of the base.
+/// This is why -1 is a reasonable choice for null data member
+/// pointers.
+llvm::Value *
+ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *Src) {
+ assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
+ E->getCastKind() == CK_BaseToDerivedMemberPointer);
+
+ if (isa<llvm::Constant>(Src))
+ return EmitMemberPointerConversion(cast<llvm::Constant>(Src), E);
+
+ CGBuilderTy &Builder = CGF.Builder;
+
+ const MemberPointerType *SrcTy =
+ E->getSubExpr()->getType()->getAs<MemberPointerType>();
+ const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>();
+
+ const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl();
+ const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl();
+
+ bool DerivedToBase =
+ E->getCastKind() == CK_DerivedToBaseMemberPointer;
+
+ const CXXRecordDecl *BaseDecl, *DerivedDecl;
+ if (DerivedToBase)
+ DerivedDecl = SrcDecl, BaseDecl = DestDecl;
+ else
+ BaseDecl = SrcDecl, DerivedDecl = DestDecl;
+
+ llvm::Constant *Adj =
+ CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+ E->path_begin(),
+ E->path_end());
+ if (!Adj) return Src;
+
+ // For member data pointers, this is just a matter of adding the
+ // offset if the source is non-null.
+ if (SrcTy->isMemberDataPointer()) {
+ llvm::Value *Dst;
+ if (DerivedToBase)
+ Dst = Builder.CreateNSWSub(Src, Adj, "adj");
+ else
+ Dst = Builder.CreateNSWAdd(Src, Adj, "adj");
+
+ // Null check.
+ llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType());
+ llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull");
+ return Builder.CreateSelect(IsNull, Src, Dst);
+ }
+
+ // The this-adjustment is left-shifted by 1 on ARM.
+ if (IsARM) {
+ uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue();
+ Offset <<= 1;
+ Adj = llvm::ConstantInt::get(Adj->getType(), Offset);
+ }
+
+ llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj");
+ llvm::Value *DstAdj;
+ if (DerivedToBase)
+ DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj");
+ else
+ DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj");
+
+ return Builder.CreateInsertValue(Src, DstAdj, 1);
+}
+
+llvm::Constant *
+ItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C,
+ const CastExpr *E) {
+ const MemberPointerType *SrcTy =
+ E->getSubExpr()->getType()->getAs<MemberPointerType>();
+ const MemberPointerType *DestTy =
+ E->getType()->getAs<MemberPointerType>();
+
+ bool DerivedToBase =
+ E->getCastKind() == CK_DerivedToBaseMemberPointer;
+
+ const CXXRecordDecl *DerivedDecl;
+ if (DerivedToBase)
+ DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl();
+ else
+ DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl();
+
+ // Calculate the offset to the base class.
+ llvm::Constant *Offset =
+ CGM.GetNonVirtualBaseClassOffset(DerivedDecl,
+ E->path_begin(),
+ E->path_end());
+ // If there's no offset, we're done.
+ if (!Offset) return C;
+
+ // If the source is a member data pointer, we have to do a null
+ // check and then add the offset. In the common case, we can fold
+ // away the offset.
+ if (SrcTy->isMemberDataPointer()) {
+ assert(C->getType() == getPtrDiffTy());
+
+ // If it's a constant int, just create a new constant int.
+ if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) {
+ int64_t Src = CI->getSExtValue();
+
+ // Null converts to null.
+ if (Src == -1) return CI;
+
+ // Otherwise, just add the offset.
+ int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue();
+ int64_t Dst = (DerivedToBase ? Src - OffsetV : Src + OffsetV);
+ return llvm::ConstantInt::get(CI->getType(), Dst, /*signed*/ true);
+ }
+
+ // Otherwise, we have to form a constant select expression.
+ llvm::Constant *Null = llvm::Constant::getAllOnesValue(C->getType());
+
+ llvm::Constant *IsNull =
+ llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, C, Null);
+
+ llvm::Constant *Dst;
+ if (DerivedToBase)
+ Dst = llvm::ConstantExpr::getNSWSub(C, Offset);
+ else
+ Dst = llvm::ConstantExpr::getNSWAdd(C, Offset);
+
+ return llvm::ConstantExpr::getSelect(IsNull, Null, Dst);
+ }
+
+ // The this-adjustment is left-shifted by 1 on ARM.
+ if (IsARM) {
+ int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue();
+ OffsetV <<= 1;
+ Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV);
+ }
+
+ llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C);
+
+ llvm::Constant *Values[2] = { CS->getOperand(0), 0 };
+ if (DerivedToBase)
+ Values[1] = llvm::ConstantExpr::getSub(CS->getOperand(1), Offset);
+ else
+ Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset);
+
+ return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
+ /*Packed=*/false);
+}
+
+
+llvm::Constant *
+ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
+ const llvm::Type *ptrdiff_t = getPtrDiffTy();
+
+ // Itanium C++ ABI 2.3:
+ // A NULL pointer is represented as -1.
+ if (MPT->isMemberDataPointer())
+ return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true);
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0);
+ llvm::Constant *Values[2] = { Zero, Zero };
+ return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2,
+ /*Packed=*/false);
+}
+
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const FieldDecl *FD) {
+ // Itanium C++ ABI 2.3:
+ // A pointer to data member is an offset from the base address of
+ // the class object containing it, represented as a ptrdiff_t
+
+ QualType ClassType = getContext().getTypeDeclType(FD->getParent());
+ const llvm::StructType *ClassLTy =
+ cast<llvm::StructType>(CGM.getTypes().ConvertType(ClassType));
+
+ const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(FD->getParent());
+ unsigned FieldNo = RL.getLLVMFieldNo(FD);
+ uint64_t Offset =
+ CGM.getTargetData().getStructLayout(ClassLTy)->getElementOffset(FieldNo);
+
+ return llvm::ConstantInt::get(getPtrDiffTy(), Offset);
+}
+
+llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
+ assert(MD->isInstance() && "Member function must not be static!");
+ MD = MD->getCanonicalDecl();
+
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::Type *ptrdiff_t = getPtrDiffTy();
+
+ // Get the function pointer (or index if this is a virtual function).
+ llvm::Constant *MemPtr[2];
+ if (MD->isVirtual()) {
+ uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD);
+
+ // FIXME: We shouldn't use / 8 here.
+ uint64_t PointerWidthInBytes =
+ getContext().Target.getPointerWidth(0) / 8;
+ uint64_t VTableOffset = (Index * PointerWidthInBytes);
+
+ if (IsARM) {
+ // ARM C++ ABI 3.2.1:
+ // This ABI specifies that adj contains twice the this
+ // adjustment, plus 1 if the member function is virtual. The
+ // least significant bit of adj then makes exactly the same
+ // discrimination as the least significant bit of ptr does for
+ // Itanium.
+ MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1);
+ } else {
+ // Itanium C++ ABI 2.3:
+ // For a virtual function, [the pointer field] is 1 plus the
+ // virtual table offset (in bytes) of the function,
+ // represented as a ptrdiff_t.
+ MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+ }
+ } else {
+ const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+ const llvm::Type *Ty;
+ // Check whether the function has a computable LLVM signature.
+ if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+ // The function has a computable LLVM signature; use the correct type.
+ Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
+ } else {
+ // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+ // function type is incomplete.
+ Ty = ptrdiff_t;
+ }
+
+ llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty);
+ MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t);
+ MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0);
+ }
+
+ return llvm::ConstantStruct::get(CGM.getLLVMContext(),
+ MemPtr, 2, /*Packed=*/false);
+}
+
+/// The comparison algorithm is pretty easy: the member pointers are
+/// the same if they're either bitwise identical *or* both null.
+///
+/// ARM is different here only because null-ness is more complicated.
+llvm::Value *
+ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
+ llvm::Value *L,
+ llvm::Value *R,
+ const MemberPointerType *MPT,
+ bool Inequality) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ llvm::ICmpInst::Predicate Eq;
+ llvm::Instruction::BinaryOps And, Or;
+ if (Inequality) {
+ Eq = llvm::ICmpInst::ICMP_NE;
+ And = llvm::Instruction::Or;
+ Or = llvm::Instruction::And;
+ } else {
+ Eq = llvm::ICmpInst::ICMP_EQ;
+ And = llvm::Instruction::And;
+ Or = llvm::Instruction::Or;
+ }
+
+ // Member data pointers are easy because there's a unique null
+ // value, so it just comes down to bitwise equality.
+ if (MPT->isMemberDataPointer())
+ return Builder.CreateICmp(Eq, L, R);
+
+ // For member function pointers, the tautologies are more complex.
+ // The Itanium tautology is:
+ // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj))
+ // The ARM tautology is:
+ // (L == R) <==> (L.ptr == R.ptr &&
+ // (L.adj == R.adj ||
+ // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0)))
+ // The inequality tautologies have exactly the same structure, except
+ // applying De Morgan's laws.
+
+ llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr");
+ llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr");
+
+ // This condition tests whether L.ptr == R.ptr. This must always be
+ // true for equality to hold.
+ llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr");
+
+ // This condition, together with the assumption that L.ptr == R.ptr,
+ // tests whether the pointers are both null. ARM imposes an extra
+ // condition.
+ llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType());
+ llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null");
+
+ // This condition tests whether L.adj == R.adj. If this isn't
+ // true, the pointers are unequal unless they're both null.
+ llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj");
+ llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj");
+ llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj");
+
+ // Null member function pointers on ARM clear the low bit of Adj,
+ // so the zero condition has to check that neither low bit is set.
+ if (IsARM) {
+ llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1);
+
+ // Compute (l.adj | r.adj) & 1 and test it against zero.
+ llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
+ llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
+ llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
+ "cmp.or.adj");
+ EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
+ }
+
+ // Tie together all our conditions.
+ llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq);
+ Result = Builder.CreateBinOp(And, PtrEq, Result,
+ Inequality ? "memptr.ne" : "memptr.eq");
+ return Result;
+}
+
+llvm::Value *
+ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
+ llvm::Value *MemPtr,
+ const MemberPointerType *MPT) {
+ CGBuilderTy &Builder = CGF.Builder;
+
+ /// For member data pointers, this is just a check against -1.
+ if (MPT->isMemberDataPointer()) {
+ assert(MemPtr->getType() == getPtrDiffTy());
+ llvm::Value *NegativeOne =
+ llvm::Constant::getAllOnesValue(MemPtr->getType());
+ return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
+ }
+
+ // In Itanium, a member function pointer is null if 'ptr' is null.
+ llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr");
+
+ llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0);
+ llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool");
+
+ // In ARM, it's that, plus the low bit of 'adj' must be zero.
+ if (IsARM) {
+ llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
+ llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
+ llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
+ llvm::Value *IsNotVirtual = Builder.CreateICmpEQ(VirtualBit, Zero,
+ "memptr.notvirtual");
+ Result = Builder.CreateAnd(Result, IsNotVirtual);
+ }
+
+ return Result;
+}
+
+/// The Itanium ABI requires non-zero initialization only for data
+/// member pointers, for which '0' is a valid offset.
+bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
+ return MPT->getPointeeType()->isFunctionType();
+}
+
+/// The generic ABI passes 'this', plus a VTT if it's initializing a
+/// base subobject.
+void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ASTContext &Context = getContext();
+
+ // 'this' is already there.
+
+ // Check if we need to add a VTT parameter (which has type void **).
+ if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
+ ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+}
+
+/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.
+void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);
+ ResTy = ArgTys[0];
+}
+
+/// The generic ABI passes 'this', plus a VTT if it's destroying a
+/// base subobject.
+void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ASTContext &Context = getContext();
+
+ // 'this' is already there.
+
+ // Check if we need to add a VTT parameter (which has type void **).
+ if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
+ ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
+}
+
+/// The ARM ABI does the same as the Itanium ABI, but returns 'this'
+/// for non-deleting destructors.
+void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);
+
+ if (Type != Dtor_Deleting)
+ ResTy = ArgTys[0];
+}
+
+void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
+ /// Create the 'this' variable.
+ BuildThisParam(CGF, Params);
+
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
+ assert(MD->isInstance());
+
+ // Check if we need a VTT parameter as well.
+ if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) {
+ ASTContext &Context = getContext();
+
+ // FIXME: avoid the fake decl
+ QualType T = Context.getPointerType(Context.VoidPtrTy);
+ ImplicitParamDecl *VTTDecl
+ = ImplicitParamDecl::Create(Context, 0, MD->getLocation(),
+ &Context.Idents.get("vtt"), T);
+ Params.push_back(std::make_pair(VTTDecl, VTTDecl->getType()));
+ getVTTDecl(CGF) = VTTDecl;
+ }
+}
+
+void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
+ ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);
+
+ // Return 'this' from certain constructors and destructors.
+ if (HasThisReturn(CGF.CurGD))
+ ResTy = Params[0].second;
+}
+
+void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ /// Initialize the 'this' slot.
+ EmitThisParam(CGF);
+
+ /// Initialize the 'vtt' slot if needed.
+ if (getVTTDecl(CGF)) {
+ getVTTValue(CGF)
+ = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
+ "vtt");
+ }
+}
+
+void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
+
+ /// Initialize the return slot to 'this' at the start of the
+ /// function.
+ if (HasThisReturn(CGF.CurGD))
+ CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue);
+}
+
+void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
+ RValue RV, QualType ResultType) {
+ if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
+ return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
+
+ // Destructor thunks in the ARM ABI have indeterminate results.
+ const llvm::Type *T =
+ cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType();
+ RValue Undef = RValue::get(llvm::UndefValue::get(T));
+ return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType);
+}
+
+/************************** Array allocation cookies **************************/
+
+bool ItaniumCXXABI::NeedsArrayCookie(QualType ElementType) {
+ ElementType = getContext().getBaseElementType(ElementType);
+ const RecordType *RT = ElementType->getAs<RecordType>();
+ if (!RT) return false;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ // If the class has a non-trivial destructor, it always needs a cookie.
+ if (!RD->hasTrivialDestructor()) return true;
+
+ // If the class's usual deallocation function takes two arguments,
+ // it needs a cookie. Otherwise we don't need a cookie.
+ const CXXMethodDecl *UsualDeallocationFunction = 0;
+
+ // Usual deallocation functions of this form are always found on the
+ // class.
+ //
+ // FIXME: what exactly is this code supposed to do if there's an
+ // ambiguity? That's possible with using declarations.
+ DeclarationName OpName =
+ getContext().DeclarationNames.getCXXOperatorName(OO_Array_Delete);
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = RD->lookup(OpName); Op != OpEnd; ++Op) {
+ const CXXMethodDecl *Delete =
+ cast<CXXMethodDecl>((*Op)->getUnderlyingDecl());
+
+ if (Delete->isUsualDeallocationFunction()) {
+ UsualDeallocationFunction = Delete;
+ break;
+ }
+ }
+
+ // No usual deallocation function, we don't need a cookie.
+ if (!UsualDeallocationFunction)
+ return false;
+
+ // The usual deallocation function doesn't take a size_t argument,
+ // so we don't need a cookie.
+ if (UsualDeallocationFunction->getNumParams() == 1)
+ return false;
+
+ assert(UsualDeallocationFunction->getNumParams() == 2 &&
+ "Unexpected deallocation function type!");
+ return true;
+}
+
+CharUnits ItaniumCXXABI::GetArrayCookieSize(QualType ElementType) {
+ if (!NeedsArrayCookie(ElementType))
+ return CharUnits::Zero();
+
+ // Padding is the maximum of sizeof(size_t) and alignof(ElementType)
+ ASTContext &Ctx = getContext();
+ return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()),
+ Ctx.getTypeAlignInChars(ElementType));
+}
+
+llvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ QualType ElementType) {
+ assert(NeedsArrayCookie(ElementType));
+
+ unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
+
+ ASTContext &Ctx = getContext();
+ QualType SizeTy = Ctx.getSizeType();
+ CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy);
+
+ // The size of the cookie.
+ CharUnits CookieSize =
+ std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType));
+
+ // Compute an offset to the cookie.
+ llvm::Value *CookiePtr = NewPtr;
+ CharUnits CookieOffset = CookieSize - SizeSize;
+ if (!CookieOffset.isZero())
+ CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr,
+ CookieOffset.getQuantity());
+
+ // Write the number of elements into the appropriate slot.
+ llvm::Value *NumElementsPtr
+ = CGF.Builder.CreateBitCast(CookiePtr,
+ CGF.ConvertType(SizeTy)->getPointerTo(AS));
+ CGF.Builder.CreateStore(NumElements, NumElementsPtr);
+
+ // Finally, compute a pointer to the actual data buffer by skipping
+ // over the cookie completely.
+ return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
+ CookieSize.getQuantity());
+}
+
+void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ QualType ElementType,
+ llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr,
+ CharUnits &CookieSize) {
+ // Derive a char* in the same address space as the pointer.
+ unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
+ const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);
+
+ // If we don't need an array cookie, bail out early.
+ if (!NeedsArrayCookie(ElementType)) {
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ NumElements = 0;
+ CookieSize = CharUnits::Zero();
+ return;
+ }
+
+ QualType SizeTy = getContext().getSizeType();
+ CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
+ const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
+
+ CookieSize
+ = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType));
+
+ CharUnits NumElementsOffset = CookieSize - SizeSize;
+
+ // Compute the allocated pointer.
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
+ -CookieSize.getQuantity());
+
+ llvm::Value *NumElementsPtr = AllocPtr;
+ if (!NumElementsOffset.isZero())
+ NumElementsPtr =
+ CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr,
+ NumElementsOffset.getQuantity());
+ NumElementsPtr =
+ CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
+ NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
+}
+
+CharUnits ARMCXXABI::GetArrayCookieSize(QualType ElementType) {
+ if (!NeedsArrayCookie(ElementType))
+ return CharUnits::Zero();
+
+ // On ARM, the cookie is always:
+ // struct array_cookie {
+ // std::size_t element_size; // element_size != 0
+ // std::size_t element_count;
+ // };
+ // TODO: what should we do if the allocated type actually wants
+ // greater alignment?
+ return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2;
+}
+
+llvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *NewPtr,
+ llvm::Value *NumElements,
+ QualType ElementType) {
+ assert(NeedsArrayCookie(ElementType));
+
+ // NewPtr is a char*.
+
+ unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace();
+
+ ASTContext &Ctx = getContext();
+ CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType());
+ const llvm::IntegerType *SizeTy =
+ cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType()));
+
+ // The cookie is always at the start of the buffer.
+ llvm::Value *CookiePtr = NewPtr;
+
+ // The first element is the element size.
+ CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS));
+ llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy,
+ Ctx.getTypeSizeInChars(ElementType).getQuantity());
+ CGF.Builder.CreateStore(ElementSize, CookiePtr);
+
+ // The second element is the element count.
+ CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1);
+ CGF.Builder.CreateStore(NumElements, CookiePtr);
+
+ // Finally, compute a pointer to the actual data buffer by skipping
+ // over the cookie completely.
+ CharUnits CookieSize = 2 * SizeSize;
+ return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr,
+ CookieSize.getQuantity());
+}
+
+void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
+ llvm::Value *Ptr,
+ QualType ElementType,
+ llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr,
+ CharUnits &CookieSize) {
+ // Derive a char* in the same address space as the pointer.
+ unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
+ const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);
+
+ // If we don't need an array cookie, bail out early.
+ if (!NeedsArrayCookie(ElementType)) {
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ NumElements = 0;
+ CookieSize = CharUnits::Zero();
+ return;
+ }
+
+ QualType SizeTy = getContext().getSizeType();
+ CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
+ const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
+
+ // The cookie size is always 2 * sizeof(size_t).
+ CookieSize = 2 * SizeSize;
+ CharUnits NumElementsOffset = CookieSize - SizeSize;
+
+ // The allocated pointer is the input ptr, minus that amount.
+ AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
+ AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
+ -CookieSize.getQuantity());
+
+ // The number of elements is at offset sizeof(size_t) relative to that.
+ llvm::Value *NumElementsPtr
+ = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
+ SizeSize.getQuantity());
+ NumElementsPtr =
+ CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
+ NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
+}
+
diff --git a/lib/CodeGen/Makefile b/lib/CodeGen/Makefile
index 4b93524267ae..6032dffec1a5 100644
--- a/lib/CodeGen/Makefile
+++ b/lib/CodeGen/Makefile
@@ -14,7 +14,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangCodeGen
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 30ee541c00fa..e1988743b7f9 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -241,11 +241,11 @@ private:
NestedNameSpecifier *Qualifier,
DeclarationName Name,
unsigned KnownArity);
- void mangleCalledExpression(const Expr *E, unsigned KnownArity);
- void mangleExpression(const Expr *E);
+ void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
void mangleCXXCtorType(CXXCtorType T);
void mangleCXXDtorType(CXXDtorType T);
+ void mangleTemplateArgs(const ExplicitTemplateArgumentList &TemplateArgs);
void mangleTemplateArgs(TemplateName Template,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs);
@@ -304,6 +304,10 @@ bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
return false;
}
+ // Class members are always mangled.
+ if (D->getDeclContext()->isRecord())
+ return true;
+
// C functions and "main" are not mangled.
if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
return false;
@@ -695,7 +699,11 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
// a program to refer to the anonymous union, and there is therefore no
// need to mangle its name.
const FieldDecl *FD = FindFirstNamedDataMember(RD);
- assert(FD && "Didn't find a named data member!");
+
+ // It's actually possible for various reasons for us to get here
+ // with an empty anonymous struct / union. Fortunately, it
+ // doesn't really matter what name we generate.
+ if (!FD) break;
assert(FD->getIdentifier() && "Data member name isn't an identifier!");
mangleSourceName(FD->getIdentifier());
@@ -1016,24 +1024,21 @@ CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
// ::= da # delete[]
case OO_Array_Delete: Out << "da"; break;
// ::= ps # + (unary)
- // ::= pl # +
+ // ::= pl # + (binary or unknown)
case OO_Plus:
- assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "ps" : "pl"); break;
// ::= ng # - (unary)
- // ::= mi # -
+ // ::= mi # - (binary or unknown)
case OO_Minus:
- assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "ng" : "mi"); break;
// ::= ad # & (unary)
- // ::= an # &
+ // ::= an # & (binary or unknown)
case OO_Amp:
- assert((Arity == 1 || Arity == 2) && "Invalid arity!");
Out << (Arity == 1? "ad" : "an"); break;
// ::= de # * (unary)
- // ::= ml # *
+ // ::= ml # * (binary or unknown)
case OO_Star:
- assert((Arity == 1 || Arity == 2) && "Invalid arity!");
+ // Use binary when unknown.
Out << (Arity == 1? "de" : "ml"); break;
// ::= co # ~
case OO_Tilde: Out << "co"; break;
@@ -1275,7 +1280,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
mangleType(Proto->getResultType());
if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
- // <builtin-type> ::= v # void
+ // <builtin-type> ::= v # void
Out << 'v';
return;
}
@@ -1536,25 +1541,6 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T,
}
-void CXXNameMangler::mangleCalledExpression(const Expr *E, unsigned Arity) {
- if (E->getType() != getASTContext().OverloadTy)
- mangleExpression(E);
- // propagate arity to dependent overloads?
-
- llvm::PointerIntPair<OverloadExpr*,1> R
- = OverloadExpr::find(const_cast<Expr*>(E));
- if (R.getInt())
- Out << "an"; // &
- const OverloadExpr *Ovl = R.getPointer();
- if (const UnresolvedMemberExpr *ME = dyn_cast<UnresolvedMemberExpr>(Ovl)) {
- mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(),
- ME->getMemberName(), Arity);
- return;
- }
-
- mangleUnresolvedName(Ovl->getQualifier(), Ovl->getName(), Arity);
-}
-
/// Mangles a member expression. Implicit accesses are not handled,
/// but that should be okay, because you shouldn't be able to
/// make an implicit access in a function template declaration.
@@ -1570,14 +1556,14 @@ void CXXNameMangler::mangleMemberExpr(const Expr *Base,
mangleUnresolvedName(Qualifier, Member, Arity);
}
-void CXXNameMangler::mangleExpression(const Expr *E) {
+void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <trinary operator-name> <expression> <expression> <expression>
- // ::= cl <expression>* E # call
+ // ::= cl <expression>* E # call
// ::= cv <type> expression # conversion with one argument
// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
- // ::= st <type> # sizeof (a type)
+ // ::= st <type> # sizeof (a type)
// ::= at <type> # alignof (a type)
// ::= <template-param>
// ::= <function-param>
@@ -1644,14 +1630,14 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
}
case Expr::CXXDefaultArgExprClass:
- mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr());
+ mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
break;
case Expr::CXXMemberCallExprClass: // fallthrough
case Expr::CallExprClass: {
const CallExpr *CE = cast<CallExpr>(E);
Out << "cl";
- mangleCalledExpression(CE->getCallee(), CE->getNumArgs());
+ mangleExpression(CE->getCallee(), CE->getNumArgs());
for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
mangleExpression(CE->getArg(I));
Out << 'E';
@@ -1682,7 +1668,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), ME->getMemberDecl()->getDeclName(),
- UnknownArity);
+ Arity);
break;
}
@@ -1690,7 +1676,9 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), ME->getMemberName(),
- UnknownArity);
+ Arity);
+ if (ME->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
}
@@ -1699,7 +1687,9 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
ME->getQualifier(), ME->getMember(),
- UnknownArity);
+ Arity);
+ if (ME->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ME->getExplicitTemplateArgs());
break;
}
@@ -1708,7 +1698,9 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
// using something as close as possible to the original lookup
// expression.
const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), UnknownArity);
+ mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), Arity);
+ if (ULE->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ULE->getExplicitTemplateArgs());
break;
}
@@ -1821,13 +1813,13 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
const ConditionalOperator *CO = cast<ConditionalOperator>(E);
mangleOperatorName(OO_Conditional, /*Arity=*/3);
mangleExpression(CO->getCond());
- mangleExpression(CO->getLHS());
- mangleExpression(CO->getRHS());
+ mangleExpression(CO->getLHS(), Arity);
+ mangleExpression(CO->getRHS(), Arity);
break;
}
case Expr::ImplicitCastExprClass: {
- mangleExpression(cast<ImplicitCastExpr>(E)->getSubExpr());
+ mangleExpression(cast<ImplicitCastExpr>(E)->getSubExpr(), Arity);
break;
}
@@ -1855,7 +1847,7 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
}
case Expr::ParenExprClass:
- mangleExpression(cast<ParenExpr>(E)->getSubExpr());
+ mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);
break;
case Expr::DeclRefExprClass: {
@@ -1869,6 +1861,12 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
Out << 'E';
break;
+ case Decl::EnumConstant: {
+ const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
+ mangleIntegerLiteral(ED->getType(), ED->getInitVal());
+ break;
+ }
+
case Decl::NonTypeTemplateParm: {
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
mangleTemplateParameter(PD->getIndex());
@@ -1897,27 +1895,23 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
}
assert(QTy && "Qualifier was not type!");
- // ::= sr <type> <unqualified-name> # dependent name
+ // ::= sr <type> <unqualified-name> # dependent name
+ // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
Out << "sr";
mangleType(QualType(QTy, 0));
-
- assert(DRE->getDeclName().getNameKind() == DeclarationName::Identifier &&
- "Unhandled decl name kind!");
- mangleSourceName(DRE->getDeclName().getAsIdentifierInfo());
+ mangleUnqualifiedName(0, DRE->getDeclName(), Arity);
+ if (DRE->hasExplicitTemplateArgs())
+ mangleTemplateArgs(DRE->getExplicitTemplateArgs());
break;
}
- case Expr::CXXBindReferenceExprClass:
- mangleExpression(cast<CXXBindReferenceExpr>(E)->getSubExpr());
- break;
-
case Expr::CXXBindTemporaryExprClass:
mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());
break;
case Expr::CXXExprWithTemporariesClass:
- mangleExpression(cast<CXXExprWithTemporaries>(E)->getSubExpr());
+ mangleExpression(cast<CXXExprWithTemporaries>(E)->getSubExpr(), Arity);
break;
case Expr::FloatingLiteralClass: {
@@ -1974,13 +1968,10 @@ void CXXNameMangler::mangleExpression(const Expr *E) {
}
case Expr::StringLiteralClass: {
- // Proposal from David Vandervoorde, 2010.06.30.
- // I've sent a comment off asking whether this needs to also
- // represent the length of the string.
+ // Revised proposal from David Vandervoorde, 2010.07.15.
Out << 'L';
- const ConstantArrayType *T = cast<ConstantArrayType>(E->getType());
- QualType CharTy = T->getElementType().getUnqualifiedType();
- mangleType(CharTy);
+ assert(isa<ConstantArrayType>(E->getType()));
+ mangleType(E->getType());
Out << 'E';
break;
}
@@ -2035,6 +2026,15 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
}
}
+void CXXNameMangler::mangleTemplateArgs(
+ const ExplicitTemplateArgumentList &TemplateArgs) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned I = 0, E = TemplateArgs.NumTemplateArgs; I != E; ++I)
+ mangleTemplateArg(0, TemplateArgs.getTemplateArgs()[I].getArgument());
+ Out << 'E';
+}
+
void CXXNameMangler::mangleTemplateArgs(TemplateName Template,
const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp
index da0fdb616d6c..9407335e3283 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -41,8 +41,6 @@ public:
MicrosoftCXXNameMangler(MangleContext &C, llvm::SmallVectorImpl<char> &Res)
: Context(C), Out(Res) { }
- llvm::raw_svector_ostream &getStream() { return Out; }
-
void mangle(const NamedDecl *D, llvm::StringRef Prefix = "?");
void mangleName(const NamedDecl *ND);
void mangleFunctionEncoding(const FunctionDecl *FD);
@@ -110,15 +108,43 @@ public:
llvm::SmallVectorImpl<char> &);
};
-class MicrosoftCXXABI : public CXXABI {
+class MicrosoftCXXABI : public CGCXXABI {
MicrosoftMangleContext MangleCtx;
public:
MicrosoftCXXABI(CodeGenModule &CGM)
- : MangleCtx(CGM.getContext(), CGM.getDiags()) {}
+ : CGCXXABI(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()) {}
MicrosoftMangleContext &getMangleContext() {
return MangleCtx;
}
+
+ void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
+ CXXCtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ // 'this' is already in place
+ // TODO: 'for base' flag
+ }
+
+ void BuildDestructorSignature(const CXXDestructorDecl *Ctor,
+ CXXDtorType Type,
+ CanQualType &ResTy,
+ llvm::SmallVectorImpl<CanQualType> &ArgTys) {
+ // 'this' is already in place
+ // TODO: 'for base' flag
+ }
+
+ void BuildInstanceFunctionParams(CodeGenFunction &CGF,
+ QualType &ResTy,
+ FunctionArgList &Params) {
+ BuildThisParam(CGF, Params);
+ // TODO: 'for base' flag
+ }
+
+ void EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
+ EmitThisParam(CGF);
+ // TODO: 'for base' flag
+ }
};
}
@@ -893,6 +919,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
switch (T->getCallConv()) {
case CC_Default:
case CC_C: Out << 'A'; break;
+ case CC_X86Pascal: Out << 'C'; break;
case CC_X86ThisCall: Out << 'E'; break;
case CC_X86StdCall: Out << 'G'; break;
case CC_X86FastCall: Out << 'I'; break;
@@ -1185,7 +1212,7 @@ void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
assert(false && "Can't yet mangle destructors!");
}
-CXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
+CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) {
return new MicrosoftCXXABI(CGM);
}
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index c65f20371552..4d221d4e657e 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -36,14 +36,36 @@ static void AssignToArrayRange(CodeGen::CGBuilderTy &Builder,
}
}
+static bool isAggregateTypeForABI(QualType T) {
+ return CodeGenFunction::hasAggregateLLVMType(T) ||
+ T->isMemberFunctionPointerType();
+}
+
ABIInfo::~ABIInfo() {}
+ASTContext &ABIInfo::getContext() const {
+ return CGT.getContext();
+}
+
+llvm::LLVMContext &ABIInfo::getVMContext() const {
+ return CGT.getLLVMContext();
+}
+
+const llvm::TargetData &ABIInfo::getTargetData() const {
+ return CGT.getTargetData();
+}
+
+
void ABIArgInfo::dump() const {
llvm::raw_ostream &OS = llvm::errs();
OS << "(ABIArgInfo Kind=";
switch (TheKind) {
case Direct:
- OS << "Direct";
+ OS << "Direct Type=";
+ if (const llvm::Type *Ty = getCoerceToType())
+ Ty->print(OS);
+ else
+ OS << "null";
break;
case Extend:
OS << "Extend";
@@ -51,10 +73,6 @@ void ABIArgInfo::dump() const {
case Ignore:
OS << "Ignore";
break;
- case Coerce:
- OS << "Coerce Type=";
- getCoerceToType()->print(OS);
- break;
case Indirect:
OS << "Indirect Align=" << getIndirectAlign()
<< " Byal=" << getIndirectByVal();
@@ -129,7 +147,7 @@ static bool hasNonTrivialDestructorOrCopyConstructor(const RecordType *RT) {
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
if (!RD)
return false;
-
+
return !RD->hasTrivialDestructor() || !RD->hasTrivialCopyConstructor();
}
@@ -162,7 +180,7 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
return 0;
const Type *Found = 0;
-
+
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
@@ -205,7 +223,7 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) {
FT = AT->getElementType();
}
- if (!CodeGenFunction::hasAggregateLLVMType(FT)) {
+ if (!isAggregateTypeForABI(FT)) {
Found = FT.getTypePtr();
} else {
Found = isSingleElementStruct(FT, Context);
@@ -272,23 +290,17 @@ namespace {
/// self-consistent and sensible LLVM IR generation, but does not
/// conform to any particular ABI.
class DefaultABIInfo : public ABIInfo {
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
+public:
+ DefaultABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
+ it->info = classifyArgumentType(it->type);
}
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -297,7 +309,8 @@ class DefaultABIInfo : public ABIInfo {
class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {}
+ DefaultTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
};
llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -305,10 +318,8 @@ llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return 0;
}
-ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (CodeGenFunction::hasAggregateLLVMType(Ty))
+ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const {
+ if (isAggregateTypeForABI(Ty))
return ABIArgInfo::getIndirect(0);
// Treat an enum type as its underlying type.
@@ -322,10 +333,9 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
//===----------------------------------------------------------------------===//
// X86-32 ABI Implementation
//===----------------------------------------------------------------------===//
-
+
/// X86_32ABIInfo - The X86-32 ABI information.
class X86_32ABIInfo : public ABIInfo {
- ASTContext &Context;
bool IsDarwinVectorABI;
bool IsSmallStructInRegABI;
@@ -337,41 +347,31 @@ class X86_32ABIInfo : public ABIInfo {
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
/// such that the argument will be passed in memory.
- ABIArgInfo getIndirectResult(QualType Ty, ASTContext &Context,
- bool ByVal = true) const;
+ ABIArgInfo getIndirectResult(QualType Ty, bool ByVal = true) const;
public:
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
+ it->info = classifyArgumentType(it->type);
}
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;
- X86_32ABIInfo(ASTContext &Context, bool d, bool p)
- : ABIInfo(), Context(Context), IsDarwinVectorABI(d),
- IsSmallStructInRegABI(p) {}
+ X86_32ABIInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p)
+ : ABIInfo(CGT), IsDarwinVectorABI(d), IsSmallStructInRegABI(p) {}
};
class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- X86_32TargetCodeGenInfo(ASTContext &Context, bool d, bool p)
- :TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {}
+ X86_32TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool d, bool p)
+ :TargetCodeGenInfo(new X86_32ABIInfo(CGT, d, p)) {}
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &CGM) const;
@@ -443,153 +443,172 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty,
return true;
}
-ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
+ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
- } else if (const VectorType *VT = RetTy->getAs<VectorType>()) {
+
+ if (const VectorType *VT = RetTy->getAs<VectorType>()) {
// On Darwin, some vectors are returned in registers.
if (IsDarwinVectorABI) {
- uint64_t Size = Context.getTypeSize(RetTy);
+ uint64_t Size = getContext().getTypeSize(RetTy);
// 128-bit vectors are a special case; they are returned in
// registers and we need to make sure to pick a type the LLVM
// backend will like.
if (Size == 128)
- return ABIArgInfo::getCoerce(llvm::VectorType::get(
- llvm::Type::getInt64Ty(VMContext), 2));
+ return ABIArgInfo::getDirect(llvm::VectorType::get(
+ llvm::Type::getInt64Ty(getVMContext()), 2));
// Always return in register if it fits in a general purpose
// register, or if it is 64 bits and has a single element.
if ((Size == 8 || Size == 16 || Size == 32) ||
(Size == 64 && VT->getNumElements() == 1))
- return ABIArgInfo::getCoerce(llvm::IntegerType::get(VMContext, Size));
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
return ABIArgInfo::getIndirect(0);
}
return ABIArgInfo::getDirect();
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ }
+
+ if (isAggregateTypeForABI(RetTy)) {
if (const RecordType *RT = RetTy->getAs<RecordType>()) {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
if (hasNonTrivialDestructorOrCopyConstructor(RT))
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
-
+
// Structures with flexible arrays are always indirect.
if (RT->getDecl()->hasFlexibleArrayMember())
return ABIArgInfo::getIndirect(0);
}
-
+
// If specified, structs and unions are always indirect.
if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())
return ABIArgInfo::getIndirect(0);
// Classify "single element" structs as their element type.
- if (const Type *SeltTy = isSingleElementStruct(RetTy, Context)) {
+ if (const Type *SeltTy = isSingleElementStruct(RetTy, getContext())) {
if (const BuiltinType *BT = SeltTy->getAs<BuiltinType>()) {
if (BT->isIntegerType()) {
// We need to use the size of the structure, padding
// bit-fields can adjust that to be larger than the single
// element type.
- uint64_t Size = Context.getTypeSize(RetTy);
- return ABIArgInfo::getCoerce(
- llvm::IntegerType::get(VMContext, (unsigned) Size));
- } else if (BT->getKind() == BuiltinType::Float) {
- assert(Context.getTypeSize(RetTy) == Context.getTypeSize(SeltTy) &&
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ return ABIArgInfo::getDirect(
+ llvm::IntegerType::get(getVMContext(), (unsigned)Size));
+ }
+
+ if (BT->getKind() == BuiltinType::Float) {
+ assert(getContext().getTypeSize(RetTy) ==
+ getContext().getTypeSize(SeltTy) &&
"Unexpect single element structure size!");
- return ABIArgInfo::getCoerce(llvm::Type::getFloatTy(VMContext));
- } else if (BT->getKind() == BuiltinType::Double) {
- assert(Context.getTypeSize(RetTy) == Context.getTypeSize(SeltTy) &&
+ return ABIArgInfo::getDirect(llvm::Type::getFloatTy(getVMContext()));
+ }
+
+ if (BT->getKind() == BuiltinType::Double) {
+ assert(getContext().getTypeSize(RetTy) ==
+ getContext().getTypeSize(SeltTy) &&
"Unexpect single element structure size!");
- return ABIArgInfo::getCoerce(llvm::Type::getDoubleTy(VMContext));
+ return ABIArgInfo::getDirect(llvm::Type::getDoubleTy(getVMContext()));
}
} else if (SeltTy->isPointerType()) {
// FIXME: It would be really nice if this could come out as the proper
// pointer type.
- const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
- return ABIArgInfo::getCoerce(PtrTy);
+ const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(getVMContext());
+ return ABIArgInfo::getDirect(PtrTy);
} else if (SeltTy->isVectorType()) {
// 64- and 128-bit vectors are never returned in a
// register when inside a structure.
- uint64_t Size = Context.getTypeSize(RetTy);
+ uint64_t Size = getContext().getTypeSize(RetTy);
if (Size == 64 || Size == 128)
return ABIArgInfo::getIndirect(0);
- return classifyReturnType(QualType(SeltTy, 0), Context, VMContext);
+ return classifyReturnType(QualType(SeltTy, 0));
}
}
// Small structures which are register sized are generally returned
// in a register.
- if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, Context)) {
- uint64_t Size = Context.getTypeSize(RetTy);
- return ABIArgInfo::getCoerce(llvm::IntegerType::get(VMContext, Size));
+ if (X86_32ABIInfo::shouldReturnTypeInRegister(RetTy, getContext())) {
+ uint64_t Size = getContext().getTypeSize(RetTy);
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),Size));
}
return ABIArgInfo::getIndirect(0);
- } else {
- // Treat an enum type as its underlying type.
- if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
-
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
+
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ return (RetTy->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
-ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty,
- ASTContext &Context,
- bool ByVal) const {
+ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal) const {
if (!ByVal)
return ABIArgInfo::getIndirect(0, false);
// Compute the byval alignment. We trust the back-end to honor the
// minimum ABI alignment for byval, to make cleaner IR.
const unsigned MinABIAlign = 4;
- unsigned Align = Context.getTypeAlign(Ty) / 8;
+ unsigned Align = getContext().getTypeAlign(Ty) / 8;
if (Align > MinABIAlign)
return ABIArgInfo::getIndirect(Align);
return ABIArgInfo::getIndirect(0);
}
-ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
+ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty) const {
// FIXME: Set alignment on indirect arguments.
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ if (isAggregateTypeForABI(Ty)) {
// Structures with flexible arrays are always indirect.
if (const RecordType *RT = Ty->getAs<RecordType>()) {
// Structures with either a non-trivial destructor or a non-trivial
// copy constructor are always indirect.
if (hasNonTrivialDestructorOrCopyConstructor(RT))
- return getIndirectResult(Ty, Context, /*ByVal=*/false);
+ return getIndirectResult(Ty, /*ByVal=*/false);
if (RT->getDecl()->hasFlexibleArrayMember())
- return getIndirectResult(Ty, Context);
+ return getIndirectResult(Ty);
}
// Ignore empty structs.
- if (Ty->isStructureType() && Context.getTypeSize(Ty) == 0)
+ if (Ty->isStructureType() && getContext().getTypeSize(Ty) == 0)
return ABIArgInfo::getIgnore();
// Expand small (<= 128-bit) record types when we know that the stack layout
// of those arguments will match the struct. This is important because the
// LLVM backend isn't smart enough to remove byval, which inhibits many
// optimizations.
- if (Context.getTypeSize(Ty) <= 4*32 &&
- canExpandIndirectArgument(Ty, Context))
+ if (getContext().getTypeSize(Ty) <= 4*32 &&
+ canExpandIndirectArgument(Ty, getContext()))
return ABIArgInfo::getExpand();
- return getIndirectResult(Ty, Context);
- } else {
- if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
+ return getIndirectResult(Ty);
+ }
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ if (const VectorType *VT = Ty->getAs<VectorType>()) {
+ // On Darwin, some vectors are passed in memory, we handle this by passing
+ // it as an i8/i16/i32/i64.
+ if (IsDarwinVectorABI) {
+ uint64_t Size = getContext().getTypeSize(Ty);
+ if ((Size == 8 || Size == 16 || Size == 32) ||
+ (Size == 64 && VT->getNumElements() == 1))
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ Size));
+ }
+
+ return ABIArgInfo::getDirect();
}
+
+
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
llvm::Value *X86_32ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -637,7 +656,7 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);
-
+
// 0-7 are the eight integer registers; the order is different
// on Darwin (for EH), but the range is the same.
// 8 is %eip.
@@ -649,7 +668,7 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
// platforms with 8-byte alignment for that type.
llvm::Value *Sixteen8 = llvm::ConstantInt::get(i8, 16);
AssignToArrayRange(Builder, Address, Sixteen8, 12, 16);
-
+
} else {
// 9 is %eflags, which doesn't get a size on Darwin for some
// reason.
@@ -673,9 +692,6 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable(
namespace {
/// X86_64ABIInfo - The X86_64 ABI information.
class X86_64ABIInfo : public ABIInfo {
- ASTContext &Context;
- const llvm::TargetData &TD;
-
enum Class {
Integer = 0,
SSE,
@@ -721,17 +737,13 @@ class X86_64ABIInfo : public ABIInfo {
/// also be ComplexX87.
void classify(QualType T, uint64_t OffsetBase, Class &Lo, Class &Hi) const;
- /// getCoerceResult - Given a source type \arg Ty and an LLVM type
- /// to coerce to, chose the best way to pass Ty in the same place
- /// that \arg CoerceTo would be passed, but while keeping the
- /// emitted code as simple as possible.
- ///
- /// FIXME: Note, this should be cleaned up to just take an enumeration of all
- /// the ways we might want to pass things, instead of constructing an LLVM
- /// type. This makes this code more explicit, and it makes it clearer that we
- /// are also doing this for correctness in the case of passing scalar types.
- ABIArgInfo getCoerceResult(QualType Ty,
- const llvm::Type *CoerceTo) const;
+ const llvm::Type *Get16ByteVectorType(QualType Ty) const;
+ const llvm::Type *GetSSETypeAtOffset(const llvm::Type *IRType,
+ unsigned IROffset, QualType SourceTy,
+ unsigned SourceOffset) const;
+ const llvm::Type *GetINTEGERTypeAtOffset(const llvm::Type *IRType,
+ unsigned IROffset, QualType SourceTy,
+ unsigned SourceOffset) const;
/// getIndirectResult - Give a source type \arg Ty, return a suitable result
/// such that the argument will be returned in memory.
@@ -741,23 +753,24 @@ class X86_64ABIInfo : public ABIInfo {
/// such that the argument will be passed in memory.
ABIArgInfo getIndirectResult(QualType Ty) const;
- ABIArgInfo classifyReturnType(QualType RetTy,
- llvm::LLVMContext &VMContext) const;
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
- ABIArgInfo classifyArgumentType(QualType Ty,
- llvm::LLVMContext &VMContext,
- unsigned &neededInt,
- unsigned &neededSSE,
- const llvm::Type *PrefType) const;
+ ABIArgInfo classifyArgumentType(QualType Ty, unsigned &neededInt,
+ unsigned &neededSSE) const;
public:
- X86_64ABIInfo(ASTContext &Ctx, const llvm::TargetData &td)
- : Context(Ctx), TD(td) {}
+ X86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ virtual void computeInfo(CGFunctionInfo &FI) const;
+
+ virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const;
+};
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const;
+/// WinX86_64ABIInfo - The Windows X86_64 ABI information.
+class WinX86_64ABIInfo : public X86_64ABIInfo {
+public:
+ WinX86_64ABIInfo(CodeGen::CodeGenTypes &CGT) : X86_64ABIInfo(CGT) {}
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;
@@ -765,8 +778,33 @@ public:
class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- X86_64TargetCodeGenInfo(ASTContext &Ctx, const llvm::TargetData &TD)
- : TargetCodeGenInfo(new X86_64ABIInfo(Ctx, TD)) {}
+ X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new X86_64ABIInfo(CGT)) {}
+
+ int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
+ return 7;
+ }
+
+ bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
+ llvm::Value *Address) const {
+ CodeGen::CGBuilderTy &Builder = CGF.Builder;
+ llvm::LLVMContext &Context = CGF.getLLVMContext();
+
+ const llvm::IntegerType *i8 = llvm::Type::getInt8Ty(Context);
+ llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);
+
+ // 0-15 are the 16 integer registers.
+ // 16 is %rip.
+ AssignToArrayRange(Builder, Address, Eight8, 0, 16);
+
+ return false;
+ }
+};
+
+class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
return 7;
@@ -865,18 +903,18 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// FIXME: _float128 and _Decimal128 are (SSE, SSEUp).
return;
}
-
+
if (const EnumType *ET = Ty->getAs<EnumType>()) {
// Classify the underlying integer type.
classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi);
return;
}
-
+
if (Ty->hasPointerRepresentation()) {
Current = Integer;
return;
}
-
+
if (Ty->isMemberPointerType()) {
if (Ty->isMemberFunctionPointerType())
Lo = Hi = Integer;
@@ -884,9 +922,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
Current = Integer;
return;
}
-
+
if (const VectorType *VT = Ty->getAs<VectorType>()) {
- uint64_t Size = Context.getTypeSize(VT);
+ uint64_t Size = getContext().getTypeSize(VT);
if (Size == 32) {
// gcc passes all <4 x char>, <2 x short>, <1 x int>, <1 x
// float> as integer.
@@ -904,7 +942,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
return;
// gcc passes <1 x long long> as INTEGER.
- if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::LongLong))
+ if (VT->getElementType()->isSpecificBuiltinType(BuiltinType::LongLong) ||
+ VT->getElementType()->isSpecificBuiltinType(BuiltinType::ULongLong) ||
+ VT->getElementType()->isSpecificBuiltinType(BuiltinType::Long) ||
+ VT->getElementType()->isSpecificBuiltinType(BuiltinType::ULong))
Current = Integer;
else
Current = SSE;
@@ -919,37 +960,37 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
}
return;
}
-
+
if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
- QualType ET = Context.getCanonicalType(CT->getElementType());
+ QualType ET = getContext().getCanonicalType(CT->getElementType());
- uint64_t Size = Context.getTypeSize(Ty);
+ uint64_t Size = getContext().getTypeSize(Ty);
if (ET->isIntegralOrEnumerationType()) {
if (Size <= 64)
Current = Integer;
else if (Size <= 128)
Lo = Hi = Integer;
- } else if (ET == Context.FloatTy)
+ } else if (ET == getContext().FloatTy)
Current = SSE;
- else if (ET == Context.DoubleTy)
+ else if (ET == getContext().DoubleTy)
Lo = Hi = SSE;
- else if (ET == Context.LongDoubleTy)
+ else if (ET == getContext().LongDoubleTy)
Current = ComplexX87;
// If this complex type crosses an eightbyte boundary then it
// should be split.
uint64_t EB_Real = (OffsetBase) / 64;
- uint64_t EB_Imag = (OffsetBase + Context.getTypeSize(ET)) / 64;
+ uint64_t EB_Imag = (OffsetBase + getContext().getTypeSize(ET)) / 64;
if (Hi == NoClass && EB_Real != EB_Imag)
Hi = Lo;
-
+
return;
}
-
- if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
+
+ if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
// Arrays are treated like structures.
- uint64_t Size = Context.getTypeSize(Ty);
+ uint64_t Size = getContext().getTypeSize(Ty);
// AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
// than two eightbytes, ..., it has class MEMORY.
@@ -960,13 +1001,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// fields, it has class MEMORY.
//
// Only need to check alignment of array base.
- if (OffsetBase % Context.getTypeAlign(AT->getElementType()))
+ if (OffsetBase % getContext().getTypeAlign(AT->getElementType()))
return;
// Otherwise implement simplified merge. We could be smarter about
// this, but it isn't worth it and would be harder to verify.
Current = NoClass;
- uint64_t EltSize = Context.getTypeSize(AT->getElementType());
+ uint64_t EltSize = getContext().getTypeSize(AT->getElementType());
uint64_t ArraySize = AT->getSize().getZExtValue();
for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
Class FieldLo, FieldHi;
@@ -983,9 +1024,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp array classification.");
return;
}
-
+
if (const RecordType *RT = Ty->getAs<RecordType>()) {
- uint64_t Size = Context.getTypeSize(Ty);
+ uint64_t Size = getContext().getTypeSize(Ty);
// AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
// than two eightbytes, ..., it has class MEMORY.
@@ -1004,7 +1045,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
if (RD->hasFlexibleArrayMember())
return;
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
// Reset Lo class, this will be recomputed.
Current = NoClass;
@@ -1031,10 +1072,6 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
if (Lo == Memory || Hi == Memory)
break;
}
-
- // If this record has no fields but isn't empty, classify as INTEGER.
- if (RD->field_empty() && Size)
- Current = Integer;
}
// Classify the fields one at a time, merging the results.
@@ -1048,7 +1085,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
// fields, it has class MEMORY.
//
// Note, skip this test for bit-fields, see below.
- if (!BitField && Offset % Context.getTypeAlign(i->getType())) {
+ if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
Lo = Memory;
return;
}
@@ -1070,7 +1107,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
continue;
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
- uint64_t Size = i->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+ uint64_t Size =
+ i->getBitWidth()->EvaluateAsInt(getContext()).getZExtValue();
uint64_t EB_Lo = Offset / 64;
uint64_t EB_Hi = (Offset + Size - 1) / 64;
@@ -1110,52 +1148,10 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
}
}
-ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty,
- const llvm::Type *CoerceTo) const {
- if (CoerceTo->isIntegerTy(64) || isa<llvm::PointerType>(CoerceTo)) {
- // Integer and pointer types will end up in a general purpose
- // register.
-
- // Treat an enum type as its underlying type.
- if (const EnumType *EnumTy = Ty->getAs<EnumType>())
- Ty = EnumTy->getDecl()->getIntegerType();
-
- if (Ty->isIntegralOrEnumerationType() || Ty->hasPointerRepresentation())
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
-
- // If this is a 8/16/32-bit structure that is passed as an int64, then it
- // will be passed in the low 8/16/32-bits of a 64-bit GPR, which is the same
- // as how an i8/i16/i32 is passed. Coerce to a i8/i16/i32 instead of a i64.
- switch (Context.getTypeSizeInChars(Ty).getQuantity()) {
- default: break;
- case 1: CoerceTo = llvm::Type::getInt8Ty(CoerceTo->getContext()); break;
- case 2: CoerceTo = llvm::Type::getInt16Ty(CoerceTo->getContext()); break;
- case 4: CoerceTo = llvm::Type::getInt32Ty(CoerceTo->getContext()); break;
- }
-
- } else if (CoerceTo->isDoubleTy()) {
- assert(Ty.isCanonical() && "should always have a canonical type here");
- assert(!Ty.hasQualifiers() && "should never have a qualified type here");
-
- // Float and double end up in a single SSE reg.
- if (Ty == Context.FloatTy || Ty == Context.DoubleTy)
- return ABIArgInfo::getDirect();
-
- // If this is a 32-bit structure that is passed as a double, then it will be
- // passed in the low 32-bits of the XMM register, which is the same as how a
- // float is passed. Coerce to a float instead of a double.
- if (Context.getTypeSizeInChars(Ty).getQuantity() == 4)
- CoerceTo = llvm::Type::getFloatTy(CoerceTo->getContext());
- }
-
- return ABIArgInfo::getCoerce(CoerceTo);
-}
-
ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
// If this is a scalar LLVM value then assume LLVM will pass it in the right
// place naturally.
- if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
@@ -1170,7 +1166,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const {
ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty) const {
// If this is a scalar LLVM value then assume LLVM will pass it in the right
// place naturally.
- if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
@@ -1185,14 +1181,297 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty) const {
// Compute the byval alignment. We trust the back-end to honor the
// minimum ABI alignment for byval, to make cleaner IR.
const unsigned MinABIAlign = 8;
- unsigned Align = Context.getTypeAlign(Ty) / 8;
+ unsigned Align = getContext().getTypeAlign(Ty) / 8;
if (Align > MinABIAlign)
return ABIArgInfo::getIndirect(Align);
return ABIArgInfo::getIndirect(0);
}
+/// Get16ByteVectorType - The ABI specifies that a value should be passed in an
+/// full vector XMM register. Pick an LLVM IR type that will be passed as a
+/// vector register.
+const llvm::Type *X86_64ABIInfo::Get16ByteVectorType(QualType Ty) const {
+ const llvm::Type *IRType = CGT.ConvertTypeRecursive(Ty);
+
+ // Wrapper structs that just contain vectors are passed just like vectors,
+ // strip them off if present.
+ const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType);
+ while (STy && STy->getNumElements() == 1) {
+ IRType = STy->getElementType(0);
+ STy = dyn_cast<llvm::StructType>(IRType);
+ }
+
+ // If the preferred type is a 16-byte vector, prefer to pass it.
+ if (const llvm::VectorType *VT = dyn_cast<llvm::VectorType>(IRType)){
+ const llvm::Type *EltTy = VT->getElementType();
+ if (VT->getBitWidth() == 128 &&
+ (EltTy->isFloatTy() || EltTy->isDoubleTy() ||
+ EltTy->isIntegerTy(8) || EltTy->isIntegerTy(16) ||
+ EltTy->isIntegerTy(32) || EltTy->isIntegerTy(64) ||
+ EltTy->isIntegerTy(128)))
+ return VT;
+ }
+
+ return llvm::VectorType::get(llvm::Type::getDoubleTy(getVMContext()), 2);
+}
+
+/// BitsContainNoUserData - Return true if the specified [start,end) bit range
+/// is known to either be off the end of the specified type or being in
+/// alignment padding. The user type specified is known to be at most 128 bits
+/// in size, and have passed through X86_64ABIInfo::classify with a successful
+/// classification that put one of the two halves in the INTEGER class.
+///
+/// It is conservatively correct to return false.
+static bool BitsContainNoUserData(QualType Ty, unsigned StartBit,
+ unsigned EndBit, ASTContext &Context) {
+ // If the bytes being queried are off the end of the type, there is no user
+ // data hiding here. This handles analysis of builtins, vectors and other
+ // types that don't contain interesting padding.
+ unsigned TySize = (unsigned)Context.getTypeSize(Ty);
+ if (TySize <= StartBit)
+ return true;
+
+ if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
+ unsigned EltSize = (unsigned)Context.getTypeSize(AT->getElementType());
+ unsigned NumElts = (unsigned)AT->getSize().getZExtValue();
+
+ // Check each element to see if the element overlaps with the queried range.
+ for (unsigned i = 0; i != NumElts; ++i) {
+ // If the element is after the span we care about, then we're done..
+ unsigned EltOffset = i*EltSize;
+ if (EltOffset >= EndBit) break;
+
+ unsigned EltStart = EltOffset < StartBit ? StartBit-EltOffset :0;
+ if (!BitsContainNoUserData(AT->getElementType(), EltStart,
+ EndBit-EltOffset, Context))
+ return false;
+ }
+ // If it overlaps no elements, then it is safe to process as padding.
+ return true;
+ }
+
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (CXXRecordDecl::base_class_const_iterator i = CXXRD->bases_begin(),
+ e = CXXRD->bases_end(); i != e; ++i) {
+ assert(!i->isVirtual() && !i->getType()->isDependentType() &&
+ "Unexpected base class!");
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
+
+ // If the base is after the span we care about, ignore it.
+ unsigned BaseOffset = (unsigned)Layout.getBaseClassOffset(Base);
+ if (BaseOffset >= EndBit) continue;
+
+ unsigned BaseStart = BaseOffset < StartBit ? StartBit-BaseOffset :0;
+ if (!BitsContainNoUserData(i->getType(), BaseStart,
+ EndBit-BaseOffset, Context))
+ return false;
+ }
+ }
+
+ // Verify that no field has data that overlaps the region of interest. Yes
+ // this could be sped up a lot by being smarter about queried fields,
+ // however we're only looking at structs up to 16 bytes, so we don't care
+ // much.
+ unsigned idx = 0;
+ for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
+ i != e; ++i, ++idx) {
+ unsigned FieldOffset = (unsigned)Layout.getFieldOffset(idx);
+
+ // If we found a field after the region we care about, then we're done.
+ if (FieldOffset >= EndBit) break;
+
+ unsigned FieldStart = FieldOffset < StartBit ? StartBit-FieldOffset :0;
+ if (!BitsContainNoUserData(i->getType(), FieldStart, EndBit-FieldOffset,
+ Context))
+ return false;
+ }
+
+ // If nothing in this record overlapped the area of interest, then we're
+ // clean.
+ return true;
+ }
+
+ return false;
+}
+
+/// ContainsFloatAtOffset - Return true if the specified LLVM IR type has a
+/// float member at the specified offset. For example, {int,{float}} has a
+/// float at offset 4. It is conservatively correct for this routine to return
+/// false.
+static bool ContainsFloatAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ const llvm::TargetData &TD) {
+ // Base case if we find a float.
+ if (IROffset == 0 && IRType->isFloatTy())
+ return true;
+
+ // If this is a struct, recurse into the field at the specified offset.
+ if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
+ const llvm::StructLayout *SL = TD.getStructLayout(STy);
+ unsigned Elt = SL->getElementContainingOffset(IROffset);
+ IROffset -= SL->getElementOffset(Elt);
+ return ContainsFloatAtOffset(STy->getElementType(Elt), IROffset, TD);
+ }
+
+ // If this is an array, recurse into the field at the specified offset.
+ if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
+ const llvm::Type *EltTy = ATy->getElementType();
+ unsigned EltSize = TD.getTypeAllocSize(EltTy);
+ IROffset -= IROffset/EltSize*EltSize;
+ return ContainsFloatAtOffset(EltTy, IROffset, TD);
+ }
+
+ return false;
+}
+
+
+/// GetSSETypeAtOffset - Return a type that will be passed by the backend in the
+/// low 8 bytes of an XMM register, corresponding to the SSE class.
+const llvm::Type *X86_64ABIInfo::
+GetSSETypeAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ QualType SourceTy, unsigned SourceOffset) const {
+ // The only three choices we have are either double, <2 x float>, or float. We
+ // pass as float if the last 4 bytes is just padding. This happens for
+ // structs that contain 3 floats.
+ if (BitsContainNoUserData(SourceTy, SourceOffset*8+32,
+ SourceOffset*8+64, getContext()))
+ return llvm::Type::getFloatTy(getVMContext());
+
+ // We want to pass as <2 x float> if the LLVM IR type contains a float at
+ // offset+0 and offset+4. Walk the LLVM IR type to find out if this is the
+ // case.
+ if (ContainsFloatAtOffset(IRType, IROffset, getTargetData()) &&
+ ContainsFloatAtOffset(IRType, IROffset+4, getTargetData()))
+ return llvm::VectorType::get(llvm::Type::getFloatTy(getVMContext()), 2);
+
+ return llvm::Type::getDoubleTy(getVMContext());
+}
+
+
+/// GetINTEGERTypeAtOffset - The ABI specifies that a value should be passed in
+/// an 8-byte GPR. This means that we either have a scalar or we are talking
+/// about the high or low part of an up-to-16-byte struct. This routine picks
+/// the best LLVM IR type to represent this, which may be i64 or may be anything
+/// else that the backend will pass in a GPR that works better (e.g. i8, %foo*,
+/// etc).
+///
+/// PrefType is an LLVM IR type that corresponds to (part of) the IR type for
+/// the source type. IROffset is an offset in bytes into the LLVM IR type that
+/// the 8-byte value references. PrefType may be null.
+///
+/// SourceTy is the source level type for the entire argument. SourceOffset is
+/// an offset into this that we're processing (which is always either 0 or 8).
+///
+const llvm::Type *X86_64ABIInfo::
+GetINTEGERTypeAtOffset(const llvm::Type *IRType, unsigned IROffset,
+ QualType SourceTy, unsigned SourceOffset) const {
+ // If we're dealing with an un-offset LLVM IR type, then it means that we're
+ // returning an 8-byte unit starting with it. See if we can safely use it.
+ if (IROffset == 0) {
+ // Pointers and int64's always fill the 8-byte unit.
+ if (isa<llvm::PointerType>(IRType) || IRType->isIntegerTy(64))
+ return IRType;
+
+ // If we have a 1/2/4-byte integer, we can use it only if the rest of the
+ // goodness in the source type is just tail padding. This is allowed to
+ // kick in for struct {double,int} on the int, but not on
+ // struct{double,int,int} because we wouldn't return the second int. We
+ // have to do this analysis on the source type because we can't depend on
+ // unions being lowered a specific way etc.
+ if (IRType->isIntegerTy(8) || IRType->isIntegerTy(16) ||
+ IRType->isIntegerTy(32)) {
+ unsigned BitWidth = cast<llvm::IntegerType>(IRType)->getBitWidth();
+
+ if (BitsContainNoUserData(SourceTy, SourceOffset*8+BitWidth,
+ SourceOffset*8+64, getContext()))
+ return IRType;
+ }
+ }
+
+ if (const llvm::StructType *STy = dyn_cast<llvm::StructType>(IRType)) {
+ // If this is a struct, recurse into the field at the specified offset.
+ const llvm::StructLayout *SL = getTargetData().getStructLayout(STy);
+ if (IROffset < SL->getSizeInBytes()) {
+ unsigned FieldIdx = SL->getElementContainingOffset(IROffset);
+ IROffset -= SL->getElementOffset(FieldIdx);
+
+ return GetINTEGERTypeAtOffset(STy->getElementType(FieldIdx), IROffset,
+ SourceTy, SourceOffset);
+ }
+ }
+
+ if (const llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(IRType)) {
+ const llvm::Type *EltTy = ATy->getElementType();
+ unsigned EltSize = getTargetData().getTypeAllocSize(EltTy);
+ unsigned EltOffset = IROffset/EltSize*EltSize;
+ return GetINTEGERTypeAtOffset(EltTy, IROffset-EltOffset, SourceTy,
+ SourceOffset);
+ }
+
+ // Okay, we don't have any better idea of what to pass, so we pass this in an
+ // integer register that isn't too big to fit the rest of the struct.
+ unsigned TySizeInBytes =
+ (unsigned)getContext().getTypeSizeInChars(SourceTy).getQuantity();
+
+ assert(TySizeInBytes != SourceOffset && "Empty field?");
+
+ // It is always safe to classify this as an integer type up to i64 that
+ // isn't larger than the structure.
+ return llvm::IntegerType::get(getVMContext(),
+ std::min(TySizeInBytes-SourceOffset, 8U)*8);
+}
+
+
+/// GetX86_64ByValArgumentPair - Given a high and low type that can ideally
+/// be used as elements of a two register pair to pass or return, return a
+/// first class aggregate to represent them. For example, if the low part of
+/// a by-value argument should be passed as i32* and the high part as float,
+/// return {i32*, float}.
+static const llvm::Type *
+GetX86_64ByValArgumentPair(const llvm::Type *Lo, const llvm::Type *Hi,
+ const llvm::TargetData &TD) {
+ // In order to correctly satisfy the ABI, we need to the high part to start
+ // at offset 8. If the high and low parts we inferred are both 4-byte types
+ // (e.g. i32 and i32) then the resultant struct type ({i32,i32}) won't have
+ // the second element at offset 8. Check for this:
+ unsigned LoSize = (unsigned)TD.getTypeAllocSize(Lo);
+ unsigned HiAlign = TD.getABITypeAlignment(Hi);
+ unsigned HiStart = llvm::TargetData::RoundUpAlignment(LoSize, HiAlign);
+ assert(HiStart != 0 && HiStart <= 8 && "Invalid x86-64 argument pair!");
+
+ // To handle this, we have to increase the size of the low part so that the
+ // second element will start at an 8 byte offset. We can't increase the size
+ // of the second element because it might make us access off the end of the
+ // struct.
+ if (HiStart != 8) {
+ // There are only two sorts of types the ABI generation code can produce for
+ // the low part of a pair that aren't 8 bytes in size: float or i8/i16/i32.
+ // Promote these to a larger type.
+ if (Lo->isFloatTy())
+ Lo = llvm::Type::getDoubleTy(Lo->getContext());
+ else {
+ assert(Lo->isIntegerTy() && "Invalid/unknown lo type");
+ Lo = llvm::Type::getInt64Ty(Lo->getContext());
+ }
+ }
+
+ const llvm::StructType *Result =
+ llvm::StructType::get(Lo->getContext(), Lo, Hi, NULL);
+
+
+ // Verify that the second element is at an 8-byte offset.
+ assert(TD.getStructLayout(Result)->getElementOffset(1) == 8 &&
+ "Invalid x86-64 argument pair!");
+ return Result;
+}
+
ABIArgInfo X86_64ABIInfo::
-classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
+classifyReturnType(QualType RetTy) const {
// AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the
// classification algorithm.
X86_64ABIInfo::Class Lo, Hi;
@@ -1200,13 +1479,18 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
// Check some invariants.
assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
- assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification.");
assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
const llvm::Type *ResType = 0;
switch (Lo) {
case NoClass:
- return ABIArgInfo::getIgnore();
+ if (Hi == NoClass)
+ return ABIArgInfo::getIgnore();
+ // If the low part is just padding, it takes no register, leave ResType
+ // null.
+ assert((Hi == SSE || Hi == Integer || Hi == X87Up) &&
+ "Unknown missing lo part");
+ break;
case SSEUp:
case X87Up:
@@ -1220,30 +1504,47 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
// AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next
// available register of the sequence %rax, %rdx is used.
case Integer:
- ResType = llvm::Type::getInt64Ty(VMContext); break;
+ ResType = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 0,
+ RetTy, 0);
+
+ // If we have a sign or zero extended integer, make sure to return Extend
+ // so that the parameter gets the right LLVM IR attributes.
+ if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ if (RetTy->isIntegralOrEnumerationType() &&
+ RetTy->isPromotableIntegerType())
+ return ABIArgInfo::getExtend();
+ }
+ break;
// AMD64-ABI 3.2.3p4: Rule 4. If the class is SSE, the next
// available SSE register of the sequence %xmm0, %xmm1 is used.
case SSE:
- ResType = llvm::Type::getDoubleTy(VMContext); break;
+ ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 0, RetTy, 0);
+ break;
// AMD64-ABI 3.2.3p4: Rule 6. If the class is X87, the value is
// returned on the X87 stack in %st0 as 80-bit x87 number.
case X87:
- ResType = llvm::Type::getX86_FP80Ty(VMContext); break;
+ ResType = llvm::Type::getX86_FP80Ty(getVMContext());
+ break;
// AMD64-ABI 3.2.3p4: Rule 8. If the class is COMPLEX_X87, the real
// part of the value is returned in %st0 and the imaginary part in
// %st1.
case ComplexX87:
assert(Hi == ComplexX87 && "Unexpected ComplexX87 classification.");
- ResType = llvm::StructType::get(VMContext,
- llvm::Type::getX86_FP80Ty(VMContext),
- llvm::Type::getX86_FP80Ty(VMContext),
+ ResType = llvm::StructType::get(getVMContext(),
+ llvm::Type::getX86_FP80Ty(getVMContext()),
+ llvm::Type::getX86_FP80Ty(getVMContext()),
NULL);
break;
}
+ const llvm::Type *HighPart = 0;
switch (Hi) {
// Memory was handled previously and X87 should
// never occur as a hi class.
@@ -1252,15 +1553,19 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
assert(0 && "Invalid classification for hi word.");
case ComplexX87: // Previously handled.
- case NoClass: break;
+ case NoClass:
+ break;
case Integer:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getInt64Ty(VMContext), NULL);
+ HighPart = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(RetTy),
+ 8, RetTy, 8);
+ if (Lo == NoClass) // Return HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
break;
case SSE:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getDoubleTy(VMContext), NULL);
+ HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy), 8, RetTy, 8);
+ if (Lo == NoClass) // Return HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
break;
// AMD64-ABI 3.2.3p4: Rule 5. If the class is SSEUP, the eightbyte
@@ -1269,7 +1574,7 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
// SSEUP should always be preceeded by SSE, just widen.
case SSEUp:
assert(Lo == SSE && "Unexpected SSEUp classification.");
- ResType = llvm::VectorType::get(llvm::Type::getDoubleTy(VMContext), 2);
+ ResType = Get16ByteVectorType(RetTy);
break;
// AMD64-ABI 3.2.3p4: Rule 7. If the class is X87UP, the value is
@@ -1279,51 +1584,32 @@ classifyReturnType(QualType RetTy, llvm::LLVMContext &VMContext) const {
// anything. However, in some cases with unions it may not be
// preceeded by X87. In such situations we follow gcc and pass the
// extra bits in an SSE reg.
- if (Lo != X87)
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getDoubleTy(VMContext), NULL);
+ if (Lo != X87) {
+ HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(RetTy),
+ 8, RetTy, 8);
+ if (Lo == NoClass) // Return HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+ }
break;
}
-
- return getCoerceResult(RetTy, ResType);
-}
-
-static const llvm::Type *Get8ByteTypeAtOffset(const llvm::Type *PrefType,
- unsigned Offset,
- const llvm::TargetData &TD) {
- if (PrefType == 0) return 0;
-
- // Pointers are always 8-bytes at offset 0.
- if (Offset == 0 && isa<llvm::PointerType>(PrefType))
- return PrefType;
-
- // TODO: 1/2/4/8 byte integers are also interesting, but we have to know that
- // the "hole" is not used in the containing struct (just undef padding).
- const llvm::StructType *STy = dyn_cast<llvm::StructType>(PrefType);
- if (STy == 0) return 0;
-
- // If this is a struct, recurse into the field at the specified offset.
- const llvm::StructLayout *SL = TD.getStructLayout(STy);
- if (Offset >= SL->getSizeInBytes()) return 0;
-
- unsigned FieldIdx = SL->getElementContainingOffset(Offset);
- Offset -= SL->getElementOffset(FieldIdx);
- return Get8ByteTypeAtOffset(STy->getElementType(FieldIdx), Offset, TD);
+ // If a high part was specified, merge it together with the low part. It is
+ // known to pass in the high eightbyte of the result. We do this by forming a
+ // first class struct aggregate with the high and low part: {low, high}
+ if (HighPart)
+ ResType = GetX86_64ByValArgumentPair(ResType, HighPart, getTargetData());
+
+ return ABIArgInfo::getDirect(ResType);
}
-ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
- llvm::LLVMContext &VMContext,
- unsigned &neededInt,
- unsigned &neededSSE,
- const llvm::Type *PrefType)const{
+ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned &neededInt,
+ unsigned &neededSSE) const {
X86_64ABIInfo::Class Lo, Hi;
classify(Ty, 0, Lo, Hi);
// Check some invariants.
// FIXME: Enforce these by construction.
assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
- assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification.");
assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
neededInt = 0;
@@ -1331,7 +1617,13 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
const llvm::Type *ResType = 0;
switch (Lo) {
case NoClass:
- return ABIArgInfo::getIgnore();
+ if (Hi == NoClass)
+ return ABIArgInfo::getIgnore();
+ // If the low part is just padding, it takes no register, leave ResType
+ // null.
+ assert((Hi == SSE || Hi == Integer || Hi == X87Up) &&
+ "Unknown missing lo part");
+ break;
// AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument
// on the stack.
@@ -1351,16 +1643,23 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
// available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8
// and %r9 is used.
case Integer:
- // It is always safe to classify this as an i64 argument.
- ResType = llvm::Type::getInt64Ty(VMContext);
++neededInt;
-
- // If we can choose a better 8-byte type based on the preferred type, and if
- // that type is still passed in a GPR, use it.
- if (const llvm::Type *PrefTypeLo = Get8ByteTypeAtOffset(PrefType, 0, TD))
- if (isa<llvm::IntegerType>(PrefTypeLo) ||
- isa<llvm::PointerType>(PrefTypeLo))
- ResType = PrefTypeLo;
+
+ // Pick an 8-byte type based on the preferred type.
+ ResType = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(Ty), 0, Ty, 0);
+
+ // If we have a sign or zero extended integer, make sure to return Extend
+ // so that the parameter gets the right LLVM IR attributes.
+ if (Hi == NoClass && isa<llvm::IntegerType>(ResType)) {
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
+ Ty = EnumTy->getDecl()->getIntegerType();
+
+ if (Ty->isIntegralOrEnumerationType() &&
+ Ty->isPromotableIntegerType())
+ return ABIArgInfo::getExtend();
+ }
+
break;
// AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next
@@ -1368,10 +1667,11 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
// order from %xmm0 to %xmm7.
case SSE:
++neededSSE;
- ResType = llvm::Type::getDoubleTy(VMContext);
+ ResType = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 0, Ty, 0);
break;
}
+ const llvm::Type *HighPart = 0;
switch (Hi) {
// Memory was handled previously, ComplexX87 and X87 should
// never occur as hi classes, and X87Up must be preceed by X87,
@@ -1383,49 +1683,49 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
break;
case NoClass: break;
-
- case Integer: {
- // It is always safe to classify this as an i64 argument.
- const llvm::Type *HiType = llvm::Type::getInt64Ty(VMContext);
+
+ case Integer:
++neededInt;
+ // Pick an 8-byte type based on the preferred type.
+ HighPart = GetINTEGERTypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8);
- // If we can choose a better 8-byte type based on the preferred type, and if
- // that type is still passed in a GPR, use it.
- if (const llvm::Type *PrefTypeHi = Get8ByteTypeAtOffset(PrefType, 8, TD))
- if (isa<llvm::IntegerType>(PrefTypeHi) ||
- isa<llvm::PointerType>(PrefTypeHi))
- HiType = PrefTypeHi;
-
- ResType = llvm::StructType::get(VMContext, ResType, HiType, NULL);
+ if (Lo == NoClass) // Pass HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
break;
- }
// X87Up generally doesn't occur here (long double is passed in
// memory), except in situations involving unions.
case X87Up:
case SSE:
- ResType = llvm::StructType::get(VMContext, ResType,
- llvm::Type::getDoubleTy(VMContext), NULL);
+ HighPart = GetSSETypeAtOffset(CGT.ConvertTypeRecursive(Ty), 8, Ty, 8);
+
+ if (Lo == NoClass) // Pass HighPart at offset 8 in memory.
+ return ABIArgInfo::getDirect(HighPart, 8);
+
++neededSSE;
break;
// AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the
// eightbyte is passed in the upper half of the last used SSE
- // register.
+ // register. This only happens when 128-bit vectors are passed.
case SSEUp:
- assert(Lo == SSE && "Unexpected SSEUp classification.");
- ResType = llvm::VectorType::get(llvm::Type::getDoubleTy(VMContext), 2);
+ assert(Lo == SSE && "Unexpected SSEUp classification");
+ ResType = Get16ByteVectorType(Ty);
break;
}
- return getCoerceResult(Ty, ResType);
+ // If a high part was specified, merge it together with the low part. It is
+ // known to pass in the high eightbyte of the result. We do this by forming a
+ // first class struct aggregate with the high and low part: {low, high}
+ if (HighPart)
+ ResType = GetX86_64ByValArgumentPair(ResType, HighPart, getTargetData());
+
+ return ABIArgInfo::getDirect(ResType);
}
-void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), VMContext);
+void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
+
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
// Keep track of the number of assigned registers.
unsigned freeIntRegs = 6, freeSSERegs = 8;
@@ -1439,17 +1739,8 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
// get assigned (in left-to-right order) for passing as follows...
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it) {
- // If the client specified a preferred IR type to use, pass it down to
- // classifyArgumentType.
- const llvm::Type *PrefType = 0;
- if (NumPrefTypes) {
- PrefType = *PrefTypes++;
- --NumPrefTypes;
- }
-
unsigned neededInt, neededSSE;
- it->info = classifyArgumentType(it->type, VMContext,
- neededInt, neededSSE, PrefType);
+ it->info = classifyArgumentType(it->type, neededInt, neededSSE);
// AMD64-ABI 3.2.3p3: If there are no registers available for any
// eightbyte of an argument, the whole argument is passed on the
@@ -1527,9 +1818,9 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
// i8* reg_save_area;
// };
unsigned neededInt, neededSSE;
-
+
Ty = CGF.getContext().getCanonicalType(Ty);
- ABIArgInfo AI = classifyArgumentType(Ty, VMContext, neededInt, neededSSE, 0);
+ ABIArgInfo AI = classifyArgumentType(Ty, neededInt, neededSSE);
// AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed
// in the registers. If not go to step 7.
@@ -1591,13 +1882,13 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
"reg_save_area");
if (neededInt && neededSSE) {
// FIXME: Cleanup.
- assert(AI.isCoerce() && "Unexpected ABI info for mixed regs");
+ assert(AI.isDirect() && "Unexpected ABI info for mixed regs");
const llvm::StructType *ST = cast<llvm::StructType>(AI.getCoerceToType());
llvm::Value *Tmp = CGF.CreateTempAlloca(ST);
assert(ST->getNumElements() == 2 && "Unexpected ABI info for mixed regs");
const llvm::Type *TyLo = ST->getElementType(0);
const llvm::Type *TyHi = ST->getElementType(1);
- assert((TyLo->isFloatingPointTy() ^ TyHi->isFloatingPointTy()) &&
+ assert((TyLo->isFPOrFPVectorTy() ^ TyHi->isFPOrFPVectorTy()) &&
"Unexpected ABI info for mixed regs");
const llvm::Type *PTyLo = llvm::PointerType::getUnqual(TyLo);
const llvm::Type *PTyHi = llvm::PointerType::getUnqual(TyHi);
@@ -1674,7 +1965,28 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return ResAddr;
}
+llvm::Value *WinX86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ const llvm::Type *BP = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
+ const llvm::Type *BPP = llvm::PointerType::getUnqual(BP);
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP,
+ "ap");
+ llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur");
+ llvm::Type *PTy =
+ llvm::PointerType::getUnqual(CGF.ConvertType(Ty));
+ llvm::Value *AddrTyped = Builder.CreateBitCast(Addr, PTy);
+
+ uint64_t Offset =
+ llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, 8);
+ llvm::Value *NextAddr =
+ Builder.CreateGEP(Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset),
+ "ap.next");
+ Builder.CreateStore(NextAddr, VAListAddrAsBPP);
+
+ return AddrTyped;
+}
//===----------------------------------------------------------------------===//
// PIC16 ABI Implementation
@@ -1683,23 +1995,18 @@ llvm::Value *X86_64ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
namespace {
class PIC16ABIInfo : public ABIInfo {
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
+public:
+ PIC16ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
+
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
+
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
+ it->info = classifyArgumentType(it->type);
}
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -1708,14 +2015,13 @@ class PIC16ABIInfo : public ABIInfo {
class PIC16TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {}
+ PIC16TargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new PIC16ABIInfo(CGT)) {}
};
}
-ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
+ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType()) {
return ABIArgInfo::getIgnore();
} else {
@@ -1723,9 +2029,7 @@ ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy,
}
}
-ABIArgInfo PIC16ABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
+ABIArgInfo PIC16ABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect();
}
@@ -1759,13 +2063,15 @@ llvm::Value *PIC16ABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
namespace {
class PPC32TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
public:
+ PPC32TargetCodeGenInfo(CodeGenTypes &CGT) : DefaultTargetCodeGenInfo(CGT) {}
+
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
// This is recovered from gcc output.
return 1; // r1 is the dedicated stack pointer
}
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *Address) const;
+ llvm::Value *Address) const;
};
}
@@ -1809,7 +2115,7 @@ PPC32TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
// 113: sfp
AssignToArrayRange(Builder, Address, Four8, 109, 113);
- return false;
+ return false;
}
@@ -1831,23 +2137,15 @@ private:
ABIKind Kind;
public:
- ARMABIInfo(ABIKind _Kind) : Kind(_Kind) {}
+ ARMABIInfo(CodeGenTypes &CGT, ABIKind _Kind) : ABIInfo(CGT), Kind(_Kind) {}
private:
ABIKind getABIKind() const { return Kind; }
- ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMCOntext) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const;
+ virtual void computeInfo(CGFunctionInfo &FI) const;
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;
@@ -1855,8 +2153,8 @@ private:
class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K)
- :TargetCodeGenInfo(new ARMABIInfo(K)) {}
+ ARMTargetCodeGenInfo(CodeGenTypes &CGT, ARMABIInfo::ABIKind K)
+ :TargetCodeGenInfo(new ARMABIInfo(CGT, K)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const {
return 13;
@@ -1865,18 +2163,13 @@ public:
}
-void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context,
- VMContext);
+void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it) {
- it->info = classifyArgumentType(it->type, Context, VMContext);
- }
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type);
- const llvm::Triple &Triple(Context.Target.getTriple());
+ const llvm::Triple &Triple(getContext().Target.getTriple());
llvm::CallingConv::ID DefaultCC;
if (Triple.getEnvironmentName() == "gnueabi" ||
Triple.getEnvironmentName() == "eabi")
@@ -1901,10 +2194,8 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
}
}
-ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (!CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty) const {
+ if (!isAggregateTypeForABI(Ty)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = Ty->getAs<EnumType>())
Ty = EnumTy->getDecl()->getIntegerType();
@@ -1914,7 +2205,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
}
// Ignore empty records.
- if (isEmptyRecord(Context, Ty, true))
+ if (isEmptyRecord(getContext(), Ty, true))
return ABIArgInfo::getIgnore();
// Structures with either a non-trivial destructor or a non-trivial
@@ -1927,21 +2218,21 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
// FIXME: This doesn't handle alignment > 64 bits.
const llvm::Type* ElemTy;
unsigned SizeRegs;
- if (Context.getTypeAlign(Ty) > 32) {
- ElemTy = llvm::Type::getInt64Ty(VMContext);
- SizeRegs = (Context.getTypeSize(Ty) + 63) / 64;
+ if (getContext().getTypeAlign(Ty) > 32) {
+ ElemTy = llvm::Type::getInt64Ty(getVMContext());
+ SizeRegs = (getContext().getTypeSize(Ty) + 63) / 64;
} else {
- ElemTy = llvm::Type::getInt32Ty(VMContext);
- SizeRegs = (Context.getTypeSize(Ty) + 31) / 32;
+ ElemTy = llvm::Type::getInt32Ty(getVMContext());
+ SizeRegs = (getContext().getTypeSize(Ty) + 31) / 32;
}
std::vector<const llvm::Type*> LLVMFields;
LLVMFields.push_back(llvm::ArrayType::get(ElemTy, SizeRegs));
- const llvm::Type* STy = llvm::StructType::get(VMContext, LLVMFields, true);
- return ABIArgInfo::getCoerce(STy);
+ const llvm::Type* STy = llvm::StructType::get(getVMContext(), LLVMFields,
+ true);
+ return ABIArgInfo::getDirect(STy);
}
-static bool isIntegerLikeType(QualType Ty,
- ASTContext &Context,
+static bool isIntegerLikeType(QualType Ty, ASTContext &Context,
llvm::LLVMContext &VMContext) {
// APCS, C Language Calling Conventions, Non-Simple Return Values: A structure
// is called integer-like if its size is less than or equal to one word, and
@@ -2011,7 +2302,7 @@ static bool isIntegerLikeType(QualType Ty,
if (!isIntegerLikeType(FD->getType(), Context, VMContext))
return false;
-
+
// Only allow at most one field in a structure. This doesn't match the
// wording above, but follows gcc in situations with a field following an
// empty structure.
@@ -2026,13 +2317,11 @@ static bool isIntegerLikeType(QualType Ty,
return true;
}
-ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
+ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy) const {
if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
- if (!CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ if (!isAggregateTypeForABI(RetTy)) {
// Treat an enum type as its underlying type.
if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
RetTy = EnumTy->getDecl()->getIntegerType();
@@ -2048,7 +2337,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// Are we following APCS?
if (getABIKind() == APCS) {
- if (isEmptyRecord(Context, RetTy, false))
+ if (isEmptyRecord(getContext(), RetTy, false))
return ABIArgInfo::getIgnore();
// Complex types are all returned as packed integers.
@@ -2056,18 +2345,18 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// FIXME: Consider using 2 x vector types if the back end handles them
// correctly.
if (RetTy->isAnyComplexType())
- return ABIArgInfo::getCoerce(llvm::IntegerType::get(
- VMContext, Context.getTypeSize(RetTy)));
+ return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(),
+ getContext().getTypeSize(RetTy)));
// Integer like structures are returned in r0.
- if (isIntegerLikeType(RetTy, Context, VMContext)) {
+ if (isIntegerLikeType(RetTy, getContext(), getVMContext())) {
// Return in the smallest viable integer type.
- uint64_t Size = Context.getTypeSize(RetTy);
+ uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 8)
- return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(VMContext));
+ return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
if (Size <= 16)
- return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(VMContext));
- return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(VMContext));
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
}
// Otherwise return in memory.
@@ -2076,19 +2365,19 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
// Otherwise this is an AAPCS variant.
- if (isEmptyRecord(Context, RetTy, true))
+ if (isEmptyRecord(getContext(), RetTy, true))
return ABIArgInfo::getIgnore();
// Aggregates <= 4 bytes are returned in r0; other aggregates
// are returned indirectly.
- uint64_t Size = Context.getTypeSize(RetTy);
+ uint64_t Size = getContext().getTypeSize(RetTy);
if (Size <= 32) {
// Return in the smallest viable integer type.
if (Size <= 8)
- return ABIArgInfo::getCoerce(llvm::Type::getInt8Ty(VMContext));
+ return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
if (Size <= 16)
- return ABIArgInfo::getCoerce(llvm::Type::getInt16Ty(VMContext));
- return ABIArgInfo::getCoerce(llvm::Type::getInt32Ty(VMContext));
+ return ABIArgInfo::getDirect(llvm::Type::getInt16Ty(getVMContext()));
+ return ABIArgInfo::getDirect(llvm::Type::getInt32Ty(getVMContext()));
}
return ABIArgInfo::getIndirect(0);
@@ -2118,21 +2407,19 @@ llvm::Value *ARMABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
return AddrTyped;
}
-ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
+ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+
+ if (isAggregateTypeForABI(RetTy))
return ABIArgInfo::getIndirect(0);
- } else {
- // Treat an enum type as its underlying type.
- if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
- RetTy = EnumTy->getDecl()->getIntegerType();
- return (RetTy->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
+ // Treat an enum type as its underlying type.
+ if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
+ RetTy = EnumTy->getDecl()->getIntegerType();
+
+ return (RetTy->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
//===----------------------------------------------------------------------===//
@@ -2142,23 +2429,19 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy,
namespace {
class SystemZABIInfo : public ABIInfo {
- bool isPromotableIntegerType(QualType Ty) const;
+public:
+ SystemZABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
- ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
+ bool isPromotableIntegerType(QualType Ty) const;
- ABIArgInfo classifyArgumentType(QualType RetTy, ASTContext &Context,
- llvm::LLVMContext &VMContext) const;
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
+ ABIArgInfo classifyArgumentType(QualType RetTy) const;
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context,
- llvm::LLVMContext &VMContext,
- const llvm::Type *const *PrefTypes,
- unsigned NumPrefTypes) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(),
- Context, VMContext);
+ virtual void computeInfo(CGFunctionInfo &FI) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context, VMContext);
+ it->info = classifyArgumentType(it->type);
}
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
@@ -2167,7 +2450,8 @@ class SystemZABIInfo : public ABIInfo {
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {}
+ SystemZTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new SystemZABIInfo(CGT)) {}
};
}
@@ -2199,28 +2483,22 @@ llvm::Value *SystemZABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
}
-ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (RetTy->isVoidType()) {
+ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {
+ if (RetTy->isVoidType())
return ABIArgInfo::getIgnore();
- } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) {
+ if (isAggregateTypeForABI(RetTy))
return ABIArgInfo::getIndirect(0);
- } else {
- return (isPromotableIntegerType(RetTy) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
+
+ return (isPromotableIntegerType(RetTy) ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
-ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
+ if (isAggregateTypeForABI(Ty))
return ABIArgInfo::getIndirect(0);
- } else {
- return (isPromotableIntegerType(Ty) ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
+
+ return (isPromotableIntegerType(Ty) ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
}
//===----------------------------------------------------------------------===//
@@ -2231,7 +2509,8 @@ namespace {
class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {}
+ MSP430TargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const;
};
@@ -2270,14 +2549,15 @@ void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
namespace {
class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
public:
- MIPSTargetCodeGenInfo(): TargetCodeGenInfo(new DefaultABIInfo()) {}
+ MIPSTargetCodeGenInfo(CodeGenTypes &CGT)
+ : TargetCodeGenInfo(new DefaultABIInfo(CGT)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const {
return 29;
}
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *Address) const;
+ llvm::Value *Address) const;
};
}
@@ -2315,7 +2595,7 @@ MIPSTargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
}
-const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const {
+const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
if (TheTargetCodeGenInfo)
return *TheTargetCodeGenInfo;
@@ -2325,56 +2605,61 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const {
const llvm::Triple &Triple = getContext().Target.getTriple();
switch (Triple.getArch()) {
default:
- return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo());
+ return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo(Types));
case llvm::Triple::mips:
case llvm::Triple::mipsel:
- return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo());
+ return *(TheTargetCodeGenInfo = new MIPSTargetCodeGenInfo(Types));
case llvm::Triple::arm:
case llvm::Triple::thumb:
// FIXME: We want to know the float calling convention as well.
if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0)
return *(TheTargetCodeGenInfo =
- new ARMTargetCodeGenInfo(ARMABIInfo::APCS));
+ new ARMTargetCodeGenInfo(Types, ARMABIInfo::APCS));
return *(TheTargetCodeGenInfo =
- new ARMTargetCodeGenInfo(ARMABIInfo::AAPCS));
+ new ARMTargetCodeGenInfo(Types, ARMABIInfo::AAPCS));
case llvm::Triple::pic16:
- return *(TheTargetCodeGenInfo = new PIC16TargetCodeGenInfo());
+ return *(TheTargetCodeGenInfo = new PIC16TargetCodeGenInfo(Types));
case llvm::Triple::ppc:
- return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo());
+ return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo(Types));
case llvm::Triple::systemz:
- return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo());
+ return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo(Types));
case llvm::Triple::msp430:
- return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo());
+ return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types));
case llvm::Triple::x86:
switch (Triple.getOS()) {
case llvm::Triple::Darwin:
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Context, true, true));
+ new X86_32TargetCodeGenInfo(Types, true, true));
case llvm::Triple::Cygwin:
case llvm::Triple::MinGW32:
- case llvm::Triple::MinGW64:
case llvm::Triple::AuroraUX:
case llvm::Triple::DragonFly:
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Context, false, true));
+ new X86_32TargetCodeGenInfo(Types, false, true));
default:
return *(TheTargetCodeGenInfo =
- new X86_32TargetCodeGenInfo(Context, false, false));
+ new X86_32TargetCodeGenInfo(Types, false, false));
}
case llvm::Triple::x86_64:
- return *(TheTargetCodeGenInfo =
- new X86_64TargetCodeGenInfo(Context, TheTargetData));
+ switch (Triple.getOS()) {
+ case llvm::Triple::Win32:
+ case llvm::Triple::MinGW64:
+ case llvm::Triple::Cygwin:
+ return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types));
+ default:
+ return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo(Types));
+ }
}
}
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h
index f0a78243ff79..9d4cf1610308 100644
--- a/lib/CodeGen/TargetInfo.h
+++ b/lib/CodeGen/TargetInfo.h
@@ -47,6 +47,16 @@ namespace clang {
virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
CodeGen::CodeGenModule &M) const { }
+ /// Determines the size of struct _Unwind_Exception on this platform,
+ /// in 8-bit units. The Itanium ABI defines this as:
+ /// struct _Unwind_Exception {
+ /// uint64 exception_class;
+ /// _Unwind_Exception_Cleanup_Fn exception_cleanup;
+ /// uint64 private_1;
+ /// uint64 private_2;
+ /// };
+ unsigned getSizeOfUnwindException() const { return 32; }
+
/// Controls whether __builtin_extend_pointer should sign-extend
/// pointers to uint64_t or zero-extend them (the default). Has
/// no effect for targets:
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index 282e9fe82e41..c059afd45439 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -83,10 +83,6 @@ void Compilation::PrintJob(llvm::raw_ostream &OS, const Job &J,
OS << '"';
}
OS << Terminator;
- } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
- for (PipedJob::const_iterator
- it = PJ->begin(), ie = PJ->end(); it != ie; ++it)
- PrintJob(OS, **it, (it + 1 != PJ->end()) ? " |\n" : "\n", Quote);
} else {
const JobList *Jobs = cast<JobList>(&J);
for (JobList::const_iterator
@@ -190,14 +186,6 @@ int Compilation::ExecuteJob(const Job &J,
const Command *&FailingCommand) const {
if (const Command *C = dyn_cast<Command>(&J)) {
return ExecuteCommand(*C, FailingCommand);
- } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) {
- // Piped commands with a single job are easy.
- if (PJ->size() == 1)
- return ExecuteCommand(**PJ->begin(), FailingCommand);
-
- FailingCommand = *PJ->begin();
- getDriver().Diag(clang::diag::err_drv_unsupported_opt) << "-pipe";
- return 1;
} else {
const JobList *Jobs = cast<JobList>(&J);
for (JobList::const_iterator
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 2fc0a5354d80..82f913484f48 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -25,6 +25,7 @@
#include "clang/Basic/Version.h"
+#include "llvm/Config/config.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -39,13 +40,13 @@
using namespace clang::driver;
using namespace clang;
-Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
+Driver::Driver(llvm::StringRef _ClangExecutable,
llvm::StringRef _DefaultHostTriple,
llvm::StringRef _DefaultImageName,
bool IsProduction, bool CXXIsProduction,
Diagnostic &_Diags)
: Opts(createDriverOptTable()), Diags(_Diags),
- Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
+ ClangExecutable(_ClangExecutable), DefaultHostTriple(_DefaultHostTriple),
DefaultImageName(_DefaultImageName),
DriverTitle("clang \"gcc-compatible\" driver"),
Host(0),
@@ -68,6 +69,10 @@ Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
CCCUseClangCXX = false;
}
+ llvm::sys::Path Executable(ClangExecutable);
+ Name = Executable.getBasename();
+ Dir = Executable.getDirname();
+
// Compute the path to the resource directory.
llvm::sys::Path P(Dir);
P.eraseComponent(); // Remove /bin from foo/bin
@@ -75,11 +80,6 @@ Driver::Driver(llvm::StringRef _Name, llvm::StringRef _Dir,
P.appendComponent("clang");
P.appendComponent(CLANG_VERSION_STRING);
ResourceDir = P.str();
-
- // Save the original clang executable path.
- P = Dir;
- P.appendComponent(Name);
- ClangExecutable = P.str();
}
Driver::~Driver() {
@@ -160,6 +160,16 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
DAL->append(*it);
}
+ // Add a default value of -mlinker-version=, if one was given and the user
+ // didn't specify one.
+#if defined(HOST_LINK_VERSION)
+ if (!Args.hasArg(options::OPT_mlinker_version_EQ)) {
+ DAL->AddJoinedArg(0, Opts->getOption(options::OPT_mlinker_version_EQ),
+ HOST_LINK_VERSION);
+ DAL->getLastArg(options::OPT_mlinker_version_EQ)->claim();
+ }
+#endif
+
return DAL;
}
@@ -176,13 +186,15 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
bool CCCPrintOptions = false, CCCPrintActions = false;
const char **Start = argv + 1, **End = argv + argc;
- const char *HostTriple = DefaultHostTriple.c_str();
InputArgList *Args = ParseArgStrings(Start, End);
// -no-canonical-prefixes is used very early in main.
Args->ClaimAllArgs(options::OPT_no_canonical_prefixes);
+ // Ignore -pipe.
+ Args->ClaimAllArgs(options::OPT_pipe);
+
// Extract -ccc args.
//
// FIXME: We need to figure out where this behavior should live. Most of it
@@ -223,14 +235,16 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
Cur = Split.second;
}
}
+ // FIXME: We shouldn't overwrite the default host triple here, but we have
+ // nowhere else to put this currently.
if (const Arg *A = Args->getLastArg(options::OPT_ccc_host_triple))
- HostTriple = A->getValue(*Args);
+ DefaultHostTriple = A->getValue(*Args);
if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir))
- Dir = A->getValue(*Args);
+ Dir = InstalledDir = A->getValue(*Args);
if (const Arg *A = Args->getLastArg(options::OPT_B))
PrefixDir = A->getValue(*Args);
- Host = GetHostInfo(HostTriple);
+ Host = GetHostInfo(DefaultHostTriple.c_str());
// Perform the default argument translations.
DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args);
@@ -248,14 +262,12 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) {
if (!HandleImmediateArgs(*C))
return C;
- // Construct the list of abstract actions to perform for this compilation. We
- // avoid passing a Compilation here simply to enforce the abstraction that
- // pipelining is not host or toolchain dependent (other than the driver driver
- // test).
+ // Construct the list of abstract actions to perform for this compilation.
if (Host->useDriverDriver())
- BuildUniversalActions(C->getArgs(), C->getActions());
+ BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(),
+ C->getActions());
else
- BuildActions(C->getArgs(), C->getActions());
+ BuildActions(C->getDefaultToolChain(), C->getArgs(), C->getActions());
if (CCCPrintActions) {
PrintActions(*C);
@@ -525,7 +537,8 @@ static bool ContainsCompileAction(const Action *A) {
return false;
}
-void Driver::BuildUniversalActions(const ArgList &Args,
+void Driver::BuildUniversalActions(const ToolChain &TC,
+ const ArgList &Args,
ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building universal build actions");
// Collect the list of architectures. Duplicates are allowed, but should only
@@ -570,7 +583,7 @@ void Driver::BuildUniversalActions(const ArgList &Args,
}
ActionList SingleActions;
- BuildActions(Args, SingleActions);
+ BuildActions(TC, Args, SingleActions);
// Add in arch bindings for every top level action, as well as lipo and
// dsymutil steps if needed.
@@ -620,7 +633,8 @@ void Driver::BuildUniversalActions(const ArgList &Args,
}
}
-void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
+void Driver::BuildActions(const ToolChain &TC, const ArgList &Args,
+ ActionList &Actions) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation actions");
// Start by constructing the list of inputs and their types.
@@ -660,7 +674,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
// found. We use a host hook here because Darwin at least has its own
// idea of what .s is.
if (const char *Ext = strrchr(Value, '.'))
- Ty = Host->lookupTypeForExtension(Ext + 1);
+ Ty = TC.LookupTypeForExtension(Ext + 1);
if (Ty == types::TY_INVALID)
Ty = types::TY_Object;
@@ -885,16 +899,6 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
void Driver::BuildJobs(Compilation &C) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
- bool SaveTemps = C.getArgs().hasArg(options::OPT_save_temps);
- bool UsePipes = C.getArgs().hasArg(options::OPT_pipe);
-
- // FIXME: Pipes are forcibly disabled until we support executing them.
- if (!CCCPrintBindings)
- UsePipes = false;
-
- // -save-temps inhibits pipes.
- if (SaveTemps && UsePipes)
- Diag(clang::diag::warn_drv_pipe_ignored_with_save_temps);
Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o);
@@ -934,7 +938,6 @@ void Driver::BuildJobs(Compilation &C) const {
InputInfo II;
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
/*BoundArch*/0,
- /*CanAcceptPipe*/ true,
/*AtTopLevel*/ true,
/*LinkingOutput*/ LinkingOutput,
II);
@@ -1032,17 +1035,11 @@ void Driver::BuildJobsForAction(Compilation &C,
const Action *A,
const ToolChain *TC,
const char *BoundArch,
- bool CanAcceptPipe,
bool AtTopLevel,
const char *LinkingOutput,
InputInfo &Result) const {
llvm::PrettyStackTraceString CrashInfo("Building compilation jobs");
- bool UsePipes = C.getArgs().hasArg(options::OPT_pipe);
- // FIXME: Pipes are forcibly disabled until we support executing them.
- if (!CCCPrintBindings)
- UsePipes = false;
-
if (const InputAction *IA = dyn_cast<InputAction>(A)) {
// FIXME: It would be nice to not claim this here; maybe the old scheme of
// just using Args was better?
@@ -1064,7 +1061,7 @@ void Driver::BuildJobsForAction(Compilation &C,
TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName());
BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(),
- CanAcceptPipe, AtTopLevel, LinkingOutput, Result);
+ AtTopLevel, LinkingOutput, Result);
return;
}
@@ -1074,7 +1071,6 @@ void Driver::BuildJobsForAction(Compilation &C,
const Tool &T = SelectToolForJob(C, TC, JA, Inputs);
// Only use pipes when there is exactly one input.
- bool TryToUsePipeInput = Inputs->size() == 1 && T.acceptsPipedInput();
InputInfoList InputInfos;
for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end();
it != ie; ++it) {
@@ -1087,33 +1083,11 @@ void Driver::BuildJobsForAction(Compilation &C,
SubJobAtTopLevel = true;
InputInfo II;
- BuildJobsForAction(C, *it, TC, BoundArch, TryToUsePipeInput,
+ BuildJobsForAction(C, *it, TC, BoundArch,
SubJobAtTopLevel, LinkingOutput, II);
InputInfos.push_back(II);
}
- // Determine if we should output to a pipe.
- bool OutputToPipe = false;
- if (CanAcceptPipe && T.canPipeOutput()) {
- // Some actions default to writing to a pipe if they are the top level phase
- // and there was no user override.
- //
- // FIXME: Is there a better way to handle this?
- if (AtTopLevel) {
- if (isa<PreprocessJobAction>(A) && !C.getArgs().hasArg(options::OPT_o))
- OutputToPipe = true;
- } else if (UsePipes)
- OutputToPipe = true;
- }
-
- // Figure out where to put the job (pipes).
- Job *Dest = &C.getJobs();
- if (InputInfos[0].isPipe()) {
- assert(TryToUsePipeInput && "Unrequested pipe!");
- assert(InputInfos.size() == 1 && "Unexpected pipe with multiple inputs.");
- Dest = &InputInfos[0].getPipe();
- }
-
// Always use the first input as the base input.
const char *BaseInput = InputInfos[0].getBaseInput();
@@ -1122,22 +1096,9 @@ void Driver::BuildJobsForAction(Compilation &C,
if (JA->getType() == types::TY_dSYM)
BaseInput = InputInfos[0].getFilename();
- // Determine the place to write output to (nothing, pipe, or filename) and
- // where to put the new job.
+ // Determine the place to write output to, if any.
if (JA->getType() == types::TY_Nothing) {
Result = InputInfo(A->getType(), BaseInput);
- } else if (OutputToPipe) {
- // Append to current piped job or create a new one as appropriate.
- PipedJob *PJ = dyn_cast<PipedJob>(Dest);
- if (!PJ) {
- PJ = new PipedJob();
- // FIXME: Temporary hack so that -ccc-print-bindings work until we have
- // pipe support. Please remove later.
- if (!CCCPrintBindings)
- cast<JobList>(Dest)->addJob(PJ);
- Dest = PJ;
- }
- Result = InputInfo(PJ, A->getType(), BaseInput);
} else {
Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, AtTopLevel),
A->getType(), BaseInput);
@@ -1153,7 +1114,7 @@ void Driver::BuildJobsForAction(Compilation &C,
}
llvm::errs() << "], output: " << Result.getAsString() << "\n";
} else {
- T.ConstructJob(C, *JA, *Dest, Result, InputInfos,
+ T.ConstructJob(C, *JA, Result, InputInfos,
C.getArgsForToolChain(TC, BoundArch), LinkingOutput);
}
}
@@ -1169,6 +1130,10 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
return C.addResultFile(FinalOutput->getValue(C.getArgs()));
}
+ // Default to writing to stdout?
+ if (AtTopLevel && isa<PreprocessJobAction>(JA))
+ return "-";
+
// Output to a temporary file?
if (!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) {
std::string TmpName =
@@ -1307,6 +1272,11 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const {
return createMinixHostInfo(*this, Triple);
case llvm::Triple::Linux:
return createLinuxHostInfo(*this, Triple);
+ case llvm::Triple::Win32:
+ return createWindowsHostInfo(*this, Triple);
+ case llvm::Triple::MinGW32:
+ case llvm::Triple::MinGW64:
+ return createMinGWHostInfo(*this, Triple);
default:
return createUnknownHostInfo(*this, Triple);
}
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 0636d9eab15c..7c5e430bb7d5 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -38,12 +38,6 @@ namespace {
/// DarwinHostInfo - Darwin host information implementation.
class DarwinHostInfo : public HostInfo {
- /// Darwin version of host.
- unsigned DarwinVersion[3];
-
- /// GCC version to use on this host.
- unsigned GCCVersion[3];
-
/// Cache of tool chains we have created.
mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains;
@@ -53,37 +47,12 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- types::ID Ty = types::lookupTypeForExtension(Ext);
-
- // Darwin always preprocesses assembly files (unless -x is used
- // explicitly).
- if (Ty == types::TY_PP_Asm)
- return types::TY_Asm;
-
- return Ty;
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple)
: HostInfo(D, Triple) {
-
- assert(Triple.getArch() != llvm::Triple::UnknownArch && "Invalid arch!");
- assert(memcmp(&getOSName()[0], "darwin", 6) == 0 &&
- "Unknown Darwin platform.");
- bool HadExtra;
- if (!Driver::GetReleaseVersion(&getOSName()[6],
- DarwinVersion[0], DarwinVersion[1],
- DarwinVersion[2], HadExtra))
- D.Diag(clang::diag::err_drv_invalid_darwin_version) << getOSName();
-
- // We can only call 4.2.1 for now.
- GCCVersion[0] = 4;
- GCCVersion[1] = 2;
- GCCVersion[2] = 1;
}
DarwinHostInfo::~DarwinHostInfo() {
@@ -147,11 +116,10 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
const char *UseNewToolChain = ::getenv("CCC_ENABLE_NEW_DARWIN_TOOLCHAIN");
if (UseNewToolChain ||
Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) {
- TC = new toolchains::DarwinClang(*this, TCTriple, DarwinVersion);
+ TC = new toolchains::DarwinClang(*this, TCTriple);
} else if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) {
// We still use the legacy DarwinGCC toolchain on X86.
- TC = new toolchains::DarwinGCC(*this, TCTriple, DarwinVersion,
- GCCVersion);
+ TC = new toolchains::DarwinGCC(*this, TCTriple);
} else
TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple);
}
@@ -170,15 +138,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- types::ID Ty = types::lookupTypeForExtension(Ext);
-
- if (Ty == types::TY_PP_Asm)
- return types::TY_Asm;
-
- return Ty;
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -212,10 +171,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -279,10 +234,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -330,10 +281,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -379,10 +326,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -399,19 +342,22 @@ bool FreeBSDHostInfo::useDriverDriver() const {
ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
const char *ArchName) const {
- bool Lib32 = false;
-
assert(!ArchName &&
"Unexpected arch name on platform without driver driver support.");
- // On x86_64 we need to be able to compile 32-bits binaries as well.
- // Compiling 64-bit binaries on i386 is not supported. We don't have a
- // lib64.
+ // Automatically handle some instances of -m32/-m64 we know about.
std::string Arch = getArchName();
ArchName = Arch.c_str();
- if (Args.hasArg(options::OPT_m32) && getArchName() == "x86_64") {
- ArchName = "i386";
- Lib32 = true;
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ } else if (Triple.getArch() == llvm::Triple::ppc ||
+ Triple.getArch() == llvm::Triple::ppc64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
+ }
}
ToolChain *&TC = ToolChains[ArchName];
@@ -419,7 +365,7 @@ ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args,
llvm::Triple TCTriple(getTriple());
TCTriple.setArchName(ArchName);
- TC = new toolchains::FreeBSD(*this, TCTriple, Lib32);
+ TC = new toolchains::FreeBSD(*this, TCTriple);
}
return TC;
@@ -439,10 +385,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -491,10 +433,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -540,10 +478,6 @@ public:
virtual bool useDriverDriver() const;
- virtual types::ID lookupTypeForExtension(const char *Ext) const {
- return types::lookupTypeForExtension(Ext);
- }
-
virtual ToolChain *CreateToolChain(const ArgList &Args,
const char *ArchName) const;
};
@@ -591,8 +525,79 @@ ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
return TC;
}
+// Windows Host Info
+
+/// WindowsHostInfo - Host information to use on Microsoft Windows.
+class WindowsHostInfo : public HostInfo {
+ /// Cache of tool chains we have created.
+ mutable llvm::StringMap<ToolChain*> ToolChains;
+
+public:
+ WindowsHostInfo(const Driver &D, const llvm::Triple& Triple);
+ ~WindowsHostInfo();
+
+ virtual bool useDriverDriver() const;
+
+ virtual types::ID lookupTypeForExtension(const char *Ext) const {
+ return types::lookupTypeForExtension(Ext);
+ }
+
+ virtual ToolChain *CreateToolChain(const ArgList &Args,
+ const char *ArchName) const;
+};
+
+WindowsHostInfo::WindowsHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : HostInfo(D, Triple) {
+}
+
+WindowsHostInfo::~WindowsHostInfo() {
+ for (llvm::StringMap<ToolChain*>::iterator
+ it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it)
+ delete it->second;
+}
+
+bool WindowsHostInfo::useDriverDriver() const {
+ return false;
+}
+
+ToolChain *WindowsHostInfo::CreateToolChain(const ArgList &Args,
+ const char *ArchName) const {
+ assert(!ArchName &&
+ "Unexpected arch name on platform without driver driver support.");
+
+ // Automatically handle some instances of -m32/-m64 we know about.
+ std::string Arch = getArchName();
+ ArchName = Arch.c_str();
+ if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
+ if (Triple.getArch() == llvm::Triple::x86 ||
+ Triple.getArch() == llvm::Triple::x86_64) {
+ ArchName =
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
+ }
+ }
+
+ ToolChain *&TC = ToolChains[ArchName];
+ if (!TC) {
+ llvm::Triple TCTriple(getTriple());
+ TCTriple.setArchName(ArchName);
+
+ TC = new toolchains::Windows(*this, TCTriple);
+ }
+
+ return TC;
}
+// FIXME: This is a placeholder.
+class MinGWHostInfo : public UnknownHostInfo {
+public:
+ MinGWHostInfo(const Driver &D, const llvm::Triple& Triple);
+};
+
+MinGWHostInfo::MinGWHostInfo(const Driver &D, const llvm::Triple& Triple)
+ : UnknownHostInfo(D, Triple) {}
+
+} // end anon namespace
+
const HostInfo *
clang::driver::createAuroraUXHostInfo(const Driver &D,
const llvm::Triple& Triple){
@@ -642,6 +647,18 @@ clang::driver::createTCEHostInfo(const Driver &D,
}
const HostInfo *
+clang::driver::createWindowsHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new WindowsHostInfo(D, Triple);
+}
+
+const HostInfo *
+clang::driver::createMinGWHostInfo(const Driver &D,
+ const llvm::Triple& Triple) {
+ return new MinGWHostInfo(D, Triple);
+}
+
+const HostInfo *
clang::driver::createUnknownHostInfo(const Driver &D,
const llvm::Triple& Triple) {
return new UnknownHostInfo(D, Triple);
diff --git a/lib/Driver/InputInfo.h b/lib/Driver/InputInfo.h
index c657bef95af0..2a2f4b995d2a 100644
--- a/lib/Driver/InputInfo.h
+++ b/lib/Driver/InputInfo.h
@@ -17,7 +17,6 @@
namespace clang {
namespace driver {
- class PipedJob;
/// InputInfo - Wrapper for information about an input source.
class InputInfo {
@@ -37,7 +36,6 @@ class InputInfo {
union {
const char *Filename;
const Arg *InputArg;
- PipedJob *Pipe;
} Data;
Class Kind;
types::ID Type;
@@ -56,15 +54,10 @@ public:
: Kind(InputArg), Type(_Type), BaseInput(_BaseInput) {
Data.InputArg = _InputArg;
}
- InputInfo(PipedJob *_Pipe, types::ID _Type, const char *_BaseInput)
- : Kind(Pipe), Type(_Type), BaseInput(_BaseInput) {
- Data.Pipe = _Pipe;
- }
bool isNothing() const { return Kind == Nothing; }
bool isFilename() const { return Kind == Filename; }
bool isInputArg() const { return Kind == InputArg; }
- bool isPipe() const { return Kind == Pipe; }
types::ID getType() const { return Type; }
const char *getBaseInput() const { return BaseInput; }
@@ -76,17 +69,11 @@ public:
assert(isInputArg() && "Invalid accessor.");
return *Data.InputArg;
}
- PipedJob &getPipe() const {
- assert(isPipe() && "Invalid accessor.");
- return *Data.Pipe;
- }
/// getAsString - Return a string name for this input, for
/// debugging.
std::string getAsString() const {
- if (isPipe())
- return "(pipe)";
- else if (isFilename())
+ if (isFilename())
return std::string("\"") + getFilename() + '"';
else if (isInputArg())
return "(input arg)";
diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp
index bfeb41a94299..fa7d0607728e 100644
--- a/lib/Driver/Job.cpp
+++ b/lib/Driver/Job.cpp
@@ -21,13 +21,6 @@ Command::Command(const Action &_Source, const Tool &_Creator,
{
}
-PipedJob::PipedJob() : Job(PipedJobClass) {}
-
-PipedJob::~PipedJob() {
- for (iterator it = begin(), ie = end(); it != ie; ++it)
- delete *it;
-}
-
JobList::JobList() : Job(JobListClass) {}
JobList::~JobList() {
@@ -36,9 +29,6 @@ JobList::~JobList() {
}
void Job::addCommand(Command *C) {
- if (PipedJob *PJ = dyn_cast<PipedJob>(this))
- PJ->addCommand(C);
- else
- cast<JobList>(this)->addJob(C);
+ cast<JobList>(this)->addJob(C);
}
diff --git a/lib/Driver/Makefile b/lib/Driver/Makefile
index 7bc340e109d3..454ab8626c2c 100644
--- a/lib/Driver/Makefile
+++ b/lib/Driver/Makefile
@@ -9,6 +9,5 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangDriver
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index 39530f211d80..3c363142d7fd 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -164,6 +164,8 @@ Option *OptTable::CreateOption(unsigned id) const {
Opt->setLinkerInput(true);
if (info.Flags & NoArgumentUnused)
Opt->setNoArgumentUnused(true);
+ if (info.Flags & NoForward)
+ Opt->setNoForward(true);
if (info.Flags & RenderAsInput)
Opt->setNoOptAsInput(true);
if (info.Flags & RenderJoined) {
diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
index dd48af8018ac..5396250dfae1 100644
--- a/lib/Driver/Option.cpp
+++ b/lib/Driver/Option.cpp
@@ -20,7 +20,7 @@ Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
const OptionGroup *_Group, const Option *_Alias)
: Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
Unsupported(false), LinkerInput(false), NoOptAsInput(false),
- DriverOption(false), NoArgumentUnused(false) {
+ DriverOption(false), NoArgumentUnused(false), NoForward(false) {
// Multi-level aliases are not supported, and alias options cannot
// have groups. This just simplifies option tracking, it is not an
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index 9fae67de32f4..94c1c6beb99f 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -10,8 +10,12 @@
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Action.h"
+#include "clang/Driver/Arg.h"
+#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/Options.h"
using namespace clang::driver;
@@ -34,3 +38,139 @@ std::string ToolChain::GetFilePath(const char *Name) const {
std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const {
return Host.getDriver().GetProgramPath(Name, *this, WantFile);
}
+
+types::ID ToolChain::LookupTypeForExtension(const char *Ext) const {
+ return types::lookupTypeForExtension(Ext);
+}
+
+/// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targetting.
+//
+// FIXME: tblgen this.
+static const char *getARMTargetCPU(const ArgList &Args,
+ const llvm::Triple &Triple) {
+ // FIXME: Warn on inconsistent use of -mcpu and -march.
+
+ // If we have -mcpu=, use that.
+ if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+ return A->getValue(Args);
+
+ llvm::StringRef MArch;
+ if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+ // Otherwise, if we have -march= choose the base CPU for that arch.
+ MArch = A->getValue(Args);
+ } else {
+ // Otherwise, use the Arch from the triple.
+ MArch = Triple.getArchName();
+ }
+
+ if (MArch == "armv2" || MArch == "armv2a")
+ return "arm2";
+ if (MArch == "armv3")
+ return "arm6";
+ if (MArch == "armv3m")
+ return "arm7m";
+ if (MArch == "armv4" || MArch == "armv4t")
+ return "arm7tdmi";
+ if (MArch == "armv5" || MArch == "armv5t")
+ return "arm10tdmi";
+ if (MArch == "armv5e" || MArch == "armv5te")
+ return "arm1026ejs";
+ if (MArch == "armv5tej")
+ return "arm926ej-s";
+ if (MArch == "armv6" || MArch == "armv6k")
+ return "arm1136jf-s";
+ if (MArch == "armv6j")
+ return "arm1136j-s";
+ if (MArch == "armv6z" || MArch == "armv6zk")
+ return "arm1176jzf-s";
+ if (MArch == "armv6t2")
+ return "arm1156t2-s";
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ return "cortex-a8";
+ if (MArch == "armv7r" || MArch == "armv7-r")
+ return "cortex-r4";
+ if (MArch == "armv7m" || MArch == "armv7-m")
+ return "cortex-m3";
+ if (MArch == "ep9312")
+ return "ep9312";
+ if (MArch == "iwmmxt")
+ return "iwmmxt";
+ if (MArch == "xscale")
+ return "xscale";
+
+ // If all else failed, return the most base CPU LLVM supports.
+ return "arm7tdmi";
+}
+
+/// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular
+/// CPU.
+//
+// FIXME: This is redundant with -mcpu, why does LLVM use this.
+// FIXME: tblgen this, or kill it!
+static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
+ if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" ||
+ CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" ||
+ CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" ||
+ CPU == "arm940t" || CPU == "ep9312")
+ return "v4t";
+
+ if (CPU == "arm10tdmi" || CPU == "arm1020t")
+ return "v5";
+
+ if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" ||
+ CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" ||
+ CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" ||
+ CPU == "iwmmxt")
+ return "v5e";
+
+ if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" ||
+ CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore")
+ return "v6";
+
+ if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s")
+ return "v6t2";
+
+ if (CPU == "cortex-a8" || CPU == "cortex-a9")
+ return "v7";
+
+ return "";
+}
+
+std::string ToolChain::ComputeLLVMTriple(const ArgList &Args) const {
+ switch (getTriple().getArch()) {
+ default:
+ return getTripleString();
+
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ // FIXME: Factor into subclasses.
+ llvm::Triple Triple = getTriple();
+
+ // Thumb2 is the default for V7 on Darwin.
+ //
+ // FIXME: Thumb should just be another -target-feaure, not in the triple.
+ llvm::StringRef Suffix =
+ getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
+ bool ThumbDefault =
+ (Suffix == "v7" && getTriple().getOS() == llvm::Triple::Darwin);
+ std::string ArchName = "arm";
+ if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
+ ArchName = "thumb";
+ Triple.setArchName(ArchName + Suffix.str());
+
+ return Triple.getTriple();
+ }
+ }
+}
+
+std::string ToolChain::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
+ // non-Darwin.
+ if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
+ options::OPT_miphoneos_version_min_EQ))
+ getDriver().Diag(clang::diag::err_drv_clang_unsupported)
+ << A->getAsString(Args);
+
+ return ComputeLLVMTriple(Args);
+}
+
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index a78d1536fa1e..471c47dd2b50 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -18,7 +18,9 @@
#include "clang/Driver/OptTable.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -31,13 +33,30 @@ using namespace clang::driver::toolchains;
/// Darwin - Darwin tool chain for i386 and x86_64.
-Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&_DarwinVersion)[3])
+Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
: ToolChain(Host, Triple), TargetInitialized(false)
{
+ // Compute the initial Darwin version based on the host.
+ bool HadExtra;
+ std::string OSName = Triple.getOSName();
+ if (!Driver::GetReleaseVersion(&OSName[6],
+ DarwinVersion[0], DarwinVersion[1],
+ DarwinVersion[2], HadExtra))
+ getDriver().Diag(clang::diag::err_drv_invalid_darwin_version) << OSName;
+
llvm::raw_string_ostream(MacosxVersionMin)
- << "10." << std::max(0, (int)_DarwinVersion[0] - 4) << '.'
- << _DarwinVersion[1];
+ << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.'
+ << DarwinVersion[1];
+}
+
+types::ID Darwin::LookupTypeForExtension(const char *Ext) const {
+ types::ID Ty = types::lookupTypeForExtension(Ext);
+
+ // Darwin always preprocesses assembly files (unless -x is used explicitly).
+ if (Ty == types::TY_PP_Asm)
+ return types::TY_Asm;
+
+ return Ty;
}
// FIXME: Can we tablegen this?
@@ -103,14 +122,13 @@ llvm::StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
}
}
-DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3],
- const unsigned (&_GCCVersion)[3])
- : Darwin(Host, Triple, DarwinVersion)
+DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple)
+ : Darwin(Host, Triple)
{
- GCCVersion[0] = _GCCVersion[0];
- GCCVersion[1] = _GCCVersion[1];
- GCCVersion[2] = _GCCVersion[2];
+ // We can only work with 4.2.1 currently.
+ GCCVersion[0] = 4;
+ GCCVersion[1] = 2;
+ GCCVersion[2] = 1;
// Set up the tool chain paths to match gcc.
ToolChainDir = "i686-apple-darwin";
@@ -174,7 +192,9 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
Path += ToolChainDir;
getProgramPaths().push_back(Path);
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
}
Darwin::~Darwin() {
@@ -184,6 +204,38 @@ Darwin::~Darwin() {
delete it->second;
}
+std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ llvm::Triple Triple(ComputeLLVMTriple(Args));
+
+ // If the target isn't initialized (e.g., an unknown Darwin platform, return
+ // the default triple).
+ if (!isTargetInitialized())
+ return Triple.getTriple();
+
+ unsigned Version[3];
+ getTargetVersion(Version);
+
+ // Mangle the target version into the OS triple component. For historical
+ // reasons that make little sense, the version passed here is the "darwin"
+ // version, which drops the 10 and offsets by 4. See inverse code when
+ // setting the OS version preprocessor define.
+ if (!isTargetIPhoneOS()) {
+ Version[0] = Version[1] + 4;
+ Version[1] = Version[2];
+ Version[2] = 0;
+ } else {
+ // Use the environment to communicate that we are targetting iPhoneOS.
+ Triple.setEnvironmentName("iphoneos");
+ }
+
+ llvm::SmallString<16> Str;
+ llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
+ << "." << Version[1] << "." << Version[2];
+ Triple.setOSName(Str.str());
+
+ return Triple.getTriple();
+}
+
Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA) const {
Action::ActionClass Key;
if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
@@ -245,7 +297,7 @@ void DarwinGCC::AddLinkSearchPathArgs(const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc/" + ToolChainDir +
"/x86_64"));
}
-
+
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/" + ToolChainDir));
Tmp = getDriver().Dir + "/../lib/gcc/" + ToolChainDir;
@@ -314,12 +366,13 @@ void DarwinGCC::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
-DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3])
- : Darwin(Host, Triple, DarwinVersion)
+DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple)
+ : Darwin(Host, Triple)
{
// We expect 'as', 'ld', etc. to be adjacent to our install dir.
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir)
+ getProgramPaths().push_back(getDriver().Dir);
}
void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
@@ -350,6 +403,39 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
break;
}
P.appendComponent("4.2.1");
+
+ // Determine the arch specific GCC subdirectory.
+ const char *ArchSpecificDir = 0;
+ switch (getTriple().getArch()) {
+ default:
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb: {
+ std::string Triple = ComputeLLVMTriple(Args);
+ llvm::StringRef TripleStr = Triple;
+ if (TripleStr.startswith("armv5") || TripleStr.startswith("thumbv5"))
+ ArchSpecificDir = "v5";
+ else if (TripleStr.startswith("armv6") || TripleStr.startswith("thumbv6"))
+ ArchSpecificDir = "v6";
+ else if (TripleStr.startswith("armv7") || TripleStr.startswith("thumbv7"))
+ ArchSpecificDir = "v7";
+ break;
+ }
+ case llvm::Triple::ppc64:
+ ArchSpecificDir = "ppc64";
+ break;
+ case llvm::Triple::x86_64:
+ ArchSpecificDir = "x86_64";
+ break;
+ }
+
+ if (ArchSpecificDir) {
+ P.appendComponent(ArchSpecificDir);
+ if (P.exists())
+ CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
+ P.eraseComponent();
+ }
+
if (P.exists())
CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
}
@@ -415,18 +501,9 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
}
}
-DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
- const char *BoundArch) const {
- DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
const OptTable &Opts = getDriver().getOpts();
- // FIXME: We really want to get out of the tool chain level argument
- // translation business, as it makes the driver functionality much
- // more opaque. For now, we follow gcc closely solely for the
- // purpose of easily achieving feature parity & testability. Once we
- // have something that works, we should reevaluate each translation
- // and try to push it down into tool specific logic.
-
Arg *OSXVersion = Args.getLastArg(options::OPT_mmacosx_version_min_EQ);
Arg *iPhoneVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
if (OSXVersion && iPhoneVersion) {
@@ -462,17 +539,17 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
if (OSXTarget) {
const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = DAL->MakeJoinedArg(0, O, OSXTarget);
- DAL->append(OSXVersion);
+ OSXVersion = Args.MakeJoinedArg(0, O, OSXTarget);
+ Args.append(OSXVersion);
} else if (iPhoneOSTarget) {
const Option *O = Opts.getOption(options::OPT_miphoneos_version_min_EQ);
- iPhoneVersion = DAL->MakeJoinedArg(0, O, iPhoneOSTarget);
- DAL->append(iPhoneVersion);
+ iPhoneVersion = Args.MakeJoinedArg(0, O, iPhoneOSTarget);
+ Args.append(iPhoneVersion);
} else {
// Otherwise, assume we are targeting OS X.
const Option *O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
- OSXVersion = DAL->MakeJoinedArg(0, O, MacosxVersionMin);
- DAL->append(OSXVersion);
+ OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
+ Args.append(OSXVersion);
}
}
@@ -495,6 +572,19 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
<< iPhoneVersion->getAsString(Args);
}
setTarget(iPhoneVersion, Major, Minor, Micro);
+}
+
+DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
+ const char *BoundArch) const {
+ DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
+ const OptTable &Opts = getDriver().getOpts();
+
+ // FIXME: We really want to get out of the tool chain level argument
+ // translation business, as it makes the driver functionality much
+ // more opaque. For now, we follow gcc closely solely for the
+ // purpose of easily achieving feature parity & testability. Once we
+ // have something that works, we should reevaluate each translation
+ // and try to push it down into tool specific logic.
for (ArgList::const_iterator it = Args.begin(),
ie = Args.end(); it != ie; ++it) {
@@ -673,6 +763,11 @@ DerivedArgList *Darwin::TranslateArgs(const DerivedArgList &Args,
llvm_unreachable("invalid Darwin arch");
}
+ // Add an explicit version min argument for the deployment target. We do this
+ // after argument translation because -Xarch_ arguments may add a version min
+ // argument.
+ AddDeploymentTarget(*DAL);
+
return DAL;
}
@@ -709,13 +804,20 @@ bool Darwin::SupportsObjCGC() const {
return !isTargetIPhoneOS();
}
+std::string
+Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args) const {
+ return ComputeLLVMTriple(Args);
+}
+
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: ToolChain(Host, Triple) {
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
}
Generic_GCC::~Generic_GCC() {
@@ -864,8 +966,16 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const {
/// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly.
-FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32)
+FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
+
+ // Determine if we are compiling 32-bit code on an x86_64 platform.
+ bool Lib32 = false;
+ if (Triple.getArch() == llvm::Triple::x86 &&
+ llvm::Triple(getDriver().DefaultHostTriple).getArch() ==
+ llvm::Triple::x86_64)
+ Lib32 = true;
+
getProgramPaths().push_back(getDriver().Dir + "/../libexec");
getProgramPaths().push_back("/usr/libexec");
if (Lib32) {
@@ -936,7 +1046,9 @@ Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA) const {
AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
@@ -973,7 +1085,8 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA) const {
Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
- getFilePaths().push_back(getDriver().Dir + "/../lib/clang/1.0/");
+ getFilePaths().push_back(getDriver().Dir +
+ "/../lib/clang/" CLANG_VERSION_STRING "/");
getFilePaths().push_back("/lib/");
getFilePaths().push_back("/usr/lib/");
@@ -994,13 +1107,35 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple& Triple)
// list), but that's messy at best.
}
+Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::AssembleJobClass:
+ T = new tools::linuxtools::Assemble(*this); break;
+ default:
+ T = &Generic_GCC::SelectTool(C, JA);
+ }
+ }
+
+ return *T;
+}
+
/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.
DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {
// Path mangling to find libexec
- getProgramPaths().push_back(getDriver().Dir);
+ getProgramPaths().push_back(getDriver().getInstalledDir());
+ if (getDriver().getInstalledDir() != getDriver().Dir.c_str())
+ getProgramPaths().push_back(getDriver().Dir);
getFilePaths().push_back(getDriver().Dir + "/../lib");
getFilePaths().push_back("/usr/lib");
@@ -1028,3 +1163,57 @@ Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const {
return *T;
}
+
+Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple)
+ : ToolChain(Host, Triple) {
+}
+
+Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA) const {
+ Action::ActionClass Key;
+ if (getDriver().ShouldUseClangCompiler(C, JA, getTriple()))
+ Key = Action::AnalyzeJobClass;
+ else
+ Key = JA.getKind();
+
+ Tool *&T = Tools[Key];
+ if (!T) {
+ switch (Key) {
+ case Action::InputClass:
+ case Action::BindArchClass:
+ case Action::LipoJobClass:
+ case Action::DsymutilJobClass:
+ assert(0 && "Invalid tool kind.");
+ case Action::PreprocessJobClass:
+ case Action::PrecompileJobClass:
+ case Action::AnalyzeJobClass:
+ case Action::CompileJobClass:
+ T = new tools::Clang(*this); break;
+ case Action::AssembleJobClass:
+ T = new tools::ClangAs(*this); break;
+ case Action::LinkJobClass:
+ T = new tools::visualstudio::Link(*this); break;
+ }
+ }
+
+ return *T;
+}
+
+bool Windows::IsIntegratedAssemblerDefault() const {
+ return true;
+}
+
+bool Windows::IsUnwindTablesDefault() const {
+ // FIXME: Gross; we should probably have some separate target
+ // definition, possibly even reusing the one in clang.
+ return getArchName() == "x86_64";
+}
+
+const char *Windows::GetDefaultRelocationModel() const {
+ return "static";
+}
+
+const char *Windows::GetForcedPicModel() const {
+ if (getArchName() == "x86_64")
+ return "pic";
+ return 0;
+}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 4bdd00fc2583..d1f15565e6c6 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -42,6 +42,11 @@ public:
/// Darwin - The base Darwin tool chain.
class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
+public:
+ /// The host version.
+ unsigned DarwinVersion[3];
+
+private:
mutable llvm::DenseMap<unsigned, Tool*> Tools;
/// Whether the information on the target has been initialized.
@@ -61,11 +66,15 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
/// initialized.
std::string MacosxVersionMin;
+private:
+ void AddDeploymentTarget(DerivedArgList &Args) const;
+
public:
- Darwin(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3]);
+ Darwin(const HostInfo &Host, const llvm::Triple& Triple);
~Darwin();
+ std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
/// @name Darwin Specific Toolchain API
/// {
@@ -144,17 +153,17 @@ public:
/// @name ToolChain Implementation
/// {
+ virtual types::ID LookupTypeForExtension(const char *Ext) const;
+
virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
const char *BoundArch) const;
virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
virtual bool IsBlocksDefault() const {
- // Blocks default to on for OS X 10.6 and iPhoneOS 3.0 and beyond.
- if (isTargetIPhoneOS())
- return !isIPhoneOSVersionLT(3);
- else
- return !isMacosxVersionLT(10, 6);
+ // Always allow blocks on Darwin; users interested in versioning are
+ // expected to use /usr/include/Blocks.h.
+ return true;
}
virtual bool IsIntegratedAssemblerDefault() const {
#ifdef DISABLE_DEFAULT_INTEGRATED_ASSEMBLER
@@ -201,8 +210,7 @@ public:
/// DarwinClang - The Darwin toolchain used by Clang.
class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
public:
- DarwinClang(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3]);
+ DarwinClang(const HostInfo &Host, const llvm::Triple& Triple);
/// @name Darwin ToolChain Implementation
/// {
@@ -225,9 +233,7 @@ class LLVM_LIBRARY_VISIBILITY DarwinGCC : public Darwin {
std::string ToolChainDir;
public:
- DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,
- const unsigned (&DarwinVersion)[3],
- const unsigned (&GCCVersion)[3]);
+ DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple);
/// @name Darwin ToolChain Implementation
/// {
@@ -247,6 +253,8 @@ public:
Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple)
: Generic_GCC(Host, Triple) {}
+ std::string ComputeEffectiveClangTriple(const ArgList &Args) const;
+
virtual const char *GetDefaultRelocationModel() const { return "pic"; }
};
@@ -266,7 +274,7 @@ public:
class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_GCC {
public:
- FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32);
+ FreeBSD(const HostInfo &Host, const llvm::Triple& Triple);
virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
};
@@ -288,6 +296,8 @@ public:
class LLVM_LIBRARY_VISIBILITY Linux : public Generic_GCC {
public:
Linux(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
};
@@ -309,6 +319,20 @@ private:
};
+class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
+ mutable llvm::DenseMap<unsigned, Tool*> Tools;
+
+public:
+ Windows(const HostInfo &Host, const llvm::Triple& Triple);
+
+ virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const;
+
+ virtual bool IsIntegratedAssemblerDefault() const;
+ virtual bool IsUnwindTablesDefault() const;
+ virtual const char *GetDefaultRelocationModel() const;
+ virtual const char *GetForcedPicModel() const;
+};
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index f423d4e3b918..8436561e6ef9 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -105,10 +105,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,
// Determine the output location.
const char *DepFile;
if (Output.getType() == types::TY_Dependencies) {
- if (Output.isPipe())
- DepFile = "-";
- else
- DepFile = Output.getFilename();
+ DepFile = Output.getFilename();
} else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
DepFile = MF->getValue(Args);
} else if (A->getOption().matches(options::OPT_M) ||
@@ -182,10 +179,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
const Arg *A = it;
if (A->getOption().matches(options::OPT_include)) {
- // Use PCH if the user requested it, except for C++ (for now).
+ // Use PCH if the user requested it.
bool UsePCH = D.CCCUsePCH;
- if (types::isCXX(Inputs[0].getType()))
- UsePCH = false;
bool FoundPTH = false;
bool FoundPCH = false;
@@ -342,35 +337,6 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
return "";
}
-/// getLLVMTriple - Get the LLVM triple to use for a particular toolchain, which
-/// may depend on command line arguments.
-static std::string getLLVMTriple(const ToolChain &TC, const ArgList &Args) {
- switch (TC.getTriple().getArch()) {
- default:
- return TC.getTripleString();
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb: {
- // FIXME: Factor into subclasses.
- llvm::Triple Triple = TC.getTriple();
-
- // Thumb2 is the default for V7 on Darwin.
- //
- // FIXME: Thumb should just be another -target-feaure, not in the triple.
- llvm::StringRef Suffix =
- getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple));
- bool ThumbDefault =
- (Suffix == "v7" && TC.getTriple().getOS() == llvm::Triple::Darwin);
- std::string ArchName = "arm";
- if (Args.hasFlag(options::OPT_mthumb, options::OPT_mno_thumb, ThumbDefault))
- ArchName = "thumb";
- Triple.setArchName(ArchName + Suffix.str());
-
- return Triple.getTriple();
- }
- }
-}
-
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
@@ -633,6 +599,11 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
CPUName = "x86-64";
else if (getToolChain().getArchName() == "i386")
CPUName = "i586";
+ } else if (getToolChain().getOS().startswith("openbsd")) {
+ if (getToolChain().getArchName() == "x86_64")
+ CPUName = "x86-64";
+ else if (getToolChain().getArchName() == "i386")
+ CPUName = "i486";
} else {
if (getToolChain().getArchName() == "x86_64")
CPUName = "x86-64";
@@ -694,57 +665,7 @@ static bool needsExceptions(const ArgList &Args, types::ID InputType,
}
}
-/// getEffectiveClangTriple - Get the "effective" target triple, which is the
-/// triple for the target but with the OS version potentially modified for
-/// Darwin's -mmacosx-version-min.
-static std::string getEffectiveClangTriple(const Driver &D,
- const ToolChain &TC,
- const ArgList &Args) {
- llvm::Triple Triple(getLLVMTriple(TC, Args));
-
- // Handle -mmacosx-version-min and -miphoneos-version-min.
- if (Triple.getOS() != llvm::Triple::Darwin) {
- // Diagnose use of -mmacosx-version-min and -miphoneos-version-min on
- // non-Darwin.
- if (Arg *A = Args.getLastArg(options::OPT_mmacosx_version_min_EQ,
- options::OPT_miphoneos_version_min_EQ))
- D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
- } else {
- const toolchains::Darwin &DarwinTC(
- reinterpret_cast<const toolchains::Darwin&>(TC));
-
- // If the target isn't initialized (e.g., an unknown Darwin platform, return
- // the default triple).
- if (!DarwinTC.isTargetInitialized())
- return Triple.getTriple();
-
- unsigned Version[3];
- DarwinTC.getTargetVersion(Version);
-
- // Mangle the target version into the OS triple component. For historical
- // reasons that make little sense, the version passed here is the "darwin"
- // version, which drops the 10 and offsets by 4. See inverse code when
- // setting the OS version preprocessor define.
- if (!DarwinTC.isTargetIPhoneOS()) {
- Version[0] = Version[1] + 4;
- Version[1] = Version[2];
- Version[2] = 0;
- } else {
- // Use the environment to communicate that we are targetting iPhoneOS.
- Triple.setEnvironmentName("iphoneos");
- }
-
- llvm::SmallString<16> Str;
- llvm::raw_svector_ostream(Str) << "darwin" << Version[0]
- << "." << Version[1] << "." << Version[2];
- Triple.setOSName(Str.str());
- }
-
- return Triple.getTriple();
-}
-
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
@@ -763,10 +684,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Select the appropriate action.
+ bool IsRewriter = false;
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
@@ -786,11 +708,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_mno_relax_all,
!IsOpt))
CmdArgs.push_back("-mrelax-all");
+
+ // When using an integrated assembler, we send -Wa, and -Xassembler options
+ // to -cc1.
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
} else if (isa<PrecompileJobAction>(JA)) {
- // Use PCH if the user requested it, except for C++ (for now).
+ // Use PCH if the user requested it.
bool UsePCH = D.CCCUsePCH;
- if (types::isCXX(Inputs[0].getType()))
- UsePCH = false;
if (UsePCH)
CmdArgs.push_back("-emit-pch");
@@ -813,6 +738,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-emit-pch");
} else if (JA.getType() == types::TY_RewrittenObjC) {
CmdArgs.push_back("-rewrite-objc");
+ IsRewriter = true;
} else {
assert(JA.getType() == types::TY_PP_Asm &&
"Unexpected output type!");
@@ -856,6 +782,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Do not enable the missing -dealloc check.
// '-analyzer-check-objc-missing-dealloc',
CmdArgs.push_back("-analyzer-check-objc-unused-ivars");
+ CmdArgs.push_back("-analyzer-check-idempotent-operations");
}
// Set the output format. The default is plist, for (lame) historical
@@ -999,6 +926,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
+ // Pass the linker version in use.
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+ CmdArgs.push_back("-target-linker-version");
+ CmdArgs.push_back(A->getValue(Args));
+ }
+
// -mno-omit-leaf-frame-pointer is default.
if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
options::OPT_mno_omit_leaf_frame_pointer, false))
@@ -1029,6 +962,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
Args.AddAllArgs(CmdArgs, options::OPT_v);
+ Args.AddLastArg(CmdArgs, options::OPT_H);
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
@@ -1201,10 +1135,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fno_show_column);
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
+ Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
Args.AddLastArg(CmdArgs, options::OPT_fwrapv);
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
+ Args.AddLastArg(CmdArgs, options::OPT_funroll_loops);
Args.AddLastArg(CmdArgs, options::OPT_pthread);
@@ -1279,15 +1215,23 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
getToolChain().getTriple().getOS() == llvm::Triple::Win32))
CmdArgs.push_back("-fms-extensions");
+ // -fborland-extensions=0 is default.
+ if (Args.hasFlag(options::OPT_fborland_extensions,
+ options::OPT_fno_borland_extensions, false))
+ CmdArgs.push_back("-fborland-extensions");
+
// -fgnu-keywords default varies depending on language; only pass if
// specified.
if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
options::OPT_fno_gnu_keywords))
A->render(Args, CmdArgs);
- // -fnext-runtime is default.
+ // -fnext-runtime defaults to on Darwin and when rewriting Objective-C, and is
+ // -the -cc1 default.
+ bool NeXTRuntimeIsDefault =
+ IsRewriter || getToolChain().getTriple().getOS() == llvm::Triple::Darwin;
if (!Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
- getToolChain().getTriple().getOS() == llvm::Triple::Darwin))
+ NeXTRuntimeIsDefault))
CmdArgs.push_back("-fgnu-runtime");
// -fobjc-nonfragile-abi=0 is default.
@@ -1389,7 +1333,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fdiagnostics-show-category");
CmdArgs.push_back(A->getValue(Args));
}
-
+
// Color diagnostics are the default, unless the terminal doesn't support
// them.
if (Args.hasFlag(options::OPT_fcolor_diagnostics,
@@ -1404,7 +1348,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_fspell_checking,
options::OPT_fno_spell_checking))
CmdArgs.push_back("-fno-spell-checking");
-
+
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
A->render(Args, CmdArgs);
@@ -1464,9 +1408,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Output.getType() == types::TY_Dependencies) {
// Handled with other dependency code.
- } else if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
} else if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
@@ -1479,9 +1420,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &II = *it;
CmdArgs.push_back("-x");
CmdArgs.push_back(types::getTypeName(II.getType()));
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -1489,7 +1428,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_undef);
- std::string Exec = getToolChain().getDriver().getClangProgramPath();
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
// Optionally embed the -cc1 level arguments into the debug info, for build
// analysis.
@@ -1498,7 +1437,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
for (ArgList::const_iterator it = Args.begin(),
ie = Args.end(); it != ie; ++it)
(*it)->render(Args, OriginalArgs);
-
+
llvm::SmallString<256> Flags;
Flags += Exec;
for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) {
@@ -1509,7 +1448,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Flags.str()));
}
- Dest.addCommand(new Command(JA, *this, Exec.c_str(), CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
// Explicitly warn that these options are unsupported, even though
// we are allowing compilation to continue.
@@ -1533,12 +1472,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
- const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
@@ -1551,7 +1488,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
- std::string TripleStr = getEffectiveClangTriple(D, getToolChain(), Args);
+ std::string TripleStr = getToolChain().ComputeEffectiveClangTriple(Args);
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Set the output mode, we currently only expect to be used as a real
@@ -1581,19 +1518,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (Input.isPipe()) {
- CmdArgs.push_back("-");
- } else {
- assert(Input.isFilename() && "Invalid input.");
- CmdArgs.push_back(Input.getFilename());
- }
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
- std::string Exec = getToolChain().getDriver().getClangProgramPath();
- Dest.addCommand(new Command(JA, *this, Exec.c_str(), CmdArgs));
+ const char *Exec = getToolChain().getDriver().getClangProgramPath();
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
@@ -1605,6 +1537,11 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
it = Args.begin(), ie = Args.end(); it != ie; ++it) {
Arg *A = *it;
if (A->getOption().hasForwardToGCC()) {
+ // Don't forward any -g arguments to assembly steps.
+ if (isa<AssembleJobAction>(JA) &&
+ A->getOption().matches(options::OPT_g_Group))
+ continue;
+
// It is unfortunate that we have to claim here, as this means
// we will basically never report anything interesting for
// platforms using a generic gcc, even if we are just using gcc
@@ -1640,10 +1577,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
else if (Arch == "x86_64" || Arch == "powerpc64")
CmdArgs.push_back("-m64");
- if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
- } else if (Output.isFilename()) {
+ if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
@@ -1678,9 +1612,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(types::getTypeName(II.getType()));
}
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
// Don't render as input, we need gcc to do the translations.
@@ -1690,7 +1622,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
const char *GCCName = getToolChain().getDriver().CCCGenericGCCName.c_str();
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath(GCCName));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void gcc::Preprocess::RenderExtraToolArgs(const JobAction &JA,
@@ -2022,10 +1954,7 @@ void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args,
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
@@ -2063,7 +1992,7 @@ void darwin::CC1::AddCPPArgs(const ArgList &Args,
}
void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2078,12 +2007,9 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-traditional-cpp");
ArgStringList OutputArgs;
- if (Output.isFilename()) {
- OutputArgs.push_back("-o");
- OutputArgs.push_back(Output.getFilename());
- } else {
- assert(Output.isPipe() && "Unexpected CC1 output.");
- }
+ assert(Output.isFilename() && "Unexpected CC1 output.");
+ OutputArgs.push_back("-o");
+ OutputArgs.push_back(Output.getFilename());
if (Args.hasArg(options::OPT_E)) {
AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs);
@@ -2097,11 +2023,11 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA,
const char *CC1Name = getCC1Name(Inputs[0].getType());
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath(CC1Name));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2133,9 +2059,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
ArgStringList OutputArgs;
if (Output.getType() != types::TY_PCH) {
OutputArgs.push_back("-o");
- if (Output.isPipe())
- OutputArgs.push_back("-");
- else if (Output.isNothing())
+ if (Output.isNothing())
OutputArgs.push_back("/dev/null");
else
OutputArgs.push_back(Output.getFilename());
@@ -2168,10 +2092,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
return;
}
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
if (OutputArgsEarly) {
@@ -2197,11 +2118,11 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA,
const char *CC1Name = getCC1Name(Inputs[0].getType());
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath(CC1Name));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2224,7 +2145,9 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
// Derived from asm spec.
AddDarwinArch(Args, CmdArgs);
- if (!getDarwinToolChain().isTargetIPhoneOS() ||
+ // Use -force_cpusubtype_ALL on x86 by default.
+ if (getToolChain().getTriple().getArch() == llvm::Triple::x86 ||
+ getToolChain().getTriple().getArch() == llvm::Triple::x86_64 ||
Args.hasArg(options::OPT_force__cpusubtype__ALL))
CmdArgs.push_back("-force_cpusubtype_ALL");
@@ -2241,18 +2164,14 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
- if (Input.isPipe()) {
- CmdArgs.push_back("-");
- } else {
- assert(Input.isFilename() && "Invalid input.");
- CmdArgs.push_back(Input.getFilename());
- }
+ assert(Input.isFilename() && "Invalid input.");
+ CmdArgs.push_back(Input.getFilename());
// asm_final spec is empty.
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void darwin::DarwinTool::AddDarwinArch(const ArgList &Args,
@@ -2272,6 +2191,22 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
+ unsigned Version[3] = { 0, 0, 0 };
+ if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
+ bool HadExtra;
+ if (!Driver::GetReleaseVersion(A->getValue(Args), Version[0],
+ Version[1], Version[2], HadExtra) ||
+ HadExtra)
+ D.Diag(clang::diag::err_drv_invalid_version_number)
+ << A->getAsString(Args);
+ }
+
+ // Newer linkers support -demangle, pass it if supported and not disabled by
+ // the user.
+ if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) {
+ CmdArgs.push_back("-demangle");
+ }
+
// Derived from the "link" spec.
Args.AddAllArgs(CmdArgs, options::OPT_static);
if (!Args.hasArg(options::OPT_static))
@@ -2413,7 +2348,7 @@ void darwin::Link::AddLinkArgs(const ArgList &Args,
}
void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2571,11 +2506,11 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("ld"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2595,11 +2530,11 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA,
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("lipo"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2615,11 +2550,11 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("dsymutil"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2629,27 +2564,21 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
- if (Output.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(Output.getFilename());
+ CmdArgs.push_back(Output.getFilename());
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("gas"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2676,10 +2605,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
- } else if (Output.isFilename()) {
+ if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
@@ -2721,9 +2647,7 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -2751,11 +2675,11 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("ld"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2765,27 +2689,21 @@ void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
- if (Output.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(Output.getFilename());
+ CmdArgs.push_back(Output.getFilename());
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2811,10 +2729,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
}
}
- if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
- } else if (Output.isFilename()) {
+ if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
@@ -2838,7 +2753,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (Triple.substr(0, 6) == "x86_64")
Triple.replace(0, 6, "amd64");
CmdArgs.push_back(Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple +
- "/3.3.5"));
+ "/4.2.1"));
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
@@ -2854,9 +2769,7 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -2864,6 +2777,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
+ if (D.CCCIsCXX) {
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("-lm");
+ }
+
// FIXME: For some reason GCC passes -lgcc before adding
// the default system libraries. Just mimic this for now.
CmdArgs.push_back("-lgcc");
@@ -2887,11 +2805,11 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("ld"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2913,27 +2831,21 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
- if (Output.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(Output.getFilename());
+ CmdArgs.push_back(Output.getFilename());
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -2959,10 +2871,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("elf_i386_fbsd");
}
- if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
- } else if (Output.isFilename()) {
+ if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
@@ -2989,6 +2898,10 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
+ Args.AddAllArgs(CmdArgs, options::OPT_s);
+ Args.AddAllArgs(CmdArgs, options::OPT_t);
+ Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
+ Args.AddAllArgs(CmdArgs, options::OPT_r);
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
@@ -3000,9 +2913,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -3053,51 +2964,79 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("ld"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
+void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ ArgStringList CmdArgs;
+
+ // Add --32/--64 to make sure we get the format we want.
+ // This is incomplete
+ if (getToolChain().getArch() == llvm::Triple::x86) {
+ CmdArgs.push_back("--32");
+ } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
+ CmdArgs.push_back("--64");
+ } else if (getToolChain().getArch() == llvm::Triple::arm) {
+ llvm::StringRef MArch = getToolChain().getArchName();
+ if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a")
+ CmdArgs.push_back("-mfpu=neon");
+ }
+
+ Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
+ options::OPT_Xassembler);
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+ CmdArgs.push_back(II.getFilename());
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("as"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+
void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
ArgStringList CmdArgs;
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
- if (Output.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(Output.getFilename());
+ CmdArgs.push_back(Output.getFilename());
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("gas"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
- if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
- } else if (Output.isFilename()) {
+ if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
@@ -3123,9 +3062,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -3156,7 +3093,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("/usr/gnu/bin/gld"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
/// DragonFly Tools
@@ -3164,7 +3101,7 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA,
// For now, DragonFly Assemble does just about the same as for
// FreeBSD, but this may change soon.
void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
+ const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
@@ -3179,30 +3116,24 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_Xassembler);
CmdArgs.push_back("-o");
- if (Output.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(Output.getFilename());
+ CmdArgs.push_back(Output.getFilename());
for (InputInfoList::const_iterator
it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
const InputInfo &II = *it;
- if (II.isPipe())
- CmdArgs.push_back("-");
- else
- CmdArgs.push_back(II.getFilename());
+ CmdArgs.push_back(II.getFilename());
}
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("as"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest, const InputInfo &Output,
- const InputInfoList &Inputs,
- const ArgList &Args,
- const char *LinkingOutput) const {
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
const Driver &D = getToolChain().getDriver();
ArgStringList CmdArgs;
@@ -3224,10 +3155,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("elf_i386");
}
- if (Output.isPipe()) {
- CmdArgs.push_back("-o");
- CmdArgs.push_back("-");
- } else if (Output.isFilename()) {
+ if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
@@ -3265,9 +3193,7 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
D.Diag(clang::diag::err_drv_no_linker_llvm_support)
<< getToolChain().getTripleString();
- if (II.isPipe())
- CmdArgs.push_back("-");
- else if (II.isFilename())
+ if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
@@ -3293,6 +3219,11 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("/usr/lib");
}
+ if (D.CCCIsCXX) {
+ CmdArgs.push_back("-lstdc++");
+ CmdArgs.push_back("-lm");
+ }
+
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-lgcc_pic");
} else {
@@ -3328,5 +3259,46 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("ld"));
- Dest.addCommand(new Command(JA, *this, Exec, CmdArgs));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
+}
+
+void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput) const {
+ const Driver &D = getToolChain().getDriver();
+ ArgStringList CmdArgs;
+
+ if (Output.isFilename()) {
+ CmdArgs.push_back(Args.MakeArgString(std::string("-out:") + Output.getFilename()));
+ } else {
+ assert(Output.isNothing() && "Invalid output.");
+ }
+
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nostartfiles)) {
+ CmdArgs.push_back("-defaultlib:libcmt");
+ }
+
+ CmdArgs.push_back("-nologo");
+
+ for (InputInfoList::const_iterator
+ it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) {
+ const InputInfo &II = *it;
+
+ // Don't try to pass LLVM inputs to visual studio linker.
+ if (II.getType() == types::TY_LLVM_BC)
+ D.Diag(clang::diag::err_drv_no_linker_llvm_support)
+ << getToolChain().getTripleString();
+
+ if (II.isFilename())
+ CmdArgs.push_back(II.getFilename());
+ else
+ II.getInputArg().renderAsInput(Args, CmdArgs);
+ }
+
+ const char *Exec =
+ Args.MakeArgString(getToolChain().GetProgramPath("link.exe"));
+ C.addCommand(new Command(JA, *this, Exec, CmdArgs));
}
diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h
index 2a181038996b..b5defa4569cf 100644
--- a/lib/Driver/Tools.h
+++ b/lib/Driver/Tools.h
@@ -41,14 +41,11 @@ namespace tools {
public:
Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasGoodDiagnostics() const { return true; }
virtual bool hasIntegratedAssembler() const { return true; }
virtual bool hasIntegratedCPP() const { return true; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -61,14 +58,11 @@ namespace tools {
ClangAs(const ToolChain &TC) : Tool("clang::as",
"clang integrated assembler", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasGoodDiagnostics() const { return true; }
virtual bool hasIntegratedAssembler() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -83,7 +77,6 @@ namespace gcc {
const ToolChain &TC) : Tool(Name, ShortName, TC) {}
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -101,8 +94,6 @@ namespace gcc {
Preprocess(const ToolChain &TC) : Common("gcc::Preprocess",
"gcc preprocessor", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasGoodDiagnostics() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
@@ -115,8 +106,6 @@ namespace gcc {
Precompile(const ToolChain &TC) : Common("gcc::Precompile",
"gcc precompile", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasGoodDiagnostics() const { return true; }
virtual bool hasIntegratedCPP() const { return true; }
@@ -129,8 +118,6 @@ namespace gcc {
Compile(const ToolChain &TC) : Common("gcc::Compile",
"gcc frontend", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasGoodDiagnostics() const { return true; }
virtual bool hasIntegratedCPP() const { return true; }
@@ -143,8 +130,6 @@ namespace gcc {
Assemble(const ToolChain &TC) : Common("gcc::Assemble",
"assembler (via gcc)", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void RenderExtraToolArgs(const JobAction &JA,
@@ -156,8 +141,6 @@ namespace gcc {
Link(const ToolChain &TC) : Common("gcc::Link",
"linker (via gcc)", TC) {}
- virtual bool acceptsPipedInput() const { return false; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void RenderExtraToolArgs(const JobAction &JA,
@@ -207,8 +190,6 @@ namespace darwin {
CC1(const char *Name, const char *ShortName,
const ToolChain &TC) : DarwinTool(Name, ShortName, TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasGoodDiagnostics() const { return true; }
virtual bool hasIntegratedCPP() const { return true; }
};
@@ -219,7 +200,6 @@ namespace darwin {
"gcc preprocessor", TC) {}
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -231,7 +211,6 @@ namespace darwin {
Compile(const ToolChain &TC) : CC1("darwin::Compile", "gcc frontend", TC) {}
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -243,12 +222,9 @@ namespace darwin {
Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble",
"assembler", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -261,12 +237,9 @@ namespace darwin {
public:
Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", TC) {}
- virtual bool acceptsPipedInput() const { return false; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -277,12 +250,9 @@ namespace darwin {
public:
Lipo(const ToolChain &TC) : DarwinTool("darwin::Lipo", "lipo", TC) {}
- virtual bool acceptsPipedInput() const { return false; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -294,12 +264,9 @@ namespace darwin {
Dsymutil(const ToolChain &TC) : DarwinTool("darwin::Dsymutil",
"dsymutil", TC) {}
- virtual bool acceptsPipedInput() const { return false; }
- virtual bool canPipeOutput() const { return false; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -314,12 +281,9 @@ namespace openbsd {
Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", "assembler",
TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -329,12 +293,9 @@ namespace openbsd {
public:
Link(const ToolChain &TC) : Tool("openbsd::Link", "linker", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -349,12 +310,9 @@ namespace freebsd {
Assemble(const ToolChain &TC) : Tool("freebsd::Assemble", "assembler",
TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -364,12 +322,9 @@ namespace freebsd {
public:
Link(const ToolChain &TC) : Tool("freebsd::Link", "linker", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -377,6 +332,22 @@ namespace freebsd {
};
} // end namespace freebsd
+ /// linux -- Directly call GNU Binutils assembler and linker
+namespace linuxtools {
+ class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
+ public:
+ Assemble(const ToolChain &TC) : Tool("linux::Assemble", "assembler",
+ TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+}
/// minix -- Directly call GNU Binutils assembler and linker
namespace minix {
class LLVM_LIBRARY_VISIBILITY Assemble : public Tool {
@@ -384,12 +355,9 @@ namespace minix {
Assemble(const ToolChain &TC) : Tool("minix::Assemble", "assembler",
TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -399,12 +367,9 @@ namespace minix {
public:
Link(const ToolChain &TC) : Tool("minix::Link", "linker", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -419,12 +384,9 @@ namespace auroraux {
Assemble(const ToolChain &TC) : Tool("auroraux::Assemble", "assembler",
TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -434,12 +396,9 @@ namespace auroraux {
public:
Link(const ToolChain &TC) : Tool("auroraux::Link", "linker", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -454,12 +413,9 @@ namespace dragonfly {
Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler",
TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -469,12 +425,9 @@ namespace dragonfly {
public:
Link(const ToolChain &TC) : Tool("dragonfly::Link", "linker", TC) {}
- virtual bool acceptsPipedInput() const { return true; }
- virtual bool canPipeOutput() const { return true; }
virtual bool hasIntegratedCPP() const { return false; }
virtual void ConstructJob(Compilation &C, const JobAction &JA,
- Job &Dest,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &TCArgs,
@@ -482,6 +435,22 @@ namespace dragonfly {
};
} // end namespace dragonfly
+ /// Visual studio tools.
+namespace visualstudio {
+ class LLVM_LIBRARY_VISIBILITY Link : public Tool {
+ public:
+ Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {}
+
+ virtual bool hasIntegratedCPP() const { return false; }
+
+ virtual void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &TCArgs,
+ const char *LinkingOutput) const;
+ };
+} // end namespace visualstudio
+
} // end namespace toolchains
} // end namespace driver
} // end namespace clang
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 87b01d4a6a2a..eb7f270ae8fb 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -37,7 +37,7 @@ namespace {
public:
ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
- : Out(o? *o : llvm::errs()), Dump(Dump) { }
+ : Out(o? *o : llvm::outs()), Dump(Dump) { }
virtual void HandleTranslationUnit(ASTContext &Context) {
PrintingPolicy Policy = Context.PrintingPolicy;
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index e916e200659c..b46212fedaf4 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -40,10 +40,16 @@ void ASTMergeAction::ExecuteAction() {
&CI.getASTContext());
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
- ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], Diags, false);
+ ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, false);
if (!Unit)
continue;
+ // Reset the argument -> string function so that it has the AST
+ // context we want, since the Sema object created by
+ // LoadFromASTFile will override it.
+ CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
+ &CI.getASTContext());
+
ASTImporter Importer(CI.getDiagnostics(),
CI.getASTContext(),
CI.getFileManager(),
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index 88f00376b722..c76488b2c62c 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -12,10 +12,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/PCHReader.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TypeOrdering.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
@@ -25,30 +25,294 @@
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/ASTWriter.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/ADT/StringSet.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Timer.h"
+#include <cstdlib>
+#include <cstdio>
+#include <sys/stat.h>
using namespace clang;
+/// \brief After failing to build a precompiled preamble (due to
+/// errors in the source that occurs in the preamble), the number of
+/// reparses during which we'll skip even trying to precompile the
+/// preamble.
+const unsigned DefaultPreambleRebuildInterval = 5;
+
ASTUnit::ASTUnit(bool _MainFileIsAST)
- : MainFileIsAST(_MainFileIsAST), ConcurrencyCheckValue(CheckUnlocked) { }
+ : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
+ CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked),
+ PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
+ ShouldCacheCodeCompletionResults(false),
+ NumTopLevelDeclsAtLastCompletionCache(0),
+ CacheCodeCompletionCoolDown(0),
+ UnsafeToFree(false) {
+}
ASTUnit::~ASTUnit() {
ConcurrencyCheckValue = CheckLocked;
+ CleanTemporaryFiles();
+ if (!PreambleFile.empty())
+ llvm::sys::Path(PreambleFile).eraseFromDisk();
+
+ // Free the buffers associated with remapped files. We are required to
+ // perform this operation here because we explicitly request that the
+ // compiler instance *not* free these buffers for each invocation of the
+ // parser.
+ if (Invocation.get()) {
+ PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ FB = PPOpts.remapped_file_buffer_begin(),
+ FBEnd = PPOpts.remapped_file_buffer_end();
+ FB != FBEnd;
+ ++FB)
+ delete FB->second;
+ }
+
+ delete SavedMainFileBuffer;
+ delete PreambleBuffer;
+
+ ClearCachedCompletionResults();
+
+ for (unsigned I = 0, N = Timers.size(); I != N; ++I)
+ delete Timers[I];
+}
+
+void ASTUnit::CleanTemporaryFiles() {
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
TemporaryFiles[I].eraseFromDisk();
+ TemporaryFiles.clear();
+}
+
+/// \brief Determine the set of code-completion contexts in which this
+/// declaration should be shown.
+static unsigned getDeclShowContexts(NamedDecl *ND,
+ const LangOptions &LangOpts,
+ bool &IsNestedNameSpecifier) {
+ IsNestedNameSpecifier = false;
+
+ if (isa<UsingShadowDecl>(ND))
+ ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
+ if (!ND)
+ return 0;
+
+ unsigned Contexts = 0;
+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
+ isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
+ // Types can appear in these contexts.
+ if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
+ Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Type - 1));
+
+ // In C++, types can appear in expressions contexts (for functional casts).
+ if (LangOpts.CPlusPlus)
+ Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
+
+ // In Objective-C, message sends can send interfaces. In Objective-C++,
+ // all types are available due to functional casts.
+ if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
+ Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+
+ // Deal with tag names.
+ if (isa<EnumDecl>(ND)) {
+ Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
+
+ // Part of the nested-name-specifier in C++0x.
+ if (LangOpts.CPlusPlus0x)
+ IsNestedNameSpecifier = true;
+ } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
+ if (Record->isUnion())
+ Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
+ else
+ Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+
+ if (LangOpts.CPlusPlus)
+ IsNestedNameSpecifier = true;
+ } else if (isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND))
+ IsNestedNameSpecifier = true;
+ } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ // Values can appear in these contexts.
+ Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
+ } else if (isa<ObjCProtocolDecl>(ND)) {
+ Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+ } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
+ Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
+
+ // Part of the nested-name-specifier.
+ IsNestedNameSpecifier = true;
+ }
+
+ return Contexts;
+}
+
+void ASTUnit::CacheCodeCompletionResults() {
+ if (!TheSema)
+ return;
+
+ llvm::Timer *CachingTimer = 0;
+ if (TimerGroup.get()) {
+ CachingTimer = new llvm::Timer("Cache global code completions",
+ *TimerGroup);
+ CachingTimer->startTimer();
+ Timers.push_back(CachingTimer);
+ }
+
+ // Clear out the previous results.
+ ClearCachedCompletionResults();
+
+ // Gather the set of global code completions.
+ typedef CodeCompletionResult Result;
+ llvm::SmallVector<Result, 8> Results;
+ TheSema->GatherGlobalCodeCompletions(Results);
+
+ // Translate global code completions into cached completions.
+ llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
+
+ for (unsigned I = 0, N = Results.size(); I != N; ++I) {
+ switch (Results[I].Kind) {
+ case Result::RK_Declaration: {
+ bool IsNestedNameSpecifier = false;
+ CachedCodeCompletionResult CachedResult;
+ CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
+ CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
+ Ctx->getLangOptions(),
+ IsNestedNameSpecifier);
+ CachedResult.Priority = Results[I].Priority;
+ CachedResult.Kind = Results[I].CursorKind;
+ CachedResult.Availability = Results[I].Availability;
+
+ // Keep track of the type of this completion in an ASTContext-agnostic
+ // way.
+ QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
+ if (UsageType.isNull()) {
+ CachedResult.TypeClass = STC_Void;
+ CachedResult.Type = 0;
+ } else {
+ CanQualType CanUsageType
+ = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
+ CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
+
+ // Determine whether we have already seen this type. If so, we save
+ // ourselves the work of formatting the type string by using the
+ // temporary, CanQualType-based hash table to find the associated value.
+ unsigned &TypeValue = CompletionTypes[CanUsageType];
+ if (TypeValue == 0) {
+ TypeValue = CompletionTypes.size();
+ CachedCompletionTypes[QualType(CanUsageType).getAsString()]
+ = TypeValue;
+ }
+
+ CachedResult.Type = TypeValue;
+ }
+
+ CachedCompletionResults.push_back(CachedResult);
+
+ /// Handle nested-name-specifiers in C++.
+ if (TheSema->Context.getLangOptions().CPlusPlus &&
+ IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
+ // The contexts in which a nested-name-specifier can appear in C++.
+ unsigned NNSContexts
+ = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+ | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
+ | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
+ | (1 << (CodeCompletionContext::CCC_Type - 1))
+ | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1));
+
+ if (isa<NamespaceDecl>(Results[I].Declaration) ||
+ isa<NamespaceAliasDecl>(Results[I].Declaration))
+ NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
+
+ if (unsigned RemainingContexts
+ = NNSContexts & ~CachedResult.ShowInContexts) {
+ // If there any contexts where this completion can be a
+ // nested-name-specifier but isn't already an option, create a
+ // nested-name-specifier completion.
+ Results[I].StartsNestedNameSpecifier = true;
+ CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
+ CachedResult.ShowInContexts = RemainingContexts;
+ CachedResult.Priority = CCP_NestedNameSpecifier;
+ CachedResult.TypeClass = STC_Void;
+ CachedResult.Type = 0;
+ CachedCompletionResults.push_back(CachedResult);
+ }
+ }
+ break;
+ }
+
+ case Result::RK_Keyword:
+ case Result::RK_Pattern:
+ // Ignore keywords and patterns; we don't care, since they are so
+ // easily regenerated.
+ break;
+
+ case Result::RK_Macro: {
+ CachedCodeCompletionResult CachedResult;
+ CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
+ CachedResult.ShowInContexts
+ = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+ | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
+ | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1));
+
+ CachedResult.Priority = Results[I].Priority;
+ CachedResult.Kind = Results[I].CursorKind;
+ CachedResult.Availability = Results[I].Availability;
+ CachedResult.TypeClass = STC_Void;
+ CachedResult.Type = 0;
+ CachedCompletionResults.push_back(CachedResult);
+ break;
+ }
+ }
+ Results[I].Destroy();
+ }
+
+ if (CachingTimer)
+ CachingTimer->stopTimer();
+
+ // Make a note of the state when we performed this caching.
+ NumTopLevelDeclsAtLastCompletionCache = top_level_size();
+ CacheCodeCompletionCoolDown = 15;
+}
+
+void ASTUnit::ClearCachedCompletionResults() {
+ for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I)
+ delete CachedCompletionResults[I].Completion;
+ CachedCompletionResults.clear();
+ CachedCompletionTypes.clear();
}
namespace {
-/// \brief Gathers information from PCHReader that will be used to initialize
+/// \brief Gathers information from ASTReader that will be used to initialize
/// a Preprocessor.
-class PCHInfoCollector : public PCHReaderListener {
+class ASTInfoCollector : public ASTReaderListener {
LangOptions &LangOpt;
HeaderSearch &HSI;
std::string &TargetTriple;
@@ -58,7 +322,7 @@ class PCHInfoCollector : public PCHReaderListener {
unsigned NumHeaderInfos;
public:
- PCHInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
+ ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
std::string &TargetTriple, std::string &Predefines,
unsigned &Counter)
: LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
@@ -115,14 +379,19 @@ class CaptureDroppedDiagnostics {
public:
CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
- : Diags(Diags), Client(StoredDiags), PreviousClient(Diags.getClient())
+ : Diags(Diags), Client(StoredDiags), PreviousClient(0)
{
- if (RequestCapture || Diags.getClient() == 0)
+ if (RequestCapture || Diags.getClient() == 0) {
+ PreviousClient = Diags.takeClient();
Diags.setClient(&Client);
+ }
}
~CaptureDroppedDiagnostics() {
- Diags.setClient(PreviousClient);
+ if (Diags.getClient() == &Client) {
+ Diags.takeClient();
+ Diags.setClient(PreviousClient);
+ }
}
};
@@ -137,12 +406,12 @@ const std::string &ASTUnit::getOriginalSourceFileName() {
return OriginalSourceFile;
}
-const std::string &ASTUnit::getPCHFileName() {
- assert(isMainFileAST() && "Not an ASTUnit from a PCH file!");
- return static_cast<PCHReader *>(Ctx->getExternalSource())->getFileName();
+const std::string &ASTUnit::getASTFileName() {
+ assert(isMainFileAST() && "Not an ASTUnit from an AST file!");
+ return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName();
}
-ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
+ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
bool OnlyLocalDecls,
RemappedFile *RemappedFiles,
@@ -156,13 +425,14 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
DiagnosticOptions DiagOpts;
Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
}
-
+
+ AST->CaptureDiagnostics = CaptureDiagnostics;
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->Diagnostics = Diags;
AST->FileMgr.reset(new FileManager);
AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
-
+
// If requested, capture diagnostics in the ASTUnit.
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
AST->StoredDiagnostics);
@@ -194,34 +464,33 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
std::string Predefines;
unsigned Counter;
- llvm::OwningPtr<PCHReader> Reader;
- llvm::OwningPtr<ExternalASTSource> Source;
+ llvm::OwningPtr<ASTReader> Reader;
- Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(),
+ Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(),
AST->getDiagnostics()));
- Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,
+ Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple,
Predefines, Counter));
- switch (Reader->ReadPCH(Filename)) {
- case PCHReader::Success:
+ switch (Reader->ReadAST(Filename)) {
+ case ASTReader::Success:
break;
- case PCHReader::Failure:
- case PCHReader::IgnorePCH:
+ case ASTReader::Failure:
+ case ASTReader::IgnorePCH:
AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
return NULL;
}
AST->OriginalSourceFile = Reader->getOriginalSourceFile();
- // PCH loaded successfully. Now create the preprocessor.
+ // AST file loaded successfully. Now create the preprocessor.
// Get information about the target being compiled for.
//
- // FIXME: This is broken, we should store the TargetOptions in the PCH.
+ // FIXME: This is broken, we should store the TargetOptions in the AST file.
TargetOptions TargetOpts;
TargetOpts.ABI = "";
- TargetOpts.CXXABI = "itanium";
+ TargetOpts.CXXABI = "";
TargetOpts.CPU = "";
TargetOpts.Features.clear();
TargetOpts.Triple = TargetTriple;
@@ -244,18 +513,26 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,
PP.getIdentifierTable(),
PP.getSelectorTable(),
PP.getBuiltinInfo(),
- /* FreeMemory = */ false,
/* size_reserve = */0));
ASTContext &Context = *AST->Ctx.get();
Reader->InitializeContext(Context);
- // Attach the PCH reader to the AST context as an external AST
+ // Attach the AST reader to the AST context as an external AST
// source, so that declarations will be deserialized from the
- // PCH file as needed.
- Source.reset(Reader.take());
+ // AST file as needed.
+ ASTReader *ReaderPtr = Reader.get();
+ llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
Context.setExternalSource(Source);
+ // Create an AST consumer, even though it isn't used.
+ AST->Consumer.reset(new ASTConsumer);
+
+ // Create a semantic analysis object and tell the AST reader about it.
+ AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
+ AST->TheSema->Initialize();
+ ReaderPtr->InitializeSema(*AST->TheSema);
+
return AST.take();
}
@@ -276,9 +553,12 @@ public:
// fundamental problem in the parser right now.
if (isa<ObjCMethodDecl>(D))
continue;
- Unit.getTopLevelDecls().push_back(D);
+ Unit.addTopLevelDecl(D);
}
}
+
+ // We're not interested in "interesting" decls.
+ void HandleInterestingDecl(DeclGroupRef) {}
};
class TopLevelDeclTrackerAction : public ASTFrontendAction {
@@ -294,37 +574,108 @@ public:
TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
virtual bool hasCodeCompletionSupport() const { return false; }
+ virtual bool usesCompleteTranslationUnit() {
+ return Unit.isCompleteTranslationUnit();
+ }
};
-}
+class PrecompilePreambleConsumer : public PCHGenerator {
+ ASTUnit &Unit;
+ std::vector<Decl *> TopLevelDecls;
-ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
- bool OnlyLocalDecls,
- bool CaptureDiagnostics) {
- // Create the compiler instance to use for building the AST.
- CompilerInstance Clang;
- llvm::OwningPtr<ASTUnit> AST;
- llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
+public:
+ PrecompilePreambleConsumer(ASTUnit &Unit,
+ const Preprocessor &PP, bool Chaining,
+ const char *isysroot, llvm::raw_ostream *Out)
+ : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
- if (!Diags.getPtr()) {
- // No diagnostics engine was provided, so create our own diagnostics object
- // with the default options.
- DiagnosticOptions DiagOpts;
- Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
+ virtual void HandleTopLevelDecl(DeclGroupRef D) {
+ for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
+ Decl *D = *it;
+ // FIXME: Currently ObjC method declarations are incorrectly being
+ // reported as top-level declarations, even though their DeclContext
+ // is the containing ObjC @interface/@implementation. This is a
+ // fundamental problem in the parser right now.
+ if (isa<ObjCMethodDecl>(D))
+ continue;
+ TopLevelDecls.push_back(D);
+ }
}
-
- Clang.setInvocation(CI);
- Clang.setDiagnostics(Diags.getPtr());
- Clang.setDiagnosticClient(Diags->getClient());
+ virtual void HandleTranslationUnit(ASTContext &Ctx) {
+ PCHGenerator::HandleTranslationUnit(Ctx);
+ if (!Unit.getDiagnostics().hasErrorOccurred()) {
+ // Translate the top-level declarations we captured during
+ // parsing into declaration IDs in the precompiled
+ // preamble. This will allow us to deserialize those top-level
+ // declarations when requested.
+ for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
+ Unit.addTopLevelDeclFromPreamble(
+ getWriter().getDeclID(TopLevelDecls[I]));
+ }
+ }
+};
+
+class PrecompilePreambleAction : public ASTFrontendAction {
+ ASTUnit &Unit;
+
+public:
+ explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
+
+ virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+ llvm::StringRef InFile) {
+ std::string Sysroot;
+ llvm::raw_ostream *OS = 0;
+ bool Chaining;
+ if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
+ OS, Chaining))
+ return 0;
+
+ const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
+ Sysroot.c_str() : 0;
+ return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining,
+ isysroot, OS);
+ }
+
+ virtual bool hasCodeCompletionSupport() const { return false; }
+ virtual bool hasASTFileSupport() const { return false; }
+ virtual bool usesCompleteTranslationUnit() { return false; }
+};
+
+}
+/// Parse the source file into a translation unit using the given compiler
+/// invocation, replacing the current translation unit.
+///
+/// \returns True if a failure occurred that causes the ASTUnit not to
+/// contain any translation-unit information, false otherwise.
+bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
+ delete SavedMainFileBuffer;
+ SavedMainFileBuffer = 0;
+
+ if (!Invocation.get()) {
+ delete OverrideMainBuffer;
+ return true;
+ }
+
+ // Create the compiler instance to use for building the AST.
+ CompilerInstance Clang;
+ Clang.setInvocation(Invocation.take());
+ OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+ // Set up diagnostics, capturing any diagnostics that would
+ // otherwise be dropped.
+ Clang.setDiagnostics(&getDiagnostics());
+ CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
+ getDiagnostics(),
+ StoredDiagnostics);
+
// Create the target instance.
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
Clang.getTargetOpts()));
if (!Clang.hasTarget()) {
- Clang.takeDiagnosticClient();
- return 0;
+ delete OverrideMainBuffer;
+ return true;
}
// Inform the target of the language options.
@@ -332,7 +683,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
// FIXME: We shouldn't need to do this, the target should be immutable once
// created. This complexity should be lifted elsewhere.
Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
-
+
assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
"Invocation must have exactly one source file!");
assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
@@ -340,53 +691,649 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
"IR inputs not support here!");
- // Create the AST unit.
- AST.reset(new ASTUnit(false));
- AST->Diagnostics = Diags;
- AST->FileMgr.reset(new FileManager);
- AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
- AST->OnlyLocalDecls = OnlyLocalDecls;
- AST->OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
-
- // Capture any diagnostics that would otherwise be dropped.
- CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
- Clang.getDiagnostics(),
- AST->StoredDiagnostics);
+ // Configure the various subsystems.
+ // FIXME: Should we retain the previous file manager?
+ FileMgr.reset(new FileManager);
+ SourceMgr.reset(new SourceManager(getDiagnostics()));
+ TheSema.reset();
+ Ctx.reset();
+ PP.reset();
+
+ // Clear out old caches and data.
+ TopLevelDecls.clear();
+ CleanTemporaryFiles();
+ PreprocessedEntitiesByFile.clear();
+
+ if (!OverrideMainBuffer) {
+ StoredDiagnostics.clear();
+ TopLevelDeclsInPreamble.clear();
+ }
// Create a file manager object to provide access to and cache the filesystem.
- Clang.setFileManager(&AST->getFileManager());
-
+ Clang.setFileManager(&getFileManager());
+
// Create the source manager.
- Clang.setSourceManager(&AST->getSourceManager());
-
- Act.reset(new TopLevelDeclTrackerAction(*AST));
+ Clang.setSourceManager(&getSourceManager());
+
+ // If the main file has been overridden due to the use of a preamble,
+ // make that override happen and introduce the preamble.
+ PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
+ std::string PriorImplicitPCHInclude;
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
+ PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
+ PreprocessorOpts.PrecompiledPreambleBytes.second
+ = PreambleEndsAtStartOfLine;
+ PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
+ PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
+ PreprocessorOpts.DisablePCHValidation = true;
+
+ // Keep track of the override buffer;
+ SavedMainFileBuffer = OverrideMainBuffer;
+
+ // The stored diagnostic has the old source manager in it; update
+ // the locations to refer into the new source manager. Since we've
+ // been careful to make sure that the source manager's state
+ // before and after are identical, so that we can reuse the source
+ // location itself.
+ for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) {
+ FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
+ getSourceManager());
+ StoredDiagnostics[I].setLocation(Loc);
+ }
+ } else {
+ PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
+ PreprocessorOpts.PrecompiledPreambleBytes.second = false;
+ }
+
+ llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
+ Act.reset(new TopLevelDeclTrackerAction(*this));
if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Clang.getFrontendOpts().Inputs[0].first))
goto error;
-
+
Act->Execute();
-
+
// Steal the created target, context, and preprocessor, and take back the
// source and file managers.
- AST->Ctx.reset(Clang.takeASTContext());
- AST->PP.reset(Clang.takePreprocessor());
+ TheSema.reset(Clang.takeSema());
+ Consumer.reset(Clang.takeASTConsumer());
+ Ctx.reset(Clang.takeASTContext());
+ PP.reset(Clang.takePreprocessor());
Clang.takeSourceManager();
Clang.takeFileManager();
- AST->Target.reset(Clang.takeTarget());
-
+ Target.reset(Clang.takeTarget());
+
Act->EndSourceFile();
- Clang.takeDiagnosticClient();
- Clang.takeInvocation();
-
- AST->Invocation.reset(Clang.takeInvocation());
- return AST.take();
+ // Remove the overridden buffer we used for the preamble.
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
+ }
+ Invocation.reset(Clang.takeInvocation());
+
+ // If we were asked to cache code-completion results and don't have any
+ // results yet, do so now.
+ if (ShouldCacheCodeCompletionResults && CachedCompletionResults.empty())
+ CacheCodeCompletionResults();
+
+ return false;
+
error:
+ // Remove the overridden buffer we used for the preamble.
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ PreprocessorOpts.DisablePCHValidation = true;
+ PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
+ delete OverrideMainBuffer;
+ }
+
Clang.takeSourceManager();
Clang.takeFileManager();
- Clang.takeDiagnosticClient();
- return 0;
+ Invocation.reset(Clang.takeInvocation());
+ return true;
+}
+
+/// \brief Simple function to retrieve a path for a preamble precompiled header.
+static std::string GetPreamblePCHPath() {
+ // FIXME: This is lame; sys::Path should provide this function (in particular,
+ // it should know how to find the temporary files dir).
+ // FIXME: This is really lame. I copied this code from the Driver!
+ std::string Error;
+ const char *TmpDir = ::getenv("TMPDIR");
+ if (!TmpDir)
+ TmpDir = ::getenv("TEMP");
+ if (!TmpDir)
+ TmpDir = ::getenv("TMP");
+ if (!TmpDir)
+ TmpDir = "/tmp";
+ llvm::sys::Path P(TmpDir);
+ P.appendComponent("preamble");
+ P.appendSuffix("pch");
+ if (P.createTemporaryFileOnDisk())
+ return std::string();
+
+ return P.str();
+}
+
+/// \brief Compute the preamble for the main file, providing the source buffer
+/// that corresponds to the main file along with a pair (bytes, start-of-line)
+/// that describes the preamble.
+std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
+ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
+ unsigned MaxLines, bool &CreatedBuffer) {
+ FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
+ PreprocessorOptions &PreprocessorOpts
+ = Invocation.getPreprocessorOpts();
+ CreatedBuffer = false;
+
+ // Try to determine if the main file has been remapped, either from the
+ // command line (to another file) or directly through the compiler invocation
+ // (to a memory buffer).
+ llvm::MemoryBuffer *Buffer = 0;
+ llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
+ if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
+ // Check whether there is a file-file remapping of the main file
+ for (PreprocessorOptions::remapped_file_iterator
+ M = PreprocessorOpts.remapped_file_begin(),
+ E = PreprocessorOpts.remapped_file_end();
+ M != E;
+ ++M) {
+ llvm::sys::PathWithStatus MPath(M->first);
+ if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
+ if (MainFileStatus->uniqueID == MStatus->uniqueID) {
+ // We found a remapping. Try to load the resulting, remapped source.
+ if (CreatedBuffer) {
+ delete Buffer;
+ CreatedBuffer = false;
+ }
+
+ Buffer = llvm::MemoryBuffer::getFile(M->second);
+ if (!Buffer)
+ return std::make_pair((llvm::MemoryBuffer*)0,
+ std::make_pair(0, true));
+ CreatedBuffer = true;
+
+ // Remove this remapping. We've captured the buffer already.
+ M = PreprocessorOpts.eraseRemappedFile(M);
+ E = PreprocessorOpts.remapped_file_end();
+ if (M == E)
+ break;
+ }
+ }
+ }
+
+ // Check whether there is a file-buffer remapping. It supercedes the
+ // file-file remapping.
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ M = PreprocessorOpts.remapped_file_buffer_begin(),
+ E = PreprocessorOpts.remapped_file_buffer_end();
+ M != E;
+ ++M) {
+ llvm::sys::PathWithStatus MPath(M->first);
+ if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
+ if (MainFileStatus->uniqueID == MStatus->uniqueID) {
+ // We found a remapping.
+ if (CreatedBuffer) {
+ delete Buffer;
+ CreatedBuffer = false;
+ }
+
+ Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
+
+ // Remove this remapping. We've captured the buffer already.
+ M = PreprocessorOpts.eraseRemappedFile(M);
+ E = PreprocessorOpts.remapped_file_buffer_end();
+ if (M == E)
+ break;
+ }
+ }
+ }
+ }
+
+ // If the main source file was not remapped, load it now.
+ if (!Buffer) {
+ Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
+ if (!Buffer)
+ return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
+
+ CreatedBuffer = true;
+ }
+
+ return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines));
+}
+
+static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
+ bool DeleteOld,
+ unsigned NewSize,
+ llvm::StringRef NewName) {
+ llvm::MemoryBuffer *Result
+ = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
+ memcpy(const_cast<char*>(Result->getBufferStart()),
+ Old->getBufferStart(), Old->getBufferSize());
+ memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
+ ' ', NewSize - Old->getBufferSize() - 1);
+ const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
+
+ if (DeleteOld)
+ delete Old;
+
+ return Result;
+}
+
+/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
+/// the source file.
+///
+/// This routine will compute the preamble of the main source file. If a
+/// non-trivial preamble is found, it will precompile that preamble into a
+/// precompiled header so that the precompiled preamble can be used to reduce
+/// reparsing time. If a precompiled preamble has already been constructed,
+/// this routine will determine if it is still valid and, if so, avoid
+/// rebuilding the precompiled preamble.
+///
+/// \param AllowRebuild When true (the default), this routine is
+/// allowed to rebuild the precompiled preamble if it is found to be
+/// out-of-date.
+///
+/// \param MaxLines When non-zero, the maximum number of lines that
+/// can occur within the preamble.
+///
+/// \returns If the precompiled preamble can be used, returns a newly-allocated
+/// buffer that should be used in place of the main file when doing so.
+/// Otherwise, returns a NULL pointer.
+llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
+ CompilerInvocation PreambleInvocation,
+ bool AllowRebuild,
+ unsigned MaxLines) {
+ FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
+ PreprocessorOptions &PreprocessorOpts
+ = PreambleInvocation.getPreprocessorOpts();
+
+ bool CreatedPreambleBuffer = false;
+ std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
+ = ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer);
+
+ if (!NewPreamble.second.first) {
+ // We couldn't find a preamble in the main source. Clear out the current
+ // preamble, if we have one. It's obviously no good any more.
+ Preamble.clear();
+ if (!PreambleFile.empty()) {
+ llvm::sys::Path(PreambleFile).eraseFromDisk();
+ PreambleFile.clear();
+ }
+ if (CreatedPreambleBuffer)
+ delete NewPreamble.first;
+
+ // The next time we actually see a preamble, precompile it.
+ PreambleRebuildCounter = 1;
+ return 0;
+ }
+
+ if (!Preamble.empty()) {
+ // We've previously computed a preamble. Check whether we have the same
+ // preamble now that we did before, and that there's enough space in
+ // the main-file buffer within the precompiled preamble to fit the
+ // new main file.
+ if (Preamble.size() == NewPreamble.second.first &&
+ PreambleEndsAtStartOfLine == NewPreamble.second.second &&
+ NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
+ memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
+ NewPreamble.second.first) == 0) {
+ // The preamble has not changed. We may be able to re-use the precompiled
+ // preamble.
+
+ // Check that none of the files used by the preamble have changed.
+ bool AnyFileChanged = false;
+
+ // First, make a record of those files that have been overridden via
+ // remapping or unsaved_files.
+ llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
+ for (PreprocessorOptions::remapped_file_iterator
+ R = PreprocessorOpts.remapped_file_begin(),
+ REnd = PreprocessorOpts.remapped_file_end();
+ !AnyFileChanged && R != REnd;
+ ++R) {
+ struct stat StatBuf;
+ if (stat(R->second.c_str(), &StatBuf)) {
+ // If we can't stat the file we're remapping to, assume that something
+ // horrible happened.
+ AnyFileChanged = true;
+ break;
+ }
+
+ OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
+ StatBuf.st_mtime);
+ }
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ R = PreprocessorOpts.remapped_file_buffer_begin(),
+ REnd = PreprocessorOpts.remapped_file_buffer_end();
+ !AnyFileChanged && R != REnd;
+ ++R) {
+ // FIXME: Should we actually compare the contents of file->buffer
+ // remappings?
+ OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
+ 0);
+ }
+
+ // Check whether anything has changed.
+ for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
+ F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
+ !AnyFileChanged && F != FEnd;
+ ++F) {
+ llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
+ = OverriddenFiles.find(F->first());
+ if (Overridden != OverriddenFiles.end()) {
+ // This file was remapped; check whether the newly-mapped file
+ // matches up with the previous mapping.
+ if (Overridden->second != F->second)
+ AnyFileChanged = true;
+ continue;
+ }
+
+ // The file was not remapped; check whether it has changed on disk.
+ struct stat StatBuf;
+ if (stat(F->first(), &StatBuf)) {
+ // If we can't stat the file, assume that something horrible happened.
+ AnyFileChanged = true;
+ } else if (StatBuf.st_size != F->second.first ||
+ StatBuf.st_mtime != F->second.second)
+ AnyFileChanged = true;
+ }
+
+ if (!AnyFileChanged) {
+ // Okay! We can re-use the precompiled preamble.
+
+ // Set the state of the diagnostic object to mimic its state
+ // after parsing the preamble.
+ getDiagnostics().Reset();
+ getDiagnostics().setNumWarnings(NumWarningsInPreamble);
+ if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
+ StoredDiagnostics.erase(
+ StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
+ StoredDiagnostics.end());
+
+ // Create a version of the main file buffer that is padded to
+ // buffer size we reserved when creating the preamble.
+ return CreatePaddedMainFileBuffer(NewPreamble.first,
+ CreatedPreambleBuffer,
+ PreambleReservedSize,
+ FrontendOpts.Inputs[0].second);
+ }
+ }
+
+ // If we aren't allowed to rebuild the precompiled preamble, just
+ // return now.
+ if (!AllowRebuild)
+ return 0;
+
+ // We can't reuse the previously-computed preamble. Build a new one.
+ Preamble.clear();
+ llvm::sys::Path(PreambleFile).eraseFromDisk();
+ PreambleRebuildCounter = 1;
+ } else if (!AllowRebuild) {
+ // We aren't allowed to rebuild the precompiled preamble; just
+ // return now.
+ return 0;
+ }
+
+ // If the preamble rebuild counter > 1, it's because we previously
+ // failed to build a preamble and we're not yet ready to try
+ // again. Decrement the counter and return a failure.
+ if (PreambleRebuildCounter > 1) {
+ --PreambleRebuildCounter;
+ return 0;
+ }
+
+ // We did not previously compute a preamble, or it can't be reused anyway.
+ llvm::Timer *PreambleTimer = 0;
+ if (TimerGroup.get()) {
+ PreambleTimer = new llvm::Timer("Precompiling preamble", *TimerGroup);
+ PreambleTimer->startTimer();
+ Timers.push_back(PreambleTimer);
+ }
+
+ // Create a new buffer that stores the preamble. The buffer also contains
+ // extra space for the original contents of the file (which will be present
+ // when we actually parse the file) along with more room in case the file
+ // grows.
+ PreambleReservedSize = NewPreamble.first->getBufferSize();
+ if (PreambleReservedSize < 4096)
+ PreambleReservedSize = 8191;
+ else
+ PreambleReservedSize *= 2;
+
+ // Save the preamble text for later; we'll need to compare against it for
+ // subsequent reparses.
+ Preamble.assign(NewPreamble.first->getBufferStart(),
+ NewPreamble.first->getBufferStart()
+ + NewPreamble.second.first);
+ PreambleEndsAtStartOfLine = NewPreamble.second.second;
+
+ delete PreambleBuffer;
+ PreambleBuffer
+ = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
+ FrontendOpts.Inputs[0].second);
+ memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
+ NewPreamble.first->getBufferStart(), Preamble.size());
+ memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
+ ' ', PreambleReservedSize - Preamble.size() - 1);
+ const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
+
+ // Remap the main source file to the preamble buffer.
+ llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
+ PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
+
+ // Tell the compiler invocation to generate a temporary precompiled header.
+ FrontendOpts.ProgramAction = frontend::GeneratePCH;
+ // FIXME: Set ChainedPCH unconditionally, once it is ready.
+ if (::getenv("LIBCLANG_CHAINING"))
+ FrontendOpts.ChainedPCH = true;
+ // FIXME: Generate the precompiled header into memory?
+ FrontendOpts.OutputFile = GetPreamblePCHPath();
+
+ // Create the compiler instance to use for building the precompiled preamble.
+ CompilerInstance Clang;
+ Clang.setInvocation(&PreambleInvocation);
+ OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+ // Set up diagnostics, capturing all of the diagnostics produced.
+ Clang.setDiagnostics(&getDiagnostics());
+ CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
+ getDiagnostics(),
+ StoredDiagnostics);
+
+ // Create the target instance.
+ Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
+ Clang.getTargetOpts()));
+ if (!Clang.hasTarget()) {
+ llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
+ Preamble.clear();
+ if (CreatedPreambleBuffer)
+ delete NewPreamble.first;
+ if (PreambleTimer)
+ PreambleTimer->stopTimer();
+ PreambleRebuildCounter = DefaultPreambleRebuildInterval;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return 0;
+ }
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
+
+ assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
+ "Invocation must have exactly one source file!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
+ "FIXME: AST inputs not yet supported here!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+ "IR inputs not support here!");
+
+ // Clear out old caches and data.
+ StoredDiagnostics.clear();
+ TopLevelDecls.clear();
+ TopLevelDeclsInPreamble.clear();
+
+ // Create a file manager object to provide access to and cache the filesystem.
+ Clang.setFileManager(new FileManager);
+
+ // Create the source manager.
+ Clang.setSourceManager(new SourceManager(getDiagnostics()));
+
+ llvm::OwningPtr<PrecompilePreambleAction> Act;
+ Act.reset(new PrecompilePreambleAction(*this));
+ if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+ Clang.getFrontendOpts().Inputs[0].first)) {
+ Clang.takeInvocation();
+ llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
+ Preamble.clear();
+ if (CreatedPreambleBuffer)
+ delete NewPreamble.first;
+ if (PreambleTimer)
+ PreambleTimer->stopTimer();
+ PreambleRebuildCounter = DefaultPreambleRebuildInterval;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return 0;
+ }
+
+ Act->Execute();
+ Act->EndSourceFile();
+ Clang.takeInvocation();
+
+ if (Diagnostics->hasErrorOccurred()) {
+ // There were errors parsing the preamble, so no precompiled header was
+ // generated. Forget that we even tried.
+ // FIXME: Should we leave a note for ourselves to try again?
+ llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
+ Preamble.clear();
+ if (CreatedPreambleBuffer)
+ delete NewPreamble.first;
+ if (PreambleTimer)
+ PreambleTimer->stopTimer();
+ TopLevelDeclsInPreamble.clear();
+ PreambleRebuildCounter = DefaultPreambleRebuildInterval;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return 0;
+ }
+
+ // Keep track of the preamble we precompiled.
+ PreambleFile = FrontendOpts.OutputFile;
+ NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
+ NumWarningsInPreamble = getDiagnostics().getNumWarnings();
+
+ // Keep track of all of the files that the source manager knows about,
+ // so we can verify whether they have changed or not.
+ FilesInPreamble.clear();
+ SourceManager &SourceMgr = Clang.getSourceManager();
+ const llvm::MemoryBuffer *MainFileBuffer
+ = SourceMgr.getBuffer(SourceMgr.getMainFileID());
+ for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
+ FEnd = SourceMgr.fileinfo_end();
+ F != FEnd;
+ ++F) {
+ const FileEntry *File = F->second->Entry;
+ if (!File || F->second->getRawBuffer() == MainFileBuffer)
+ continue;
+
+ FilesInPreamble[File->getName()]
+ = std::make_pair(F->second->getSize(), File->getModificationTime());
+ }
+
+ if (PreambleTimer)
+ PreambleTimer->stopTimer();
+
+ PreambleRebuildCounter = 1;
+ PreprocessorOpts.eraseRemappedFile(
+ PreprocessorOpts.remapped_file_buffer_end() - 1);
+ return CreatePaddedMainFileBuffer(NewPreamble.first,
+ CreatedPreambleBuffer,
+ PreambleReservedSize,
+ FrontendOpts.Inputs[0].second);
+}
+
+void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
+ std::vector<Decl *> Resolved;
+ Resolved.reserve(TopLevelDeclsInPreamble.size());
+ ExternalASTSource &Source = *getASTContext().getExternalSource();
+ for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
+ // Resolve the declaration ID to an actual declaration, possibly
+ // deserializing the declaration in the process.
+ Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
+ if (D)
+ Resolved.push_back(D);
+ }
+ TopLevelDeclsInPreamble.clear();
+ TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
+}
+
+unsigned ASTUnit::getMaxPCHLevel() const {
+ if (!getOnlyLocalDecls())
+ return Decl::MaxPCHLevel;
+
+ unsigned Result = 0;
+ if (isMainFileAST() || SavedMainFileBuffer)
+ ++Result;
+ return Result;
+}
+
+ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ bool OnlyLocalDecls,
+ bool CaptureDiagnostics,
+ bool PrecompilePreamble,
+ bool CompleteTranslationUnit,
+ bool CacheCodeCompletionResults) {
+ if (!Diags.getPtr()) {
+ // No diagnostics engine was provided, so create our own diagnostics object
+ // with the default options.
+ DiagnosticOptions DiagOpts;
+ Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
+ }
+
+ // Create the AST unit.
+ llvm::OwningPtr<ASTUnit> AST;
+ AST.reset(new ASTUnit(false));
+ AST->Diagnostics = Diags;
+ AST->CaptureDiagnostics = CaptureDiagnostics;
+ AST->OnlyLocalDecls = OnlyLocalDecls;
+ AST->CompleteTranslationUnit = CompleteTranslationUnit;
+ AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
+ AST->Invocation.reset(CI);
+ CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
+
+ if (getenv("LIBCLANG_TIMING"))
+ AST->TimerGroup.reset(
+ new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
+
+
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
+ if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
+ AST->PreambleRebuildCounter = 1;
+ OverrideMainBuffer
+ = AST->getMainBufferWithPrecompiledPreamble(*AST->Invocation);
+ }
+
+ llvm::Timer *ParsingTimer = 0;
+ if (AST->TimerGroup.get()) {
+ ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
+ ParsingTimer->startTimer();
+ AST->Timers.push_back(ParsingTimer);
+ }
+
+ bool Failed = AST->Parse(OverrideMainBuffer);
+ if (ParsingTimer)
+ ParsingTimer->stopTimer();
+
+ return Failed? 0 : AST.take();
}
ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
@@ -396,12 +1343,18 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
bool OnlyLocalDecls,
RemappedFile *RemappedFiles,
unsigned NumRemappedFiles,
- bool CaptureDiagnostics) {
+ bool CaptureDiagnostics,
+ bool PrecompilePreamble,
+ bool CompleteTranslationUnit,
+ bool CacheCodeCompletionResults) {
+ bool CreatedDiagnosticsObject = false;
+
if (!Diags.getPtr()) {
// No diagnostics engine was provided, so create our own diagnostics object
// with the default options.
DiagnosticOptions DiagOpts;
Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
+ CreatedDiagnosticsObject = true;
}
llvm::SmallVector<const char *, 16> Args;
@@ -413,7 +1366,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
Args.push_back("-fsyntax-only");
// FIXME: We shouldn't have to pass in the path info.
- driver::Driver TheDriver("clang", "/", llvm::sys::getHostTriple(),
+ driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
"a.out", false, false, *Diags);
// Don't check that inputs exist, they have been remapped.
@@ -444,7 +1397,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
CompilerInvocation::CreateFromArgs(*CI,
const_cast<const char **>(CCArgs.data()),
const_cast<const char **>(CCArgs.data()) +
- CCArgs.size(),
+ CCArgs.size(),
*Diags);
// Override any files that need remapping
@@ -455,7 +1408,468 @@ ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
// Override the resources path.
CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
- CI->getFrontendOpts().DisableFree = true;
+ CI->getFrontendOpts().DisableFree = false;
return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
- CaptureDiagnostics);
+ CaptureDiagnostics, PrecompilePreamble,
+ CompleteTranslationUnit,
+ CacheCodeCompletionResults);
+}
+
+bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
+ if (!Invocation.get())
+ return true;
+
+ llvm::Timer *ReparsingTimer = 0;
+ if (TimerGroup.get()) {
+ ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup);
+ ReparsingTimer->startTimer();
+ Timers.push_back(ReparsingTimer);
+ }
+
+ // Remap files.
+ PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
+ for (PreprocessorOptions::remapped_file_buffer_iterator
+ R = PPOpts.remapped_file_buffer_begin(),
+ REnd = PPOpts.remapped_file_buffer_end();
+ R != REnd;
+ ++R) {
+ delete R->second;
+ }
+ Invocation->getPreprocessorOpts().clearRemappedFiles();
+ for (unsigned I = 0; I != NumRemappedFiles; ++I)
+ Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
+ RemappedFiles[I].second);
+
+ // If we have a preamble file lying around, or if we might try to
+ // build a precompiled preamble, do so now.
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
+ OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
+
+ // Clear out the diagnostics state.
+ if (!OverrideMainBuffer)
+ getDiagnostics().Reset();
+
+ // Parse the sources
+ bool Result = Parse(OverrideMainBuffer);
+ if (ReparsingTimer)
+ ReparsingTimer->stopTimer();
+
+ if (ShouldCacheCodeCompletionResults) {
+ if (CacheCodeCompletionCoolDown > 0)
+ --CacheCodeCompletionCoolDown;
+ else if (top_level_size() != NumTopLevelDeclsAtLastCompletionCache)
+ CacheCodeCompletionResults();
+ }
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------//
+// Code completion
+//----------------------------------------------------------------------------//
+
+namespace {
+ /// \brief Code completion consumer that combines the cached code-completion
+ /// results from an ASTUnit with the code-completion results provided to it,
+ /// then passes the result on to
+ class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
+ unsigned NormalContexts;
+ ASTUnit &AST;
+ CodeCompleteConsumer &Next;
+
+ public:
+ AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
+ bool IncludeMacros, bool IncludeCodePatterns,
+ bool IncludeGlobals)
+ : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
+ Next.isOutputBinary()), AST(AST), Next(Next)
+ {
+ // Compute the set of contexts in which we will look when we don't have
+ // any information about the specific context.
+ NormalContexts
+ = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
+ | (1 << (CodeCompletionContext::CCC_Statement - 1))
+ | (1 << (CodeCompletionContext::CCC_Expression - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
+ | (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
+ | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
+
+ if (AST.getASTContext().getLangOptions().CPlusPlus)
+ NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1))
+ | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
+ | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
+ }
+
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults);
+
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates) {
+ Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
+ }
+ };
+}
+
+/// \brief Helper function that computes which global names are hidden by the
+/// local code-completion results.
+void CalculateHiddenNames(const CodeCompletionContext &Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults,
+ ASTContext &Ctx,
+ llvm::StringSet<> &HiddenNames) {
+ bool OnlyTagNames = false;
+ switch (Context.getKind()) {
+ case CodeCompletionContext::CCC_Other:
+ case CodeCompletionContext::CCC_TopLevel:
+ case CodeCompletionContext::CCC_ObjCInterface:
+ case CodeCompletionContext::CCC_ObjCImplementation:
+ case CodeCompletionContext::CCC_ObjCIvarList:
+ case CodeCompletionContext::CCC_ClassStructUnion:
+ case CodeCompletionContext::CCC_Statement:
+ case CodeCompletionContext::CCC_Expression:
+ case CodeCompletionContext::CCC_ObjCMessageReceiver:
+ case CodeCompletionContext::CCC_MemberAccess:
+ case CodeCompletionContext::CCC_Namespace:
+ case CodeCompletionContext::CCC_Type:
+ case CodeCompletionContext::CCC_Name:
+ case CodeCompletionContext::CCC_PotentiallyQualifiedName:
+ break;
+
+ case CodeCompletionContext::CCC_EnumTag:
+ case CodeCompletionContext::CCC_UnionTag:
+ case CodeCompletionContext::CCC_ClassOrStructTag:
+ OnlyTagNames = true;
+ break;
+
+ case CodeCompletionContext::CCC_ObjCProtocolName:
+ case CodeCompletionContext::CCC_MacroName:
+ case CodeCompletionContext::CCC_MacroNameUse:
+ case CodeCompletionContext::CCC_PreprocessorExpression:
+ case CodeCompletionContext::CCC_PreprocessorDirective:
+ case CodeCompletionContext::CCC_NaturalLanguage:
+ case CodeCompletionContext::CCC_SelectorName:
+ case CodeCompletionContext::CCC_TypeQualifiers:
+ // We're looking for nothing, or we're looking for names that cannot
+ // be hidden.
+ return;
+ }
+
+ typedef CodeCompletionResult Result;
+ for (unsigned I = 0; I != NumResults; ++I) {
+ if (Results[I].Kind != Result::RK_Declaration)
+ continue;
+
+ unsigned IDNS
+ = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
+
+ bool Hiding = false;
+ if (OnlyTagNames)
+ Hiding = (IDNS & Decl::IDNS_Tag);
+ else {
+ unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
+ Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
+ Decl::IDNS_NonMemberOperator);
+ if (Ctx.getLangOptions().CPlusPlus)
+ HiddenIDNS |= Decl::IDNS_Tag;
+ Hiding = (IDNS & HiddenIDNS);
+ }
+
+ if (!Hiding)
+ continue;
+
+ DeclarationName Name = Results[I].Declaration->getDeclName();
+ if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
+ HiddenNames.insert(Identifier->getName());
+ else
+ HiddenNames.insert(Name.getAsString());
+ }
+}
+
+
+void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {
+ // Merge the results we were given with the results we cached.
+ bool AddedResult = false;
+ unsigned InContexts
+ = (Context.getKind() == CodeCompletionContext::CCC_Other? NormalContexts
+ : (1 << (Context.getKind() - 1)));
+
+ // Contains the set of names that are hidden by "local" completion results.
+ llvm::StringSet<> HiddenNames;
+ llvm::SmallVector<CodeCompletionString *, 4> StringsToDestroy;
+ typedef CodeCompletionResult Result;
+ llvm::SmallVector<Result, 8> AllResults;
+ for (ASTUnit::cached_completion_iterator
+ C = AST.cached_completion_begin(),
+ CEnd = AST.cached_completion_end();
+ C != CEnd; ++C) {
+ // If the context we are in matches any of the contexts we are
+ // interested in, we'll add this result.
+ if ((C->ShowInContexts & InContexts) == 0)
+ continue;
+
+ // If we haven't added any results previously, do so now.
+ if (!AddedResult) {
+ CalculateHiddenNames(Context, Results, NumResults, S.Context,
+ HiddenNames);
+ AllResults.insert(AllResults.end(), Results, Results + NumResults);
+ AddedResult = true;
+ }
+
+ // Determine whether this global completion result is hidden by a local
+ // completion result. If so, skip it.
+ if (C->Kind != CXCursor_MacroDefinition &&
+ HiddenNames.count(C->Completion->getTypedText()))
+ continue;
+
+ // Adjust priority based on similar type classes.
+ unsigned Priority = C->Priority;
+ CXCursorKind CursorKind = C->Kind;
+ CodeCompletionString *Completion = C->Completion;
+ if (!Context.getPreferredType().isNull()) {
+ if (C->Kind == CXCursor_MacroDefinition) {
+ Priority = getMacroUsagePriority(C->Completion->getTypedText(),
+ Context.getPreferredType()->isAnyPointerType());
+ } else if (C->Type) {
+ CanQualType Expected
+ = S.Context.getCanonicalType(
+ Context.getPreferredType().getUnqualifiedType());
+ SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
+ if (ExpectedSTC == C->TypeClass) {
+ // We know this type is similar; check for an exact match.
+ llvm::StringMap<unsigned> &CachedCompletionTypes
+ = AST.getCachedCompletionTypes();
+ llvm::StringMap<unsigned>::iterator Pos
+ = CachedCompletionTypes.find(QualType(Expected).getAsString());
+ if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
+ Priority /= CCF_ExactTypeMatch;
+ else
+ Priority /= CCF_SimilarTypeMatch;
+ }
+ }
+ }
+
+ // Adjust the completion string, if required.
+ if (C->Kind == CXCursor_MacroDefinition &&
+ Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
+ // Create a new code-completion string that just contains the
+ // macro name, without its arguments.
+ Completion = new CodeCompletionString;
+ Completion->AddTypedTextChunk(C->Completion->getTypedText());
+ StringsToDestroy.push_back(Completion);
+ CursorKind = CXCursor_NotImplemented;
+ Priority = CCP_CodePattern;
+ }
+
+ AllResults.push_back(Result(Completion, Priority, CursorKind,
+ C->Availability));
+ }
+
+ // If we did not add any cached completion results, just forward the
+ // results we were given to the next consumer.
+ if (!AddedResult) {
+ Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
+ return;
+ }
+
+ Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
+ AllResults.size());
+
+ for (unsigned I = 0, N = StringsToDestroy.size(); I != N; ++I)
+ delete StringsToDestroy[I];
+}
+
+
+
+void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
+ RemappedFile *RemappedFiles,
+ unsigned NumRemappedFiles,
+ bool IncludeMacros,
+ bool IncludeCodePatterns,
+ CodeCompleteConsumer &Consumer,
+ Diagnostic &Diag, LangOptions &LangOpts,
+ SourceManager &SourceMgr, FileManager &FileMgr,
+ llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
+ llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
+ if (!Invocation.get())
+ return;
+
+ llvm::Timer *CompletionTimer = 0;
+ if (TimerGroup.get()) {
+ llvm::SmallString<128> TimerName;
+ llvm::raw_svector_ostream TimerNameOut(TimerName);
+ TimerNameOut << "Code completion @ " << File << ":" << Line << ":"
+ << Column;
+ CompletionTimer = new llvm::Timer(TimerNameOut.str(), *TimerGroup);
+ CompletionTimer->startTimer();
+ Timers.push_back(CompletionTimer);
+ }
+
+ CompilerInvocation CCInvocation(*Invocation);
+ FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
+ PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
+
+ FrontendOpts.ShowMacrosInCodeCompletion
+ = IncludeMacros && CachedCompletionResults.empty();
+ FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
+ FrontendOpts.ShowGlobalSymbolsInCodeCompletion
+ = CachedCompletionResults.empty();
+ FrontendOpts.CodeCompletionAt.FileName = File;
+ FrontendOpts.CodeCompletionAt.Line = Line;
+ FrontendOpts.CodeCompletionAt.Column = Column;
+
+ // Turn on spell-checking when performing code completion. It leads
+ // to better results.
+ unsigned SpellChecking = CCInvocation.getLangOpts().SpellChecking;
+ CCInvocation.getLangOpts().SpellChecking = 1;
+
+ // Set the language options appropriately.
+ LangOpts = CCInvocation.getLangOpts();
+
+ CompilerInstance Clang;
+ Clang.setInvocation(&CCInvocation);
+ OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
+
+ // Set up diagnostics, capturing any diagnostics produced.
+ Clang.setDiagnostics(&Diag);
+ CaptureDroppedDiagnostics Capture(true,
+ Clang.getDiagnostics(),
+ StoredDiagnostics);
+
+ // Create the target instance.
+ Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
+ Clang.getTargetOpts()));
+ if (!Clang.hasTarget()) {
+ Clang.takeInvocation();
+ CCInvocation.getLangOpts().SpellChecking = SpellChecking;
+ return;
+ }
+
+ // Inform the target of the language options.
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
+
+ assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
+ "Invocation must have exactly one source file!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
+ "FIXME: AST inputs not yet supported here!");
+ assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+ "IR inputs not support here!");
+
+
+ // Use the source and file managers that we were given.
+ Clang.setFileManager(&FileMgr);
+ Clang.setSourceManager(&SourceMgr);
+
+ // Remap files.
+ PreprocessorOpts.clearRemappedFiles();
+ PreprocessorOpts.RetainRemappedFileBuffers = true;
+ for (unsigned I = 0; I != NumRemappedFiles; ++I) {
+ PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
+ RemappedFiles[I].second);
+ OwnedBuffers.push_back(RemappedFiles[I].second);
+ }
+
+ // Use the code completion consumer we were given, but adding any cached
+ // code-completion results.
+ AugmentedCodeCompleteConsumer
+ AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion,
+ FrontendOpts.ShowCodePatternsInCodeCompletion,
+ FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
+ Clang.setCodeCompletionConsumer(&AugmentedConsumer);
+
+ // If we have a precompiled preamble, try to use it. We only allow
+ // the use of the precompiled preamble if we're if the completion
+ // point is within the main file, after the end of the precompiled
+ // preamble.
+ llvm::MemoryBuffer *OverrideMainBuffer = 0;
+ if (!PreambleFile.empty()) {
+ using llvm::sys::FileStatus;
+ llvm::sys::PathWithStatus CompleteFilePath(File);
+ llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
+ if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
+ if (const FileStatus *MainStatus = MainPath.getFileStatus())
+ if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
+ OverrideMainBuffer
+ = getMainBufferWithPrecompiledPreamble(CCInvocation, false,
+ Line - 1);
+ }
+
+ // If the main file has been overridden due to the use of a preamble,
+ // make that override happen and introduce the preamble.
+ if (OverrideMainBuffer) {
+ PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
+ PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
+ PreprocessorOpts.PrecompiledPreambleBytes.second
+ = PreambleEndsAtStartOfLine;
+ PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
+ PreprocessorOpts.DisablePCHValidation = true;
+
+ // The stored diagnostics have the old source manager. Copy them
+ // to our output set of stored diagnostics, updating the source
+ // manager to the one we were given.
+ for (unsigned I = 0, N = this->StoredDiagnostics.size(); I != N; ++I) {
+ StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
+ FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
+ StoredDiagnostics[I].setLocation(Loc);
+ }
+
+ OwnedBuffers.push_back(OverrideMainBuffer);
+ } else {
+ PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
+ PreprocessorOpts.PrecompiledPreambleBytes.second = false;
+ }
+
+ llvm::OwningPtr<SyntaxOnlyAction> Act;
+ Act.reset(new SyntaxOnlyAction);
+ if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
+ Clang.getFrontendOpts().Inputs[0].first)) {
+ Act->Execute();
+ Act->EndSourceFile();
+ }
+
+ if (CompletionTimer)
+ CompletionTimer->stopTimer();
+
+ // Steal back our resources.
+ Clang.takeFileManager();
+ Clang.takeSourceManager();
+ Clang.takeInvocation();
+ Clang.takeCodeCompletionConsumer();
+ CCInvocation.getLangOpts().SpellChecking = SpellChecking;
+}
+
+bool ASTUnit::Save(llvm::StringRef File) {
+ if (getDiagnostics().hasErrorOccurred())
+ return true;
+
+ // FIXME: Can we somehow regenerate the stat cache here, or do we need to
+ // unconditionally create a stat cache when we parse the file?
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo,
+ llvm::raw_fd_ostream::F_Binary);
+ if (!ErrorInfo.empty() || Out.has_error())
+ return true;
+
+ std::vector<unsigned char> Buffer;
+ llvm::BitstreamWriter Stream(Buffer);
+ ASTWriter Writer(Stream);
+ Writer.WriteAST(getSema(), 0, 0);
+
+ // Write the generated bitstream to "Out".
+ if (!Buffer.empty())
+ Out.write((char *)&Buffer.front(), Buffer.size());
+ Out.close();
+ return Out.has_error();
}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 8757e2c9e37a..5a31495397ae 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -15,17 +15,9 @@ add_clang_library(clangFrontend
FrontendAction.cpp
FrontendActions.cpp
FrontendOptions.cpp
- GeneratePCH.cpp
InitHeaderSearch.cpp
InitPreprocessor.cpp
LangStandards.cpp
- PCHReader.cpp
- PCHReaderDecl.cpp
- PCHReaderStmt.cpp
- PCHWriter.cpp
- PCHWriterDecl.cpp
- PCHWriterStmt.cpp
- PrintParserCallbacks.cpp
PrintPreprocessedOutput.cpp
StmtXML.cpp
TextDiagnosticBuffer.cpp
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index a5fcebe99411..53f7362ac276 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -311,14 +311,19 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) {
// the next token.
assert(!ParsingPreprocessorDirective);
Offset HashOff = (Offset) Out.tell();
- EmitToken(Tok);
// Get the next token.
- L.LexFromRawLexer(Tok);
+ Token NextTok;
+ L.LexFromRawLexer(NextTok);
- // If we see the start of line, then we had a null directive "#".
- if (Tok.isAtStartOfLine())
+ // If we see the start of line, then we had a null directive "#". In
+ // this case, discard both tokens.
+ if (NextTok.isAtStartOfLine())
goto NextToken;
+
+ // The token is the start of a directive. Emit it.
+ EmitToken(Tok);
+ Tok = NextTok;
// Did we see 'include'/'import'/'include_next'?
if (Tok.isNot(tok::identifier)) {
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 5037c83556aa..ce0b07243b05 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Sema/Sema.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/Diagnostic.h"
@@ -20,11 +21,11 @@
#include "clang/Lex/PTHManager.h"
#include "clang/Frontend/ChainedDiagnosticClient.h"
#include "clang/Frontend/FrontendAction.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/Serialization/ASTReader.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/LLVMContext.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -37,7 +38,7 @@
using namespace clang;
CompilerInstance::CompilerInstance()
- : Invocation(new CompilerInvocation()), Reader(0) {
+ : Invocation(new CompilerInvocation()) {
}
CompilerInstance::~CompilerInstance() {
@@ -55,10 +56,6 @@ void CompilerInstance::setDiagnostics(Diagnostic *Value) {
Diagnostics = Value;
}
-void CompilerInstance::setDiagnosticClient(DiagnosticClient *Value) {
- DiagClient.reset(Value);
-}
-
void CompilerInstance::setTarget(TargetInfo *Value) {
Target.reset(Value);
}
@@ -79,6 +76,10 @@ void CompilerInstance::setASTContext(ASTContext *Value) {
Context.reset(Value);
}
+void CompilerInstance::setSema(Sema *S) {
+ TheSema.reset(S);
+}
+
void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
Consumer.reset(Value);
}
@@ -126,14 +127,11 @@ static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
// Chain in a diagnostic client which will log the diagnostics.
DiagnosticClient *Logger =
new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
- Diags.setClient(new ChainedDiagnosticClient(Diags.getClient(), Logger));
+ Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
}
void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv);
-
- if (Diagnostics)
- DiagClient.reset(Diagnostics->getClient());
}
llvm::IntrusiveRefCntPtr<Diagnostic>
@@ -150,22 +148,20 @@ CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
// bit of a problem. So, just create a text diagnostic printer
// to complain about this problem, and pretend that the user
// didn't try to use binary output.
- DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
- Diags->setClient(DiagClient.take());
+ Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
Diags->Report(diag::err_fe_stderr_binary);
return Diags;
} else {
- DiagClient.reset(new BinaryDiagnosticSerializer(llvm::errs()));
+ Diags->setClient(new BinaryDiagnosticSerializer(llvm::errs()));
}
} else {
- DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
+ Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
}
// Chain in -verify checker, if requested.
if (Opts.VerifyDiagnostics)
- DiagClient.reset(new VerifyDiagnosticsClient(*Diags, DiagClient.take()));
+ Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient()));
- Diags->setClient(DiagClient.take());
if (!Opts.DumpBuildInformation.empty())
SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
@@ -245,42 +241,48 @@ void CompilerInstance::createASTContext() {
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) {
+void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
+ bool DisablePCHValidation,
+ void *DeserializationListener){
llvm::OwningPtr<ExternalASTSource> Source;
Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
- getPreprocessor(), getASTContext()));
- // Remember the PCHReader, but in a non-owning way.
- Reader = static_cast<PCHReader*>(Source.get());
+ DisablePCHValidation,
+ getPreprocessor(), getASTContext(),
+ DeserializationListener));
getASTContext().setExternalSource(Source);
}
ExternalASTSource *
CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
const std::string &Sysroot,
+ bool DisablePCHValidation,
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:
+ ASTContext &Context,
+ void *DeserializationListener) {
+ llvm::OwningPtr<ASTReader> Reader;
+ Reader.reset(new ASTReader(PP, &Context,
+ Sysroot.empty() ? 0 : Sysroot.c_str(),
+ DisablePCHValidation));
+
+ Reader->setDeserializationListener(
+ static_cast<ASTDeserializationListener *>(DeserializationListener));
+ switch (Reader->ReadAST(Path)) {
+ case ASTReader::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:
+ case ASTReader::Failure:
// Unrecoverable failure: don't even try to process the input file.
break;
- case PCHReader::IgnorePCH:
+ case ASTReader::IgnorePCH:
// No suitable PCH file could be found. Return an error.
break;
}
@@ -290,17 +292,42 @@ CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
// Code Completion
+static bool EnableCodeCompletion(Preprocessor &PP,
+ const std::string &Filename,
+ unsigned Line,
+ unsigned Column) {
+ // 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 true;
+ }
+
+ // Truncate the named file at the given line/column.
+ PP.SetCodeCompletionPoint(Entry, Line, Column);
+ return false;
+}
+
void CompilerInstance::createCodeCompletionConsumer() {
const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
- CompletionConsumer.reset(
- createCodeCompletionConsumer(getPreprocessor(),
- Loc.FileName, Loc.Line, Loc.Column,
- getFrontendOpts().DebugCodeCompletionPrinter,
- getFrontendOpts().ShowMacrosInCodeCompletion,
+ if (!CompletionConsumer) {
+ CompletionConsumer.reset(
+ createCodeCompletionConsumer(getPreprocessor(),
+ Loc.FileName, Loc.Line, Loc.Column,
+ getFrontendOpts().DebugCodeCompletionPrinter,
+ getFrontendOpts().ShowMacrosInCodeCompletion,
getFrontendOpts().ShowCodePatternsInCodeCompletion,
- llvm::outs()));
- if (!CompletionConsumer)
+ getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
+ llvm::outs()));
+ if (!CompletionConsumer)
+ return;
+ } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
+ Loc.Line, Loc.Column)) {
+ CompletionConsumer.reset();
return;
+ }
if (CompletionConsumer->isOutputBinary() &&
llvm::sys::Program::ChangeStdoutToBinary()) {
@@ -321,24 +348,24 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
bool UseDebugPrinter,
bool ShowMacros,
bool ShowCodePatterns,
+ bool ShowGlobals,
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;
+ if (EnableCodeCompletion(PP, Filename, Line, Column))
return 0;
- }
-
- // Truncate the named file at the given line/column.
- PP.SetCodeCompletionPoint(Entry, Line, Column);
// Set up the creation routine for code-completion.
if (UseDebugPrinter)
- return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS);
+ return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
+ ShowGlobals, OS);
else
- return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS);
+ return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
+ ShowGlobals, OS);
+}
+
+void CompilerInstance::createSema(bool CompleteTranslationUnit,
+ CodeCompleteConsumer *CompletionConsumer) {
+ TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
+ CompleteTranslationUnit, CompletionConsumer));
}
// Output Files
@@ -437,7 +464,7 @@ bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
// Figure out where to get and map in the main file.
if (InputFile != "-") {
const FileEntry *File = FileMgr.getFile(InputFile);
- if (File) SourceMgr.createMainFileID(File, SourceLocation());
+ if (File) SourceMgr.createMainFileID(File);
if (SourceMgr.getMainFileID().isInvalid()) {
Diags.Report(diag::err_fe_error_reading) << InputFile;
return false;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 418d25b0d47d..8c644833b20e 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -18,11 +18,12 @@
#include "clang/Driver/Option.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/LangStandard.h"
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
@@ -112,8 +113,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
Res.push_back("-analyzer-experimental-checks");
if (Opts.EnableExperimentalInternalChecks)
Res.push_back("-analyzer-experimental-internal-checks");
- if (Opts.EnableIdempotentOperationChecker)
- Res.push_back("-analyzer-idempotent-operation");
+ if (Opts.IdempotentOps)
+ Res.push_back("-analyzer-check-idempotent-operations");
}
static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
@@ -148,9 +149,12 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
// SimplifyLibCalls is only derived.
// TimePasses is only derived.
// UnitAtATime is unused.
- // UnrollLoops is only derived.
// Inlining is only derived.
-
+
+ // UnrollLoops is derived, but also accepts an option, no
+ // harm in pushing it back here.
+ if (Opts.UnrollLoops)
+ Res.push_back("-funroll-loops");
if (Opts.DataSections)
Res.push_back("-fdata-sections");
if (Opts.FunctionSections)
@@ -241,6 +245,8 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
Res.push_back("-fno-diagnostics-fixit-info");
if (Opts.ShowSourceRanges)
Res.push_back("-fdiagnostics-print-source-range-info");
+ if (Opts.ShowParseableFixits)
+ Res.push_back("-fdiagnostics-parseable-fixits");
if (Opts.ShowColors)
Res.push_back("-fcolor-diagnostics");
if (Opts.VerifyDiagnostics)
@@ -316,6 +322,7 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::ASTPrintXML: return "-ast-print-xml";
case frontend::ASTView: return "-ast-view";
case frontend::BoostCon: return "-boostcon";
+ case frontend::CreateModule: return "-create-module";
case frontend::DumpRawTokens: return "-dump-raw-tokens";
case frontend::DumpTokens: return "-dump-tokens";
case frontend::EmitAssembly: return "-S";
@@ -329,10 +336,9 @@ static const char *getActionName(frontend::ActionKind Kind) {
case frontend::GeneratePCH: return "-emit-pch";
case frontend::GeneratePTH: return "-emit-pth";
case frontend::InitOnly: return "-init-only";
- 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::PrintPreamble: return "-print-preamble";
case frontend::PrintPreprocessedInput: return "-E";
case frontend::RewriteMacros: return "-rewrite-macros";
case frontend::RewriteObjC: return "-rewrite-objc";
@@ -361,12 +367,16 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,
Res.push_back("-code-completion-macros");
if (Opts.ShowCodePatternsInCodeCompletion)
Res.push_back("-code-completion-patterns");
+ if (!Opts.ShowGlobalSymbolsInCodeCompletion)
+ Res.push_back("-no-code-completion-globals");
if (Opts.ShowStats)
Res.push_back("-print-stats");
if (Opts.ShowTimers)
Res.push_back("-ftime-report");
if (Opts.ShowVersion)
Res.push_back("-version");
+ if (Opts.FixWhatYouCan)
+ Res.push_back("-fix-what-you-can");
bool NeedLang = false;
for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
@@ -416,6 +426,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,
Res.push_back("-ast-merge");
Res.push_back(Opts.ASTMergeFiles[i]);
}
+ for (unsigned i = 0, e = Opts.Modules.size(); i != e; ++i) {
+ Res.push_back("-import-module");
+ Res.push_back(Opts.Modules[i]);
+ }
for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i) {
Res.push_back("-mllvm");
Res.push_back(Opts.LLVMArgs[i]);
@@ -512,6 +526,8 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-fgnu-keywords");
if (Opts.Microsoft)
Res.push_back("-fms-extensions");
+ if (Opts.Borland)
+ Res.push_back("-fborland-extensions");
if (Opts.ObjCNonFragileABI)
Res.push_back("-fobjc-nonfragile-abi");
if (Opts.ObjCNonFragileABI2)
@@ -676,6 +692,8 @@ static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
else if (!Opts.ShowCPP && Opts.ShowMacros)
Res.push_back("-dM");
+ if (Opts.ShowHeaderIncludes)
+ Res.push_back("-H");
if (!Opts.ShowLineMarkers)
Res.push_back("-P");
if (Opts.ShowComments)
@@ -696,8 +714,14 @@ static void TargetOptsToArgs(const TargetOptions &Opts,
Res.push_back("-target-abi");
Res.push_back(Opts.ABI);
}
- Res.push_back("-cxx-abi");
- Res.push_back(Opts.CXXABI);
+ if (!Opts.LinkerVersion.empty()) {
+ Res.push_back("-target-linker-version");
+ Res.push_back(Opts.LinkerVersion);
+ }
+ if (!Opts.CXXABI.empty()) {
+ Res.push_back("-cxx-abi");
+ Res.push_back(Opts.CXXABI);
+ }
for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
Res.push_back("-target-feature");
Res.push_back(Opts.Features[i]);
@@ -789,15 +813,15 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead);
Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
+ Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG);
Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks);
Opts.EnableExperimentalInternalChecks =
Args.hasArg(OPT_analyzer_experimental_internal_checks);
- Opts.EnableIdempotentOperationChecker =
- Args.hasArg(OPT_analyzer_idempotent_operation);
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 3, Diags);
Opts.InlineCall = Args.hasArg(OPT_analyzer_inline_call);
+ Opts.IdempotentOps = Args.hasArg(OPT_analysis_WarnIdempotentOps);
}
static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
@@ -829,7 +853,8 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.OptimizeSize = Args.hasArg(OPT_Os);
Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
Args.hasArg(OPT_ffreestanding));
- Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
+ Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) ||
+ (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
@@ -838,6 +863,7 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
+ Opts.HiddenWeakVTables = Args.hasArg(OPT_fhidden_weak_vtables);
Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
@@ -916,6 +942,7 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
<< ShowCategory;
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
+ Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary);
Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags);
@@ -985,14 +1012,12 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::GeneratePTH; break;
case OPT_init_only:
Opts.ProgramAction = frontend::InitOnly; break;
- case OPT_parse_noop:
- Opts.ProgramAction = frontend::ParseNoop; break;
- case OPT_parse_print_callbacks:
- Opts.ProgramAction = frontend::ParsePrintCallbacks; break;
case OPT_fsyntax_only:
Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
case OPT_print_decl_contexts:
Opts.ProgramAction = frontend::PrintDeclContext; break;
+ case OPT_print_preamble:
+ Opts.ProgramAction = frontend::PrintPreamble; break;
case OPT_E:
Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
case OPT_rewrite_macros:
@@ -1005,6 +1030,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::RunAnalysis; break;
case OPT_Eonly:
Opts.ProgramAction = frontend::RunPreprocessorOnly; break;
+ case OPT_create_module:
+ Opts.ProgramAction = frontend::CreateModule; break;
}
}
@@ -1039,12 +1066,16 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
Opts.ShowCodePatternsInCodeCompletion
= Args.hasArg(OPT_code_completion_patterns);
+ Opts.ShowGlobalSymbolsInCodeCompletion
+ = !Args.hasArg(OPT_no_code_completion_globals);
Opts.ShowStats = Args.hasArg(OPT_print_stats);
Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
Opts.ShowVersion = Args.hasArg(OPT_version);
Opts.ViewClassInheritance = Args.getLastArgValue(OPT_cxx_inheritance_view);
Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
+ Opts.FixWhatYouCan = Args.hasArg(OPT_fix_what_you_can);
+ Opts.Modules = Args.getAllArgValues(OPT_import_module);
InputKind DashX = IK_None;
if (const Arg *A = Args.getLastArg(OPT_x)) {
@@ -1123,7 +1154,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F),
ie = Args.filtered_end(); it != ie; ++it)
Opts.AddPath((*it)->getValue(Args), frontend::Angled, true,
- /*IsFramework=*/ (*it)->getOption().matches(OPT_F));
+ /*IsFramework=*/ (*it)->getOption().matches(OPT_F), true);
// Add -iprefix/-iwith-prefix/-iwithprefixbefore options.
llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
@@ -1135,21 +1166,22 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Prefix = A->getValue(Args);
else if (A->getOption().matches(OPT_iwithprefix))
Opts.AddPath(Prefix.str() + A->getValue(Args),
- frontend::System, false, false);
+ frontend::System, false, false, true);
else
Opts.AddPath(Prefix.str() + A->getValue(Args),
- frontend::Angled, false, false);
+ frontend::Angled, false, false, true);
}
for (arg_iterator it = Args.filtered_begin(OPT_idirafter),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::After, true, false);
+ Opts.AddPath((*it)->getValue(Args), frontend::After, true, false, true);
for (arg_iterator it = Args.filtered_begin(OPT_iquote),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false);
- for (arg_iterator it = Args.filtered_begin(OPT_isystem),
+ Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false, true);
+ for (arg_iterator it = Args.filtered_begin(OPT_isystem, OPT_iwithsysroot),
ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::System, true, false);
+ Opts.AddPath((*it)->getValue(Args), frontend::System, true, false,
+ (*it)->getOption().matches(OPT_iwithsysroot));
// FIXME: Need options for the various environment variables!
}
@@ -1287,6 +1319,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
!Opts.AsmPreprocessor);
Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+ Opts.Borland = Args.hasArg(OPT_fborland_extensions);
Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings);
if (Args.hasArg(OPT_fno_lax_vector_conversions))
@@ -1360,6 +1393,24 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.TokenCache = Opts.ImplicitPTHInclude;
Opts.UsePredefines = !Args.hasArg(OPT_undef);
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
+ Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
+
+ if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
+ llvm::StringRef Value(A->getValue(Args));
+ size_t Comma = Value.find(',');
+ unsigned Bytes = 0;
+ unsigned EndOfLine = 0;
+
+ if (Comma == llvm::StringRef::npos ||
+ Value.substr(0, Comma).getAsInteger(10, Bytes) ||
+ Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
+ Diags.Report(diag::err_drv_preamble_format);
+ else {
+ Opts.PrecompiledPreambleBytes.first = Bytes;
+ Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
+ }
+ }
+
// Add macros from the command line.
for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
ie = Args.filtered_end(); it != ie; ++it) {
@@ -1379,7 +1430,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
// PCH is handled specially, we need to extra the original include path.
if (A->getOption().matches(OPT_include_pch)) {
std::string OriginalFile =
- PCHReader::getOriginalSourceFile(A->getValue(Args), Diags);
+ ASTReader::getOriginalSourceFile(A->getValue(Args), Diags);
if (OriginalFile.empty())
continue;
@@ -1411,10 +1462,11 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
ArgList &Args) {
using namespace cc1options;
Opts.ShowCPP = !Args.hasArg(OPT_dM);
- Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
- Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
Opts.ShowComments = Args.hasArg(OPT_C);
+ Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
+ Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
+ Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
}
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
@@ -1422,16 +1474,13 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
- Opts.Triple = Args.getLastArgValue(OPT_triple);
Opts.Features = Args.getAllArgValues(OPT_target_feature);
+ Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
+ Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
// Use the host triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getHostTriple();
-
- // Use the Itanium C++ ABI if unspecified.
- if (Opts.CXXABI.empty())
- Opts.CXXABI = "itanium";
}
//
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 14aee3559c9e..cdff8077ee47 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -53,7 +53,6 @@ public:
virtual void EndOfMainFile() {
OutputDependencyFile();
- OS->flush();
delete OS;
OS = 0;
}
diff --git a/lib/Frontend/DiagChecker.cpp b/lib/Frontend/DiagChecker.cpp
index a50cc99ab79e..66d7ed7cf40a 100644
--- a/lib/Frontend/DiagChecker.cpp
+++ b/lib/Frontend/DiagChecker.cpp
@@ -13,7 +13,7 @@
#include "clang/Frontend/Utils.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Sema/ParseAST.h"
+#include "clang/Parse/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index dbbf69c8b12c..b244c5ce0225 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -8,13 +8,14 @@
//===----------------------------------------------------------------------===//
#include "clang/Frontend/FrontendAction.h"
+#include "clang/AST/ASTConsumer.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 "clang/Parse/ParseAST.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/ErrorHandling.h"
@@ -50,7 +51,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
std::string Error;
- ASTUnit *AST = ASTUnit::LoadFromPCHFile(Filename, Diags);
+ ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags);
if (!AST)
goto failure;
@@ -112,18 +113,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!usesPreprocessorOnly()) {
CI.createASTContext();
- /// Use PCH? If so, we want the PCHReader active before the consumer
- /// is created, because the consumer might be interested in the reader
- /// (e.g. the PCH writer for chaining).
+ llvm::OwningPtr<ASTConsumer> Consumer(CreateASTConsumer(CI, Filename));
+
+ /// Use PCH?
if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) {
assert(hasPCHSupport() && "This action does not have PCH support!");
CI.createPCHExternalASTSource(
- CI.getPreprocessorOpts().ImplicitPCHInclude);
+ CI.getPreprocessorOpts().ImplicitPCHInclude,
+ CI.getPreprocessorOpts().DisablePCHValidation,
+ CI.getInvocation().getFrontendOpts().ChainedPCH?
+ Consumer->GetASTDeserializationListener() : 0);
if (!CI.getASTContext().getExternalSource())
goto failure;
}
- CI.setASTConsumer(CreateASTConsumer(CI, Filename));
+ CI.setASTConsumer(Consumer.take());
if (!CI.hasASTConsumer())
goto failure;
}
@@ -192,12 +196,16 @@ void FrontendAction::EndSourceFile() {
// FIXME: There is more per-file stuff we could just drop here?
if (CI.getFrontendOpts().DisableFree) {
CI.takeASTConsumer();
- if (!isCurrentFileAST())
+ if (!isCurrentFileAST()) {
+ CI.takeSema();
CI.takeASTContext();
+ }
} else {
- CI.setASTConsumer(0);
- if (!isCurrentFileAST())
+ if (!isCurrentFileAST()) {
+ CI.setSema(0);
CI.setASTContext(0);
+ }
+ CI.setASTConsumer(0);
}
// Inform the preprocessor we are done.
@@ -221,6 +229,7 @@ void FrontendAction::EndSourceFile() {
CI.getDiagnosticClient().EndSourceFile();
if (isCurrentFileAST()) {
+ CI.takeSema();
CI.takeASTContext();
CI.takePreprocessor();
CI.takeSourceManager();
@@ -249,9 +258,10 @@ void ASTFrontendAction::ExecuteAction() {
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();
- ParseAST(CI.getPreprocessor(), &CI.getASTConsumer(), CI.getASTContext(),
- CI.getFrontendOpts().ShowStats,
- usesCompleteTranslationUnit(), CompletionConsumer);
+ if (!CI.hasSema())
+ CI.createSema(usesCompleteTranslationUnit(), CompletionConsumer);
+
+ ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats);
}
ASTConsumer *
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 3a53dee80614..5bc6506e1fd9 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -18,7 +18,9 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/Utils.h"
+#include "clang/Serialization/ASTWriter.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -69,22 +71,35 @@ ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
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);
+ std::string Sysroot;
+ llvm::raw_ostream *OS = 0;
+ bool Chaining;
+ if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OS, Chaining))
return 0;
+
+ const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
+ Sysroot.c_str() : 0;
+ return new PCHGenerator(CI.getPreprocessor(), Chaining, isysroot, OS);
+}
+
+bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
+ llvm::StringRef InFile,
+ std::string &Sysroot,
+ llvm::raw_ostream *&OS,
+ bool &Chaining) {
+ Sysroot = CI.getHeaderSearchOpts().Sysroot;
+ if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
+ CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
+ return true;
}
- llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
+ OS = CI.createDefaultOutputFile(true, InFile);
if (!OS)
- return 0;
+ return true;
- PCHReader *Chain = CI.getInvocation().getFrontendOpts().ChainedPCH ?
- CI.getPCHReader() : 0;
- const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
- Sysroot.c_str() : 0;
- return CreatePCHGenerator(CI.getPreprocessor(), OS, Chain, isysroot);
+ Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
+ !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
+ return false;
}
ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
@@ -146,15 +161,6 @@ void GeneratePTHAction::ExecuteAction() {
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();
@@ -169,19 +175,6 @@ void PreprocessOnlyAction::ExecuteAction() {
} while (Tok.isNot(tok::eof));
}
-void PrintParseAction::ExecuteAction() {
- CompilerInstance &CI = getCompilerInstance();
- Preprocessor &PP = getCompilerInstance().getPreprocessor();
- llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile());
- if (!OS) return;
-
- llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS));
-
- Parser P(PP, *PA);
- PP.EnterMainSourceFile();
- P.ParseTranslationUnit();
-}
-
void PrintPreprocessedAction::ExecuteAction() {
CompilerInstance &CI = getCompilerInstance();
// Output file needs to be set to 'Binary', to avoid converting Unix style
@@ -192,3 +185,32 @@ void PrintPreprocessedAction::ExecuteAction() {
DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
CI.getPreprocessorOutputOpts());
}
+
+void PrintPreambleAction::ExecuteAction() {
+ switch (getCurrentFileKind()) {
+ case IK_C:
+ case IK_CXX:
+ case IK_ObjC:
+ case IK_ObjCXX:
+ case IK_OpenCL:
+ break;
+
+ case IK_None:
+ case IK_Asm:
+ case IK_PreprocessedC:
+ case IK_PreprocessedCXX:
+ case IK_PreprocessedObjC:
+ case IK_PreprocessedObjCXX:
+ case IK_AST:
+ case IK_LLVM_IR:
+ // We can't do anything with these.
+ return;
+ }
+
+ llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile());
+ if (Buffer) {
+ unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
+ llvm::outs().write(Buffer->getBufferStart(), Preamble);
+ delete Buffer;
+ }
+}
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index d640d42492f1..df917136203f 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -1,4 +1,4 @@
-//===--- InitHeaderSearch.cpp - Initialize header search paths ----------*-===//
+//===--- InitHeaderSearch.cpp - Initialize header search paths ------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -195,6 +195,8 @@ void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(llvm::StringRef Base,
System, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++",
System, true, false, false);
+ AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/" + Arch,
+ System, true, false, false);
AddPath(Base + "/" + Arch + "/" + Version + "/include/c++/backward",
System, true, false, false);
}
@@ -323,9 +325,19 @@ static bool getSystemRegistryString(const char*, const char*, char*, size_t) {
// Get Visual Studio installation directory.
static bool getVisualStudioDir(std::string &path) {
+ // First check the environment variables that vsvars32.bat sets.
+ const char* vcinstalldir = getenv("VCINSTALLDIR");
+ if(vcinstalldir) {
+ char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC"));
+ if (p)
+ *p = '\0';
+ path = vcinstalldir;
+ return(true);
+ }
+
char vsIDEInstallDir[256];
char vsExpressIDEInstallDir[256];
- // Try the Windows registry first.
+ // Then try the windows registry.
bool hasVCDir = getSystemRegistryString(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION",
"InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1);
@@ -440,7 +452,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
if (getVisualStudioDir(VSDir)) {
AddPath(VSDir + "\\VC\\include", System, false, false, false);
if (getWindowsSDKDir(WindowsSDKDir))
- AddPath(WindowsSDKDir, System, false, false, false);
+ AddPath(WindowsSDKDir + "\\include", System, false, false, false);
else
AddPath(VSDir + "\\VC\\PlatformSDK\\Include",
System, false, false, false);
@@ -510,7 +522,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,
AddPath("/boot/develop/headers/glibc", System, true, false, false);
AddPath("/boot/develop/headers/posix", System, true, false, false);
AddPath("/boot/develop/headers", System, true, false, false);
- break;
+ break;
case llvm::Triple::MinGW64:
case llvm::Triple::MinGW32:
AddPath("c:/mingw/include", System, true, false, false);
@@ -549,12 +561,16 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
System, true, false, false);
break;
case llvm::Triple::MinGW64:
+ // Try gcc 4.5.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.5.0");
// Try gcc 4.4.0
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.4.0");
// Try gcc 4.3.0
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw64", "4.3.0");
// Fall through.
case llvm::Triple::MinGW32:
+ // Try gcc 4.5.0
+ AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.0");
// Try gcc 4.4.0
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.4.0");
// Try gcc 4.3.0
@@ -716,6 +732,11 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
AddGnuCPlusPlusIncludePaths(
"/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4",
"x86_64-pc-linux-gnu", "32", "", triple);
+
+ // Gentoo amd64 llvm-gcc trunk
+ AddGnuCPlusPlusIncludePaths(
+ "/usr/lib/llvm-gcc-4.2-9999/include/c++/4.2.1",
+ "x86_64-pc-linux-gnu", "", "", triple);
break;
case llvm::Triple::FreeBSD:
@@ -723,6 +744,17 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple) {
// FreeBSD 7.3
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2", "", "", "", triple);
break;
+ case llvm::Triple::NetBSD:
+ AddGnuCPlusPlusIncludePaths("/usr/include/g++", "", "", "", triple);
+ break;
+ case llvm::Triple::OpenBSD: {
+ std::string t = triple.getTriple();
+ if (t.substr(0, 6) == "x86_64")
+ t.replace(0, 6, "amd64");
+ AddGnuCPlusPlusIncludePaths("/usr/include/g++",
+ t, "", "", triple);
+ break;
+ }
case llvm::Triple::Minix:
AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3",
"", "", "", triple);
@@ -889,7 +921,7 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS,
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);
+ !E.IsSysRootRelative);
}
// Add entries from CPATH and friends.
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 889b6e52a456..0d07192b50e5 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -169,10 +169,11 @@ static void DefineTypeSize(llvm::StringRef MacroName, unsigned TypeWidth,
llvm::StringRef ValSuffix, bool isSigned,
MacroBuilder& Builder) {
long long MaxVal;
- if (isSigned)
- MaxVal = (1LL << (TypeWidth - 1)) - 1;
- else
- MaxVal = ~0LL >> (64-TypeWidth);
+ if (isSigned) {
+ assert(TypeWidth != 1);
+ MaxVal = ~0ULL >> (65-TypeWidth);
+ } else
+ MaxVal = ~0ULL >> (64-TypeWidth);
Builder.defineMacro(MacroName, llvm::Twine(MaxVal) + ValSuffix);
}
@@ -318,7 +319,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__cplusplus");
else
// C++ [cpp.predefined]p1:
- // The name_ _cplusplusis defined to the value199711Lwhen compiling a
+ // The name_ _cplusplusis defined to the value 199711L when compiling a
// C++ translation unit.
Builder.defineMacro("__cplusplus", "199711L");
Builder.defineMacro("__private_extern__", "extern");
@@ -339,9 +340,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
// Since we define wchar_t in C++ mode.
Builder.defineMacro("_WCHAR_T_DEFINED");
Builder.defineMacro("_NATIVE_WCHAR_T_DEFINED");
- // FIXME: This should be temporary until we have a __pragma
- // solution, to avoid some errors flagged in VC++ headers.
- Builder.defineMacro("_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES", "0");
+ Builder.append("class type_info;");
}
}
@@ -477,7 +476,7 @@ static void InitializeFileRemapping(Diagnostic &Diags,
FileManager &FileMgr,
const PreprocessorOptions &InitOpts) {
// Remap files in the source manager (with buffers).
- for (PreprocessorOptions::remapped_file_buffer_iterator
+ for (PreprocessorOptions::const_remapped_file_buffer_iterator
Remap = InitOpts.remapped_file_buffer_begin(),
RemapEnd = InitOpts.remapped_file_buffer_end();
Remap != RemapEnd;
@@ -489,19 +488,21 @@ static void InitializeFileRemapping(Diagnostic &Diags,
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
<< Remap->first;
- delete Remap->second;
+ if (!InitOpts.RetainRemappedFileBuffers)
+ delete Remap->second;
continue;
}
// Override the contents of the "from" file with the contents of
// the "to" file.
- SourceMgr.overrideFileContents(FromFile, Remap->second);
+ SourceMgr.overrideFileContents(FromFile, Remap->second,
+ InitOpts.RetainRemappedFileBuffers);
}
// Remap files in the source manager (with other files).
- for (PreprocessorOptions::remapped_file_iterator
- Remap = InitOpts.remapped_file_begin(),
- RemapEnd = InitOpts.remapped_file_end();
+ for (PreprocessorOptions::const_remapped_file_iterator
+ Remap = InitOpts.remapped_file_begin(),
+ RemapEnd = InitOpts.remapped_file_end();
Remap != RemapEnd;
++Remap) {
// Find the file that we're mapping to.
@@ -596,6 +597,10 @@ void clang::InitializePreprocessor(Preprocessor &PP,
if (!PP.getLangOptions().AsmPreprocessor)
Builder.append("# 1 \"<built-in>\" 2");
+ // Instruct the preprocessor to skip the preamble.
+ PP.setSkipMainFilePreamble(InitOpts.PrecompiledPreambleBytes.first,
+ InitOpts.PrecompiledPreambleBytes.second);
+
// Copy PredefinedBuffer into the Preprocessor.
PP.setPredefines(Predefines.str());
diff --git a/lib/Frontend/Makefile b/lib/Frontend/Makefile
index 3eb4bc95f4c3..3c13ad69cc67 100644
--- a/lib/Frontend/Makefile
+++ b/lib/Frontend/Makefile
@@ -9,7 +9,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangFrontend
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
deleted file mode 100644
index 922067748336..000000000000
--- a/lib/Frontend/PrintParserCallbacks.cpp
+++ /dev/null
@@ -1,852 +0,0 @@
-//===--- PrintParserActions.cpp - Implement -parse-print-callbacks mode ---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This code simply runs the preprocessor on the input file and prints out the
-// result. This is the traditional behavior of the -E option.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/Utils.h"
-#include "clang/Parse/Action.h"
-#include "clang/Parse/DeclSpec.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace clang;
-
-namespace {
- class ParserPrintActions : public MinimalAction {
- llvm::raw_ostream& Out;
-
- public:
- ParserPrintActions(Preprocessor &PP, llvm::raw_ostream& OS)
- : MinimalAction(PP), Out(OS) {}
-
- // Printing Functions which also must call MinimalAction
-
- /// ActOnDeclarator - This callback is invoked when a declarator is parsed
- /// and 'Init' specifies the initializer if any. This is for things like:
- /// "int X = 4" or "typedef int foo".
- virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
- Out << __FUNCTION__ << " ";
- if (IdentifierInfo *II = D.getIdentifier()) {
- Out << "'" << II->getName() << "'";
- } else {
- Out << "<anon>";
- }
- Out << "\n";
-
- // Pass up to EmptyActions so that the symbol table is maintained right.
- return MinimalAction::ActOnDeclarator(S, D);
- }
- /// ActOnPopScope - This callback is called immediately before the specified
- /// scope is popped and deleted.
- virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {
- Out << __FUNCTION__ << "\n";
- return MinimalAction::ActOnPopScope(Loc, S);
- }
-
- /// ActOnTranslationUnitScope - This callback is called once, immediately
- /// after creating the translation unit scope (in Parser::Initialize).
- virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
- Out << __FUNCTION__ << "\n";
- MinimalAction::ActOnTranslationUnitScope(Loc, S);
- }
-
-
- Action::DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtocols,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
- Out << __FUNCTION__ << "\n";
- return MinimalAction::ActOnStartClassInterface(AtInterfaceLoc,
- ClassName, ClassLoc,
- SuperName, SuperLoc,
- ProtoRefs, NumProtocols,
- ProtoLocs, EndProtoLoc,
- AttrList);
- }
-
- /// ActOnForwardClassDeclaration -
- /// 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,
- IdentLocs, NumElts);
- }
-
- // Pure Printing
-
- /// ActOnParamDeclarator - This callback is invoked when a parameter
- /// declarator is parsed. This callback only occurs for functions
- /// with prototypes. S is the function prototype scope for the
- /// parameters (C++ [basic.scope.proto]).
- virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) {
- Out << __FUNCTION__ << " ";
- if (IdentifierInfo *II = D.getIdentifier()) {
- Out << "'" << II->getName() << "'";
- } else {
- Out << "<anon>";
- }
- Out << "\n";
- return DeclPtrTy();
- }
-
- /// AddInitializerToDecl - This action is called immediately after
- /// ParseDeclarator (when an initializer is present). The code is factored
- /// this way to make sure we are able to handle the following:
- /// void func() { int xx = xx; }
- /// This allows ActOnDeclarator to register "xx" prior to parsing the
- /// initializer. The declaration above should still result in a warning,
- /// since the reference to "xx" is uninitialized.
- virtual void AddInitializerToDecl(DeclPtrTy Dcl, ExprArg Init) {
- Out << __FUNCTION__ << "\n";
- }
-
- /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed,
- /// this gives the actions implementation a chance to process the group as
- /// a whole.
- virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS,
- DeclPtrTy *Group,
- unsigned NumDecls) {
- Out << __FUNCTION__ << "\n";
- return DeclGroupPtrTy();
- }
-
- /// ActOnStartOfFunctionDef - This is called at the start of a function
- /// definition, instead of calling ActOnDeclarator. The Declarator includes
- /// information about formal arguments that are part of this function.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope,
- Declarator &D){
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- /// ActOnStartOfFunctionDef - This is called at the start of a function
- /// definition, after the FunctionDecl has already been created.
- virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
- Out << __FUNCTION__ << "\n";
- }
-
- /// ActOnFunctionDefBody - This is called when a function body has completed
- /// parsing. Decl is the DeclTy returned by ParseStartOfFunctionDef.
- virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc,
- ExprArg AsmString) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
- /// no declarator (e.g. "struct foo;") is parsed.
- virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
- DeclSpec &DS) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- /// ActOnLinkageSpec - Parsed a C++ linkage-specification that
- /// contained braces. Lang/StrSize contains the language string that
- /// was parsed at location Loc. Decls/NumDecls provides the
- /// declarations parsed inside the linkage specification.
- virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc,
- SourceLocation LBrace,
- SourceLocation RBrace, const char *Lang,
- unsigned StrSize,
- DeclPtrTy *Decls, unsigned NumDecls) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- /// ActOnLinkageSpec - Parsed a C++ linkage-specification without
- /// braces. Lang/StrSize contains the language string that was
- /// parsed at location Loc. D is the declaration parsed.
- virtual DeclPtrTy ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
- unsigned StrSize, DeclPtrTy D) {
- return DeclPtrTy();
- }
-
- //===------------------------------------------------------------------===//
- // Type Parsing Callbacks.
- //===------------------------------------------------------------------===//
-
- virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
- Out << __FUNCTION__ << "\n";
- return TypeResult();
- }
-
- virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
- SourceLocation KWLoc, CXXScopeSpec &SS,
- IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr, AccessSpecifier AS,
- MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent) {
- // TagType is an instance of DeclSpec::TST, indicating what kind of tag this
- // is (struct/union/enum/class).
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- /// Act on @defs() element found when parsing a structure. ClassName is the
- /// name of the referenced class.
- virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
- IdentifierInfo *ClassName,
- llvm::SmallVectorImpl<DeclPtrTy> &Decls) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD,
- SourceLocation DeclStart,
- Declarator &D, ExprTy *BitfieldWidth) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart,
- DeclPtrTy IntfDecl,
- Declarator &D, ExprTy *BitfieldWidth,
- tok::ObjCKeywordKind visibility) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl,
- DeclPtrTy *Fields, unsigned NumFields,
- SourceLocation LBrac, SourceLocation RBrac,
- AttributeList *AttrList) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl,
- DeclPtrTy LastEnumConstant,
- SourceLocation IdLoc,IdentifierInfo *Id,
- SourceLocation EqualLoc, ExprTy *Val) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, DeclPtrTy EnumDecl,
- DeclPtrTy *Elements, unsigned NumElements,
- Scope *S, AttributeList *AttrList) {
- Out << __FUNCTION__ << "\n";
- }
-
- //===------------------------------------------------------------------===//
- // Statement Parsing Callbacks.
- //===------------------------------------------------------------------===//
-
- virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L,
- SourceLocation R,
- MultiStmtArg Elts,
- bool isStmtExpr) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
- SourceLocation StartLoc,
- SourceLocation EndLoc) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) {
- Out << __FUNCTION__ << "\n";
- return OwningStmtResult(*this, Expr->release());
- }
-
- /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
- /// which can specify an RHS value.
- virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc,
- ExprArg LHSVal,
- SourceLocation DotDotDotLoc,
- ExprArg RHSVal,
- SourceLocation ColonLoc) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
- SourceLocation ColonLoc,
- StmtArg SubStmt, Scope *CurScope){
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation ColonLoc,
- StmtArg SubStmt) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
- FullExprArg CondVal, DeclPtrTy CondVar,
- StmtArg ThenVal,
- SourceLocation ElseLoc,
- StmtArg ElseVal) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
- ExprArg Cond,
- DeclPtrTy CondVar) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
- StmtArg Switch,
- StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
- FullExprArg Cond, DeclPtrTy CondVar,
- StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
- SourceLocation WhileLoc,
- SourceLocation LPLoc, ExprArg Cond,
- SourceLocation RPLoc){
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc,
- StmtArg First, FullExprArg Second,
- DeclPtrTy SecondVar,
- FullExprArg Third,
- SourceLocation RParenLoc,
- StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnObjCForCollectionStmt(
- SourceLocation ForColLoc,
- SourceLocation LParenLoc,
- StmtArg First, ExprArg Second,
- SourceLocation RParenLoc, StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
- SourceLocation LabelLoc,
- IdentifierInfo *LabelII) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
- SourceLocation StarLoc,
- ExprArg DestExp) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
- Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
- Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
- ExprArg RetValExp) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
- virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
- bool IsSimple,
- bool IsVolatile,
- unsigned NumOutputs,
- unsigned NumInputs,
- IdentifierInfo **Names,
- MultiExprArg Constraints,
- MultiExprArg Exprs,
- ExprArg AsmString,
- MultiExprArg Clobbers,
- SourceLocation RParenLoc,
- bool MSAsm) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- // Objective-c statements
- virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
- SourceLocation RParen,
- DeclPtrTy Parm,
- StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
- StmtArg Body) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
- StmtArg Try,
- MultiStmtArg CatchStmts,
- StmtArg Finally) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg Throw,
- Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
- ExprArg SynchExpr,
- StmtArg SynchBody) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- // C++ Statements
- virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
- DeclPtrTy ExceptionDecl,
- StmtArg HandlerBlock) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
- StmtArg TryBlock,
- MultiStmtArg Handlers) {
- Out << __FUNCTION__ << "\n";
- return StmtEmpty();
- }
-
- //===------------------------------------------------------------------===//
- // Expression Parsing Callbacks.
- //===------------------------------------------------------------------===//
-
- // Primary Expressions.
-
- /// ActOnIdentifierExpr - Parse an identifier in expression context.
- /// 'HasTrailingLParen' indicates whether or not the identifier has a '('
- /// token immediately after it.
- virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
- IdentifierInfo &II,
- bool HasTrailingLParen,
- const CXXScopeSpec *SS,
- bool isAddressOfOperand) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
- Scope *S, SourceLocation OperatorLoc,
- OverloadedOperatorKind Op,
- bool HasTrailingLParen, const CXXScopeSpec &SS,
- bool isAddressOfOperand) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXConversionFunctionExpr(
- Scope *S, SourceLocation OperatorLoc,
- TypeTy *Type, bool HasTrailingLParen,
- const CXXScopeSpec &SS,bool isAddressOfOperand) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
- tok::TokenKind Kind) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCharacterConstant(const Token &) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnNumericConstant(const Token &) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- /// ActOnStringLiteral - The specified tokens were lexed as pasted string
- /// fragments (e.g. "foo" "bar" L"baz").
- virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
- unsigned NumToks) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
- ExprArg Val) {
- Out << __FUNCTION__ << "\n";
- return move(Val); // Default impl returns operand.
- }
-
- // Postfix Expressions.
- virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind,
- ExprArg Input) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
- SourceLocation LLoc,
- ExprArg Idx,
- SourceLocation RLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation MemberLoc,
- IdentifierInfo &Member,
- DeclPtrTy ImplDecl,
- const CXXScopeSpec *SS=0) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- // Unary Operators. 'Tok' is the token for the operator.
- virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg Input) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- virtual OwningExprResult
- ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
- void *TyOrEx, const SourceRange &ArgRange) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen,
- ExprArg Op) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
- MultiExprArg InitList,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- virtual OwningExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- TypeTy *Ty, SourceLocation RParenLoc,
- ExprArg Op) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
- tok::TokenKind Kind,
- ExprArg LHS, ExprArg RHS) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
- /// in the case of a the GNU conditional expr extension.
- virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
- SourceLocation ColonLoc,
- ExprArg Cond, ExprArg LHS,
- ExprArg RHS) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- //===--------------------- GNU Extension Expressions ------------------===//
-
- virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc,
- SourceLocation LabLoc,
- IdentifierInfo *LabelII) {// "&&foo"
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc,
- StmtArg SubStmt,
- SourceLocation RPLoc) { // "({..})"
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S,
- SourceLocation BuiltinLoc,
- SourceLocation TypeLoc,
- TypeTy *Arg1,
- OffsetOfComponent *CompPtr,
- unsigned NumComponents,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- // __builtin_types_compatible_p(type1, type2)
- virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
- TypeTy *arg1,TypeTy *arg2,
- SourceLocation RPLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- // __builtin_choose_expr(constExpr, expr1, expr2)
- virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
- ExprArg cond, ExprArg expr1,
- ExprArg expr2,
- SourceLocation RPLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- // __builtin_va_arg(expr, type)
- virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc,
- ExprArg expr, TypeTy *type,
- SourceLocation RPLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
- StmtArg Body,
- Scope *CurScope) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc,
- IdentifierInfo *Ident,
- SourceLocation LBrace,
- AttributeList *AttrList) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) {
- Out << __FUNCTION__ << "\n";
- return;
- }
-
-#if 0
- // FIXME: AttrList should be deleted by this function, but the definition
- // would have to be available.
- virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-#endif
-
- virtual void ActOnParamDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- ExprArg defarg) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
- SourceLocation EqualLoc,
- SourceLocation ArgLoc) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return;
- }
-
- virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
- DeclPtrTy Method) {
- Out << __FUNCTION__ << "\n";
- }
-
- virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
- ExprArg AssertExpr,
- ExprArg AssertMessageExpr) {
- Out << __FUNCTION__ << "\n";
- return DeclPtrTy();
- }
-
- virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc,
- TypeTy *Ty,
- SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc,
- ExprArg Op,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc,
- SourceLocation LParenLoc,
- bool isType, void *TyOrExpr,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
- tok::TokenKind Kind) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange,
- TypeTy *TypeRep,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation *CommaLocs,
- SourceLocation RParenLoc) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S,
- SourceLocation StartLoc,
- Declarator &D,
- SourceLocation EqualLoc,
- ExprArg AssignExprVal) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc,
- bool UseGlobal,
- SourceLocation PlacementLParen,
- MultiExprArg PlacementArgs,
- SourceLocation PlacementRParen,
- SourceRange TypeIdParens,
- Declarator &D,
- SourceLocation ConstructorLParen,
- MultiExprArg ConstructorArgs,
- SourceLocation ConstructorRParen) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
- bool UseGlobal, bool ArrayForm,
- ExprArg Operand) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
-
- virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
- SourceLocation KWLoc,
- SourceLocation LParen,
- TypeTy *Ty,
- SourceLocation RParen) {
- Out << __FUNCTION__ << "\n";
- return ExprEmpty();
- }
- };
-}
-
-MinimalAction *clang::CreatePrintParserActionsAction(Preprocessor &PP,
- llvm::raw_ostream* OS) {
- return new ParserPrintActions(PP, *OS);
-}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 73bca9a6caa1..cfaf8a23b118 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -85,6 +85,10 @@ public:
llvm::raw_ostream &OS;
private:
unsigned CurLine;
+
+ /// The current include nesting level, used by header include dumping (-H).
+ unsigned CurrentIncludeDepth;
+
bool EmittedTokensOnThisLine;
bool EmittedMacroOnThisLine;
SrcMgr::CharacteristicKind FileType;
@@ -92,19 +96,22 @@ private:
bool Initialized;
bool DisableLineMarkers;
bool DumpDefines;
+ bool DumpHeaderIncludes;
bool UseLineDirective;
+ bool HasProcessedPredefines;
public:
PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
- bool lineMarkers, bool defines)
+ bool lineMarkers, bool defines, bool headers)
: PP(pp), SM(PP.getSourceManager()),
ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
- DumpDefines(defines) {
- CurLine = 0;
+ DumpDefines(defines), DumpHeaderIncludes(headers) {
+ CurLine = CurrentIncludeDepth = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
EmittedMacroOnThisLine = false;
FileType = SrcMgr::C_User;
Initialized = false;
+ HasProcessedPredefines = false;
// If we're in microsoft mode, use normal #line instead of line markers.
UseLineDirective = PP.getLangOptions().Microsoft;
@@ -137,6 +144,9 @@ public:
/// MacroDefined - This hook is called whenever a macro definition is seen.
void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
+ /// MacroUndefined - This hook is called whenever a macro #undef is seen.
+ void MacroUndefined(SourceLocation Loc, const IdentifierInfo *II,
+ const MacroInfo *MI);
};
} // end anonymous namespace
@@ -216,7 +226,7 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc);
unsigned NewLine = UserLoc.getLine();
-
+
if (Reason == PPCallbacks::EnterFile) {
SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc();
if (IncludeLoc.isValid())
@@ -228,16 +238,41 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
// directive and emits a bunch of spaces that aren't needed. Emulate this
// strange behavior.
}
+
+ // Adjust the current include depth.
+ if (Reason == PPCallbacks::EnterFile) {
+ ++CurrentIncludeDepth;
+ } else {
+ if (CurrentIncludeDepth)
+ --CurrentIncludeDepth;
+
+ // We track when we are done with the predefines by watching for the first
+ // place where we drop back to a nesting depth of 0.
+ if (CurrentIncludeDepth == 0 && !HasProcessedPredefines)
+ HasProcessedPredefines = true;
+ }
CurLine = NewLine;
- if (DisableLineMarkers) return;
-
CurFilename.clear();
CurFilename += UserLoc.getFilename();
Lexer::Stringify(CurFilename);
FileType = NewFileType;
+ // Dump the header include information, if enabled and we are past the
+ // predefines buffer.
+ if (DumpHeaderIncludes && HasProcessedPredefines &&
+ Reason == PPCallbacks::EnterFile) {
+ llvm::SmallString<256> Msg;
+ llvm::raw_svector_ostream OS(Msg);
+ for (unsigned i = 0; i != CurrentIncludeDepth; ++i)
+ OS << '.';
+ OS << ' ' << CurFilename << '\n';
+ llvm::errs() << OS.str();
+ }
+
+ if (DisableLineMarkers) return;
+
if (!Initialized) {
WriteLineInfo(CurLine);
Initialized = true;
@@ -280,6 +315,16 @@ void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II,
EmittedMacroOnThisLine = true;
}
+void PrintPPOutputPPCallbacks::MacroUndefined(SourceLocation Loc,
+ const IdentifierInfo *II,
+ const MacroInfo *MI) {
+ // Only print out macro definitions in -dD mode.
+ if (!DumpDefines) return;
+
+ MoveToLine(Loc);
+ OS << "#undef " << II->getName();
+ EmittedMacroOnThisLine = true;
+}
void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
const IdentifierInfo *Kind,
@@ -516,7 +561,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
PrintPPOutputPPCallbacks *Callbacks =
new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
- Opts.ShowMacros);
+ Opts.ShowMacros, Opts.ShowHeaderIncludes);
PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks));
PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
Callbacks));
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index 21dc0ba0a188..b6607349d76d 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -32,7 +32,8 @@ namespace {
void addSpecialAttribute(const char* pName, StringLiteral* Str) {
- Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+ Doc.addAttribute(pName, Doc.escapeString(Str->getString().data(),
+ Str->getString().size()));
}
void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S) {
@@ -261,7 +262,6 @@ const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) {
case UnaryOperator::Real: return "__real";
case UnaryOperator::Imag: return "__imag";
case UnaryOperator::Extension: return "__extension__";
- case UnaryOperator::OffsetOf: return "__builtin_offsetof";
}
}
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 1b5b7e2ea863..1e453a08fdb9 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -447,11 +447,11 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
if (NumHints && DiagOpts->ShowFixits) {
for (const FixItHint *Hint = Hints, *LastHint = Hints + NumHints;
Hint != LastHint; ++Hint) {
- if (Hint->InsertionLoc.isValid()) {
+ if (!Hint->CodeToInsert.empty()) {
// We have an insertion hint. Determine whether the inserted
// code is on the same line as the caret.
std::pair<FileID, unsigned> HintLocInfo
- = SM.getDecomposedInstantiationLoc(Hint->InsertionLoc);
+ = SM.getDecomposedInstantiationLoc(Hint->RemoveRange.getBegin());
if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) ==
SM.getLineNumber(FID, FileOffset)) {
// Insert the new code into the line just below the code
@@ -537,6 +537,48 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,
if (DiagOpts->ShowColors)
OS.resetColor();
}
+
+ if (DiagOpts->ShowParseableFixits) {
+
+ // We follow FixItRewriter's example in not (yet) handling
+ // fix-its in macros.
+ bool BadApples = false;
+ for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
+ if (Hint->RemoveRange.isInvalid() ||
+ Hint->RemoveRange.getBegin().isMacroID() ||
+ Hint->RemoveRange.getEnd().isMacroID()) {
+ BadApples = true;
+ break;
+ }
+ }
+
+ if (!BadApples) {
+ for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
+
+ SourceLocation B = Hint->RemoveRange.getBegin();
+ SourceLocation E = Hint->RemoveRange.getEnd();
+
+ std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
+ std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
+
+ // Adjust for token ranges.
+ if (Hint->RemoveRange.isTokenRange())
+ EInfo.second += Lexer::MeasureTokenLength(E, SM, *LangOpts);
+
+ // We specifically do not do word-wrapping or tab-expansion here,
+ // because this is supposed to be easy to parse.
+ OS << "fix-it:\"";
+ OS.write_escaped(SM.getPresumedLoc(B).getFilename());
+ OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
+ << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
+ << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
+ << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
+ << "}:\"";
+ OS.write_escaped(Hint->CodeToInsert);
+ OS << "\"\n";
+ }
+ }
+ }
}
/// \brief Skip over whitespace in the string, starting at the given
diff --git a/lib/Frontend/VerifyDiagnosticsClient.cpp b/lib/Frontend/VerifyDiagnosticsClient.cpp
index ae36481444da..31eb28f912ca 100644
--- a/lib/Frontend/VerifyDiagnosticsClient.cpp
+++ b/lib/Frontend/VerifyDiagnosticsClient.cpp
@@ -171,13 +171,12 @@ public:
: Begin(Begin), End(End), C(Begin), P(Begin), PEnd(NULL) { }
// Return true if string literal is next.
- bool Next(const std::string &S) {
- std::string::size_type LEN = S.length();
+ bool Next(llvm::StringRef S) {
P = C;
- PEnd = C + LEN;
+ PEnd = C + S.size();
if (PEnd > End)
return false;
- return !memcmp(P, S.c_str(), LEN);
+ return !memcmp(P, S.data(), S.size());
}
// Return true if number is next.
@@ -198,9 +197,9 @@ public:
// Return true if string literal is found.
// When true, P marks begin-position of S in content.
- bool Search(const std::string &S) {
+ bool Search(llvm::StringRef S) {
P = std::search(C, End, S.begin(), S.end());
- PEnd = P + S.length();
+ PEnd = P + S.size();
return P != End;
}
@@ -484,7 +483,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() {
ExpectedData ED;
// Ensure any diagnostics go to the primary client.
- DiagnosticClient *CurClient = Diags.getClient();
+ DiagnosticClient *CurClient = Diags.takeClient();
Diags.setClient(PrimaryClient.get());
// If we have a preprocessor, scan the source for expected diagnostic
@@ -507,6 +506,7 @@ void VerifyDiagnosticsClient::CheckDiagnostics() {
"note", false));
}
+ Diags.takeClient();
Diags.setClient(CurClient);
// Reset the buffer, we have processed all the diagnostics in it.
diff --git a/lib/FrontendTool/CMakeLists.txt b/lib/FrontendTool/CMakeLists.txt
new file mode 100644
index 000000000000..26c9fc7b5106
--- /dev/null
+++ b/lib/FrontendTool/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangFrontendTool
+ ExecuteCompilerInvocation.cpp
+ )
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
new file mode 100644
index 000000000000..63c628780762
--- /dev/null
+++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -0,0 +1,155 @@
+//===--- ExecuteCompilerInvocation.cpp ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds ExecuteCompilerInvocation(). It is split into its own file to
+// minimize the impact of pulling in essentially everything else in Clang.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/FrontendTool/Utils.h"
+#include "clang/Checker/FrontendActions.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Rewrite/FrontendActions.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/System/DynamicLibrary.h"
+using namespace clang;
+
+static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
+ using namespace clang::frontend;
+
+ switch (CI.getFrontendOpts().ProgramAction) {
+ default:
+ 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 BoostCon: return new BoostConAction();
+ case CreateModule: return 0;
+ case DumpRawTokens: return new DumpRawTokensAction();
+ 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 EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
+ case EmitObj: return new EmitObjAction();
+ case FixIt: return new FixItAction();
+ case GeneratePCH: return new GeneratePCHAction();
+ case GeneratePTH: return new GeneratePTHAction();
+ case InheritanceView: return new InheritanceViewAction();
+ case InitOnly: return new InitOnlyAction();
+ case ParseSyntaxOnly: return new SyntaxOnlyAction();
+
+ case PluginAction: {
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == CI.getFrontendOpts().ActionName) {
+ llvm::OwningPtr<PluginASTAction> P(it->instantiate());
+ if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
+ return 0;
+ return P.take();
+ }
+ }
+
+ CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+ << CI.getFrontendOpts().ActionName;
+ return 0;
+ }
+
+ case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreamble: return new PrintPreambleAction();
+ case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ 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();
+ }
+}
+
+static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
+ // Create the underlying action.
+ FrontendAction *Act = CreateFrontendBaseAction(CI);
+ if (!Act)
+ return 0;
+
+ // If there are any AST files to merge, create a frontend action
+ // adaptor to perform the merge.
+ if (!CI.getFrontendOpts().ASTMergeFiles.empty())
+ Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
+ CI.getFrontendOpts().ASTMergeFiles.size());
+
+ return Act;
+}
+
+bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) {
+ // Honor -help.
+ if (Clang->getFrontendOpts().ShowHelp) {
+ llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
+ Opts->PrintHelp(llvm::outs(), "clang -cc1",
+ "LLVM 'Clang' Compiler: http://clang.llvm.org");
+ return 0;
+ }
+
+ // Honor -version.
+ //
+ // FIXME: Use a better -version message?
+ if (Clang->getFrontendOpts().ShowVersion) {
+ llvm::cl::PrintVersionMessage();
+ return 0;
+ }
+
+ // Honor -mllvm.
+ //
+ // FIXME: Remove this, one day.
+ if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
+ unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
+ const char **Args = new const char*[NumArgs + 2];
+ Args[0] = "clang (LLVM option parsing)";
+ for (unsigned i = 0; i != NumArgs; ++i)
+ Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
+ Args[NumArgs + 1] = 0;
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
+ }
+
+ // Load any requested plugins.
+ for (unsigned i = 0,
+ e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) {
+ const std::string &Path = Clang->getFrontendOpts().Plugins[i];
+ std::string Error;
+ if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
+ Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin)
+ << Path << Error;
+ }
+
+ // If there were errors in processing arguments, don't do anything else.
+ bool Success = false;
+ if (!Clang->getDiagnostics().getNumErrors()) {
+ // Create and execute the frontend action.
+ llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(*Clang));
+ if (Act) {
+ Success = Clang->ExecuteAction(*Act);
+ if (Clang->getFrontendOpts().DisableFree)
+ Act.take();
+ }
+ }
+
+ return Success;
+}
diff --git a/lib/FrontendTool/Makefile b/lib/FrontendTool/Makefile
new file mode 100644
index 000000000000..c43213ff99d0
--- /dev/null
+++ b/lib/FrontendTool/Makefile
@@ -0,0 +1,13 @@
+##===- clang/lib/FrontendTool/Makefile ---------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+LIBRARYNAME := clangFrontendTool
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Headers/CMakeLists.txt b/lib/Headers/CMakeLists.txt
index 97a99d676e87..a1b5f50caa08 100644
--- a/lib/Headers/CMakeLists.txt
+++ b/lib/Headers/CMakeLists.txt
@@ -1,12 +1,15 @@
set(files
altivec.h
+ avxintrin.h
emmintrin.h
float.h
+ immintrin.h
iso646.h
limits.h
mm_malloc.h
mmintrin.h
pmmintrin.h
+ smmintrin.h
stdarg.h
stdbool.h
stddef.h
diff --git a/lib/Headers/Makefile b/lib/Headers/Makefile
index ebb83843cacd..d75b1a2e7cae 100644
--- a/lib/Headers/Makefile
+++ b/lib/Headers/Makefile
@@ -38,6 +38,7 @@ all-local:: $(OBJHEADERS)
PROJ_headers := $(DESTDIR)$(PROJ_prefix)/lib/clang/$(CLANG_VERSION)/include
INSTHEADERS := $(addprefix $(PROJ_headers)/, $(HEADERS))
+INSTHEADERS += $(PROJ_headers)/arm_neon.h
$(PROJ_headers):
$(Verb) $(MKDIR) $@
diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h
index d3d5ad90aef1..89bd259b6733 100644
--- a/lib/Headers/altivec.h
+++ b/lib/Headers/altivec.h
@@ -45,18 +45,30 @@ vec_perm(vector signed char a, vector signed char b, vector unsigned char c);
static vector unsigned char __ATTRS_o_ai
vec_perm(vector unsigned char a, vector unsigned char b, vector unsigned char c);
+static vector bool char __ATTRS_o_ai
+vec_perm(vector bool char a, vector bool char b, vector unsigned char c);
+
static vector short __ATTRS_o_ai
vec_perm(vector short a, vector short b, vector unsigned char c);
static vector unsigned short __ATTRS_o_ai
vec_perm(vector unsigned short a, vector unsigned short b, vector unsigned char c);
+static vector bool short __ATTRS_o_ai
+vec_perm(vector bool short a, vector bool short b, vector unsigned char c);
+
+static vector pixel __ATTRS_o_ai
+vec_perm(vector pixel a, vector pixel b, vector unsigned char c);
+
static vector int __ATTRS_o_ai
vec_perm(vector int a, vector int b, vector unsigned char c);
static vector unsigned int __ATTRS_o_ai
vec_perm(vector unsigned int a, vector unsigned int b, vector unsigned char c);
+static vector bool int __ATTRS_o_ai
+vec_perm(vector bool int a, vector bool int b, vector unsigned char c);
+
static vector float __ATTRS_o_ai
vec_perm(vector float a, vector float b, vector unsigned char c);
@@ -123,36 +135,108 @@ vec_add(vector signed char a, vector signed char b)
return a + b;
}
+static vector signed char __ATTRS_o_ai
+vec_add(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a + b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_add(vector signed char a, vector bool char b)
+{
+ return a + (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_add(vector unsigned char a, vector unsigned char b)
{
return a + b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_add(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a + b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_add(vector unsigned char a, vector bool char b)
+{
+ return a + (vector unsigned char)b;
+}
+
static vector short __ATTRS_o_ai
vec_add(vector short a, vector short b)
{
return a + b;
}
+static vector short __ATTRS_o_ai
+vec_add(vector bool short a, vector short b)
+{
+ return (vector short)a + b;
+}
+
+static vector short __ATTRS_o_ai
+vec_add(vector short a, vector bool short b)
+{
+ return a + (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_add(vector unsigned short a, vector unsigned short b)
{
return a + b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_add(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a + b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_add(vector unsigned short a, vector bool short b)
+{
+ return a + (vector unsigned short)b;
+}
+
static vector int __ATTRS_o_ai
vec_add(vector int a, vector int b)
{
return a + b;
}
+static vector int __ATTRS_o_ai
+vec_add(vector bool int a, vector int b)
+{
+ return (vector int)a + b;
+}
+
+static vector int __ATTRS_o_ai
+vec_add(vector int a, vector bool int b)
+{
+ return a + (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_add(vector unsigned int a, vector unsigned int b)
{
return a + b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_add(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a + b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_add(vector unsigned int a, vector bool int b)
+{
+ return a + (vector unsigned int)b;
+}
+
static vector float __ATTRS_o_ai
vec_add(vector float a, vector float b)
{
@@ -169,12 +253,36 @@ vec_vaddubm(vector signed char a, vector signed char b)
return a + b;
}
+static vector signed char __ATTRS_o_ai
+vec_vaddubm(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a + b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vaddubm(vector signed char a, vector bool char b)
+{
+ return a + (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vaddubm(vector unsigned char a, vector unsigned char b)
{
return a + b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubm(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a + b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubm(vector unsigned char a, vector bool char b)
+{
+ return a + (vector unsigned char)b;
+}
+
/* vec_vadduhm */
#define __builtin_altivec_vadduhm vec_vadduhm
@@ -185,12 +293,36 @@ vec_vadduhm(vector short a, vector short b)
return a + b;
}
+static vector short __ATTRS_o_ai
+vec_vadduhm(vector bool short a, vector short b)
+{
+ return (vector short)a + b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vadduhm(vector short a, vector bool short b)
+{
+ return a + (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vadduhm(vector unsigned short a, vector unsigned short b)
{
return a + b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhm(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a + b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhm(vector unsigned short a, vector bool short b)
+{
+ return a + (vector unsigned short)b;
+}
+
/* vec_vadduwm */
#define __builtin_altivec_vadduwm vec_vadduwm
@@ -201,12 +333,36 @@ vec_vadduwm(vector int a, vector int b)
return a + b;
}
+static vector int __ATTRS_o_ai
+vec_vadduwm(vector bool int a, vector int b)
+{
+ return (vector int)a + b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vadduwm(vector int a, vector bool int b)
+{
+ return a + (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vadduwm(vector unsigned int a, vector unsigned int b)
{
return a + b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_vadduwm(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a + b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduwm(vector unsigned int a, vector bool int b)
+{
+ return a + (vector unsigned int)b;
+}
+
/* vec_vaddfp */
#define __builtin_altivec_vaddfp vec_vaddfp
@@ -241,84 +397,228 @@ vec_adds(vector signed char a, vector signed char b)
return __builtin_altivec_vaddsbs(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_adds(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vaddsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_adds(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vaddsbs(a, (vector signed char)b);
+}
+
static vector unsigned char __ATTRS_o_ai
vec_adds(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vaddubs(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_adds(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vaddubs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_adds(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vaddubs(a, (vector unsigned char)b);
+}
+
static vector short __ATTRS_o_ai
vec_adds(vector short a, vector short b)
{
return __builtin_altivec_vaddshs(a, b);
}
+static vector short __ATTRS_o_ai
+vec_adds(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vaddshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_adds(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vaddshs(a, (vector short)b);
+}
+
static vector unsigned short __ATTRS_o_ai
vec_adds(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vadduhs(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_adds(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vadduhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_adds(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vadduhs(a, (vector unsigned short)b);
+}
+
static vector int __ATTRS_o_ai
vec_adds(vector int a, vector int b)
{
return __builtin_altivec_vaddsws(a, b);
}
+static vector int __ATTRS_o_ai
+vec_adds(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vaddsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_adds(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vaddsws(a, (vector int)b);
+}
+
static vector unsigned int __ATTRS_o_ai
vec_adds(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vadduws(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_adds(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vadduws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_adds(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vadduws(a, (vector unsigned int)b);
+}
+
/* vec_vaddsbs */
-static vector signed char __attribute__((__always_inline__))
+static vector signed char __ATTRS_o_ai
vec_vaddsbs(vector signed char a, vector signed char b)
{
return __builtin_altivec_vaddsbs(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_vaddsbs(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vaddsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vaddsbs(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vaddsbs(a, (vector signed char)b);
+}
+
/* vec_vaddubs */
-static vector unsigned char __attribute__((__always_inline__))
+static vector unsigned char __ATTRS_o_ai
vec_vaddubs(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vaddubs(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubs(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vaddubs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vaddubs(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vaddubs(a, (vector unsigned char)b);
+}
+
/* vec_vaddshs */
-static vector short __attribute__((__always_inline__))
+static vector short __ATTRS_o_ai
vec_vaddshs(vector short a, vector short b)
{
return __builtin_altivec_vaddshs(a, b);
}
+static vector short __ATTRS_o_ai
+vec_vaddshs(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vaddshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vaddshs(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vaddshs(a, (vector short)b);
+}
+
/* vec_vadduhs */
-static vector unsigned short __attribute__((__always_inline__))
+static vector unsigned short __ATTRS_o_ai
vec_vadduhs(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vadduhs(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhs(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vadduhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vadduhs(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vadduhs(a, (vector unsigned short)b);
+}
+
/* vec_vaddsws */
-static vector int __attribute__((__always_inline__))
+static vector int __ATTRS_o_ai
vec_vaddsws(vector int a, vector int b)
{
return __builtin_altivec_vaddsws(a, b);
}
+static vector int __ATTRS_o_ai
+vec_vaddsws(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vaddsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vaddsws(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vaddsws(a, (vector int)b);
+}
+
/* vec_vadduws */
-static vector unsigned int __attribute__((__always_inline__))
+static vector unsigned int __ATTRS_o_ai
vec_vadduws(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vadduws(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_vadduws(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vadduws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vadduws(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vadduws(a, (vector unsigned int)b);
+}
+
/* vec_and */
#define __builtin_altivec_vand vec_and
@@ -329,36 +629,126 @@ vec_and(vector signed char a, vector signed char b)
return a & b;
}
+static vector signed char __ATTRS_o_ai
+vec_and(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_and(vector signed char a, vector bool char b)
+{
+ return a & (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_and(vector unsigned char a, vector unsigned char b)
{
return a & b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_and(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_and(vector unsigned char a, vector bool char b)
+{
+ return a & (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_and(vector bool char a, vector bool char b)
+{
+ return a & b;
+}
+
static vector short __ATTRS_o_ai
vec_and(vector short a, vector short b)
{
return a & b;
}
+static vector short __ATTRS_o_ai
+vec_and(vector bool short a, vector short b)
+{
+ return (vector short)a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_and(vector short a, vector bool short b)
+{
+ return a & (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_and(vector unsigned short a, vector unsigned short b)
{
return a & b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_and(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_and(vector unsigned short a, vector bool short b)
+{
+ return a & (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_and(vector bool short a, vector bool short b)
+{
+ return a & b;
+}
+
static vector int __ATTRS_o_ai
vec_and(vector int a, vector int b)
{
return a & b;
}
+static vector int __ATTRS_o_ai
+vec_and(vector bool int a, vector int b)
+{
+ return (vector int)a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_and(vector int a, vector bool int b)
+{
+ return a & (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_and(vector unsigned int a, vector unsigned int b)
{
return a & b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_and(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_and(vector unsigned int a, vector bool int b)
+{
+ return a & (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_and(vector bool int a, vector bool int b)
+{
+ return a & b;
+}
+
static vector float __ATTRS_o_ai
vec_and(vector float a, vector float b)
{
@@ -366,6 +756,20 @@ vec_and(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_and(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_and(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_vand */
static vector signed char __ATTRS_o_ai
@@ -374,36 +778,126 @@ vec_vand(vector signed char a, vector signed char b)
return a & b;
}
+static vector signed char __ATTRS_o_ai
+vec_vand(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vand(vector signed char a, vector bool char b)
+{
+ return a & (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vand(vector unsigned char a, vector unsigned char b)
{
return a & b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_vand(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vand(vector unsigned char a, vector bool char b)
+{
+ return a & (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vand(vector bool char a, vector bool char b)
+{
+ return a & b;
+}
+
static vector short __ATTRS_o_ai
vec_vand(vector short a, vector short b)
{
return a & b;
}
+static vector short __ATTRS_o_ai
+vec_vand(vector bool short a, vector short b)
+{
+ return (vector short)a & b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vand(vector short a, vector bool short b)
+{
+ return a & (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vand(vector unsigned short a, vector unsigned short b)
{
return a & b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_vand(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vand(vector unsigned short a, vector bool short b)
+{
+ return a & (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vand(vector bool short a, vector bool short b)
+{
+ return a & b;
+}
+
static vector int __ATTRS_o_ai
vec_vand(vector int a, vector int b)
{
return a & b;
}
+static vector int __ATTRS_o_ai
+vec_vand(vector bool int a, vector int b)
+{
+ return (vector int)a & b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vand(vector int a, vector bool int b)
+{
+ return a & (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vand(vector unsigned int a, vector unsigned int b)
{
return a & b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_vand(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vand(vector unsigned int a, vector bool int b)
+{
+ return a & (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vand(vector bool int a, vector bool int b)
+{
+ return a & b;
+}
+
static vector float __ATTRS_o_ai
vec_vand(vector float a, vector float b)
{
@@ -411,6 +905,20 @@ vec_vand(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_vand(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vand(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & (vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_andc */
#define __builtin_altivec_vandc vec_andc
@@ -421,36 +929,126 @@ vec_andc(vector signed char a, vector signed char b)
return a & ~b;
}
+static vector signed char __ATTRS_o_ai
+vec_andc(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & ~b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_andc(vector signed char a, vector bool char b)
+{
+ return a & ~(vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_andc(vector unsigned char a, vector unsigned char b)
{
return a & ~b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_andc(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & ~b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_andc(vector unsigned char a, vector bool char b)
+{
+ return a & ~(vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_andc(vector bool char a, vector bool char b)
+{
+ return a & ~b;
+}
+
static vector short __ATTRS_o_ai
vec_andc(vector short a, vector short b)
{
return a & ~b;
}
+static vector short __ATTRS_o_ai
+vec_andc(vector bool short a, vector short b)
+{
+ return (vector short)a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_andc(vector short a, vector bool short b)
+{
+ return a & ~(vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_andc(vector unsigned short a, vector unsigned short b)
{
return a & ~b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_andc(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & ~b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_andc(vector unsigned short a, vector bool short b)
+{
+ return a & ~(vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_andc(vector bool short a, vector bool short b)
+{
+ return a & ~b;
+}
+
static vector int __ATTRS_o_ai
vec_andc(vector int a, vector int b)
{
return a & ~b;
}
+static vector int __ATTRS_o_ai
+vec_andc(vector bool int a, vector int b)
+{
+ return (vector int)a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_andc(vector int a, vector bool int b)
+{
+ return a & ~(vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_andc(vector unsigned int a, vector unsigned int b)
{
return a & ~b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_andc(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & ~b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_andc(vector unsigned int a, vector bool int b)
+{
+ return a & ~(vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_andc(vector bool int a, vector bool int b)
+{
+ return a & ~b;
+}
+
static vector float __ATTRS_o_ai
vec_andc(vector float a, vector float b)
{
@@ -458,6 +1056,20 @@ vec_andc(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_andc(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_andc(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_vandc */
static vector signed char __ATTRS_o_ai
@@ -466,36 +1078,126 @@ vec_vandc(vector signed char a, vector signed char b)
return a & ~b;
}
+static vector signed char __ATTRS_o_ai
+vec_vandc(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a & ~b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vandc(vector signed char a, vector bool char b)
+{
+ return a & ~(vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vandc(vector unsigned char a, vector unsigned char b)
{
return a & ~b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_vandc(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a & ~b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vandc(vector unsigned char a, vector bool char b)
+{
+ return a & ~(vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vandc(vector bool char a, vector bool char b)
+{
+ return a & ~b;
+}
+
static vector short __ATTRS_o_ai
vec_vandc(vector short a, vector short b)
{
return a & ~b;
}
+static vector short __ATTRS_o_ai
+vec_vandc(vector bool short a, vector short b)
+{
+ return (vector short)a & ~b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vandc(vector short a, vector bool short b)
+{
+ return a & ~(vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vandc(vector unsigned short a, vector unsigned short b)
{
return a & ~b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_vandc(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a & ~b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vandc(vector unsigned short a, vector bool short b)
+{
+ return a & ~(vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vandc(vector bool short a, vector bool short b)
+{
+ return a & ~b;
+}
+
static vector int __ATTRS_o_ai
vec_vandc(vector int a, vector int b)
{
return a & ~b;
}
+static vector int __ATTRS_o_ai
+vec_vandc(vector bool int a, vector int b)
+{
+ return (vector int)a & ~b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vandc(vector int a, vector bool int b)
+{
+ return a & ~(vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vandc(vector unsigned int a, vector unsigned int b)
{
return a & ~b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_vandc(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a & ~b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vandc(vector unsigned int a, vector bool int b)
+{
+ return a & ~(vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vandc(vector bool int a, vector bool int b)
+{
+ return a & ~b;
+}
+
static vector float __ATTRS_o_ai
vec_vandc(vector float a, vector float b)
{
@@ -503,6 +1205,20 @@ vec_vandc(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_vandc(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vandc(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a & ~(vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_avg */
static vector signed char __ATTRS_o_ai
@@ -623,214 +1339,218 @@ vec_vcmpbfp(vector float a, vector float b)
/* vec_cmpeq */
-static vector /*bool*/ char __ATTRS_o_ai
+static vector bool char __ATTRS_o_ai
vec_cmpeq(vector signed char a, vector signed char b)
{
- return __builtin_altivec_vcmpequb((vector char)a, (vector char)b);
+ return (vector bool char)
+ __builtin_altivec_vcmpequb((vector char)a, (vector char)b);
}
-static vector /*bool*/ char __ATTRS_o_ai
+static vector bool char __ATTRS_o_ai
vec_cmpeq(vector unsigned char a, vector unsigned char b)
{
- return __builtin_altivec_vcmpequb((vector char)a, (vector char)b);
+ return (vector bool char)
+ __builtin_altivec_vcmpequb((vector char)a, (vector char)b);
}
-static vector /*bool*/ short __ATTRS_o_ai
+static vector bool short __ATTRS_o_ai
vec_cmpeq(vector short a, vector short b)
{
- return __builtin_altivec_vcmpequh(a, b);
+ return (vector bool short)__builtin_altivec_vcmpequh(a, b);
}
-static vector /*bool*/ short __ATTRS_o_ai
+static vector bool short __ATTRS_o_ai
vec_cmpeq(vector unsigned short a, vector unsigned short b)
{
- return __builtin_altivec_vcmpequh((vector short)a, (vector short)b);
+ return (vector bool short)
+ __builtin_altivec_vcmpequh((vector short)a, (vector short)b);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmpeq(vector int a, vector int b)
{
- return __builtin_altivec_vcmpequw(a, b);
+ return (vector bool int)__builtin_altivec_vcmpequw(a, b);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmpeq(vector unsigned int a, vector unsigned int b)
{
- return __builtin_altivec_vcmpequw((vector int)a, (vector int)b);
+ return (vector bool int)
+ __builtin_altivec_vcmpequw((vector int)a, (vector int)b);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmpeq(vector float a, vector float b)
{
- return __builtin_altivec_vcmpeqfp(a, b);
+ return (vector bool int)__builtin_altivec_vcmpeqfp(a, b);
}
/* vec_cmpge */
-static vector /*bool*/ int __attribute__((__always_inline__))
+static vector bool int __attribute__((__always_inline__))
vec_cmpge(vector float a, vector float b)
{
- return __builtin_altivec_vcmpgefp(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgefp(a, b);
}
/* vec_vcmpgefp */
-static vector /*bool*/ int __attribute__((__always_inline__))
+static vector bool int __attribute__((__always_inline__))
vec_vcmpgefp(vector float a, vector float b)
{
- return __builtin_altivec_vcmpgefp(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgefp(a, b);
}
/* vec_cmpgt */
-static vector /*bool*/ char __ATTRS_o_ai
+static vector bool char __ATTRS_o_ai
vec_cmpgt(vector signed char a, vector signed char b)
{
- return __builtin_altivec_vcmpgtsb(a, b);
+ return (vector bool char)__builtin_altivec_vcmpgtsb(a, b);
}
-static vector /*bool*/ char __ATTRS_o_ai
+static vector bool char __ATTRS_o_ai
vec_cmpgt(vector unsigned char a, vector unsigned char b)
{
- return __builtin_altivec_vcmpgtub(a, b);
+ return (vector bool char)__builtin_altivec_vcmpgtub(a, b);
}
-static vector /*bool*/ short __ATTRS_o_ai
+static vector bool short __ATTRS_o_ai
vec_cmpgt(vector short a, vector short b)
{
- return __builtin_altivec_vcmpgtsh(a, b);
+ return (vector bool short)__builtin_altivec_vcmpgtsh(a, b);
}
-static vector /*bool*/ short __ATTRS_o_ai
+static vector bool short __ATTRS_o_ai
vec_cmpgt(vector unsigned short a, vector unsigned short b)
{
- return __builtin_altivec_vcmpgtuh(a, b);
+ return (vector bool short)__builtin_altivec_vcmpgtuh(a, b);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmpgt(vector int a, vector int b)
{
- return __builtin_altivec_vcmpgtsw(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgtsw(a, b);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmpgt(vector unsigned int a, vector unsigned int b)
{
- return __builtin_altivec_vcmpgtuw(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgtuw(a, b);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmpgt(vector float a, vector float b)
{
- return __builtin_altivec_vcmpgtfp(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgtfp(a, b);
}
/* vec_vcmpgtsb */
-static vector /*bool*/ char __attribute__((__always_inline__))
+static vector bool char __attribute__((__always_inline__))
vec_vcmpgtsb(vector signed char a, vector signed char b)
{
- return __builtin_altivec_vcmpgtsb(a, b);
+ return (vector bool char)__builtin_altivec_vcmpgtsb(a, b);
}
/* vec_vcmpgtub */
-static vector /*bool*/ char __attribute__((__always_inline__))
+static vector bool char __attribute__((__always_inline__))
vec_vcmpgtub(vector unsigned char a, vector unsigned char b)
{
- return __builtin_altivec_vcmpgtub(a, b);
+ return (vector bool char)__builtin_altivec_vcmpgtub(a, b);
}
/* vec_vcmpgtsh */
-static vector /*bool*/ short __attribute__((__always_inline__))
+static vector bool short __attribute__((__always_inline__))
vec_vcmpgtsh(vector short a, vector short b)
{
- return __builtin_altivec_vcmpgtsh(a, b);
+ return (vector bool short)__builtin_altivec_vcmpgtsh(a, b);
}
/* vec_vcmpgtuh */
-static vector /*bool*/ short __attribute__((__always_inline__))
+static vector bool short __attribute__((__always_inline__))
vec_vcmpgtuh(vector unsigned short a, vector unsigned short b)
{
- return __builtin_altivec_vcmpgtuh(a, b);
+ return (vector bool short)__builtin_altivec_vcmpgtuh(a, b);
}
/* vec_vcmpgtsw */
-static vector /*bool*/ int __attribute__((__always_inline__))
+static vector bool int __attribute__((__always_inline__))
vec_vcmpgtsw(vector int a, vector int b)
{
- return __builtin_altivec_vcmpgtsw(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgtsw(a, b);
}
/* vec_vcmpgtuw */
-static vector /*bool*/ int __attribute__((__always_inline__))
+static vector bool int __attribute__((__always_inline__))
vec_vcmpgtuw(vector unsigned int a, vector unsigned int b)
{
- return __builtin_altivec_vcmpgtuw(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgtuw(a, b);
}
/* vec_vcmpgtfp */
-static vector /*bool*/ int __attribute__((__always_inline__))
+static vector bool int __attribute__((__always_inline__))
vec_vcmpgtfp(vector float a, vector float b)
{
- return __builtin_altivec_vcmpgtfp(a, b);
+ return (vector bool int)__builtin_altivec_vcmpgtfp(a, b);
}
/* vec_cmple */
-static vector /*bool*/ int __attribute__((__always_inline__))
+static vector bool int __attribute__((__always_inline__))
vec_cmple(vector float a, vector float b)
{
- return __builtin_altivec_vcmpgefp(b, a);
+ return (vector bool int)__builtin_altivec_vcmpgefp(b, a);
}
/* vec_cmplt */
-static vector /*bool*/ char __ATTRS_o_ai
+static vector bool char __ATTRS_o_ai
vec_cmplt(vector signed char a, vector signed char b)
{
- return __builtin_altivec_vcmpgtsb(b, a);
+ return (vector bool char)__builtin_altivec_vcmpgtsb(b, a);
}
-static vector /*bool*/ char __ATTRS_o_ai
+static vector bool char __ATTRS_o_ai
vec_cmplt(vector unsigned char a, vector unsigned char b)
{
- return __builtin_altivec_vcmpgtub(b, a);
+ return (vector bool char)__builtin_altivec_vcmpgtub(b, a);
}
-static vector /*bool*/ short __ATTRS_o_ai
+static vector bool short __ATTRS_o_ai
vec_cmplt(vector short a, vector short b)
{
- return __builtin_altivec_vcmpgtsh(b, a);
+ return (vector bool short)__builtin_altivec_vcmpgtsh(b, a);
}
-static vector /*bool*/ short __ATTRS_o_ai
+static vector bool short __ATTRS_o_ai
vec_cmplt(vector unsigned short a, vector unsigned short b)
{
- return __builtin_altivec_vcmpgtuh(b, a);
+ return (vector bool short)__builtin_altivec_vcmpgtuh(b, a);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmplt(vector int a, vector int b)
{
- return __builtin_altivec_vcmpgtsw(b, a);
+ return (vector bool int)__builtin_altivec_vcmpgtsw(b, a);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmplt(vector unsigned int a, vector unsigned int b)
{
- return __builtin_altivec_vcmpgtuw(b, a);
+ return (vector bool int)__builtin_altivec_vcmpgtuw(b, a);
}
-static vector /*bool*/ int __ATTRS_o_ai
+static vector bool int __ATTRS_o_ai
vec_cmplt(vector float a, vector float b)
{
- return __builtin_altivec_vcmpgtfp(b, a);
+ return (vector bool int)__builtin_altivec_vcmpgtfp(b, a);
}
/* vec_ctf */
@@ -1001,6 +1721,12 @@ vec_ld(int a, unsigned char *b)
return (vector unsigned char)__builtin_altivec_lvx(a, b);
}
+static vector bool char __ATTRS_o_ai
+vec_ld(int a, vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvx(a, b);
+}
+
static vector short __ATTRS_o_ai
vec_ld(int a, vector short *b)
{
@@ -1025,6 +1751,18 @@ vec_ld(int a, unsigned short *b)
return (vector unsigned short)__builtin_altivec_lvx(a, b);
}
+static vector bool short __ATTRS_o_ai
+vec_ld(int a, vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvx(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_ld(int a, vector pixel *b)
+{
+ return (vector pixel)__builtin_altivec_lvx(a, b);
+}
+
static vector int __ATTRS_o_ai
vec_ld(int a, vector int *b)
{
@@ -1049,6 +1787,12 @@ vec_ld(int a, unsigned int *b)
return (vector unsigned int)__builtin_altivec_lvx(a, b);
}
+static vector bool int __ATTRS_o_ai
+vec_ld(int a, vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvx(a, b);
+}
+
static vector float __ATTRS_o_ai
vec_ld(int a, vector float *b)
{
@@ -1087,6 +1831,12 @@ vec_lvx(int a, unsigned char *b)
return (vector unsigned char)__builtin_altivec_lvx(a, b);
}
+static vector bool char __ATTRS_o_ai
+vec_lvx(int a, vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvx(a, b);
+}
+
static vector short __ATTRS_o_ai
vec_lvx(int a, vector short *b)
{
@@ -1111,6 +1861,18 @@ vec_lvx(int a, unsigned short *b)
return (vector unsigned short)__builtin_altivec_lvx(a, b);
}
+static vector bool short __ATTRS_o_ai
+vec_lvx(int a, vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvx(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvx(int a, vector pixel *b)
+{
+ return (vector pixel)__builtin_altivec_lvx(a, b);
+}
+
static vector int __ATTRS_o_ai
vec_lvx(int a, vector int *b)
{
@@ -1135,6 +1897,12 @@ vec_lvx(int a, unsigned int *b)
return (vector unsigned int)__builtin_altivec_lvx(a, b);
}
+static vector bool int __ATTRS_o_ai
+vec_lvx(int a, vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvx(a, b);
+}
+
static vector float __ATTRS_o_ai
vec_lvx(int a, vector float *b)
{
@@ -1265,6 +2033,12 @@ vec_ldl(int a, unsigned char *b)
return (vector unsigned char)__builtin_altivec_lvxl(a, b);
}
+static vector bool char __ATTRS_o_ai
+vec_ldl(int a, vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvxl(a, b);
+}
+
static vector short __ATTRS_o_ai
vec_ldl(int a, vector short *b)
{
@@ -1289,6 +2063,18 @@ vec_ldl(int a, unsigned short *b)
return (vector unsigned short)__builtin_altivec_lvxl(a, b);
}
+static vector bool short __ATTRS_o_ai
+vec_ldl(int a, vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_ldl(int a, vector pixel *b)
+{
+ return (vector pixel short)__builtin_altivec_lvxl(a, b);
+}
+
static vector int __ATTRS_o_ai
vec_ldl(int a, vector int *b)
{
@@ -1313,6 +2099,12 @@ vec_ldl(int a, unsigned int *b)
return (vector unsigned int)__builtin_altivec_lvxl(a, b);
}
+static vector bool int __ATTRS_o_ai
+vec_ldl(int a, vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvxl(a, b);
+}
+
static vector float __ATTRS_o_ai
vec_ldl(int a, vector float *b)
{
@@ -1351,6 +2143,12 @@ vec_lvxl(int a, unsigned char *b)
return (vector unsigned char)__builtin_altivec_lvxl(a, b);
}
+static vector bool char __ATTRS_o_ai
+vec_lvxl(int a, vector bool char *b)
+{
+ return (vector bool char)__builtin_altivec_lvxl(a, b);
+}
+
static vector short __ATTRS_o_ai
vec_lvxl(int a, vector short *b)
{
@@ -1375,6 +2173,18 @@ vec_lvxl(int a, unsigned short *b)
return (vector unsigned short)__builtin_altivec_lvxl(a, b);
}
+static vector bool short __ATTRS_o_ai
+vec_lvxl(int a, vector bool short *b)
+{
+ return (vector bool short)__builtin_altivec_lvxl(a, b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_lvxl(int a, vector pixel *b)
+{
+ return (vector pixel)__builtin_altivec_lvxl(a, b);
+}
+
static vector int __ATTRS_o_ai
vec_lvxl(int a, vector int *b)
{
@@ -1399,6 +2209,12 @@ vec_lvxl(int a, unsigned int *b)
return (vector unsigned int)__builtin_altivec_lvxl(a, b);
}
+static vector bool int __ATTRS_o_ai
+vec_lvxl(int a, vector bool int *b)
+{
+ return (vector bool int)__builtin_altivec_lvxl(a, b);
+}
+
static vector float __ATTRS_o_ai
vec_lvxl(int a, vector float *b)
{
@@ -1549,41 +2365,113 @@ vec_vmhaddshs(vector signed short a, vector signed short b, vector signed short
/* vec_max */
static vector signed char __ATTRS_o_ai
-vec_max(vector signed char a, vector signed char b)
+vec_max(vector signed char a, vector signed char b)
{
return __builtin_altivec_vmaxsb(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_max(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vmaxsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_max(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxsb(a, (vector signed char)b);
+}
+
static vector unsigned char __ATTRS_o_ai
-vec_max(vector unsigned char a, vector unsigned char b)
+vec_max(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vmaxub(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_max(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmaxub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_max(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxub(a, (vector unsigned char)b);
+}
+
static vector short __ATTRS_o_ai
vec_max(vector short a, vector short b)
{
return __builtin_altivec_vmaxsh(a, b);
}
+static vector short __ATTRS_o_ai
+vec_max(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vmaxsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_max(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxsh(a, (vector short)b);
+}
+
static vector unsigned short __ATTRS_o_ai
vec_max(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vmaxuh(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_max(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmaxuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_max(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxuh(a, (vector unsigned short)b);
+}
+
static vector int __ATTRS_o_ai
vec_max(vector int a, vector int b)
{
return __builtin_altivec_vmaxsw(a, b);
}
+static vector int __ATTRS_o_ai
+vec_max(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vmaxsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_max(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxsw(a, (vector int)b);
+}
+
static vector unsigned int __ATTRS_o_ai
vec_max(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vmaxuw(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_max(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vmaxuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_max(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxuw(a, (vector unsigned int)b);
+}
+
static vector float __ATTRS_o_ai
vec_max(vector float a, vector float b)
{
@@ -1592,52 +2480,124 @@ vec_max(vector float a, vector float b)
/* vec_vmaxsb */
-static vector signed char __attribute__((__always_inline__))
-vec_vmaxsb(vector signed char a, vector signed char b)
+static vector signed char __ATTRS_o_ai
+vec_vmaxsb(vector signed char a, vector signed char b)
{
return __builtin_altivec_vmaxsb(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_vmaxsb(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vmaxsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vmaxsb(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxsb(a, (vector signed char)b);
+}
+
/* vec_vmaxub */
-static vector unsigned char __attribute__((__always_inline__))
-vec_vmaxub(vector unsigned char a, vector unsigned char b)
+static vector unsigned char __ATTRS_o_ai
+vec_vmaxub(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vmaxub(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_vmaxub(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vmaxub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vmaxub(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vmaxub(a, (vector unsigned char)b);
+}
+
/* vec_vmaxsh */
-static vector short __attribute__((__always_inline__))
+static vector short __ATTRS_o_ai
vec_vmaxsh(vector short a, vector short b)
{
return __builtin_altivec_vmaxsh(a, b);
}
+static vector short __ATTRS_o_ai
+vec_vmaxsh(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vmaxsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vmaxsh(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxsh(a, (vector short)b);
+}
+
/* vec_vmaxuh */
-static vector unsigned short __attribute__((__always_inline__))
+static vector unsigned short __ATTRS_o_ai
vec_vmaxuh(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vmaxuh(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_vmaxuh(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vmaxuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vmaxuh(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vmaxuh(a, (vector unsigned short)b);
+}
+
/* vec_vmaxsw */
-static vector int __attribute__((__always_inline__))
+static vector int __ATTRS_o_ai
vec_vmaxsw(vector int a, vector int b)
{
return __builtin_altivec_vmaxsw(a, b);
}
+static vector int __ATTRS_o_ai
+vec_vmaxsw(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vmaxsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vmaxsw(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxsw(a, (vector int)b);
+}
+
/* vec_vmaxuw */
-static vector unsigned int __attribute__((__always_inline__))
+static vector unsigned int __ATTRS_o_ai
vec_vmaxuw(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vmaxuw(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_vmaxuw(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vmaxuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vmaxuw(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vmaxuw(a, (vector unsigned int)b);
+}
+
/* vec_vmaxfp */
static vector float __attribute__((__always_inline__))
@@ -1664,6 +2624,14 @@ vec_mergeh(vector unsigned char a, vector unsigned char b)
0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
}
+static vector bool char __ATTRS_o_ai
+vec_mergeh(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
static vector short __ATTRS_o_ai
vec_mergeh(vector short a, vector short b)
{
@@ -1680,6 +2648,22 @@ vec_mergeh(vector unsigned short a, vector unsigned short b)
0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
}
+static vector bool short __ATTRS_o_ai
+vec_mergeh(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_mergeh(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
static vector int __ATTRS_o_ai
vec_mergeh(vector int a, vector int b)
{
@@ -1696,6 +2680,14 @@ vec_mergeh(vector unsigned int a, vector unsigned int b)
0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
}
+static vector bool int __ATTRS_o_ai
+vec_mergeh(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
static vector float __ATTRS_o_ai
vec_mergeh(vector float a, vector float b)
{
@@ -1724,6 +2716,14 @@ vec_vmrghb(vector unsigned char a, vector unsigned char b)
0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
}
+static vector bool char __ATTRS_o_ai
+vec_vmrghb(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x10, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13,
+ 0x04, 0x14, 0x05, 0x15, 0x06, 0x16, 0x07, 0x17));
+}
+
/* vec_vmrghh */
#define __builtin_altivec_vmrghh vec_vmrghh
@@ -1744,6 +2744,22 @@ vec_vmrghh(vector unsigned short a, vector unsigned short b)
0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
}
+static vector bool short __ATTRS_o_ai
+vec_vmrghh(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vmrghh(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x10, 0x11, 0x02, 0x03, 0x12, 0x13,
+ 0x04, 0x05, 0x14, 0x15, 0x06, 0x07, 0x16, 0x17));
+}
+
/* vec_vmrghw */
#define __builtin_altivec_vmrghw vec_vmrghw
@@ -1764,6 +2780,14 @@ vec_vmrghw(vector unsigned int a, vector unsigned int b)
0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
}
+static vector bool int __ATTRS_o_ai
+vec_vmrghw(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13,
+ 0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17));
+}
+
static vector float __ATTRS_o_ai
vec_vmrghw(vector float a, vector float b)
{
@@ -1790,6 +2814,14 @@ vec_mergel(vector unsigned char a, vector unsigned char b)
0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
}
+static vector bool char __ATTRS_o_ai
+vec_mergel(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
static vector short __ATTRS_o_ai
vec_mergel(vector short a, vector short b)
{
@@ -1806,6 +2838,22 @@ vec_mergel(vector unsigned short a, vector unsigned short b)
0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
}
+static vector bool short __ATTRS_o_ai
+vec_mergel(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_mergel(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
static vector int __ATTRS_o_ai
vec_mergel(vector int a, vector int b)
{
@@ -1822,6 +2870,14 @@ vec_mergel(vector unsigned int a, vector unsigned int b)
0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
}
+static vector bool int __ATTRS_o_ai
+vec_mergel(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
static vector float __ATTRS_o_ai
vec_mergel(vector float a, vector float b)
{
@@ -1850,6 +2906,14 @@ vec_vmrglb(vector unsigned char a, vector unsigned char b)
0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
}
+static vector bool char __ATTRS_o_ai
+vec_vmrglb(vector bool char a, vector bool char b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x18, 0x09, 0x19, 0x0A, 0x1A, 0x0B, 0x1B,
+ 0x0C, 0x1C, 0x0D, 0x1D, 0x0E, 0x1E, 0x0F, 0x1F));
+}
+
/* vec_vmrglh */
#define __builtin_altivec_vmrglh vec_vmrglh
@@ -1870,6 +2934,22 @@ vec_vmrglh(vector unsigned short a, vector unsigned short b)
0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
}
+static vector bool short __ATTRS_o_ai
+vec_vmrglh(vector bool short a, vector bool short b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vmrglh(vector pixel a, vector pixel b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x18, 0x19, 0x0A, 0x0B, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x1C, 0x1D, 0x0E, 0x0F, 0x1E, 0x1F));
+}
+
/* vec_vmrglw */
#define __builtin_altivec_vmrglw vec_vmrglw
@@ -1890,6 +2970,14 @@ vec_vmrglw(vector unsigned int a, vector unsigned int b)
0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
}
+static vector bool int __ATTRS_o_ai
+vec_vmrglw(vector bool int a, vector bool int b)
+{
+ return vec_perm(a, b, (vector unsigned char)
+ (0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F));
+}
+
static vector float __ATTRS_o_ai
vec_vmrglw(vector float a, vector float b)
{
@@ -1909,41 +2997,113 @@ vec_mfvscr(void)
/* vec_min */
static vector signed char __ATTRS_o_ai
-vec_min(vector signed char a, vector signed char b)
+vec_min(vector signed char a, vector signed char b)
{
return __builtin_altivec_vminsb(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_min(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vminsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_min(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vminsb(a, (vector signed char)b);
+}
+
static vector unsigned char __ATTRS_o_ai
-vec_min(vector unsigned char a, vector unsigned char b)
+vec_min(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vminub(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_min(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vminub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_min(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vminub(a, (vector unsigned char)b);
+}
+
static vector short __ATTRS_o_ai
vec_min(vector short a, vector short b)
{
return __builtin_altivec_vminsh(a, b);
}
+static vector short __ATTRS_o_ai
+vec_min(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vminsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_min(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vminsh(a, (vector short)b);
+}
+
static vector unsigned short __ATTRS_o_ai
vec_min(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vminuh(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_min(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vminuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_min(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vminuh(a, (vector unsigned short)b);
+}
+
static vector int __ATTRS_o_ai
vec_min(vector int a, vector int b)
{
return __builtin_altivec_vminsw(a, b);
}
+static vector int __ATTRS_o_ai
+vec_min(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vminsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_min(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vminsw(a, (vector int)b);
+}
+
static vector unsigned int __ATTRS_o_ai
vec_min(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vminuw(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_min(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vminuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_min(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vminuw(a, (vector unsigned int)b);
+}
+
static vector float __ATTRS_o_ai
vec_min(vector float a, vector float b)
{
@@ -1952,52 +3112,124 @@ vec_min(vector float a, vector float b)
/* vec_vminsb */
-static vector signed char __attribute__((__always_inline__))
-vec_vminsb(vector signed char a, vector signed char b)
+static vector signed char __ATTRS_o_ai
+vec_vminsb(vector signed char a, vector signed char b)
{
return __builtin_altivec_vminsb(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_vminsb(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vminsb((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vminsb(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vminsb(a, (vector signed char)b);
+}
+
/* vec_vminub */
-static vector unsigned char __attribute__((__always_inline__))
-vec_vminub(vector unsigned char a, vector unsigned char b)
+static vector unsigned char __ATTRS_o_ai
+vec_vminub(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vminub(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_vminub(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vminub((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vminub(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vminub(a, (vector unsigned char)b);
+}
+
/* vec_vminsh */
-static vector short __attribute__((__always_inline__))
+static vector short __ATTRS_o_ai
vec_vminsh(vector short a, vector short b)
{
return __builtin_altivec_vminsh(a, b);
}
+static vector short __ATTRS_o_ai
+vec_vminsh(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vminsh((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vminsh(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vminsh(a, (vector short)b);
+}
+
/* vec_vminuh */
-static vector unsigned short __attribute__((__always_inline__))
+static vector unsigned short __ATTRS_o_ai
vec_vminuh(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vminuh(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_vminuh(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vminuh((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vminuh(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vminuh(a, (vector unsigned short)b);
+}
+
/* vec_vminsw */
-static vector int __attribute__((__always_inline__))
+static vector int __ATTRS_o_ai
vec_vminsw(vector int a, vector int b)
{
return __builtin_altivec_vminsw(a, b);
}
+static vector int __ATTRS_o_ai
+vec_vminsw(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vminsw((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vminsw(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vminsw(a, (vector int)b);
+}
+
/* vec_vminuw */
-static vector unsigned int __attribute__((__always_inline__))
+static vector unsigned int __ATTRS_o_ai
vec_vminuw(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vminuw(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_vminuw(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vminuw((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vminuw(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vminuw(a, (vector unsigned int)b);
+}
+
/* vec_vminfp */
static vector float __attribute__((__always_inline__))
@@ -2179,6 +3411,12 @@ vec_mtvscr(vector unsigned char a)
}
static void __ATTRS_o_ai
+vec_mtvscr(vector bool char a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
vec_mtvscr(vector short a)
{
__builtin_altivec_mtvscr((vector int)a);
@@ -2191,6 +3429,18 @@ vec_mtvscr(vector unsigned short a)
}
static void __ATTRS_o_ai
+vec_mtvscr(vector bool short a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
+vec_mtvscr(vector pixel a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
vec_mtvscr(vector int a)
{
__builtin_altivec_mtvscr((vector int)a);
@@ -2203,6 +3453,12 @@ vec_mtvscr(vector unsigned int a)
}
static void __ATTRS_o_ai
+vec_mtvscr(vector bool int a)
+{
+ __builtin_altivec_mtvscr((vector int)a);
+}
+
+static void __ATTRS_o_ai
vec_mtvscr(vector float a)
{
__builtin_altivec_mtvscr((vector int)a);
@@ -2356,6 +3612,12 @@ vec_nor(vector unsigned char a, vector unsigned char b)
return ~(a | b);
}
+static vector bool char __ATTRS_o_ai
+vec_nor(vector bool char a, vector bool char b)
+{
+ return ~(a | b);
+}
+
static vector short __ATTRS_o_ai
vec_nor(vector short a, vector short b)
{
@@ -2368,6 +3630,12 @@ vec_nor(vector unsigned short a, vector unsigned short b)
return ~(a | b);
}
+static vector bool short __ATTRS_o_ai
+vec_nor(vector bool short a, vector bool short b)
+{
+ return ~(a | b);
+}
+
static vector int __ATTRS_o_ai
vec_nor(vector int a, vector int b)
{
@@ -2380,6 +3648,12 @@ vec_nor(vector unsigned int a, vector unsigned int b)
return ~(a | b);
}
+static vector bool int __ATTRS_o_ai
+vec_nor(vector bool int a, vector bool int b)
+{
+ return ~(a | b);
+}
+
static vector float __ATTRS_o_ai
vec_nor(vector float a, vector float b)
{
@@ -2401,6 +3675,12 @@ vec_vnor(vector unsigned char a, vector unsigned char b)
return ~(a | b);
}
+static vector bool char __ATTRS_o_ai
+vec_vnor(vector bool char a, vector bool char b)
+{
+ return ~(a | b);
+}
+
static vector short __ATTRS_o_ai
vec_vnor(vector short a, vector short b)
{
@@ -2413,6 +3693,12 @@ vec_vnor(vector unsigned short a, vector unsigned short b)
return ~(a | b);
}
+static vector bool short __ATTRS_o_ai
+vec_vnor(vector bool short a, vector bool short b)
+{
+ return ~(a | b);
+}
+
static vector int __ATTRS_o_ai
vec_vnor(vector int a, vector int b)
{
@@ -2425,6 +3711,12 @@ vec_vnor(vector unsigned int a, vector unsigned int b)
return ~(a | b);
}
+static vector bool int __ATTRS_o_ai
+vec_vnor(vector bool int a, vector bool int b)
+{
+ return ~(a | b);
+}
+
static vector float __ATTRS_o_ai
vec_vnor(vector float a, vector float b)
{
@@ -2442,36 +3734,126 @@ vec_or(vector signed char a, vector signed char b)
return a | b;
}
+static vector signed char __ATTRS_o_ai
+vec_or(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a | b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_or(vector signed char a, vector bool char b)
+{
+ return a | (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_or(vector unsigned char a, vector unsigned char b)
{
return a | b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_or(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a | b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_or(vector unsigned char a, vector bool char b)
+{
+ return a | (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_or(vector bool char a, vector bool char b)
+{
+ return a | b;
+}
+
static vector short __ATTRS_o_ai
vec_or(vector short a, vector short b)
{
return a | b;
}
+static vector short __ATTRS_o_ai
+vec_or(vector bool short a, vector short b)
+{
+ return (vector short)a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_or(vector short a, vector bool short b)
+{
+ return a | (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_or(vector unsigned short a, vector unsigned short b)
{
return a | b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_or(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a | b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_or(vector unsigned short a, vector bool short b)
+{
+ return a | (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_or(vector bool short a, vector bool short b)
+{
+ return a | b;
+}
+
static vector int __ATTRS_o_ai
vec_or(vector int a, vector int b)
{
return a | b;
}
+static vector int __ATTRS_o_ai
+vec_or(vector bool int a, vector int b)
+{
+ return (vector int)a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_or(vector int a, vector bool int b)
+{
+ return a | (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_or(vector unsigned int a, vector unsigned int b)
{
return a | b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_or(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a | b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_or(vector unsigned int a, vector bool int b)
+{
+ return a | (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_or(vector bool int a, vector bool int b)
+{
+ return a | b;
+}
+
static vector float __ATTRS_o_ai
vec_or(vector float a, vector float b)
{
@@ -2479,6 +3861,20 @@ vec_or(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_or(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_or(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_vor */
static vector signed char __ATTRS_o_ai
@@ -2487,36 +3883,126 @@ vec_vor(vector signed char a, vector signed char b)
return a | b;
}
+static vector signed char __ATTRS_o_ai
+vec_vor(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a | b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vor(vector signed char a, vector bool char b)
+{
+ return a | (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vor(vector unsigned char a, vector unsigned char b)
{
return a | b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_vor(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a | b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vor(vector unsigned char a, vector bool char b)
+{
+ return a | (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vor(vector bool char a, vector bool char b)
+{
+ return a | b;
+}
+
static vector short __ATTRS_o_ai
vec_vor(vector short a, vector short b)
{
return a | b;
}
+static vector short __ATTRS_o_ai
+vec_vor(vector bool short a, vector short b)
+{
+ return (vector short)a | b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vor(vector short a, vector bool short b)
+{
+ return a | (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vor(vector unsigned short a, vector unsigned short b)
{
return a | b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_vor(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a | b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vor(vector unsigned short a, vector bool short b)
+{
+ return a | (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vor(vector bool short a, vector bool short b)
+{
+ return a | b;
+}
+
static vector int __ATTRS_o_ai
vec_vor(vector int a, vector int b)
{
return a | b;
}
+static vector int __ATTRS_o_ai
+vec_vor(vector bool int a, vector int b)
+{
+ return (vector int)a | b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vor(vector int a, vector bool int b)
+{
+ return a | (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vor(vector unsigned int a, vector unsigned int b)
{
return a | b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_vor(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a | b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vor(vector unsigned int a, vector bool int b)
+{
+ return a | (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vor(vector bool int a, vector bool int b)
+{
+ return a | b;
+}
+
static vector float __ATTRS_o_ai
vec_vor(vector float a, vector float b)
{
@@ -2524,6 +4010,20 @@ vec_vor(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_vor(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vor(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a | (vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_pack */
static vector signed char __ATTRS_o_ai
@@ -2542,6 +4042,14 @@ vec_pack(vector unsigned short a, vector unsigned short b)
0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
}
+static vector bool char __ATTRS_o_ai
+vec_pack(vector bool short a, vector bool short b)
+{
+ return (vector bool char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
static vector short __ATTRS_o_ai
vec_pack(vector int a, vector int b)
{
@@ -2558,6 +4066,14 @@ vec_pack(vector unsigned int a, vector unsigned int b)
0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
}
+static vector bool short __ATTRS_o_ai
+vec_pack(vector bool int a, vector bool int b)
+{
+ return (vector bool short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
/* vec_vpkuhum */
#define __builtin_altivec_vpkuhum vec_vpkuhum
@@ -2578,6 +4094,14 @@ vec_vpkuhum(vector unsigned short a, vector unsigned short b)
0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
}
+static vector bool char __ATTRS_o_ai
+vec_vpkuhum(vector bool short a, vector bool short b)
+{
+ return (vector bool char)vec_perm(a, b, (vector unsigned char)
+ (0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
+ 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F));
+}
+
/* vec_vpkuwum */
#define __builtin_altivec_vpkuwum vec_vpkuwum
@@ -2598,6 +4122,14 @@ vec_vpkuwum(vector unsigned int a, vector unsigned int b)
0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
}
+static vector bool short __ATTRS_o_ai
+vec_vpkuwum(vector bool int a, vector bool int b)
+{
+ return (vector bool short)vec_perm(a, b, (vector unsigned char)
+ (0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
+ 0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F));
+}
+
/* vec_packpx */
static vector pixel __attribute__((__always_inline__))
@@ -2740,6 +4272,12 @@ vec_perm(vector unsigned char a, vector unsigned char b, vector unsigned char c)
return (vector unsigned char)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
}
+vector bool char __ATTRS_o_ai
+vec_perm(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (vector bool char)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
vector short __ATTRS_o_ai
vec_perm(vector short a, vector short b, vector unsigned char c)
{
@@ -2752,6 +4290,18 @@ vec_perm(vector unsigned short a, vector unsigned short b, vector unsigned char
return (vector unsigned short)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
}
+vector bool short __ATTRS_o_ai
+vec_perm(vector bool short a, vector bool short b, vector unsigned char c)
+{
+ return (vector bool short)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector pixel __ATTRS_o_ai
+vec_perm(vector pixel a, vector pixel b, vector unsigned char c)
+{
+ return (vector pixel)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
vector int __ATTRS_o_ai
vec_perm(vector int a, vector int b, vector unsigned char c)
{
@@ -2764,6 +4314,12 @@ vec_perm(vector unsigned int a, vector unsigned int b, vector unsigned char c)
return (vector unsigned int)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
}
+vector bool int __ATTRS_o_ai
+vec_perm(vector bool int a, vector bool int b, vector unsigned char c)
+{
+ return (vector bool int)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
vector float __ATTRS_o_ai
vec_perm(vector float a, vector float b, vector unsigned char c)
{
@@ -2784,6 +4340,12 @@ vec_vperm(vector unsigned char a, vector unsigned char b, vector unsigned char c
return (vector unsigned char)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
}
+vector bool char __ATTRS_o_ai
+vec_vperm(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (vector bool char)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
vector short __ATTRS_o_ai
vec_vperm(vector short a, vector short b, vector unsigned char c)
{
@@ -2796,6 +4358,18 @@ vec_vperm(vector unsigned short a, vector unsigned short b, vector unsigned char
return (vector unsigned short)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
}
+vector bool short __ATTRS_o_ai
+vec_vperm(vector bool short a, vector bool short b, vector unsigned char c)
+{
+ return (vector bool short)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
+vector pixel __ATTRS_o_ai
+vec_vperm(vector pixel a, vector pixel b, vector unsigned char c)
+{
+ return (vector pixel)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
vector int __ATTRS_o_ai
vec_vperm(vector int a, vector int b, vector unsigned char c)
{
@@ -2808,6 +4382,12 @@ vec_vperm(vector unsigned int a, vector unsigned int b, vector unsigned char c)
return (vector unsigned int)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
}
+vector bool int __ATTRS_o_ai
+vec_vperm(vector bool int a, vector bool int b, vector unsigned char c)
+{
+ return (vector bool int)__builtin_altivec_vperm_4si((vector int)a, (vector int)b, c);
+}
+
vector float __ATTRS_o_ai
vec_vperm(vector float a, vector float b, vector unsigned char c)
{
@@ -2952,36 +4532,108 @@ vec_sel(vector signed char a, vector signed char b, vector unsigned char c)
return (a & ~(vector signed char)c) | (b & (vector signed char)c);
}
+static vector signed char __ATTRS_o_ai
+vec_sel(vector signed char a, vector signed char b, vector bool char c)
+{
+ return (a & ~(vector signed char)c) | (b & (vector signed char)c);
+}
+
static vector unsigned char __ATTRS_o_ai
vec_sel(vector unsigned char a, vector unsigned char b, vector unsigned char c)
{
return (a & ~c) | (b & c);
}
+static vector unsigned char __ATTRS_o_ai
+vec_sel(vector unsigned char a, vector unsigned char b, vector bool char c)
+{
+ return (a & ~(vector unsigned char)c) | (b & (vector unsigned char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sel(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (a & ~(vector bool char)c) | (b & (vector bool char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sel(vector bool char a, vector bool char b, vector bool char c)
+{
+ return (a & ~c) | (b & c);
+}
+
static vector short __ATTRS_o_ai
vec_sel(vector short a, vector short b, vector unsigned short c)
{
return (a & ~(vector short)c) | (b & (vector short)c);
}
+static vector short __ATTRS_o_ai
+vec_sel(vector short a, vector short b, vector bool short c)
+{
+ return (a & ~(vector short)c) | (b & (vector short)c);
+}
+
static vector unsigned short __ATTRS_o_ai
vec_sel(vector unsigned short a, vector unsigned short b, vector unsigned short c)
{
return (a & ~c) | (b & c);
}
+static vector unsigned short __ATTRS_o_ai
+vec_sel(vector unsigned short a, vector unsigned short b, vector bool short c)
+{
+ return (a & ~(vector unsigned short)c) | (b & (vector unsigned short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sel(vector bool short a, vector bool short b, vector unsigned short c)
+{
+ return (a & ~(vector bool short)c) | (b & (vector bool short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sel(vector bool short a, vector bool short b, vector bool short c)
+{
+ return (a & ~c) | (b & c);
+}
+
static vector int __ATTRS_o_ai
vec_sel(vector int a, vector int b, vector unsigned int c)
{
return (a & ~(vector int)c) | (b & (vector int)c);
}
+static vector int __ATTRS_o_ai
+vec_sel(vector int a, vector int b, vector bool int c)
+{
+ return (a & ~(vector int)c) | (b & (vector int)c);
+}
+
static vector unsigned int __ATTRS_o_ai
vec_sel(vector unsigned int a, vector unsigned int b, vector unsigned int c)
{
return (a & ~c) | (b & c);
}
+static vector unsigned int __ATTRS_o_ai
+vec_sel(vector unsigned int a, vector unsigned int b, vector bool int c)
+{
+ return (a & ~(vector unsigned int)c) | (b & (vector unsigned int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sel(vector bool int a, vector bool int b, vector unsigned int c)
+{
+ return (a & ~(vector bool int)c) | (b & (vector bool int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sel(vector bool int a, vector bool int b, vector bool int c)
+{
+ return (a & ~c) | (b & c);
+}
+
static vector float __ATTRS_o_ai
vec_sel(vector float a, vector float b, vector unsigned int c)
{
@@ -2989,6 +4641,13 @@ vec_sel(vector float a, vector float b, vector unsigned int c)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_sel(vector float a, vector float b, vector bool int c)
+{
+ vector int res = ((vector int)a & ~(vector int)c) | ((vector int)b & (vector int)c);
+ return (vector float)res;
+}
+
/* vec_vsel */
static vector signed char __ATTRS_o_ai
@@ -2997,36 +4656,108 @@ vec_vsel(vector signed char a, vector signed char b, vector unsigned char c)
return (a & ~(vector signed char)c) | (b & (vector signed char)c);
}
+static vector signed char __ATTRS_o_ai
+vec_vsel(vector signed char a, vector signed char b, vector bool char c)
+{
+ return (a & ~(vector signed char)c) | (b & (vector signed char)c);
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vsel(vector unsigned char a, vector unsigned char b, vector unsigned char c)
{
return (a & ~c) | (b & c);
}
+static vector unsigned char __ATTRS_o_ai
+vec_vsel(vector unsigned char a, vector unsigned char b, vector bool char c)
+{
+ return (a & ~(vector unsigned char)c) | (b & (vector unsigned char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsel(vector bool char a, vector bool char b, vector unsigned char c)
+{
+ return (a & ~(vector bool char)c) | (b & (vector bool char)c);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsel(vector bool char a, vector bool char b, vector bool char c)
+{
+ return (a & ~c) | (b & c);
+}
+
static vector short __ATTRS_o_ai
vec_vsel(vector short a, vector short b, vector unsigned short c)
{
return (a & ~(vector short)c) | (b & (vector short)c);
}
+static vector short __ATTRS_o_ai
+vec_vsel(vector short a, vector short b, vector bool short c)
+{
+ return (a & ~(vector short)c) | (b & (vector short)c);
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vsel(vector unsigned short a, vector unsigned short b, vector unsigned short c)
{
return (a & ~c) | (b & c);
}
+static vector unsigned short __ATTRS_o_ai
+vec_vsel(vector unsigned short a, vector unsigned short b, vector bool short c)
+{
+ return (a & ~(vector unsigned short)c) | (b & (vector unsigned short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsel(vector bool short a, vector bool short b, vector unsigned short c)
+{
+ return (a & ~(vector bool short)c) | (b & (vector bool short)c);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsel(vector bool short a, vector bool short b, vector bool short c)
+{
+ return (a & ~c) | (b & c);
+}
+
static vector int __ATTRS_o_ai
vec_vsel(vector int a, vector int b, vector unsigned int c)
{
return (a & ~(vector int)c) | (b & (vector int)c);
}
+static vector int __ATTRS_o_ai
+vec_vsel(vector int a, vector int b, vector bool int c)
+{
+ return (a & ~(vector int)c) | (b & (vector int)c);
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vsel(vector unsigned int a, vector unsigned int b, vector unsigned int c)
{
return (a & ~c) | (b & c);
}
+static vector unsigned int __ATTRS_o_ai
+vec_vsel(vector unsigned int a, vector unsigned int b, vector bool int c)
+{
+ return (a & ~(vector unsigned int)c) | (b & (vector unsigned int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsel(vector bool int a, vector bool int b, vector unsigned int c)
+{
+ return (a & ~(vector bool int)c) | (b & (vector bool int)c);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsel(vector bool int a, vector bool int b, vector bool int c)
+{
+ return (a & ~c) | (b & c);
+}
+
static vector float __ATTRS_o_ai
vec_vsel(vector float a, vector float b, vector unsigned int c)
{
@@ -3034,6 +4765,13 @@ vec_vsel(vector float a, vector float b, vector unsigned int c)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_vsel(vector float a, vector float b, vector bool int c)
+{
+ vector int res = ((vector int)a & ~(vector int)c) | ((vector int)b & (vector int)c);
+ return (vector float)res;
+}
+
/* vec_sl */
static vector signed char __ATTRS_o_ai
@@ -3127,7 +4865,7 @@ vec_vslw(vector unsigned int a, vector unsigned int b)
static vector signed char __ATTRS_o_ai
vec_sld(vector signed char a, vector signed char b, unsigned char c)
{
- return (vector signed char)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3135,7 +4873,7 @@ vec_sld(vector signed char a, vector signed char b, unsigned char c)
static vector unsigned char __ATTRS_o_ai
vec_sld(vector unsigned char a, vector unsigned char b, unsigned char c)
{
- return (vector unsigned char)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3143,7 +4881,7 @@ vec_sld(vector unsigned char a, vector unsigned char b, unsigned char c)
static vector short __ATTRS_o_ai
vec_sld(vector short a, vector short b, unsigned char c)
{
- return (vector short)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3151,7 +4889,15 @@ vec_sld(vector short a, vector short b, unsigned char c)
static vector unsigned short __ATTRS_o_ai
vec_sld(vector unsigned short a, vector unsigned short b, unsigned char c)
{
- return (vector unsigned short)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sld(vector pixel a, vector pixel b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3167,7 +4913,7 @@ vec_sld(vector int a, vector int b, unsigned char c)
static vector unsigned int __ATTRS_o_ai
vec_sld(vector unsigned int a, vector unsigned int b, unsigned char c)
{
- return (vector unsigned int)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3175,7 +4921,7 @@ vec_sld(vector unsigned int a, vector unsigned int b, unsigned char c)
static vector float __ATTRS_o_ai
vec_sld(vector float a, vector float b, unsigned char c)
{
- return (vector float)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3185,7 +4931,7 @@ vec_sld(vector float a, vector float b, unsigned char c)
static vector signed char __ATTRS_o_ai
vec_vsldoi(vector signed char a, vector signed char b, unsigned char c)
{
- return (vector signed char)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3193,7 +4939,7 @@ vec_vsldoi(vector signed char a, vector signed char b, unsigned char c)
static vector unsigned char __ATTRS_o_ai
vec_vsldoi(vector unsigned char a, vector unsigned char b, unsigned char c)
{
- return (vector unsigned char)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3201,7 +4947,7 @@ vec_vsldoi(vector unsigned char a, vector unsigned char b, unsigned char c)
static vector short __ATTRS_o_ai
vec_vsldoi(vector short a, vector short b, unsigned char c)
{
- return (vector short)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3209,7 +4955,15 @@ vec_vsldoi(vector short a, vector short b, unsigned char c)
static vector unsigned short __ATTRS_o_ai
vec_vsldoi(vector unsigned short a, vector unsigned short b, unsigned char c)
{
- return (vector unsigned short)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
+ (c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
+ c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsldoi(vector pixel a, vector pixel b, unsigned char c)
+{
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3225,7 +4979,7 @@ vec_vsldoi(vector int a, vector int b, unsigned char c)
static vector unsigned int __ATTRS_o_ai
vec_vsldoi(vector unsigned int a, vector unsigned int b, unsigned char c)
{
- return (vector unsigned int)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3233,7 +4987,7 @@ vec_vsldoi(vector unsigned int a, vector unsigned int b, unsigned char c)
static vector float __ATTRS_o_ai
vec_vsldoi(vector float a, vector float b, unsigned char c)
{
- return (vector float)vec_perm(a, b, (vector unsigned char)
+ return vec_perm(a, b, (vector unsigned char)
(c, c+1, c+2, c+3, c+4, c+5, c+6, c+7,
c+8, c+9, c+10, c+11, c+12, c+13, c+14, c+15));
}
@@ -3276,6 +5030,24 @@ vec_sll(vector unsigned char a, vector unsigned int b)
return (vector unsigned char)__builtin_altivec_vsl((vector int)a, (vector int)b);
}
+static vector bool char __ATTRS_o_ai
+vec_sll(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sll(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_sll(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
static vector short __ATTRS_o_ai
vec_sll(vector short a, vector unsigned char b)
{
@@ -3312,6 +5084,42 @@ vec_sll(vector unsigned short a, vector unsigned int b)
return (vector unsigned short)__builtin_altivec_vsl((vector int)a, (vector int)b);
}
+static vector bool short __ATTRS_o_ai
+vec_sll(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sll(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_sll(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sll(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sll(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sll(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_sll(vector int a, vector unsigned char b)
{
@@ -3348,6 +5156,24 @@ vec_sll(vector unsigned int a, vector unsigned int b)
return (vector unsigned int)__builtin_altivec_vsl((vector int)a, (vector int)b);
}
+static vector bool int __ATTRS_o_ai
+vec_sll(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sll(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_sll(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
/* vec_vsl */
static vector signed char __ATTRS_o_ai
@@ -3386,6 +5212,24 @@ vec_vsl(vector unsigned char a, vector unsigned int b)
return (vector unsigned char)__builtin_altivec_vsl((vector int)a, (vector int)b);
}
+static vector bool char __ATTRS_o_ai
+vec_vsl(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsl(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsl(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
static vector short __ATTRS_o_ai
vec_vsl(vector short a, vector unsigned char b)
{
@@ -3422,6 +5266,42 @@ vec_vsl(vector unsigned short a, vector unsigned int b)
return (vector unsigned short)__builtin_altivec_vsl((vector int)a, (vector int)b);
}
+static vector bool short __ATTRS_o_ai
+vec_vsl(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsl(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsl(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsl(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsl(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsl(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_vsl(vector int a, vector unsigned char b)
{
@@ -3458,6 +5338,24 @@ vec_vsl(vector unsigned int a, vector unsigned int b)
return (vector unsigned int)__builtin_altivec_vsl((vector int)a, (vector int)b);
}
+static vector bool int __ATTRS_o_ai
+vec_vsl(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsl(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsl(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsl((vector int)a, (vector int)b);
+}
+
/* vec_slo */
static vector signed char __ATTRS_o_ai
@@ -3508,6 +5406,18 @@ vec_slo(vector unsigned short a, vector unsigned char b)
return (vector unsigned short)__builtin_altivec_vslo((vector int)a, (vector int)b);
}
+static vector pixel __ATTRS_o_ai
+vec_slo(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_slo(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_slo(vector int a, vector signed char b)
{
@@ -3594,6 +5504,18 @@ vec_vslo(vector unsigned short a, vector unsigned char b)
return (vector unsigned short)__builtin_altivec_vslo((vector int)a, (vector int)b);
}
+static vector pixel __ATTRS_o_ai
+vec_vslo(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vslo(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vslo((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_vslo(vector int a, vector signed char b)
{
@@ -3635,20 +5557,26 @@ vec_vslo(vector float a, vector unsigned char b)
static vector signed char __ATTRS_o_ai
vec_splat(vector signed char a, unsigned char b)
{
- return (vector signed char)vec_perm(a, a, (vector unsigned char)(b));
+ return vec_perm(a, a, (vector unsigned char)(b));
}
static vector unsigned char __ATTRS_o_ai
vec_splat(vector unsigned char a, unsigned char b)
{
- return (vector unsigned char)vec_perm(a, a, (vector unsigned char)(b));
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_splat(vector bool char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
}
static vector short __ATTRS_o_ai
vec_splat(vector short a, unsigned char b)
{
b *= 2;
- return (vector short)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
}
@@ -3656,7 +5584,23 @@ static vector unsigned short __ATTRS_o_ai
vec_splat(vector unsigned short a, unsigned char b)
{
b *= 2;
- return (vector unsigned short)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_splat(vector bool short a, unsigned char b)
+{
+ b *= 2;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_splat(vector pixel a, unsigned char b)
+{
+ b *= 2;
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
}
@@ -3672,7 +5616,15 @@ static vector unsigned int __ATTRS_o_ai
vec_splat(vector unsigned int a, unsigned char b)
{
b *= 4;
- return (vector unsigned int)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_splat(vector bool int a, unsigned char b)
+{
+ b *= 4;
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
}
@@ -3680,7 +5632,7 @@ static vector float __ATTRS_o_ai
vec_splat(vector float a, unsigned char b)
{
b *= 4;
- return (vector float)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
}
@@ -3691,13 +5643,19 @@ vec_splat(vector float a, unsigned char b)
static vector signed char __ATTRS_o_ai
vec_vspltb(vector signed char a, unsigned char b)
{
- return (vector signed char)vec_perm(a, a, (vector unsigned char)(b));
+ return vec_perm(a, a, (vector unsigned char)(b));
}
static vector unsigned char __ATTRS_o_ai
vec_vspltb(vector unsigned char a, unsigned char b)
{
- return (vector unsigned char)vec_perm(a, a, (vector unsigned char)(b));
+ return vec_perm(a, a, (vector unsigned char)(b));
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vspltb(vector bool char a, unsigned char b)
+{
+ return vec_perm(a, a, (vector unsigned char)(b));
}
/* vec_vsplth */
@@ -3708,7 +5666,7 @@ static vector short __ATTRS_o_ai
vec_vsplth(vector short a, unsigned char b)
{
b *= 2;
- return (vector short)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
}
@@ -3716,7 +5674,23 @@ static vector unsigned short __ATTRS_o_ai
vec_vsplth(vector unsigned short a, unsigned char b)
{
b *= 2;
- return (vector unsigned short)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsplth(vector bool short a, unsigned char b)
+{
+ b *= 2;
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsplth(vector pixel a, unsigned char b)
+{
+ b *= 2;
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1, b, b+1));
}
@@ -3728,7 +5702,7 @@ static vector int __ATTRS_o_ai
vec_vspltw(vector int a, unsigned char b)
{
b *= 4;
- return (vector int)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
}
@@ -3736,7 +5710,15 @@ static vector unsigned int __ATTRS_o_ai
vec_vspltw(vector unsigned int a, unsigned char b)
{
b *= 4;
- return (vector unsigned int)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
+ (b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vspltw(vector bool int a, unsigned char b)
+{
+ b *= 4;
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
}
@@ -3744,7 +5726,7 @@ static vector float __ATTRS_o_ai
vec_vspltw(vector float a, unsigned char b)
{
b *= 4;
- return (vector float)vec_perm(a, a, (vector unsigned char)
+ return vec_perm(a, a, (vector unsigned char)
(b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3, b, b+1, b+2, b+3));
}
@@ -4039,6 +6021,24 @@ vec_srl(vector unsigned char a, vector unsigned int b)
return (vector unsigned char)__builtin_altivec_vsr((vector int)a, (vector int)b);
}
+static vector bool char __ATTRS_o_ai
+vec_srl(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_srl(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_srl(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
static vector short __ATTRS_o_ai
vec_srl(vector short a, vector unsigned char b)
{
@@ -4075,6 +6075,42 @@ vec_srl(vector unsigned short a, vector unsigned int b)
return (vector unsigned short)__builtin_altivec_vsr((vector int)a, (vector int)b);
}
+static vector bool short __ATTRS_o_ai
+vec_srl(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_srl(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_srl(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_srl(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_srl(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_srl(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_srl(vector int a, vector unsigned char b)
{
@@ -4111,6 +6147,24 @@ vec_srl(vector unsigned int a, vector unsigned int b)
return (vector unsigned int)__builtin_altivec_vsr((vector int)a, (vector int)b);
}
+static vector bool int __ATTRS_o_ai
+vec_srl(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_srl(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_srl(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
/* vec_vsr */
static vector signed char __ATTRS_o_ai
@@ -4149,6 +6203,24 @@ vec_vsr(vector unsigned char a, vector unsigned int b)
return (vector unsigned char)__builtin_altivec_vsr((vector int)a, (vector int)b);
}
+static vector bool char __ATTRS_o_ai
+vec_vsr(vector bool char a, vector unsigned char b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsr(vector bool char a, vector unsigned short b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vsr(vector bool char a, vector unsigned int b)
+{
+ return (vector bool char)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
static vector short __ATTRS_o_ai
vec_vsr(vector short a, vector unsigned char b)
{
@@ -4185,6 +6257,42 @@ vec_vsr(vector unsigned short a, vector unsigned int b)
return (vector unsigned short)__builtin_altivec_vsr((vector int)a, (vector int)b);
}
+static vector bool short __ATTRS_o_ai
+vec_vsr(vector bool short a, vector unsigned char b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsr(vector bool short a, vector unsigned short b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vsr(vector bool short a, vector unsigned int b)
+{
+ return (vector bool short)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsr(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsr(vector pixel a, vector unsigned short b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsr(vector pixel a, vector unsigned int b)
+{
+ return (vector pixel)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_vsr(vector int a, vector unsigned char b)
{
@@ -4221,6 +6329,24 @@ vec_vsr(vector unsigned int a, vector unsigned int b)
return (vector unsigned int)__builtin_altivec_vsr((vector int)a, (vector int)b);
}
+static vector bool int __ATTRS_o_ai
+vec_vsr(vector bool int a, vector unsigned char b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsr(vector bool int a, vector unsigned short b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vsr(vector bool int a, vector unsigned int b)
+{
+ return (vector bool int)__builtin_altivec_vsr((vector int)a, (vector int)b);
+}
+
/* vec_sro */
static vector signed char __ATTRS_o_ai
@@ -4271,6 +6397,18 @@ vec_sro(vector unsigned short a, vector unsigned char b)
return (vector unsigned short)__builtin_altivec_vsro((vector int)a, (vector int)b);
}
+static vector pixel __ATTRS_o_ai
+vec_sro(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_sro(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_sro(vector int a, vector signed char b)
{
@@ -4357,6 +6495,18 @@ vec_vsro(vector unsigned short a, vector unsigned char b)
return (vector unsigned short)__builtin_altivec_vsro((vector int)a, (vector int)b);
}
+static vector pixel __ATTRS_o_ai
+vec_vsro(vector pixel a, vector signed char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
+static vector pixel __ATTRS_o_ai
+vec_vsro(vector pixel a, vector unsigned char b)
+{
+ return (vector pixel)__builtin_altivec_vsro((vector int)a, (vector int)b);
+}
+
static vector int __ATTRS_o_ai
vec_vsro(vector int a, vector signed char b)
{
@@ -4420,6 +6570,24 @@ vec_st(vector unsigned char a, int b, unsigned char *c)
}
static void __ATTRS_o_ai
+vec_st(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_st(vector short a, int b, vector short *c)
{
__builtin_altivec_stvx((vector int)a, b, c);
@@ -4444,6 +6612,42 @@ vec_st(vector unsigned short a, int b, unsigned short *c)
}
static void __ATTRS_o_ai
+vec_st(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_st(vector int a, int b, vector int *c)
{
__builtin_altivec_stvx(a, b, c);
@@ -4468,6 +6672,24 @@ vec_st(vector unsigned int a, int b, unsigned int *c)
}
static void __ATTRS_o_ai
+vec_st(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_st(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_st(vector float a, int b, vector float *c)
{
__builtin_altivec_stvx((vector int)a, b, c);
@@ -4506,6 +6728,24 @@ vec_stvx(vector unsigned char a, int b, unsigned char *c)
}
static void __ATTRS_o_ai
+vec_stvx(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvx(vector short a, int b, vector short *c)
{
__builtin_altivec_stvx((vector int)a, b, c);
@@ -4530,6 +6770,42 @@ vec_stvx(vector unsigned short a, int b, unsigned short *c)
}
static void __ATTRS_o_ai
+vec_stvx(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvx(vector int a, int b, vector int *c)
{
__builtin_altivec_stvx(a, b, c);
@@ -4554,6 +6830,24 @@ vec_stvx(vector unsigned int a, int b, unsigned int *c)
}
static void __ATTRS_o_ai
+vec_stvx(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvx(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvx(vector float a, int b, vector float *c)
{
__builtin_altivec_stvx((vector int)a, b, c);
@@ -4580,6 +6874,18 @@ vec_ste(vector unsigned char a, int b, unsigned char *c)
}
static void __ATTRS_o_ai
+vec_ste(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_ste(vector short a, int b, short *c)
{
__builtin_altivec_stvehx(a, b, c);
@@ -4592,6 +6898,30 @@ vec_ste(vector unsigned short a, int b, unsigned short *c)
}
static void __ATTRS_o_ai
+vec_ste(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_ste(vector int a, int b, int *c)
{
__builtin_altivec_stvewx(a, b, c);
@@ -4604,6 +6934,18 @@ vec_ste(vector unsigned int a, int b, unsigned int *c)
}
static void __ATTRS_o_ai
+vec_ste(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_ste(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_ste(vector float a, int b, float *c)
{
__builtin_altivec_stvewx((vector int)a, b, c);
@@ -4623,6 +6965,18 @@ vec_stvebx(vector unsigned char a, int b, unsigned char *c)
__builtin_altivec_stvebx((vector char)a, b, c);
}
+static void __ATTRS_o_ai
+vec_stvebx(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvebx(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvebx((vector char)a, b, c);
+}
+
/* vec_stvehx */
static void __ATTRS_o_ai
@@ -4637,6 +6991,30 @@ vec_stvehx(vector unsigned short a, int b, unsigned short *c)
__builtin_altivec_stvehx((vector short)a, b, c);
}
+static void __ATTRS_o_ai
+vec_stvehx(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvehx(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvehx((vector short)a, b, c);
+}
+
/* vec_stvewx */
static void __ATTRS_o_ai
@@ -4652,6 +7030,18 @@ vec_stvewx(vector unsigned int a, int b, unsigned int *c)
}
static void __ATTRS_o_ai
+vec_stvewx(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvewx(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvewx((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvewx(vector float a, int b, float *c)
{
__builtin_altivec_stvewx((vector int)a, b, c);
@@ -4684,6 +7074,24 @@ vec_stl(vector unsigned char a, int b, unsigned char *c)
}
static void __ATTRS_o_ai
+vec_stl(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stl(vector short a, int b, vector short *c)
{
__builtin_altivec_stvxl((vector int)a, b, c);
@@ -4708,6 +7116,42 @@ vec_stl(vector unsigned short a, int b, unsigned short *c)
}
static void __ATTRS_o_ai
+vec_stl(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stl(vector int a, int b, vector int *c)
{
__builtin_altivec_stvxl(a, b, c);
@@ -4732,6 +7176,24 @@ vec_stl(vector unsigned int a, int b, unsigned int *c)
}
static void __ATTRS_o_ai
+vec_stl(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stl(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stl(vector float a, int b, vector float *c)
{
__builtin_altivec_stvxl((vector int)a, b, c);
@@ -4770,6 +7232,24 @@ vec_stvxl(vector unsigned char a, int b, unsigned char *c)
}
static void __ATTRS_o_ai
+vec_stvxl(vector bool char a, int b, signed char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool char a, int b, unsigned char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool char a, int b, vector bool char *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvxl(vector short a, int b, vector short *c)
{
__builtin_altivec_stvxl((vector int)a, b, c);
@@ -4794,6 +7274,42 @@ vec_stvxl(vector unsigned short a, int b, unsigned short *c)
}
static void __ATTRS_o_ai
+vec_stvxl(vector bool short a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool short a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool short a, int b, vector bool short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector pixel a, int b, short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector pixel a, int b, unsigned short *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector pixel a, int b, vector pixel *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvxl(vector int a, int b, vector int *c)
{
__builtin_altivec_stvxl(a, b, c);
@@ -4818,6 +7334,24 @@ vec_stvxl(vector unsigned int a, int b, unsigned int *c)
}
static void __ATTRS_o_ai
+vec_stvxl(vector bool int a, int b, int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool int a, int b, unsigned int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
+vec_stvxl(vector bool int a, int b, vector bool int *c)
+{
+ __builtin_altivec_stvxl((vector int)a, b, c);
+}
+
+static void __ATTRS_o_ai
vec_stvxl(vector float a, int b, vector float *c)
{
__builtin_altivec_stvxl((vector int)a, b, c);
@@ -4837,36 +7371,108 @@ vec_sub(vector signed char a, vector signed char b)
return a - b;
}
+static vector signed char __ATTRS_o_ai
+vec_sub(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a - b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_sub(vector signed char a, vector bool char b)
+{
+ return a - (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_sub(vector unsigned char a, vector unsigned char b)
{
return a - b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_sub(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a - b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_sub(vector unsigned char a, vector bool char b)
+{
+ return a - (vector unsigned char)b;
+}
+
static vector short __ATTRS_o_ai
vec_sub(vector short a, vector short b)
{
return a - b;
}
+static vector short __ATTRS_o_ai
+vec_sub(vector bool short a, vector short b)
+{
+ return (vector short)a - b;
+}
+
+static vector short __ATTRS_o_ai
+vec_sub(vector short a, vector bool short b)
+{
+ return a - (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_sub(vector unsigned short a, vector unsigned short b)
{
return a - b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_sub(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a - b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_sub(vector unsigned short a, vector bool short b)
+{
+ return a - (vector unsigned short)b;
+}
+
static vector int __ATTRS_o_ai
vec_sub(vector int a, vector int b)
{
return a - b;
}
+static vector int __ATTRS_o_ai
+vec_sub(vector bool int a, vector int b)
+{
+ return (vector int)a - b;
+}
+
+static vector int __ATTRS_o_ai
+vec_sub(vector int a, vector bool int b)
+{
+ return a - (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_sub(vector unsigned int a, vector unsigned int b)
{
return a - b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_sub(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a - b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_sub(vector unsigned int a, vector bool int b)
+{
+ return a - (vector unsigned int)b;
+}
+
static vector float __ATTRS_o_ai
vec_sub(vector float a, vector float b)
{
@@ -4883,12 +7489,36 @@ vec_vsububm(vector signed char a, vector signed char b)
return a - b;
}
+static vector signed char __ATTRS_o_ai
+vec_vsububm(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a - b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsububm(vector signed char a, vector bool char b)
+{
+ return a - (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vsububm(vector unsigned char a, vector unsigned char b)
{
return a - b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_vsububm(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a - b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububm(vector unsigned char a, vector bool char b)
+{
+ return a - (vector unsigned char)b;
+}
+
/* vec_vsubuhm */
#define __builtin_altivec_vsubuhm vec_vsubuhm
@@ -4899,12 +7529,36 @@ vec_vsubuhm(vector short a, vector short b)
return a - b;
}
+static vector short __ATTRS_o_ai
+vec_vsubuhm(vector bool short a, vector short b)
+{
+ return (vector short)a - b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vsubuhm(vector short a, vector bool short b)
+{
+ return a - (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vsubuhm(vector unsigned short a, vector unsigned short b)
{
return a - b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhm(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a - b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhm(vector unsigned short a, vector bool short b)
+{
+ return a - (vector unsigned short)b;
+}
+
/* vec_vsubuwm */
#define __builtin_altivec_vsubuwm vec_vsubuwm
@@ -4915,12 +7569,36 @@ vec_vsubuwm(vector int a, vector int b)
return a - b;
}
+static vector int __ATTRS_o_ai
+vec_vsubuwm(vector bool int a, vector int b)
+{
+ return (vector int)a - b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vsubuwm(vector int a, vector bool int b)
+{
+ return a - (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vsubuwm(vector unsigned int a, vector unsigned int b)
{
return a - b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuwm(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a - b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuwm(vector unsigned int a, vector bool int b)
+{
+ return a - (vector unsigned int)b;
+}
+
/* vec_vsubfp */
#define __builtin_altivec_vsubfp vec_vsubfp
@@ -4955,84 +7633,228 @@ vec_subs(vector signed char a, vector signed char b)
return __builtin_altivec_vsubsbs(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_subs(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vsubsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_subs(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vsubsbs(a, (vector signed char)b);
+}
+
static vector unsigned char __ATTRS_o_ai
vec_subs(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vsububs(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_subs(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vsububs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_subs(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vsububs(a, (vector unsigned char)b);
+}
+
static vector short __ATTRS_o_ai
vec_subs(vector short a, vector short b)
{
return __builtin_altivec_vsubshs(a, b);
}
+static vector short __ATTRS_o_ai
+vec_subs(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vsubshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_subs(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vsubshs(a, (vector short)b);
+}
+
static vector unsigned short __ATTRS_o_ai
vec_subs(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vsubuhs(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_subs(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsubuhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_subs(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vsubuhs(a, (vector unsigned short)b);
+}
+
static vector int __ATTRS_o_ai
vec_subs(vector int a, vector int b)
{
return __builtin_altivec_vsubsws(a, b);
}
+static vector int __ATTRS_o_ai
+vec_subs(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vsubsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_subs(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vsubsws(a, (vector int)b);
+}
+
static vector unsigned int __ATTRS_o_ai
vec_subs(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vsubuws(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_subs(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubuws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_subs(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vsubuws(a, (vector unsigned int)b);
+}
+
/* vec_vsubsbs */
-static vector signed char __attribute__((__always_inline__))
+static vector signed char __ATTRS_o_ai
vec_vsubsbs(vector signed char a, vector signed char b)
{
return __builtin_altivec_vsubsbs(a, b);
}
+static vector signed char __ATTRS_o_ai
+vec_vsubsbs(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vsubsbs((vector signed char)a, b);
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vsubsbs(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vsubsbs(a, (vector signed char)b);
+}
+
/* vec_vsububs */
-static vector unsigned char __attribute__((__always_inline__))
+static vector unsigned char __ATTRS_o_ai
vec_vsububs(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vsububs(a, b);
}
+static vector unsigned char __ATTRS_o_ai
+vec_vsububs(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vsububs((vector unsigned char)a, b);
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vsububs(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vsububs(a, (vector unsigned char)b);
+}
+
/* vec_vsubshs */
-static vector short __attribute__((__always_inline__))
+static vector short __ATTRS_o_ai
vec_vsubshs(vector short a, vector short b)
{
return __builtin_altivec_vsubshs(a, b);
}
+static vector short __ATTRS_o_ai
+vec_vsubshs(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vsubshs((vector short)a, b);
+}
+
+static vector short __ATTRS_o_ai
+vec_vsubshs(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vsubshs(a, (vector short)b);
+}
+
/* vec_vsubuhs */
-static vector unsigned short __attribute__((__always_inline__))
+static vector unsigned short __ATTRS_o_ai
vec_vsubuhs(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vsubuhs(a, b);
}
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhs(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vsubuhs((vector unsigned short)a, b);
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vsubuhs(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vsubuhs(a, (vector unsigned short)b);
+}
+
/* vec_vsubsws */
-static vector int __attribute__((__always_inline__))
+static vector int __ATTRS_o_ai
vec_vsubsws(vector int a, vector int b)
{
return __builtin_altivec_vsubsws(a, b);
}
+static vector int __ATTRS_o_ai
+vec_vsubsws(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vsubsws((vector int)a, b);
+}
+
+static vector int __ATTRS_o_ai
+vec_vsubsws(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vsubsws(a, (vector int)b);
+}
+
/* vec_vsubuws */
-static vector unsigned int __attribute__((__always_inline__))
+static vector unsigned int __ATTRS_o_ai
vec_vsubuws(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vsubuws(a, b);
}
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuws(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vsubuws((vector unsigned int)a, b);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vsubuws(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vsubuws(a, (vector unsigned int)b);
+}
+
/* vec_sum4s */
static vector int __ATTRS_o_ai
@@ -5133,28 +7955,64 @@ vec_unpackh(vector signed char a)
return __builtin_altivec_vupkhsb((vector char)a);
}
+static vector bool short __ATTRS_o_ai
+vec_unpackh(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupkhsb((vector char)a);
+}
+
static vector int __ATTRS_o_ai
vec_unpackh(vector short a)
{
return __builtin_altivec_vupkhsh(a);
}
+static vector bool int __ATTRS_o_ai
+vec_unpackh(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_unpackh(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
/* vec_vupkhsb */
-static vector short __attribute__((__always_inline__))
+static vector short __ATTRS_o_ai
vec_vupkhsb(vector signed char a)
{
return __builtin_altivec_vupkhsb((vector char)a);
}
+static vector bool short __ATTRS_o_ai
+vec_vupkhsb(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupkhsb((vector char)a);
+}
+
/* vec_vupkhsh */
-static vector int __attribute__((__always_inline__))
+static vector int __ATTRS_o_ai
vec_vupkhsh(vector short a)
{
return __builtin_altivec_vupkhsh(a);
}
+static vector bool int __ATTRS_o_ai
+vec_vupkhsh(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vupkhsh(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupkhsh((vector short)a);
+}
+
/* vec_unpackl */
static vector short __ATTRS_o_ai
@@ -5163,28 +8021,64 @@ vec_unpackl(vector signed char a)
return __builtin_altivec_vupklsb((vector char)a);
}
+static vector bool short __ATTRS_o_ai
+vec_unpackl(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupklsb((vector char)a);
+}
+
static vector int __ATTRS_o_ai
vec_unpackl(vector short a)
{
return __builtin_altivec_vupklsh(a);
}
+static vector bool int __ATTRS_o_ai
+vec_unpackl(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupklsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_unpackl(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupklsh((vector short)a);
+}
+
/* vec_vupklsb */
-static vector short __attribute__((__always_inline__))
+static vector short __ATTRS_o_ai
vec_vupklsb(vector signed char a)
{
return __builtin_altivec_vupklsb((vector char)a);
}
+static vector bool short __ATTRS_o_ai
+vec_vupklsb(vector bool char a)
+{
+ return (vector bool short)__builtin_altivec_vupklsb((vector char)a);
+}
+
/* vec_vupklsh */
-static vector int __attribute__((__always_inline__))
+static vector int __ATTRS_o_ai
vec_vupklsh(vector short a)
{
return __builtin_altivec_vupklsh(a);
}
+static vector bool int __ATTRS_o_ai
+vec_vupklsh(vector bool short a)
+{
+ return (vector bool int)__builtin_altivec_vupklsh((vector short)a);
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vupklsh(vector pixel a)
+{
+ return (vector unsigned int)__builtin_altivec_vupklsh((vector short)a);
+}
+
/* vec_xor */
#define __builtin_altivec_vxor vec_xor
@@ -5195,36 +8089,126 @@ vec_xor(vector signed char a, vector signed char b)
return a ^ b;
}
+static vector signed char __ATTRS_o_ai
+vec_xor(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a ^ b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_xor(vector signed char a, vector bool char b)
+{
+ return a ^ (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_xor(vector unsigned char a, vector unsigned char b)
{
return a ^ b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_xor(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a ^ b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_xor(vector unsigned char a, vector bool char b)
+{
+ return a ^ (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_xor(vector bool char a, vector bool char b)
+{
+ return a ^ b;
+}
+
static vector short __ATTRS_o_ai
vec_xor(vector short a, vector short b)
{
return a ^ b;
}
+static vector short __ATTRS_o_ai
+vec_xor(vector bool short a, vector short b)
+{
+ return (vector short)a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_xor(vector short a, vector bool short b)
+{
+ return a ^ (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_xor(vector unsigned short a, vector unsigned short b)
{
return a ^ b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_xor(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a ^ b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_xor(vector unsigned short a, vector bool short b)
+{
+ return a ^ (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_xor(vector bool short a, vector bool short b)
+{
+ return a ^ b;
+}
+
static vector int __ATTRS_o_ai
vec_xor(vector int a, vector int b)
{
return a ^ b;
}
+static vector int __ATTRS_o_ai
+vec_xor(vector bool int a, vector int b)
+{
+ return (vector int)a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_xor(vector int a, vector bool int b)
+{
+ return a ^ (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_xor(vector unsigned int a, vector unsigned int b)
{
return a ^ b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_xor(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a ^ b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_xor(vector unsigned int a, vector bool int b)
+{
+ return a ^ (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_xor(vector bool int a, vector bool int b)
+{
+ return a ^ b;
+}
+
static vector float __ATTRS_o_ai
vec_xor(vector float a, vector float b)
{
@@ -5232,6 +8216,20 @@ vec_xor(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_xor(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_xor(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
/* vec_vxor */
static vector signed char __ATTRS_o_ai
@@ -5240,36 +8238,126 @@ vec_vxor(vector signed char a, vector signed char b)
return a ^ b;
}
+static vector signed char __ATTRS_o_ai
+vec_vxor(vector bool char a, vector signed char b)
+{
+ return (vector signed char)a ^ b;
+}
+
+static vector signed char __ATTRS_o_ai
+vec_vxor(vector signed char a, vector bool char b)
+{
+ return a ^ (vector signed char)b;
+}
+
static vector unsigned char __ATTRS_o_ai
vec_vxor(vector unsigned char a, vector unsigned char b)
{
return a ^ b;
}
+static vector unsigned char __ATTRS_o_ai
+vec_vxor(vector bool char a, vector unsigned char b)
+{
+ return (vector unsigned char)a ^ b;
+}
+
+static vector unsigned char __ATTRS_o_ai
+vec_vxor(vector unsigned char a, vector bool char b)
+{
+ return a ^ (vector unsigned char)b;
+}
+
+static vector bool char __ATTRS_o_ai
+vec_vxor(vector bool char a, vector bool char b)
+{
+ return a ^ b;
+}
+
static vector short __ATTRS_o_ai
vec_vxor(vector short a, vector short b)
{
return a ^ b;
}
+static vector short __ATTRS_o_ai
+vec_vxor(vector bool short a, vector short b)
+{
+ return (vector short)a ^ b;
+}
+
+static vector short __ATTRS_o_ai
+vec_vxor(vector short a, vector bool short b)
+{
+ return a ^ (vector short)b;
+}
+
static vector unsigned short __ATTRS_o_ai
vec_vxor(vector unsigned short a, vector unsigned short b)
{
return a ^ b;
}
+static vector unsigned short __ATTRS_o_ai
+vec_vxor(vector bool short a, vector unsigned short b)
+{
+ return (vector unsigned short)a ^ b;
+}
+
+static vector unsigned short __ATTRS_o_ai
+vec_vxor(vector unsigned short a, vector bool short b)
+{
+ return a ^ (vector unsigned short)b;
+}
+
+static vector bool short __ATTRS_o_ai
+vec_vxor(vector bool short a, vector bool short b)
+{
+ return a ^ b;
+}
+
static vector int __ATTRS_o_ai
vec_vxor(vector int a, vector int b)
{
return a ^ b;
}
+static vector int __ATTRS_o_ai
+vec_vxor(vector bool int a, vector int b)
+{
+ return (vector int)a ^ b;
+}
+
+static vector int __ATTRS_o_ai
+vec_vxor(vector int a, vector bool int b)
+{
+ return a ^ (vector int)b;
+}
+
static vector unsigned int __ATTRS_o_ai
vec_vxor(vector unsigned int a, vector unsigned int b)
{
return a ^ b;
}
+static vector unsigned int __ATTRS_o_ai
+vec_vxor(vector bool int a, vector unsigned int b)
+{
+ return (vector unsigned int)a ^ b;
+}
+
+static vector unsigned int __ATTRS_o_ai
+vec_vxor(vector unsigned int a, vector bool int b)
+{
+ return a ^ (vector unsigned int)b;
+}
+
+static vector bool int __ATTRS_o_ai
+vec_vxor(vector bool int a, vector bool int b)
+{
+ return a ^ b;
+}
+
static vector float __ATTRS_o_ai
vec_vxor(vector float a, vector float b)
{
@@ -5277,6 +8365,20 @@ vec_vxor(vector float a, vector float b)
return (vector float)res;
}
+static vector float __ATTRS_o_ai
+vec_vxor(vector bool int a, vector float b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
+static vector float __ATTRS_o_ai
+vec_vxor(vector float a, vector bool int b)
+{
+ vector unsigned int res = (vector unsigned int)a ^ (vector unsigned int)b;
+ return (vector float)res;
+}
+
/* ------------------------------ predicates ------------------------------------ */
/* vec_all_eq */
@@ -5288,36 +8390,132 @@ vec_all_eq(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_all_eq(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_eq(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
}
static int __ATTRS_o_ai
+vec_all_eq(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_eq(vector short a, vector short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_eq(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_eq(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
}
static int __ATTRS_o_ai
+vec_all_eq(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector pixel a, vector pixel b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_eq(vector int a, vector int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_eq(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_eq(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
}
static int __ATTRS_o_ai
+vec_all_eq(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_eq(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_eq(vector float a, vector float b)
{
return __builtin_altivec_vcmpeqfp_p(__CR6_LT, a, b);
@@ -5332,36 +8530,132 @@ vec_all_ge(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_all_ge(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
vec_all_ge(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, b, a);
}
static int __ATTRS_o_ai
+vec_all_ge(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
vec_all_ge(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, b, a);
}
static int __ATTRS_o_ai
+vec_all_ge(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
vec_all_ge(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, b, a);
}
static int __ATTRS_o_ai
+vec_all_ge(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
vec_all_ge(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, b, a);
}
static int __ATTRS_o_ai
+vec_all_ge(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
vec_all_ge(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, b, a);
}
static int __ATTRS_o_ai
+vec_all_ge(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_ge(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
vec_all_ge(vector float a, vector float b)
{
return __builtin_altivec_vcmpgefp_p(__CR6_LT, a, b);
@@ -5376,36 +8670,132 @@ vec_all_gt(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_all_gt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_gt(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_gt(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_gt(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_gt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_gt(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_gt(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_gt(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_gt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_gt(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, a, b);
}
static int __ATTRS_o_ai
+vec_all_gt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_gt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_gt(vector float a, vector float b)
{
return __builtin_altivec_vcmpgtfp_p(__CR6_LT, a, b);
@@ -5428,36 +8818,132 @@ vec_all_le(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_all_le(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_le(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_le(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_le(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_le(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_le(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_le(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_le(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_le(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_le(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_le(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_all_le(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_le(vector float a, vector float b)
{
return __builtin_altivec_vcmpgefp_p(__CR6_LT, b, a);
@@ -5472,36 +8958,132 @@ vec_all_lt(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_all_lt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
vec_all_lt(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_LT, b, a);
}
static int __ATTRS_o_ai
+vec_all_lt(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
vec_all_lt(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_LT, b, a);
}
static int __ATTRS_o_ai
+vec_all_lt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
vec_all_lt(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_LT, b, a);
}
static int __ATTRS_o_ai
+vec_all_lt(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
vec_all_lt(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_LT, b, a);
}
static int __ATTRS_o_ai
+vec_all_lt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
vec_all_lt(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_LT, b, a);
}
static int __ATTRS_o_ai
+vec_all_lt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_all_lt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
vec_all_lt(vector float a, vector float b)
{
return __builtin_altivec_vcmpgtfp_p(__CR6_LT, b, a);
@@ -5524,36 +9106,132 @@ vec_all_ne(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_all_ne(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_ne(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
}
static int __ATTRS_o_ai
+vec_all_ne(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_all_ne(vector short a, vector short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_ne(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_ne(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
}
static int __ATTRS_o_ai
+vec_all_ne(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector pixel a, vector pixel b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_all_ne(vector int a, vector int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_EQ, a, b);
}
static int __ATTRS_o_ai
+vec_all_ne(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_ne(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
}
static int __ATTRS_o_ai
+vec_all_ne(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_all_ne(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_all_ne(vector float a, vector float b)
{
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ, a, b);
@@ -5608,36 +9286,132 @@ vec_any_eq(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_any_eq(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_eq(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
}
static int __ATTRS_o_ai
+vec_any_eq(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_EQ_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_eq(vector short a, vector short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_eq(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_eq(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)a, (vector short)b);
}
static int __ATTRS_o_ai
+vec_any_eq(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector pixel a, vector pixel b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_EQ_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_eq(vector int a, vector int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_eq(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_eq(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
}
static int __ATTRS_o_ai
+vec_any_eq(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_eq(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_EQ_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_eq(vector float a, vector float b)
{
return __builtin_altivec_vcmpeqfp_p(__CR6_EQ_REV, a, b);
@@ -5652,36 +9426,133 @@ vec_any_ge(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_any_ge(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
vec_any_ge(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_ge(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
vec_any_ge(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_ge(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
vec_any_ge(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_ge(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
vec_any_ge(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_ge(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
vec_any_ge(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_ge(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_ge(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
vec_any_ge(vector float a, vector float b)
{
return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, a, b);
@@ -5696,36 +9567,135 @@ vec_any_gt(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_any_gt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_gt(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_gt(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_gt(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_gt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_gt(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_gt(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_gt(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_gt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_gt(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_gt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_gt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_gt(vector float a, vector float b)
{
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, a, b);
@@ -5740,36 +9710,136 @@ vec_any_le(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_any_le(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_LT_REV, a, (vector signed char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_le(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_le(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, a, (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_LT_REV, (vector unsigned char)a,
+ (vector unsigned char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_le(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_le(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_LT_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_le(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_le(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, a, (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_LT_REV, (vector unsigned short)a,
+ (vector unsigned short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_le(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_le(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_LT_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_le(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_le(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, a, (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)a, b);
+}
+
+static int __ATTRS_o_ai
+vec_any_le(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_LT_REV, (vector unsigned int)a,
+ (vector unsigned int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_le(vector float a, vector float b)
{
return __builtin_altivec_vcmpgefp_p(__CR6_EQ_REV, b, a);
@@ -5784,36 +9854,136 @@ vec_any_lt(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_any_lt(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtsb_p(__CR6_EQ_REV, (vector signed char)b, a);
+}
+
+static int __ATTRS_o_ai
vec_any_lt(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_lt(vector unsigned char a, vector bool char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool char a, vector unsigned char b)
+{
+ return
+ __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, b, (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpgtub_p(__CR6_EQ_REV, (vector unsigned char)b,
+ (vector unsigned char)a);
+}
+
+static int __ATTRS_o_ai
vec_any_lt(vector short a, vector short b)
{
return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_lt(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtsh_p(__CR6_EQ_REV, (vector short)b, a);
+}
+
+static int __ATTRS_o_ai
vec_any_lt(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_lt(vector unsigned short a, vector bool short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool short a, vector unsigned short b)
+{
+ return
+ __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, b, (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpgtuh_p(__CR6_EQ_REV, (vector unsigned short)b,
+ (vector unsigned short)a);
+}
+
+static int __ATTRS_o_ai
vec_any_lt(vector int a, vector int b)
{
return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_lt(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtsw_p(__CR6_EQ_REV, (vector int)b, a);
+}
+
+static int __ATTRS_o_ai
vec_any_lt(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, b, a);
}
static int __ATTRS_o_ai
+vec_any_lt(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)b, a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, b, (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
+vec_any_lt(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpgtuw_p(__CR6_EQ_REV, (vector unsigned int)b,
+ (vector unsigned int)a);
+}
+
+static int __ATTRS_o_ai
vec_any_lt(vector float a, vector float b)
{
return __builtin_altivec_vcmpgtfp_p(__CR6_EQ_REV, b, a);
@@ -5836,36 +10006,132 @@ vec_any_ne(vector signed char a, vector signed char b)
}
static int __ATTRS_o_ai
+vec_any_ne(vector signed char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_ne(vector unsigned char a, vector unsigned char b)
{
return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
}
static int __ATTRS_o_ai
+vec_any_ne(vector unsigned char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool char a, vector signed char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool char a, vector unsigned char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool char a, vector bool char b)
+{
+ return __builtin_altivec_vcmpequb_p(__CR6_LT_REV, (vector char)a, (vector char)b);
+}
+
+static int __ATTRS_o_ai
vec_any_ne(vector short a, vector short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_ne(vector short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_ne(vector unsigned short a, vector unsigned short b)
{
return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)a, (vector short)b);
}
static int __ATTRS_o_ai
+vec_any_ne(vector unsigned short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool short a, vector short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool short a, vector unsigned short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool short a, vector bool short b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector pixel a, vector pixel b)
+{
+ return __builtin_altivec_vcmpequh_p(__CR6_LT_REV, (vector short)a, (vector short)b);
+}
+
+static int __ATTRS_o_ai
vec_any_ne(vector int a, vector int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, a, b);
}
static int __ATTRS_o_ai
+vec_any_ne(vector int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_ne(vector unsigned int a, vector unsigned int b)
{
return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
}
static int __ATTRS_o_ai
+vec_any_ne(vector unsigned int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool int a, vector int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool int a, vector unsigned int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
+vec_any_ne(vector bool int a, vector bool int b)
+{
+ return __builtin_altivec_vcmpequw_p(__CR6_LT_REV, (vector int)a, (vector int)b);
+}
+
+static int __ATTRS_o_ai
vec_any_ne(vector float a, vector float b)
{
return __builtin_altivec_vcmpeqfp_p(__CR6_LT_REV, a, b);
diff --git a/lib/Headers/avxintrin.h b/lib/Headers/avxintrin.h
new file mode 100644
index 000000000000..884d31cb8917
--- /dev/null
+++ b/lib/Headers/avxintrin.h
@@ -0,0 +1,1156 @@
+/*===---- avxintrin.h - AVX intrinsics -------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#error "Never use <avxintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+typedef double __v4df __attribute__ ((__vector_size__ (32)));
+typedef float __v8sf __attribute__ ((__vector_size__ (32)));
+typedef long long __v4di __attribute__ ((__vector_size__ (32)));
+typedef int __v8si __attribute__ ((__vector_size__ (32)));
+typedef short __v16hi __attribute__ ((__vector_size__ (32)));
+typedef char __v32qi __attribute__ ((__vector_size__ (32)));
+
+typedef float __m256 __attribute__ ((__vector_size__ (32)));
+typedef double __m256d __attribute__((__vector_size__(32)));
+typedef long long __m256i __attribute__((__vector_size__(32)));
+
+/* Arithmetic */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_add_pd(__m256d a, __m256d b)
+{
+ return a+b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_add_ps(__m256 a, __m256 b)
+{
+ return a+b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_sub_pd(__m256d a, __m256d b)
+{
+ return a-b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_sub_ps(__m256 a, __m256 b)
+{
+ return a-b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_addsub_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_addsubpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_addsub_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_addsubps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_div_pd(__m256d a, __m256d b)
+{
+ return a / b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_div_ps(__m256 a, __m256 b)
+{
+ return a / b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_max_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_maxpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_max_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_maxps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_min_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_minpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_min_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_minps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_mul_pd(__m256d a, __m256d b)
+{
+ return a * b;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_mul_ps(__m256 a, __m256 b)
+{
+ return a * b;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_sqrt_pd(__m256d a)
+{
+ return (__m256d)__builtin_ia32_sqrtpd256((__v4df)a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_sqrt_ps(__m256 a)
+{
+ return (__m256)__builtin_ia32_sqrtps256((__v8sf)a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_rsqrt_ps(__m256 a)
+{
+ return (__m256)__builtin_ia32_rsqrtps256((__v8sf)a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_rcp_ps(__m256 a)
+{
+ return (__m256)__builtin_ia32_rcpps256((__v8sf)a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_round_pd(__m256d v, const int m)
+{
+ return (__m256d)__builtin_ia32_roundpd256((__v4df)v, m);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_round_ps(__m256 v, const int m)
+{
+ return (__m256)__builtin_ia32_roundps256((__v8sf)v, m);
+}
+
+#define _mm256_ceil_pd(V) _mm256_round_pd((V), _MM_FROUND_CEIL)
+#define _mm256_floor_pd(V) _mm256_round_pd((V), _MM_FROUND_FLOOR)
+#define _mm256_ceil_ps(V) _mm256_round_ps((V), _MM_FROUND_CEIL)
+#define _mm256_floor_ps(V) _mm256_round_ps((V), _MM_FROUND_FLOOR)
+
+/* Logical */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_and_pd(__m256d a, __m256d b)
+{
+ return (__m256d)((__v4di)a & (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_and_ps(__m256 a, __m256 b)
+{
+ return (__m256)((__v8si)a & (__v8si)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_andnot_pd(__m256d a, __m256d b)
+{
+ return (__m256d)(~(__v4di)a & (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_andnot_ps(__m256 a, __m256 b)
+{
+ return (__m256)(~(__v8si)a & (__v8si)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_or_pd(__m256d a, __m256d b)
+{
+ return (__m256d)((__v4di)a | (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_or_ps(__m256 a, __m256 b)
+{
+ return (__m256)((__v8si)a | (__v8si)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_xor_pd(__m256d a, __m256d b)
+{
+ return (__m256d)((__v4di)a ^ (__v4di)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_xor_ps(__m256 a, __m256 b)
+{
+ return (__m256)((__v8si)a ^ (__v8si)b);
+}
+
+/* Horizontal arithmetic */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_hadd_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_haddpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_hadd_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_haddps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_hsub_pd(__m256d a, __m256d b)
+{
+ return (__m256d)__builtin_ia32_hsubpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_hsub_ps(__m256 a, __m256 b)
+{
+ return (__m256)__builtin_ia32_hsubps256((__v8sf)a, (__v8sf)b);
+}
+
+/* Vector permutations */
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_permutevar_pd(__m128d a, __m128i c)
+{
+ return (__m128d)__builtin_ia32_vpermilvarpd((__v2df)a, (__v2di)c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_permutevar_pd(__m256d a, __m256i c)
+{
+ return (__m256d)__builtin_ia32_vpermilvarpd256((__v4df)a, (__v4di)c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_permutevar_ps(__m128 a, __m128i c)
+{
+ return (__m128)__builtin_ia32_vpermilvarps((__v4sf)a, (__v4si)c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_permutevar_ps(__m256 a, __m256i c)
+{
+ return (__m256)__builtin_ia32_vpermilvarps256((__v8sf)a,
+ (__v8si)c);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_permute_pd(__m128d a, const int c)
+{
+ return (__m128d)__builtin_ia32_vpermilpd((__v2df)a, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_permute_pd(__m256d a, const int c)
+{
+ return (__m256d)__builtin_ia32_vpermilpd256((__v4df)a, c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_permute_ps(__m128 a, const int c)
+{
+ return (__m128)__builtin_ia32_vpermilps((__v4sf)a, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_permute_ps(__m256 a, const int c)
+{
+ return (__m256)__builtin_ia32_vpermilps256((__v8sf)a, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_permute2f128_pd(__m256d a, __m256d b, const int c)
+{
+ return (__m256d)__builtin_ia32_vperm2f128_pd256((__v4df)a, (__v4df)b, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_permute2f128_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_vperm2f128_ps256((__v8sf)a, (__v8sf)b, c);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_permute2f128_si256(__m256i a, __m256i b, const int c)
+{
+ return (__m256i)__builtin_ia32_vperm2f128_si256((__v8si)a, (__v8si)b, c);
+}
+
+/* Vector Blend */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_blend_pd(__m256d a, __m256d b, const int c)
+{
+ return (__m256d)__builtin_ia32_blendpd256((__v4df)a, (__v4df)b, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_blend_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_blendps256((__v8sf)a, (__v8sf)b, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_blendv_pd(__m256d a, __m256d b, __m256d c)
+{
+ return (__m256d)__builtin_ia32_blendvpd256((__v4df)a, (__v4df)b, (__v4df)c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_blendv_ps(__m256 a, __m256 b, __m256 c)
+{
+ return (__m256)__builtin_ia32_blendvps256((__v8sf)a, (__v8sf)b, (__v8sf)c);
+}
+
+/* Vector Dot Product */
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_dp_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_dpps256((__v8sf)a, (__v8sf)b, c);
+}
+
+/* Vector shuffle */
+#define _mm256_shuffle_ps(a, b, mask) \
+ (__builtin_shufflevector((__v8sf)(a), (__v8sf)(b), \
+ (mask) & 0x3, ((mask) & 0xc) >> 2, \
+ (((mask) & 0x30) >> 4) + 8, (((mask) & 0xc0) >> 6) + 8, \
+ (mask) & 0x3 + 4, (((mask) & 0xc) >> 2) + 4, \
+ (((mask) & 0x30) >> 4) + 12, (((mask) & 0xc0) >> 6) + 12))
+
+#define _mm256_shuffle_pd(a, b, mask) \
+ (__builtin_shufflevector((__v4df)(a), (__v4df)(b), \
+ (mask) & 0x1, \
+ (((mask) & 0x2) >> 1) + 4, \
+ (((mask) & 0x4) >> 2) + 2, \
+ (((mask) & 0x8) >> 3) + 6))
+
+/* Compare */
+#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */
+#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */
+#define _CMP_LE_OS 0x02 /* Less-than-or-equal (ordered, signaling) */
+#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */
+#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */
+#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */
+#define _CMP_NLE_US 0x06 /* Not-less-than-or-equal (unordered, signaling) */
+#define _CMP_ORD_Q 0x07 /* Ordered (nonsignaling) */
+#define _CMP_EQ_UQ 0x08 /* Equal (unordered, non-signaling) */
+#define _CMP_NGE_US 0x09 /* Not-greater-than-or-equal (unord, signaling) */
+#define _CMP_NGT_US 0x0a /* Not-greater-than (unordered, signaling) */
+#define _CMP_FALSE_OQ 0x0b /* False (ordered, non-signaling) */
+#define _CMP_NEQ_OQ 0x0c /* Not-equal (ordered, non-signaling) */
+#define _CMP_GE_OS 0x0d /* Greater-than-or-equal (ordered, signaling) */
+#define _CMP_GT_OS 0x0e /* Greater-than (ordered, signaling) */
+#define _CMP_TRUE_UQ 0x0f /* True (unordered, non-signaling) */
+#define _CMP_EQ_OS 0x10 /* Equal (ordered, signaling) */
+#define _CMP_LT_OQ 0x11 /* Less-than (ordered, non-signaling) */
+#define _CMP_LE_OQ 0x12 /* Less-than-or-equal (ordered, non-signaling) */
+#define _CMP_UNORD_S 0x13 /* Unordered (signaling) */
+#define _CMP_NEQ_US 0x14 /* Not-equal (unordered, signaling) */
+#define _CMP_NLT_UQ 0x15 /* Not-less-than (unordered, non-signaling) */
+#define _CMP_NLE_UQ 0x16 /* Not-less-than-or-equal (unord, non-signaling) */
+#define _CMP_ORD_S 0x17 /* Ordered (signaling) */
+#define _CMP_EQ_US 0x18 /* Equal (unordered, signaling) */
+#define _CMP_NGE_UQ 0x19 /* Not-greater-than-or-equal (unord, non-sign) */
+#define _CMP_NGT_UQ 0x1a /* Not-greater-than (unordered, non-signaling) */
+#define _CMP_FALSE_OS 0x1b /* False (ordered, signaling) */
+#define _CMP_NEQ_OS 0x1c /* Not-equal (ordered, signaling) */
+#define _CMP_GE_OQ 0x1d /* Greater-than-or-equal (ordered, non-signaling) */
+#define _CMP_GT_OQ 0x1e /* Greater-than (ordered, non-signaling) */
+#define _CMP_TRUE_US 0x1f /* True (unordered, signaling) */
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_pd(__m128d a, __m128d b, const int c)
+{
+ return (__m128d)__builtin_ia32_cmppd((__v2df)a, (__v2df)b, c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_ps(__m128 a, __m128 b, const int c)
+{
+ return (__m128)__builtin_ia32_cmpps((__v4sf)a, (__v4sf)b, c);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_cmp_pd(__m256d a, __m256d b, const int c)
+{
+ return (__m256d)__builtin_ia32_cmppd256((__v4df)a, (__v4df)b, c);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_cmp_ps(__m256 a, __m256 b, const int c)
+{
+ return (__m256)__builtin_ia32_cmpps256((__v8sf)a, (__v8sf)b, c);
+}
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_sd(__m128d a, __m128d b, const int c)
+{
+ return (__m128d)__builtin_ia32_cmpsd((__v2df)a, (__v2df)b, c);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cmp_ss(__m128 a, __m128 b, const int c)
+{
+ return (__m128)__builtin_ia32_cmpss((__v4sf)a, (__v4sf)b, c);
+}
+
+/* Vector extract */
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm256_extractf128_pd(__m256d a, const int o)
+{
+ return (__m128d)__builtin_ia32_vextractf128_pd256((__v4df)a, o);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm256_extractf128_ps(__m256 a, const int o)
+{
+ return (__m128)__builtin_ia32_vextractf128_ps256((__v8sf)a, o);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_extractf128_si256(__m256i a, const int o)
+{
+ return (__m128i)__builtin_ia32_vextractf128_si256((__v8si)a, o);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi32(__m256i a, int const imm)
+{
+ __v8si b = (__v8si)a;
+ return b[imm];
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi16(__m256i a, int const imm)
+{
+ __v16hi b = (__v16hi)a;
+ return b[imm];
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi8(__m256i a, int const imm)
+{
+ __v32qi b = (__v32qi)a;
+ return b[imm];
+}
+
+#ifdef __x86_64__
+static __inline long long __attribute__((__always_inline__, __nodebug__))
+_mm256_extract_epi64(__m256i a, const int imm)
+{
+ __v4di b = (__v4di)a;
+ return b[imm];
+}
+#endif
+
+/* Vector insert */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_insertf128_pd(__m256d a, __m128d b, const int o)
+{
+ return (__m256d)__builtin_ia32_vinsertf128_pd256((__v4df)a, (__v2df)b, o);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_insertf128_ps(__m256 a, __m128 b, const int o)
+{
+ return (__m256)__builtin_ia32_vinsertf128_ps256((__v8sf)a, (__v4sf)b, o);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insertf128_si256(__m256i a, __m128i b, const int o)
+{
+ return (__m256i)__builtin_ia32_vinsertf128_si256((__v8si)a, (__v4si)b, o);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi32(__m256i a, int b, int const imm)
+{
+ __v8si c = (__v8si)a;
+ c[imm & 7] = b;
+ return (__m256i)c;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi16(__m256i a, int b, int const imm)
+{
+ __v16hi c = (__v16hi)a;
+ c[imm & 15] = b;
+ return (__m256i)c;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi8(__m256i a, int b, int const imm)
+{
+ __v32qi c = (__v32qi)a;
+ c[imm & 31] = b;
+ return (__m256i)c;
+}
+
+#ifdef __x86_64__
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_insert_epi64(__m256i a, int b, int const imm)
+{
+ __v4di c = (__v4di)a;
+ c[imm & 3] = b;
+ return (__m256i)c;
+}
+#endif
+
+/* Conversion */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtepi32_pd(__m128i a)
+{
+ return (__m256d)__builtin_ia32_cvtdq2pd256((__v4si) a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtepi32_ps(__m256i a)
+{
+ return (__m256)__builtin_ia32_cvtdq2ps256((__v8si) a);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtpd_ps(__m256d a)
+{
+ return (__m128)__builtin_ia32_cvtpd2ps256((__v4df) a);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtps_epi32(__m256 a)
+{
+ return (__m256i)__builtin_ia32_cvtps2dq256((__v8sf) a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtps_pd(__m128 a)
+{
+ return (__m256d)__builtin_ia32_cvtps2pd256((__v4sf) a);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvttpd_epi32(__m256d a)
+{
+ return (__m128i)__builtin_ia32_cvttpd2dq256((__v4df) a);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvtpd_epi32(__m256d a)
+{
+ return (__m128i)__builtin_ia32_cvtpd2dq256((__v4df) a);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_cvttps_epi32(__m256 a)
+{
+ return (__m256i)__builtin_ia32_cvttps2dq256((__v8sf) a);
+}
+
+/* Vector replicate */
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_movehdup_ps(__m256 a)
+{
+ return __builtin_shufflevector(a, a, 1, 1, 3, 3, 5, 5, 7, 7);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_moveldup_ps(__m256 a)
+{
+ return __builtin_shufflevector(a, a, 0, 0, 2, 2, 4, 4, 6, 6);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_movedup_pd(__m256d a)
+{
+ return __builtin_shufflevector(a, a, 0, 0, 2, 2);
+}
+
+/* Unpack and Interleave */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_unpackhi_pd(__m256d a, __m256d b)
+{
+ return __builtin_shufflevector(a, b, 1, 5, 1+2, 5+2);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_unpacklo_pd(__m256d a, __m256d b)
+{
+ return __builtin_shufflevector(a, b, 0, 4, 0+2, 4+2);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_unpackhi_ps(__m256 a, __m256 b)
+{
+ return __builtin_shufflevector(a, b, 2, 10, 2+1, 10+1, 6, 14, 6+1, 14+1);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_unpacklo_ps(__m256 a, __m256 b)
+{
+ return __builtin_shufflevector(a, b, 0, 8, 0+1, 8+1, 4, 12, 4+1, 12+1);
+}
+
+/* Bit Test */
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testz_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_vtestzpd((__v2df)a, (__v2df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testc_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_vtestcpd((__v2df)a, (__v2df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testnzc_pd(__m128d a, __m128d b)
+{
+ return __builtin_ia32_vtestnzcpd((__v2df)a, (__v2df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testz_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_vtestzps((__v4sf)a, (__v4sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testc_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_vtestcps((__v4sf)a, (__v4sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm_testnzc_ps(__m128 a, __m128 b)
+{
+ return __builtin_ia32_vtestnzcps((__v4sf)a, (__v4sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testz_pd(__m256d a, __m256d b)
+{
+ return __builtin_ia32_vtestzpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testc_pd(__m256d a, __m256d b)
+{
+ return __builtin_ia32_vtestcpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testnzc_pd(__m256d a, __m256d b)
+{
+ return __builtin_ia32_vtestnzcpd256((__v4df)a, (__v4df)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testz_ps(__m256 a, __m256 b)
+{
+ return __builtin_ia32_vtestzps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testc_ps(__m256 a, __m256 b)
+{
+ return __builtin_ia32_vtestcps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testnzc_ps(__m256 a, __m256 b)
+{
+ return __builtin_ia32_vtestnzcps256((__v8sf)a, (__v8sf)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testz_si256(__m256i a, __m256i b)
+{
+ return __builtin_ia32_ptestz256((__v4di)a, (__v4di)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testc_si256(__m256i a, __m256i b)
+{
+ return __builtin_ia32_ptestc256((__v4di)a, (__v4di)b);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_testnzc_si256(__m256i a, __m256i b)
+{
+ return __builtin_ia32_ptestnzc256((__v4di)a, (__v4di)b);
+}
+
+/* Vector extract sign mask */
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_movemask_pd(__m256d a)
+{
+ return __builtin_ia32_movmskpd256((__v4df)a);
+}
+
+static __inline int __attribute__((__always_inline__, __nodebug__))
+_mm256_movemask_ps(__m256 a)
+{
+ return __builtin_ia32_movmskps256((__v8sf)a);
+}
+
+/* Vector zero */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_zeroall(void)
+{
+ __builtin_ia32_vzeroall();
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_zeroupper(void)
+{
+ __builtin_ia32_vzeroupper();
+}
+
+/* Vector load with broadcast */
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_broadcast_ss(float const *a)
+{
+ return (__m128)__builtin_ia32_vbroadcastss(a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_sd(double const *a)
+{
+ return (__m256d)__builtin_ia32_vbroadcastsd256(a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_ss(float const *a)
+{
+ return (__m256)__builtin_ia32_vbroadcastss256(a);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_pd(__m128d const *a)
+{
+ return (__m256d)__builtin_ia32_vbroadcastf128_pd256(a);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_broadcast_ps(__m128 const *a)
+{
+ return (__m256)__builtin_ia32_vbroadcastf128_ps256(a);
+}
+
+/* SIMD load ops */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_load_pd(double const *p)
+{
+ return *(__m256d *)p;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_load_ps(float const *p)
+{
+ return *(__m256 *)p;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_loadu_pd(double const *p)
+{
+ return (__m256d)__builtin_ia32_loadupd256(p);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_loadu_ps(float const *p)
+{
+ return (__m256)__builtin_ia32_loadups256(p);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_load_si256(__m256i const *p)
+{
+ return *p;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_loadu_si256(__m256i const *p)
+{
+ return (__m256i)__builtin_ia32_loaddqu256((char const *)p);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_lddqu_si256(__m256i const *p)
+{
+ return (__m256i)__builtin_ia32_lddqu256((char const *)p);
+}
+
+/* SIMD store ops */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_store_pd(double *p, __m256d a)
+{
+ *(__m256d *)p = a;
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_store_ps(float *p, __m256 a)
+{
+ *(__m256 *)p = a;
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_storeu_pd(double *p, __m256d a)
+{
+ __builtin_ia32_storeupd256(p, (__v4df)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_storeu_ps(float *p, __m256 a)
+{
+ __builtin_ia32_storeups256(p, (__v8sf)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_store_si256(__m256i *p, __m256i a)
+{
+ *p = a;
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_storeu_si256(__m256i *p, __m256i a)
+{
+ __builtin_ia32_storedqu256((char *)p, (__v32qi)a);
+}
+
+/* Conditional load ops */
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm_maskload_pd(double const *p, __m128d m)
+{
+ return (__m128d)__builtin_ia32_maskloadpd((const __v2df *)p, (__v2df)m);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_maskload_pd(double const *p, __m256d m)
+{
+ return (__m256d)__builtin_ia32_maskloadpd256((const __v4df *)p, (__v4df)m);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_maskload_ps(float const *p, __m128 m)
+{
+ return (__m128)__builtin_ia32_maskloadps((const __v4sf *)p, (__v4sf)m);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_maskload_ps(float const *p, __m256 m)
+{
+ return (__m256)__builtin_ia32_maskloadps256((const __v8sf *)p, (__v8sf)m);
+}
+
+/* Conditional store ops */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_maskstore_ps(float *p, __m256 m, __m256 a)
+{
+ __builtin_ia32_maskstoreps256((__v8sf *)p, (__v8sf)m, (__v8sf)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm_maskstore_pd(double *p, __m128d m, __m128d a)
+{
+ __builtin_ia32_maskstorepd((__v2df *)p, (__v2df)m, (__v2df)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_maskstore_pd(double *p, __m256d m, __m256d a)
+{
+ __builtin_ia32_maskstorepd256((__v4df *)p, (__v4df)m, (__v4df)a);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm_maskstore_ps(float *p, __m128 m, __m128 a)
+{
+ __builtin_ia32_maskstoreps((__v4sf *)p, (__v4sf)m, (__v4sf)a);
+}
+
+/* Cacheability support ops */
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_stream_si256(__m256i *a, __m256i b)
+{
+ __builtin_ia32_movntdq256((__v4di *)a, (__v4di)b);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_stream_pd(double *a, __m256d b)
+{
+ __builtin_ia32_movntpd256(a, (__v4df)b);
+}
+
+static __inline void __attribute__((__always_inline__, __nodebug__))
+_mm256_stream_ps(float *p, __m256 a)
+{
+ __builtin_ia32_movntps256(p, (__v8sf)a);
+}
+
+/* Create vectors */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_set_pd(double a, double b, double c, double d)
+{
+ return (__m256d){ d, c, b, a };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_set_ps(float a, float b, float c, float d,
+ float e, float f, float g, float h)
+{
+ return (__m256){ h, g, f, e, d, c, b, a };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi32(int i0, int i1, int i2, int i3,
+ int i4, int i5, int i6, int i7)
+{
+ return (__m256i)(__v8si){ i7, i6, i5, i4, i3, i2, i1, i0 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi16(short w15, short w14, short w13, short w12,
+ short w11, short w10, short w09, short w08,
+ short w07, short w06, short w05, short w04,
+ short w03, short w02, short w01, short w00)
+{
+ return (__m256i)(__v16hi){ w00, w01, w02, w03, w04, w05, w06, w07,
+ w08, w09, w10, w11, w12, w13, w14, w15 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi8(char b31, char b30, char b29, char b28,
+ char b27, char b26, char b25, char b24,
+ char b23, char b22, char b21, char b20,
+ char b19, char b18, char b17, char b16,
+ char b15, char b14, char b13, char b12,
+ char b11, char b10, char b09, char b08,
+ char b07, char b06, char b05, char b04,
+ char b03, char b02, char b01, char b00)
+{
+ return (__m256i)(__v32qi){
+ b00, b01, b02, b03, b04, b05, b06, b07,
+ b08, b09, b10, b11, b12, b13, b14, b15,
+ b16, b17, b18, b19, b20, b21, b22, b23,
+ b24, b25, b26, b27, b28, b29, b30, b31
+ };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set_epi64x(long long a, long long b, long long c, long long d)
+{
+ return (__m256i)(__v4di){ d, c, b, a };
+}
+
+/* Create vectors with elements in reverse order */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_pd(double a, double b, double c, double d)
+{
+ return (__m256d){ a, b, c, d };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_ps(float a, float b, float c, float d,
+ float e, float f, float g, float h)
+{
+ return (__m256){ a, b, c, d, e, f, g, h };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi32(int i0, int i1, int i2, int i3,
+ int i4, int i5, int i6, int i7)
+{
+ return (__m256i)(__v8si){ i0, i1, i2, i3, i4, i5, i6, i7 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi16(short w15, short w14, short w13, short w12,
+ short w11, short w10, short w09, short w08,
+ short w07, short w06, short w05, short w04,
+ short w03, short w02, short w01, short w00)
+{
+ return (__m256i)(__v16hi){ w15, w14, w13, w12, w11, w10, w09, w08,
+ w07, w06, w05, w04, w03, w02, w01, w00 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi8(char b31, char b30, char b29, char b28,
+ char b27, char b26, char b25, char b24,
+ char b23, char b22, char b21, char b20,
+ char b19, char b18, char b17, char b16,
+ char b15, char b14, char b13, char b12,
+ char b11, char b10, char b09, char b08,
+ char b07, char b06, char b05, char b04,
+ char b03, char b02, char b01, char b00)
+{
+ return (__m256i)(__v32qi){
+ b31, b30, b29, b28, b27, b26, b25, b24,
+ b23, b22, b21, b20, b19, b18, b17, b16,
+ b15, b14, b13, b12, b11, b10, b09, b08,
+ b07, b06, b05, b04, b03, b02, b01, b00 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setr_epi64x(long long a, long long b, long long c, long long d)
+{
+ return (__m256i)(__v4di){ a, b, c, d };
+}
+
+/* Create vectors with repeated elements */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_pd(double w)
+{
+ return (__m256d){ w, w, w, w };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_ps(float w)
+{
+ return (__m256){ w, w, w, w, w, w, w, w };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi32(int i)
+{
+ return (__m256i)(__v8si){ i, i, i, i, i, i, i, i };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi16(short w)
+{
+ return (__m256i)(__v16hi){ w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi8(char b)
+{
+ return (__m256i)(__v32qi){ b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b,
+ b, b, b, b, b, b, b, b, b, b, b, b, b, b, b, b };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_set1_epi64x(long long q)
+{
+ return (__m256i)(__v4di){ q, q, q, q };
+}
+
+/* Create zeroed vectors */
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_setzero_pd(void)
+{
+ return (__m256d){ 0, 0, 0, 0 };
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_setzero_ps(void)
+{
+ return (__m256){ 0, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_setzero_si256(void)
+{
+ return (__m256i){ 0LL, 0LL, 0LL, 0LL };
+}
+
+/* Cast between vector types */
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd_ps(__m256d in)
+{
+ return (__m256)in;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd_si256(__m256d in)
+{
+ return (__m256i)in;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_castps_pd(__m256 in)
+{
+ return (__m256d)in;
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_castps_si256(__m256 in)
+{
+ return (__m256i)in;
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi256_ps(__m256i in)
+{
+ return (__m256)in;
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi256_pd(__m256i in)
+{
+ return (__m256d)in;
+}
+
+static __inline __m128d __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd256_pd128(__m256d in)
+{
+ return __builtin_shufflevector(in, in, 0, 1);
+}
+
+static __inline __m128 __attribute__((__always_inline__, __nodebug__))
+_mm256_castps256_ps128(__m256 in)
+{
+ return __builtin_shufflevector(in, in, 0, 1, 2, 3);
+}
+
+static __inline __m128i __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi256_si128(__m256i in)
+{
+ return __builtin_shufflevector(in, in, 0, 1);
+}
+
+static __inline __m256d __attribute__((__always_inline__, __nodebug__))
+_mm256_castpd128_pd256(__m128d in)
+{
+ __m128d zero = _mm_setzero_pd();
+ return __builtin_shufflevector(in, zero, 0, 1, 2, 2);
+}
+
+static __inline __m256 __attribute__((__always_inline__, __nodebug__))
+_mm256_castps128_ps256(__m128 in)
+{
+ __m128 zero = _mm_setzero_ps();
+ return __builtin_shufflevector(in, zero, 0, 1, 2, 3, 4, 4, 4, 4);
+}
+
+static __inline __m256i __attribute__((__always_inline__, __nodebug__))
+_mm256_castsi128_si256(__m128i in)
+{
+ __m128i zero = _mm_setzero_si128();
+ return __builtin_shufflevector(in, zero, 0, 1, 2, 2);
+}
diff --git a/lib/Headers/emmintrin.h b/lib/Headers/emmintrin.h
index f297f36b549c..e5dfe26b49a6 100644
--- a/lib/Headers/emmintrin.h
+++ b/lib/Headers/emmintrin.h
@@ -1,4 +1,4 @@
-/*===---- xmmintrin.h - SSE intrinsics -------------------------------------===
+/*===---- emmintrin.h - SSE2 intrinsics ------------------------------------===
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,7 +20,7 @@
*
*===-----------------------------------------------------------------------===
*/
-
+
#ifndef __EMMINTRIN_H
#define __EMMINTRIN_H
@@ -33,6 +33,9 @@
typedef double __m128d __attribute__((__vector_size__(16)));
typedef long long __m128i __attribute__((__vector_size__(16)));
+/* Type defines. */
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+typedef long long __v2di __attribute__ ((__vector_size__ (16)));
typedef short __v8hi __attribute__((__vector_size__(16)));
typedef char __v16qi __attribute__((__vector_size__(16)));
@@ -1194,7 +1197,7 @@ static __inline__ int __attribute__((__always_inline__, __nodebug__))
_mm_extract_epi16(__m128i a, int imm)
{
__v8hi b = (__v8hi)a;
- return b[imm];
+ return (unsigned short)b[imm];
}
static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))
diff --git a/lib/Headers/immintrin.h b/lib/Headers/immintrin.h
new file mode 100644
index 000000000000..a19deaac6db9
--- /dev/null
+++ b/lib/Headers/immintrin.h
@@ -0,0 +1,59 @@
+/*===---- immintrin.h - Intel intrinsics -----------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __IMMINTRIN_H
+#define __IMMINTRIN_H
+
+#ifdef __MMX__
+#include <mmintrin.h>
+#endif
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#ifdef __SSE3__
+#include <pmmintrin.h>
+#endif
+
+#ifdef __SSSE3__
+#include <tmmintrin.h>
+#endif
+
+#if defined (__SSE4_2__) || defined (__SSE4_1__)
+#include <smmintrin.h>
+#endif
+
+#if defined (__AES__) || defined (__PCLMUL__)
+#include <wmmintrin.h>
+#endif
+
+#ifdef __AVX__
+#include <avxintrin.h>
+#endif
+
+#endif /* __IMMINTRIN_H */
diff --git a/lib/Headers/mmintrin.h b/lib/Headers/mmintrin.h
index 401d8a7aaede..bad9e1c059dc 100644
--- a/lib/Headers/mmintrin.h
+++ b/lib/Headers/mmintrin.h
@@ -443,6 +443,64 @@ _mm_setr_pi8(char __b7, char __b6, char __b5, char __b4, char __b3, char __b2,
return (__m64)(__v8qi){ __b7, __b6, __b5, __b4, __b3, __b2, __b1, __b0 };
}
+
+/* Aliases for compatibility. */
+#define _m_empty _mm_empty
+#define _m_from_int _mm_cvtsi32_si64
+#define _m_to_int _mm_cvtsi64_si32
+#define _m_packsswb _mm_packs_pi16
+#define _m_packssdw _mm_packs_pi32
+#define _m_packuswb _mm_packs_pu16
+#define _m_punpckhbw _mm_unpackhi_pi8
+#define _m_punpckhwd _mm_unpackhi_pi16
+#define _m_punpckhdq _mm_unpackhi_pi32
+#define _m_punpcklbw _mm_unpacklo_pi8
+#define _m_punpcklwd _mm_unpacklo_pi16
+#define _m_punpckldq _mm_unpacklo_pi32
+#define _m_paddb _mm_add_pi8
+#define _m_paddw _mm_add_pi16
+#define _m_paddd _mm_add_pi32
+#define _m_paddsb _mm_adds_pi8
+#define _m_paddsw _mm_adds_pi16
+#define _m_paddusb _mm_adds_pu8
+#define _m_paddusw _mm_adds_pu16
+#define _m_psubb _mm_sub_pi8
+#define _m_psubw _mm_sub_pi16
+#define _m_psubd _mm_sub_pi32
+#define _m_psubsb _mm_subs_pi8
+#define _m_psubsw _mm_subs_pi16
+#define _m_psubusb _mm_subs_pu8
+#define _m_psubusw _mm_subs_pu16
+#define _m_pmaddwd _mm_madd_pi16
+#define _m_pmulhw _mm_mulhi_pi16
+#define _m_pmullw _mm_mullo_pi16
+#define _m_psllw _mm_sll_pi16
+#define _m_psllwi _mm_slli_pi16
+#define _m_pslld _mm_sll_pi32
+#define _m_pslldi _mm_slli_pi32
+#define _m_psllq _mm_sll_si64
+#define _m_psllqi _mm_slli_si64
+#define _m_psraw _mm_sra_pi16
+#define _m_psrawi _mm_srai_pi16
+#define _m_psrad _mm_sra_pi32
+#define _m_psradi _mm_srai_pi32
+#define _m_psrlw _mm_srl_pi16
+#define _m_psrlwi _mm_srli_pi16
+#define _m_psrld _mm_srl_pi32
+#define _m_psrldi _mm_srli_pi32
+#define _m_psrlq _mm_srl_si64
+#define _m_psrlqi _mm_srli_si64
+#define _m_pand _mm_and_si64
+#define _m_pandn _mm_andnot_si64
+#define _m_por _mm_or_si64
+#define _m_pxor _mm_xor_si64
+#define _m_pcmpeqb _mm_cmpeq_pi8
+#define _m_pcmpeqw _mm_cmpeq_pi16
+#define _m_pcmpeqd _mm_cmpeq_pi32
+#define _m_pcmpgtb _mm_cmpgt_pi8
+#define _m_pcmpgtw _mm_cmpgt_pi16
+#define _m_pcmpgtd _mm_cmpgt_pi32
+
#endif /* __MMX__ */
#endif /* __MMINTRIN_H */
diff --git a/lib/Headers/nmmintrin.h b/lib/Headers/nmmintrin.h
index cc213ce46b6e..f12622d7be68 100644
--- a/lib/Headers/nmmintrin.h
+++ b/lib/Headers/nmmintrin.h
@@ -1,25 +1,25 @@
-/*===---- nmmintrin.h - SSE intrinsics -------------------------------------===
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-* THE SOFTWARE.
-*
-*===-----------------------------------------------------------------------===
-*/
+/*===---- nmmintrin.h - SSE4 intrinsics ------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
#ifndef _NMMINTRIN_H
#define _NMMINTRIN_H
diff --git a/lib/Headers/smmintrin.h b/lib/Headers/smmintrin.h
index 4b0d9e754183..2b8b32190620 100644
--- a/lib/Headers/smmintrin.h
+++ b/lib/Headers/smmintrin.h
@@ -30,10 +30,6 @@
#include <tmmintrin.h>
-/* Type defines. */
-typedef double __v2df __attribute__ ((__vector_size__ (16)));
-typedef long long __v2di __attribute__ ((__vector_size__ (16)));
-
/* SSE4 Rounding macros. */
#define _MM_FROUND_TO_NEAREST_INT 0x00
#define _MM_FROUND_TO_NEG_INF 0x01
@@ -213,11 +209,13 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
__a;}))
#endif /* __x86_64__ */
-/* Extract int from packed integer array at index. */
+/* Extract int from packed integer array at index. This returns the element
+ * as a zero extended value, so it is unsigned.
+ */
#define _mm_extract_epi8(X, N) (__extension__ ({ __v16qi __a = (__v16qi)(X); \
- __a[N];}))
+ (unsigned char)__a[N];}))
#define _mm_extract_epi32(X, N) (__extension__ ({ __v4si __a = (__v4si)(X); \
- __a[N];}))
+ (unsigned)__a[N];}))
#ifdef __x86_64__
#define _mm_extract_epi64(X, N) (__extension__ ({ __v2di __a = (__v2di)(X); \
__a[N];}))
diff --git a/lib/Headers/stddef.h b/lib/Headers/stddef.h
index b1d0d528746d..84ec1a7b4e24 100644
--- a/lib/Headers/stddef.h
+++ b/lib/Headers/stddef.h
@@ -34,12 +34,13 @@ typedef __typeof__(sizeof(int)) size_t;
#ifndef __cplusplus
#ifndef _WCHAR_T
#define _WCHAR_T
-typedef __typeof__(*L"") wchar_t;
+typedef __WCHAR_TYPE__ wchar_t;
#endif
#endif
#undef NULL
#ifdef __cplusplus
+#undef __null // VC++ hack.
#define NULL __null
#else
#define NULL ((void*)0)
diff --git a/lib/Headers/x86intrin.h b/lib/Headers/x86intrin.h
new file mode 100644
index 000000000000..e5e7a6a2b316
--- /dev/null
+++ b/lib/Headers/x86intrin.h
@@ -0,0 +1,31 @@
+/*===---- x86intrin.h - X86 intrinsics -------------------------------------===
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __X86INTRIN_H
+#define __X86INTRIN_H
+
+#include <immintrin.h>
+
+// FIXME: SSE4A, 3dNOW, FMA4, XOP, LWP, ABM, POPCNT
+
+#endif /* __X86INTRIN_H */
diff --git a/lib/Headers/xmmintrin.h b/lib/Headers/xmmintrin.h
index 75e06b5f9754..8363b4594b1f 100644
--- a/lib/Headers/xmmintrin.h
+++ b/lib/Headers/xmmintrin.h
@@ -416,6 +416,12 @@ _mm_cvtps_pi32(__m128 a)
return (__m64)__builtin_ia32_cvtps2pi(a);
}
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_ps2pi(__m128 a)
+{
+ return _mm_cvtps_pi32(a);
+}
+
static __inline__ int __attribute__((__always_inline__, __nodebug__))
_mm_cvttss_si32(__m128 a)
{
@@ -440,6 +446,12 @@ _mm_cvttps_pi32(__m128 a)
return (__m64)__builtin_ia32_cvttps2pi(a);
}
+static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))
+_mm_cvtt_ps2pi(__m128 a)
+{
+ return _mm_cvttps_pi32(a);
+}
+
static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
_mm_cvtsi32_ss(__m128 a, int b)
{
@@ -447,6 +459,12 @@ _mm_cvtsi32_ss(__m128 a, int b)
return a;
}
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_si2ss(__m128 a, int b)
+{
+ return _mm_cvtsi32_ss(a, b);
+}
+
#ifdef __x86_64__
static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
@@ -464,6 +482,12 @@ _mm_cvtpi32_ps(__m128 a, __m64 b)
return __builtin_ia32_cvtpi2ps(a, (__v2si)b);
}
+static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))
+_mm_cvt_pi2ps(__m128 a, __m64 b)
+{
+ return _mm_cvtpi32_ps(a, b);
+}
+
static __inline__ float __attribute__((__always_inline__, __nodebug__))
_mm_cvtss_f32(__m128 a)
{
@@ -590,6 +614,12 @@ _mm_store1_ps(float *p, __m128 a)
}
static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_mm_store_ps1(float *p, __m128 a)
+{
+ return _mm_store1_ps(p, a);
+}
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
_mm_store_ps(float *p, __m128 a)
{
*(__m128 *)p = a;
@@ -602,9 +632,9 @@ _mm_storer_ps(float *p, __m128 a)
_mm_store_ps(p, a);
}
-#define _MM_HINT_T0 1
+#define _MM_HINT_T0 3
#define _MM_HINT_T1 2
-#define _MM_HINT_T2 3
+#define _MM_HINT_T2 1
#define _MM_HINT_NTA 0
/* FIXME: We have to #define this because "sel" must be a constant integer, and
@@ -908,6 +938,23 @@ do { \
(row3) = _mm_movehl_ps(tmp3, tmp1); \
} while (0)
+/* Aliases for compatibility. */
+#define _m_pextrw _mm_extract_pi16
+#define _m_pinsrw _mm_insert_pi16
+#define _m_pmaxsw _mm_max_pi16
+#define _m_pmaxub _mm_max_pu8
+#define _m_pminsw _mm_min_pi16
+#define _m_pminub _mm_min_pu8
+#define _m_pmovmskb _mm_movemask_pi8
+#define _m_pmulhuw _mm_mulhi_pu16
+#define _m_pshufw _mm_shuffle_pi16
+#define _m_maskmovq _mm_maskmove_si64
+#define _m_pavgb _mm_avg_pu8
+#define _m_pavgw _mm_avg_pu16
+#define _m_psadbw _mm_sad_pu8
+#define _m_ _mm_
+#define _m_ _mm_
+
/* Ugly hack for backwards-compatibility (compatible with gcc) */
#ifdef __SSE2__
#include <emmintrin.h>
diff --git a/lib/Index/CMakeLists.txt b/lib/Index/CMakeLists.txt
index 4d6703563613..61f69b218e26 100644
--- a/lib/Index/CMakeLists.txt
+++ b/lib/Index/CMakeLists.txt
@@ -11,6 +11,5 @@ add_clang_library(clangIndex
IndexProvider.cpp
Indexer.cpp
Program.cpp
- ResolveLocation.cpp
SelectorMap.cpp
)
diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp
index 7a247191bee6..749dcc899322 100644
--- a/lib/Index/Entity.cpp
+++ b/lib/Index/Entity.cpp
@@ -134,7 +134,7 @@ Entity EntityGetter::VisitVarDecl(VarDecl *D) {
return Entity();
// If it's static it cannot be referred to by another translation unit.
- if (D->getStorageClass() == VarDecl::Static)
+ if (D->getStorageClass() == SC_Static)
return Entity(D);
return VisitNamedDecl(D);
@@ -142,7 +142,7 @@ Entity EntityGetter::VisitVarDecl(VarDecl *D) {
Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
// If it's static it cannot be refered to by another translation unit.
- if (D->getStorageClass() == FunctionDecl::Static)
+ if (D->getStorageClass() == SC_Static)
return Entity(D);
return VisitNamedDecl(D);
diff --git a/lib/Index/Makefile b/lib/Index/Makefile
index e87e638f69ec..8607d781e5d7 100644
--- a/lib/Index/Makefile
+++ b/lib/Index/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangIndex
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
deleted file mode 100644
index ccd7a126b40c..000000000000
--- a/lib/Index/ResolveLocation.cpp
+++ /dev/null
@@ -1,602 +0,0 @@
-//===--- ResolveLocation.cpp - Source location resolver ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines the ResolveLocationInAST function, which resolves a
-// source location into a ASTLocation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Index/Utils.h"
-#include "clang/Index/ASTLocation.h"
-#include "clang/AST/TypeLocVisitor.h"
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Basic/SourceManager.h"
-using namespace clang;
-using namespace idx;
-
-namespace {
-
-/// \brief Base for the LocResolver classes. Mostly does source range checking.
-class LocResolverBase {
-protected:
- ASTContext &Ctx;
- SourceLocation Loc;
-
- ASTLocation ResolveInDeclarator(Decl *D, Stmt *Stm, TypeSourceInfo *TInfo);
-
- enum RangePos {
- BeforeLoc,
- ContainsLoc,
- AfterLoc
- };
-
- RangePos CheckRange(SourceRange Range);
- RangePos CheckRange(TypeSourceInfo *TInfo);
- RangePos CheckRange(Decl *D) {
- if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
- if (ContainsLocation(DD->getTypeSourceInfo()))
- return ContainsLoc;
- if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
- if (ContainsLocation(TD->getTypeSourceInfo()))
- return ContainsLoc;
-
- return CheckRange(D->getSourceRange());
- }
- RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
- RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getLocalSourceRange()); }
-
- template <typename T>
- bool isBeforeLocation(T Node) {
- return CheckRange(Node) == BeforeLoc;
- }
-
- template <typename T>
- bool isAfterLocation(T Node) {
- return CheckRange(Node) == AfterLoc;
- }
-
-public:
- LocResolverBase(ASTContext &ctx, SourceLocation loc)
- : Ctx(ctx), Loc(loc) {}
-
- template <typename T>
- bool ContainsLocation(T Node) {
- return CheckRange(Node) == ContainsLoc;
- }
-
-#ifndef NDEBUG
- /// \brief Debugging output.
- void print(Decl *D);
- /// \brief Debugging output.
- void print(Stmt *Node);
-#endif
-};
-
-/// \brief Searches a statement for the ASTLocation that corresponds to a source
-/// location.
-class StmtLocResolver : public LocResolverBase,
- public StmtVisitor<StmtLocResolver,
- ASTLocation > {
- Decl * const Parent;
-
-public:
- StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
- : LocResolverBase(ctx, loc), Parent(parent) {}
-
- ASTLocation VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
- ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
- ASTLocation VisitDeclStmt(DeclStmt *Node);
- ASTLocation VisitStmt(Stmt *Node);
-};
-
-/// \brief Searches a declaration for the ASTLocation that corresponds to a
-/// source location.
-class DeclLocResolver : public LocResolverBase,
- public DeclVisitor<DeclLocResolver,
- ASTLocation > {
-public:
- DeclLocResolver(ASTContext &ctx, SourceLocation loc)
- : LocResolverBase(ctx, loc) {}
-
- ASTLocation VisitDeclContext(DeclContext *DC);
- ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
- 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);
-};
-
-class TypeLocResolver : public LocResolverBase,
- public TypeLocVisitor<TypeLocResolver, ASTLocation> {
- Decl * const ParentDecl;
-
-public:
- TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
- : LocResolverBase(ctx, loc), ParentDecl(pd) { }
-
- ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
- ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
- ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
- ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
- ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
- ASTLocation VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
- ASTLocation VisitTypeLoc(TypeLoc TL);
-};
-
-} // anonymous namespace
-
-ASTLocation
-StmtLocResolver::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
- assert(ContainsLocation(Node) &&
- "Should visit only after verifying that loc is in range");
-
- if (Node->isArgumentType()) {
- TypeSourceInfo *TInfo = Node->getArgumentTypeInfo();
- if (ContainsLocation(TInfo))
- return ResolveInDeclarator(Parent, Node, TInfo);
- } else {
- Expr *SubNode = Node->getArgumentExpr();
- if (ContainsLocation(SubNode))
- return Visit(SubNode);
- }
-
- return ASTLocation(Parent, Node);
-}
-
-
-ASTLocation
-StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
- assert(ContainsLocation(Node) &&
- "Should visit only after verifying that loc is in range");
-
- if (Node->getNumArgs() == 1)
- // Unary operator. Let normal child traversal handle it.
- return VisitCallExpr(Node);
-
- assert(Node->getNumArgs() == 2 &&
- "Wrong args for the C++ operator call expr ?");
-
- llvm::SmallVector<Expr *, 3> Nodes;
- // Binary operator. Check in order of 1-left arg, 2-callee, 3-right arg.
- Nodes.push_back(Node->getArg(0));
- Nodes.push_back(Node->getCallee());
- Nodes.push_back(Node->getArg(1));
-
- for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
- RangePos RP = CheckRange(Nodes[i]);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return Visit(Nodes[i]);
- }
-
- return ASTLocation(Parent, Node);
-}
-
-ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
- assert(ContainsLocation(Node) &&
- "Should visit only after verifying that loc is in range");
-
- // Search all declarations of this DeclStmt.
- for (DeclStmt::decl_iterator
- I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return DeclLocResolver(Ctx, Loc).Visit(*I);
- }
-
- return ASTLocation(Parent, Node);
-}
-
-ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
- assert(ContainsLocation(Node) &&
- "Should visit only after verifying that loc is in range");
-
- // Search the child statements.
- for (Stmt::child_iterator
- I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
- if (*I == NULL)
- continue;
-
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return Visit(*I);
- }
-
- return ASTLocation(Parent, Node);
-}
-
-ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
- for (DeclContext::decl_iterator
- I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return Visit(*I);
- }
-
- return ASTLocation(cast<Decl>(DC));
-}
-
-ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
- ASTLocation ASTLoc = VisitDeclContext(TU);
- if (ASTLoc.getParentDecl() == TU)
- return ASTLocation();
- return ASTLoc;
-}
-
-ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
- assert(ContainsLocation(D) &&
- "Should visit only after verifying that loc is in range");
-
- if (ContainsLocation(D->getTypeSourceInfo()))
- return ResolveInDeclarator(D, 0, D->getTypeSourceInfo());
-
- // First, search through the parameters of the function.
- for (FunctionDecl::param_iterator
- I = D->param_begin(), E = D->param_end(); I != E; ++I) {
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- return ASTLocation(D);
- if (RP == ContainsLoc)
- return Visit(*I);
- }
-
- // We didn't find the location in the parameters and we didn't get passed it.
-
- if (!D->isThisDeclarationADefinition())
- return ASTLocation(D);
-
- // Second, search through the declarations that are part of the function.
- // If we find the location there, we won't have to search through its body.
-
- for (DeclContext::decl_iterator
- I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
- if (isa<ParmVarDecl>(*I))
- continue; // We already searched through the parameters.
-
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return Visit(*I);
- }
-
- // We didn't find a declaration that corresponds to the source location.
-
- // Finally, search through the body of the function.
- Stmt *Body = D->getBody();
- assert(Body && "Expected definition");
- assert(!isBeforeLocation(Body) &&
- "This function is supposed to contain the loc");
- if (isAfterLocation(Body))
- return ASTLocation(D);
-
- // The body contains the location.
- assert(ContainsLocation(Body));
- return StmtLocResolver(Ctx, Loc, D).Visit(Body);
-}
-
-ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
- assert(ContainsLocation(D) &&
- "Should visit only after verifying that loc is in range");
- if (ContainsLocation(D->getTypeSourceInfo()))
- return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeSourceInfo());
-
- return ASTLocation(D);
-}
-
-ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
- assert(ContainsLocation(D) &&
- "Should visit only after verifying that loc is in range");
-
- if (ContainsLocation(D->getTypeSourceInfo()))
- return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeSourceInfo());
-
- return ASTLocation(D);
-}
-
-ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
- assert(ContainsLocation(D) &&
- "Should visit only after verifying that loc is in range");
-
- // Check whether the location points to the init expression.
- Expr *Init = D->getInit();
- if (Init && ContainsLocation(Init))
- return StmtLocResolver(Ctx, Loc, D).Visit(Init);
-
- if (ContainsLocation(D->getTypeSourceInfo()))
- return ResolveInDeclarator(D, 0, D->getTypeSourceInfo());
-
- 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");
-
- // First, search through the parameters of the method.
- for (ObjCMethodDecl::param_iterator
- I = D->param_begin(), E = D->param_end(); I != E; ++I) {
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- return ASTLocation(D);
- if (RP == ContainsLoc)
- return Visit(*I);
- }
-
- // We didn't find the location in the parameters and we didn't get passed it.
-
- if (!D->getBody())
- return ASTLocation(D);
-
- // Second, search through the declarations that are part of the method.
- // If we find he location there, we won't have to search through its body.
-
- for (DeclContext::decl_iterator
- I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
- if (isa<ParmVarDecl>(*I))
- continue; // We already searched through the parameters.
-
- RangePos RP = CheckRange(*I);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return Visit(*I);
- }
-
- // We didn't find a declaration that corresponds to the source location.
-
- // Finally, search through the body of the method.
- Stmt *Body = D->getBody();
- assert(Body && "Expected definition");
- assert(!isBeforeLocation(Body) &&
- "This method is supposed to contain the loc");
- if (isAfterLocation(Body))
- return ASTLocation(D);
-
- // The body contains the location.
- assert(ContainsLocation(Body));
- return StmtLocResolver(Ctx, Loc, D).Visit(Body);
-}
-
-ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
- assert(ContainsLocation(D) &&
- "Should visit only after verifying that loc is in range");
- if (DeclContext *DC = dyn_cast<DeclContext>(D))
- return VisitDeclContext(DC);
- return ASTLocation(D);
-}
-
-ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
- // Continue the 'id' magic by making the builtin type (which cannot
- // actually be spelled) map to the typedef.
- BuiltinType *T = TL.getTypePtr();
- if (T->getKind() == BuiltinType::ObjCId) {
- TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
- return ASTLocation(ParentDecl, D, TL.getNameLoc());
- }
-
- // Same thing with 'Class'.
- if (T->getKind() == BuiltinType::ObjCClass) {
- TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
- return ASTLocation(ParentDecl, D, TL.getNameLoc());
- }
-
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
- if (ContainsLocation(TL.getNameLoc()))
- return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
-
- for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
- ParmVarDecl *Parm = TL.getArg(i);
- RangePos RP = CheckRange(Parm);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return DeclLocResolver(Ctx, Loc).Visit(Parm);
- }
-
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
-
- Expr *E = TL.getSizeExpr();
- if (E && ContainsLocation(E))
- return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
-
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
- if (ContainsLocation(TL.getNameLoc()))
- return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
-
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
-
- for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
- SourceLocation L = TL.getProtocolLoc(i);
- RangePos RP = CheckRange(L);
- if (RP == AfterLoc)
- break;
- if (RP == ContainsLoc)
- return ASTLocation(ParentDecl, TL.getProtocol(i), L);
- }
-
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
- assert(ContainsLocation(TL) &&
- "Should visit only after verifying that loc is in range");
- return ASTLocation(ParentDecl, TL);
-}
-
-ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
- TypeSourceInfo *TInfo) {
- assert(ContainsLocation(TInfo) &&
- "Should visit only after verifying that loc is in range");
-
- (void)TypeLocResolver(Ctx, Loc, D);
- for (TypeLoc TL = TInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
- if (ContainsLocation(TL))
- return TypeLocResolver(Ctx, Loc, D).Visit(TL);
-
- assert(0 && "Should have found the loc in a typeloc");
- return ASTLocation(D, Stm);
-}
-
-LocResolverBase::RangePos LocResolverBase::CheckRange(TypeSourceInfo *TInfo) {
- if (!TInfo)
- return BeforeLoc; // Keep looking.
-
- for (TypeLoc TL = TInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
- if (ContainsLocation(TL))
- return ContainsLoc;
-
- return BeforeLoc; // Keep looking.
-}
-
-LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
- if (!Range.isValid())
- return BeforeLoc; // Keep looking.
-
- // Update the end source range to cover the full length of the token
- // positioned at the end of the source range.
- //
- // e.g.,
- // int foo
- // ^ ^
- //
- // will be updated to
- // int foo
- // ^ ^
- unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
- Ctx.getSourceManager(),
- Ctx.getLangOptions());
- Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
-
- SourceManager &SourceMgr = Ctx.getSourceManager();
- if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
- return BeforeLoc;
-
- if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
- return AfterLoc;
-
- return ContainsLoc;
-}
-
-#ifndef NDEBUG
-void LocResolverBase::print(Decl *D) {
- llvm::raw_ostream &OS = llvm::outs();
- OS << "#### DECL " << D->getDeclKindName() << " ####\n";
- D->print(OS);
- OS << " <";
- D->getLocStart().print(OS, Ctx.getSourceManager());
- OS << " > - <";
- D->getLocEnd().print(OS, Ctx.getSourceManager());
- OS << ">\n\n";
- OS.flush();
-}
-
-void LocResolverBase::print(Stmt *Node) {
- llvm::raw_ostream &OS = llvm::outs();
- OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
- Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
- OS << " <";
- Node->getLocStart().print(OS, Ctx.getSourceManager());
- OS << " > - <";
- Node->getLocEnd().print(OS, Ctx.getSourceManager());
- OS << ">\n\n";
- OS.flush();
-}
-#endif
-
-
-/// \brief Returns the AST node that a source location points to.
-///
-ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- ASTLocation *LastLoc) {
- if (Loc.isInvalid())
- return ASTLocation();
-
- if (LastLoc && LastLoc->isValid()) {
- DeclContext *DC = 0;
-
- if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
- DC = Dcl->getDeclContext();
- } else if (LastLoc->isStmt()) {
- Decl *Parent = LastLoc->getParentDecl();
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
- DC = FD;
- else {
- // This is needed to handle statements within an initializer.
- // Example:
- // void func() { long double fabsf = __builtin_fabsl(__x); }
- // In this case, the 'parent' of __builtin_fabsl is fabsf.
- DC = Parent->getDeclContext();
- }
- } else { // We have 'N_NamedRef' or 'N_Type'
- DC = LastLoc->getParentDecl()->getDeclContext();
- }
- assert(DC && "Missing DeclContext");
-
- FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
- DeclLocResolver DLocResolver(Ctx, Loc);
-
- if (FD && FD->isThisDeclarationADefinition() &&
- DLocResolver.ContainsLocation(FD)) {
- return DLocResolver.VisitFunctionDecl(FD);
- }
- // Fall through and try the slow path...
- // FIXME: Optimize more cases.
- }
- return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
-}
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 91b14f638ded..917829be47c6 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -27,7 +27,9 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cctype>
@@ -247,6 +249,200 @@ unsigned Lexer::MeasureTokenLength(SourceLocation Loc,
return TheTok.getLength();
}
+SourceLocation Lexer::GetBeginningOfToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ bool Invalid = false;
+ llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return Loc;
+
+ // Back up from the current location until we hit the beginning of a line
+ // (or the buffer). We'll relex from that point.
+ const char *BufStart = Buffer.data();
+ const char *StrData = BufStart+LocInfo.second;
+ if (StrData[0] == '\n' || StrData[0] == '\r')
+ return Loc;
+
+ const char *LexStart = StrData;
+ while (LexStart != BufStart) {
+ if (LexStart[0] == '\n' || LexStart[0] == '\r') {
+ ++LexStart;
+ break;
+ }
+
+ --LexStart;
+ }
+
+ // Create a lexer starting at the beginning of this token.
+ SourceLocation LexerStartLoc = Loc.getFileLocWithOffset(-LocInfo.second);
+ Lexer TheLexer(LexerStartLoc, LangOpts, BufStart, LexStart, Buffer.end());
+ TheLexer.SetCommentRetentionState(true);
+
+ // Lex tokens until we find the token that contains the source location.
+ Token TheTok;
+ do {
+ TheLexer.LexFromRawLexer(TheTok);
+
+ if (TheLexer.getBufferLocation() > StrData) {
+ // Lexing this token has taken the lexer past the source location we're
+ // looking for. If the current token encompasses our source location,
+ // return the beginning of that token.
+ if (TheLexer.getBufferLocation() - TheTok.getLength() <= StrData)
+ return TheTok.getLocation();
+
+ // We ended up skipping over the source location entirely, which means
+ // that it points into whitespace. We're done here.
+ break;
+ }
+ } while (TheTok.getKind() != tok::eof);
+
+ // We've passed our source location; just return the original source location.
+ return Loc;
+}
+
+namespace {
+ enum PreambleDirectiveKind {
+ PDK_Skipped,
+ PDK_StartIf,
+ PDK_EndIf,
+ PDK_Unknown
+ };
+}
+
+std::pair<unsigned, bool>
+Lexer::ComputePreamble(const llvm::MemoryBuffer *Buffer, unsigned MaxLines) {
+ // Create a lexer starting at the beginning of the file. Note that we use a
+ // "fake" file source location at offset 1 so that the lexer will track our
+ // position within the file.
+ const unsigned StartOffset = 1;
+ SourceLocation StartLoc = SourceLocation::getFromRawEncoding(StartOffset);
+ LangOptions LangOpts;
+ Lexer TheLexer(StartLoc, LangOpts, Buffer->getBufferStart(),
+ Buffer->getBufferStart(), Buffer->getBufferEnd());
+
+ bool InPreprocessorDirective = false;
+ Token TheTok;
+ Token IfStartTok;
+ unsigned IfCount = 0;
+ unsigned Line = 0;
+
+ do {
+ TheLexer.LexFromRawLexer(TheTok);
+
+ if (InPreprocessorDirective) {
+ // If we've hit the end of the file, we're done.
+ if (TheTok.getKind() == tok::eof) {
+ InPreprocessorDirective = false;
+ break;
+ }
+
+ // If we haven't hit the end of the preprocessor directive, skip this
+ // token.
+ if (!TheTok.isAtStartOfLine())
+ continue;
+
+ // We've passed the end of the preprocessor directive, and will look
+ // at this token again below.
+ InPreprocessorDirective = false;
+ }
+
+ // Keep track of the # of lines in the preamble.
+ if (TheTok.isAtStartOfLine()) {
+ ++Line;
+
+ // If we were asked to limit the number of lines in the preamble,
+ // and we're about to exceed that limit, we're done.
+ if (MaxLines && Line >= MaxLines)
+ break;
+ }
+
+ // Comments are okay; skip over them.
+ if (TheTok.getKind() == tok::comment)
+ continue;
+
+ if (TheTok.isAtStartOfLine() && TheTok.getKind() == tok::hash) {
+ // This is the start of a preprocessor directive.
+ Token HashTok = TheTok;
+ InPreprocessorDirective = true;
+
+ // Figure out which direective this is. Since we're lexing raw tokens,
+ // we don't have an identifier table available. Instead, just look at
+ // the raw identifier to recognize and categorize preprocessor directives.
+ TheLexer.LexFromRawLexer(TheTok);
+ if (TheTok.getKind() == tok::identifier && !TheTok.needsCleaning()) {
+ const char *IdStart = Buffer->getBufferStart()
+ + TheTok.getLocation().getRawEncoding() - 1;
+ llvm::StringRef Keyword(IdStart, TheTok.getLength());
+ PreambleDirectiveKind PDK
+ = llvm::StringSwitch<PreambleDirectiveKind>(Keyword)
+ .Case("include", PDK_Skipped)
+ .Case("__include_macros", PDK_Skipped)
+ .Case("define", PDK_Skipped)
+ .Case("undef", PDK_Skipped)
+ .Case("line", PDK_Skipped)
+ .Case("error", PDK_Skipped)
+ .Case("pragma", PDK_Skipped)
+ .Case("import", PDK_Skipped)
+ .Case("include_next", PDK_Skipped)
+ .Case("warning", PDK_Skipped)
+ .Case("ident", PDK_Skipped)
+ .Case("sccs", PDK_Skipped)
+ .Case("assert", PDK_Skipped)
+ .Case("unassert", PDK_Skipped)
+ .Case("if", PDK_StartIf)
+ .Case("ifdef", PDK_StartIf)
+ .Case("ifndef", PDK_StartIf)
+ .Case("elif", PDK_Skipped)
+ .Case("else", PDK_Skipped)
+ .Case("endif", PDK_EndIf)
+ .Default(PDK_Unknown);
+
+ switch (PDK) {
+ case PDK_Skipped:
+ continue;
+
+ case PDK_StartIf:
+ if (IfCount == 0)
+ IfStartTok = HashTok;
+
+ ++IfCount;
+ continue;
+
+ case PDK_EndIf:
+ // Mismatched #endif. The preamble ends here.
+ if (IfCount == 0)
+ break;
+
+ --IfCount;
+ continue;
+
+ case PDK_Unknown:
+ // We don't know what this directive is; stop at the '#'.
+ break;
+ }
+ }
+
+ // We only end up here if we didn't recognize the preprocessor
+ // directive or it was one that can't occur in the preamble at this
+ // point. Roll back the current token to the location of the '#'.
+ InPreprocessorDirective = false;
+ TheTok = HashTok;
+ }
+
+ // We hit a token that we don't recognize as being in the
+ // "preprocessing only" part of the file, so we're no longer in
+ // the preamble.
+ break;
+ } while (true);
+
+ SourceLocation End = IfCount? IfStartTok.getLocation() : TheTok.getLocation();
+ return std::make_pair(End.getRawEncoding() - StartLoc.getRawEncoding(),
+ IfCount? IfStartTok.isAtStartOfLine()
+ : TheTok.isAtStartOfLine());
+}
+
//===----------------------------------------------------------------------===//
// Character information.
//===----------------------------------------------------------------------===//
@@ -476,7 +672,7 @@ static char DecodeTrigraphChar(const char *CP, Lexer *L) {
}
if (!L->isLexingRawMode())
- L->Diag(CP-2, diag::trigraph_converted) << std::string()+Res;
+ L->Diag(CP-2, diag::trigraph_converted) << llvm::StringRef(&Res, 1);
return Res;
}
@@ -647,6 +843,14 @@ Slash:
// Helper methods for lexing.
//===----------------------------------------------------------------------===//
+/// \brief Routine that indiscriminately skips bytes in the source file.
+void Lexer::SkipBytes(unsigned Bytes, bool StartOfLine) {
+ BufferPtr += Bytes;
+ if (BufferPtr > BufferEnd)
+ BufferPtr = BufferEnd;
+ IsAtStartOfLine = StartOfLine;
+}
+
void Lexer::LexIdentifier(Token &Result, const char *CurPtr) {
// Match [_A-Za-z0-9]*, we have already matched [_A-Za-z$]
unsigned Size;
@@ -716,6 +920,16 @@ FinishIdentifier:
}
}
+/// isHexaLiteral - Return true if Start points to a hex constant.
+/// in microsoft mode (where this is supposed to be several different tokens).
+static bool isHexaLiteral(const char *Start, const LangOptions &Features) {
+ unsigned Size;
+ char C1 = Lexer::getCharAndSizeNoWarn(Start, Size, Features);
+ if (C1 != '0')
+ return false;
+ char C2 = Lexer::getCharAndSizeNoWarn(Start + Size, Size, Features);
+ return (C2 == 'x' || C2 == 'X');
+}
/// LexNumericConstant - Lex the remainder of a integer or floating point
/// constant. From[-1] is the first character lexed. Return the end of the
@@ -731,12 +945,16 @@ void Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
}
// If we fell out, check for a sign, due to 1e+12. If we have one, continue.
- if ((C == '-' || C == '+') && (PrevCh == 'E' || PrevCh == 'e'))
- return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
+ if ((C == '-' || C == '+') && (PrevCh == 'E' || PrevCh == 'e')) {
+ // If we are in Microsoft mode, don't continue if the constant is hex.
+ // For example, MSVC will accept the following as 3 tokens: 0x1234567e+1
+ if (!Features.Microsoft || !isHexaLiteral(BufferPtr, Features))
+ return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
+ }
// If we have a hex FP constant, continue.
if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p') &&
- (!PP || !PP->getLangOptions().CPlusPlus0x))
+ !Features.CPlusPlus0x)
return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
// Update the location of token as well as BufferPtr.
@@ -759,7 +977,9 @@ void Lexer::LexStringLiteral(Token &Result, const char *CurPtr, bool Wide) {
if (C == '\n' || C == '\r' || // Newline.
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
- if (!isLexingRawMode() && !Features.AsmPreprocessor)
+ if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+ else if (!isLexingRawMode() && !Features.AsmPreprocessor)
Diag(BufferPtr, diag::err_unterminated_string);
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
return;
@@ -836,7 +1056,9 @@ void Lexer::LexCharConstant(Token &Result, const char *CurPtr) {
C = getAndAdvanceChar(CurPtr, Result);
} else if (C == '\n' || C == '\r' || // Newline.
(C == 0 && CurPtr-1 == BufferEnd)) { // End of file.
- if (!isLexingRawMode() && !Features.AsmPreprocessor)
+ if (C == 0 && PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+ else if (!isLexingRawMode() && !Features.AsmPreprocessor)
Diag(BufferPtr, diag::err_unterminated_char);
FormTokenWithChars(Result, CurPtr-1, tok::unknown);
return;
@@ -980,7 +1202,13 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) {
}
}
- if (CurPtr == BufferEnd+1) { --CurPtr; break; }
+ if (CurPtr == BufferEnd+1) {
+ if (PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+
+ --CurPtr;
+ break;
+ }
} while (C != '\n' && C != '\r');
// Found but did not consume the newline. Notify comment handlers about the
@@ -1219,7 +1447,9 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) {
Diag(CurPtr-1, diag::warn_nested_block_comment);
}
} else if (C == 0 && CurPtr == BufferEnd+1) {
- if (!isLexingRawMode() && !PP->isCodeCompletionFile(FileLoc))
+ if (PP && PP->isCodeCompletionFile(FileLoc))
+ PP->CodeCompleteNaturalLanguage();
+ else if (!isLexingRawMode())
Diag(BufferPtr, diag::err_unterminated_block_comment);
// Note: the user probably forgot a */. We could continue immediately
// after the /*, but this would involve lexing a lot of what really is the
@@ -1305,6 +1535,11 @@ std::string Lexer::ReadToEndOfLine() {
// Next, lex the character, which should handle the EOM transition.
Lex(Tmp);
+ if (Tmp.is(tok::code_completion)) {
+ if (PP && PP->getCodeCompletionHandler())
+ PP->getCodeCompletionHandler()->CodeCompleteNaturalLanguage();
+ Lex(Tmp);
+ }
assert(Tmp.is(tok::eom) && "Unexpected token!");
// Finally, we're done, return the string we found.
@@ -1318,6 +1553,22 @@ std::string Lexer::ReadToEndOfLine() {
/// This returns true if Result contains a token, false if PP.Lex should be
/// called again.
bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
+ // Check if we are performing code completion.
+ if (PP && PP->isCodeCompletionFile(FileLoc)) {
+ // We're at the end of the file, but we've been asked to consider the
+ // end of the file to be a code-completion token. Return the
+ // code-completion token.
+ Result.startToken();
+ FormTokenWithChars(Result, CurPtr, tok::code_completion);
+
+ // Only do the eof -> code_completion translation once.
+ PP->SetCodeCompletionPoint(0, 0, 0);
+
+ // Silence any diagnostics that occur once we hit the code-completion point.
+ PP->getDiagnostics().setSuppressAllDiagnostics(true);
+ return true;
+ }
+
// If we hit the end of the file while parsing a preprocessor directive,
// end the preprocessor directive first. The next token returned will
// then be the end of file.
@@ -1340,29 +1591,14 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
FormTokenWithChars(Result, BufferEnd, tok::eof);
return true;
}
-
- // Otherwise, check if we are code-completing, then issue diagnostics for
- // unterminated #if and missing newline.
-
- if (PP && PP->isCodeCompletionFile(FileLoc)) {
- // We're at the end of the file, but we've been asked to consider the
- // end of the file to be a code-completion token. Return the
- // code-completion token.
- Result.startToken();
- FormTokenWithChars(Result, CurPtr, tok::code_completion);
-
- // Only do the eof -> code_completion translation once.
- PP->SetCodeCompletionPoint(0, 0, 0);
-
- // Silence any diagnostics that occur once we hit the code-completion point.
- PP->getDiagnostics().setSuppressAllDiagnostics(true);
- return true;
- }
+ // Issue diagnostics for unterminated #if and missing newline.
+
// If we are in a #if directive, emit an error.
while (!ConditionalStack.empty()) {
- PP->Diag(ConditionalStack.back().IfLoc,
- diag::err_pp_unterminated_conditional);
+ if (!PP->isCodeCompletionFile(FileLoc))
+ PP->Diag(ConditionalStack.back().IfLoc,
+ diag::err_pp_unterminated_conditional);
ConditionalStack.pop_back();
}
diff --git a/lib/Lex/LiteralSupport.cpp b/lib/Lex/LiteralSupport.cpp
index b8fd3ce9e9ff..fb543d0f03b3 100644
--- a/lib/Lex/LiteralSupport.cpp
+++ b/lib/Lex/LiteralSupport.cpp
@@ -170,6 +170,7 @@ static unsigned ProcessCharEscape(const char *&ThisTokBuf,
static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd,
char *&ResultBuf, bool &HadError,
SourceLocation Loc, Preprocessor &PP,
+ bool wide,
bool Complain) {
// FIXME: Add a warning - UCN's are only valid in C++ & C99.
// FIXME: Handle wide strings.
@@ -190,6 +191,7 @@ static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd,
UTF32 UcnVal = 0;
unsigned short UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8);
+ unsigned short UcnLenSave = UcnLen;
for (; ThisTokBuf != ThisTokEnd && UcnLen; ++ThisTokBuf, UcnLen--) {
int CharVal = HexDigitValue(ThisTokBuf[0]);
if (CharVal == -1) break;
@@ -214,6 +216,17 @@ static void ProcessUCNEscape(const char *&ThisTokBuf, const char *ThisTokEnd,
HadError = 1;
return;
}
+ if (wide) {
+ (void)UcnLenSave;
+ assert(UcnLenSave == 4 &&
+ "ProcessUCNEscape - only ucn length of 4 supported");
+ // little endian assumed.
+ *ResultBuf++ = (UcnVal & 0x000000FF);
+ *ResultBuf++ = (UcnVal & 0x0000FF00) >> 8;
+ *ResultBuf++ = (UcnVal & 0x00FF0000) >> 16;
+ *ResultBuf++ = (UcnVal & 0xFF000000) >> 24;
+ return;
+ }
// Now that we've parsed/checked the UCN, we convert from UTF32->UTF8.
// The conversion below was inspired by:
// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
@@ -323,7 +336,7 @@ NumericLiteralParser(const char *begin, const char *end,
// Done.
} else if (isxdigit(*s) && !(*s == 'e' || *s == 'E')) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
- diag::err_invalid_decimal_digit) << std::string(s, s+1);
+ diag::err_invalid_decimal_digit) << llvm::StringRef(s, 1);
hadError = true;
return;
} else if (*s == '.') {
@@ -439,7 +452,7 @@ NumericLiteralParser(const char *begin, const char *end,
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-begin),
isFPConstant ? diag::err_invalid_suffix_float_constant :
diag::err_invalid_suffix_integer_constant)
- << std::string(SuffixBegin, ThisTokEnd);
+ << llvm::StringRef(SuffixBegin, ThisTokEnd-SuffixBegin);
hadError = true;
return;
}
@@ -510,7 +523,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
// Done.
} else if (isxdigit(*s)) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
- diag::err_invalid_binary_digit) << std::string(s, s+1);
+ diag::err_invalid_binary_digit) << llvm::StringRef(s, 1);
hadError = true;
}
// Other suffixes will be diagnosed by the caller.
@@ -540,7 +553,7 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
// the code is using an incorrect base.
if (isxdigit(*s) && *s != 'e' && *s != 'E') {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
- diag::err_invalid_octal_digit) << std::string(s, s+1);
+ diag::err_invalid_octal_digit) << llvm::StringRef(s, 1);
hadError = true;
return;
}
@@ -830,12 +843,14 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
}
const char *ThisTokEnd = ThisTokBuf+ThisTokLen-1; // Skip end quote.
-
+ bool wide = false;
// TODO: Input character set mapping support.
// Skip L marker for wide strings.
- if (ThisTokBuf[0] == 'L')
+ if (ThisTokBuf[0] == 'L') {
+ wide = true;
++ThisTokBuf;
+ }
assert(ThisTokBuf[0] == '"' && "Expected quote, lexer broken?");
++ThisTokBuf;
@@ -880,7 +895,8 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
// Is this a Universal Character Name escape?
if (ThisTokBuf[1] == 'u' || ThisTokBuf[1] == 'U') {
ProcessUCNEscape(ThisTokBuf, ThisTokEnd, ResultPtr,
- hadError, StringToks[i].getLocation(), PP, Complain);
+ hadError, StringToks[i].getLocation(), PP, wide,
+ Complain);
continue;
}
// Otherwise, this is a non-UCN escape character. Process it.
@@ -911,6 +927,20 @@ StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
hadError = 1;
return;
}
+ } else if (Complain) {
+ // Complain if this string literal has too many characters.
+ unsigned MaxChars = PP.getLangOptions().CPlusPlus? 65536
+ : PP.getLangOptions().C99 ? 4095
+ : 509;
+
+ if (GetNumStringChars() > MaxChars)
+ PP.Diag(StringToks[0].getLocation(), diag::ext_string_too_long)
+ << GetNumStringChars() << MaxChars
+ << (PP.getLangOptions().CPlusPlus? 2
+ : PP.getLangOptions().C99 ? 1
+ : 0)
+ << SourceRange(StringToks[0].getLocation(),
+ StringToks[NumStringToks-1].getLocation());
}
}
diff --git a/lib/Lex/MacroInfo.cpp b/lib/Lex/MacroInfo.cpp
index fda884c4da4c..c6d09349b5ef 100644
--- a/lib/Lex/MacroInfo.cpp
+++ b/lib/Lex/MacroInfo.cpp
@@ -20,13 +20,32 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
IsC99Varargs = false;
IsGNUVarargs = false;
IsBuiltinMacro = false;
+ IsFromAST = false;
IsDisabled = false;
IsUsed = true;
+ IsAllowRedefinitionsWithoutWarning = false;
ArgumentList = 0;
NumArguments = 0;
}
+MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) {
+ Location = MI.Location;
+ EndLocation = MI.EndLocation;
+ ReplacementTokens = MI.ReplacementTokens;
+ IsFunctionLike = MI.IsFunctionLike;
+ IsC99Varargs = MI.IsC99Varargs;
+ IsGNUVarargs = MI.IsGNUVarargs;
+ IsBuiltinMacro = MI.IsBuiltinMacro;
+ IsFromAST = MI.IsFromAST;
+ IsDisabled = MI.IsDisabled;
+ IsUsed = MI.IsUsed;
+ IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning;
+ ArgumentList = 0;
+ NumArguments = 0;
+ setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
+}
+
/// isIdenticalTo - Return true if the specified macro definition is equal to
/// this macro in spelling, arguments, and whitespace. This is used to emit
/// duplicate definition warnings. This implements the rules in C99 6.10.3.
diff --git a/lib/Lex/Makefile b/lib/Lex/Makefile
index 938b8d5f0540..d80fb55c78a7 100644
--- a/lib/Lex/Makefile
+++ b/lib/Lex/Makefile
@@ -15,7 +15,6 @@ CLANG_LEVEL := ../..
include $(CLANG_LEVEL)/../../Makefile.config
LIBRARYNAME := clangLex
-BUILD_ARCHIVE = 1
ifeq ($(ARCH),PowerPC)
CXX.Flags += -maltivec
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 417724b77787..8da7def9ed4d 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -16,6 +16,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/APInt.h"
@@ -25,7 +26,7 @@ using namespace clang;
// Utility Methods for Preprocessor Directive Handling.
//===----------------------------------------------------------------------===//
-MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) {
+MacroInfo *Preprocessor::AllocateMacroInfo() {
MacroInfo *MI;
if (!MICache.empty()) {
@@ -33,15 +34,26 @@ MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) {
MICache.pop_back();
} else
MI = (MacroInfo*) BP.Allocate<MacroInfo>();
+ return MI;
+}
+
+MacroInfo *Preprocessor::AllocateMacroInfo(SourceLocation L) {
+ MacroInfo *MI = AllocateMacroInfo();
new (MI) MacroInfo(L);
return MI;
}
+MacroInfo *Preprocessor::CloneMacroInfo(const MacroInfo &MacroToClone) {
+ MacroInfo *MI = AllocateMacroInfo();
+ new (MI) MacroInfo(MacroToClone, BP);
+ return MI;
+}
+
/// ReleaseMacroInfo - Release the specified MacroInfo. This memory will
/// be reused for allocating new MacroInfo objects.
-void Preprocessor::ReleaseMacroInfo(MacroInfo* MI) {
+void Preprocessor::ReleaseMacroInfo(MacroInfo *MI) {
MICache.push_back(MI);
- MI->FreeArgumentList(BP);
+ MI->FreeArgumentList();
}
@@ -63,6 +75,13 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) {
// Read the token, don't allow macro expansion on it.
LexUnexpandedToken(MacroNameTok);
+ if (MacroNameTok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteMacroName(isDefineUndef == 1);
+ LexUnexpandedToken(MacroNameTok);
+ return;
+ }
+
// Missing macro name?
if (MacroNameTok.is(tok::eom)) {
Diag(MacroNameTok, diag::err_pp_missing_macro_name);
@@ -166,13 +185,20 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation IfTokenLoc,
while (1) {
CurLexer->Lex(Tok);
+ if (Tok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteInConditionalExclusion();
+ continue;
+ }
+
// If this is the end of the buffer, we have an error.
if (Tok.is(tok::eof)) {
// Emit errors for each unterminated conditional on the stack, including
// the current one.
while (!CurPPLexer->ConditionalStack.empty()) {
- Diag(CurPPLexer->ConditionalStack.back().IfLoc,
- diag::err_pp_unterminated_conditional);
+ if (!isCodeCompletionFile(Tok.getLocation()))
+ Diag(CurPPLexer->ConditionalStack.back().IfLoc,
+ diag::err_pp_unterminated_conditional);
CurPPLexer->ConditionalStack.pop_back();
}
@@ -510,7 +536,11 @@ TryAgain:
// Handle stuff like "# /*foo*/ define X" in -E -C mode.
LexUnexpandedToken(Result);
goto TryAgain;
-
+ case tok::code_completion:
+ if (CodeComplete)
+ CodeComplete->CodeCompleteDirective(
+ CurPPLexer->getConditionalStackDepth() > 0);
+ return;
case tok::numeric_constant: // # 7 GNU line marker directive.
if (getLangOptions().AsmPreprocessor)
break; // # 4 is not a preprocessor directive in .S files.
@@ -1445,15 +1475,15 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok) {
if (!OtherMI->isUsed())
Diag(OtherMI->getDefinitionLoc(), diag::pp_macro_not_used);
- // Macros must be identical. This means all tokes and whitespace
+ // Macros must be identical. This means all tokens and whitespace
// separation must be the same. C99 6.10.3.2.
- if (!MI->isIdenticalTo(*OtherMI, *this)) {
+ if (!OtherMI->isAllowRedefinitionsWithoutWarning() &&
+ !MI->isIdenticalTo(*OtherMI, *this)) {
Diag(MI->getDefinitionLoc(), diag::ext_pp_macro_redef)
<< MacroNameTok.getIdentifierInfo();
Diag(OtherMI->getDefinitionLoc(), diag::note_previous_definition);
}
}
-
ReleaseMacroInfo(OtherMI);
}
@@ -1490,7 +1520,8 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) {
// If the callbacks want to know, tell them about the macro #undef.
if (Callbacks)
- Callbacks->MacroUndefined(MacroNameTok.getIdentifierInfo(), MI);
+ Callbacks->MacroUndefined(MacroNameTok.getLocation(),
+ MacroNameTok.getIdentifierInfo(), MI);
// Free macro definition.
ReleaseMacroInfo(MI);
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index 756ce27a93dc..163e869400aa 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -19,11 +19,14 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LiteralSupport.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LexDiagnostic.h"
#include "llvm/ADT/APSInt.h"
using namespace clang;
+namespace {
+
/// PPValue - Represents the value of a subexpression of a preprocessor
/// conditional and the source range covered by it.
class PPValue {
@@ -47,6 +50,8 @@ public:
void setEnd(SourceLocation L) { Range.setEnd(L); }
};
+}
+
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
Token &PeekTok, bool ValueLive,
Preprocessor &PP);
@@ -88,6 +93,12 @@ static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
PP.LexUnexpandedToken(PeekTok);
}
+ if (PeekTok.is(tok::code_completion)) {
+ if (PP.getCodeCompletionHandler())
+ PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
// If we don't have a pp-identifier now, this is an error.
if ((II = PeekTok.getIdentifierInfo()) == 0) {
PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
@@ -138,6 +149,12 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
bool ValueLive, Preprocessor &PP) {
DT.State = DefinedTracker::Unknown;
+ if (PeekTok.is(tok::code_completion)) {
+ if (PP.getCodeCompletionHandler())
+ PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
+ PP.LexUnexpandedToken(PeekTok);
+ }
+
// If this token's spelling is a pp-identifier, check to see if it is
// 'defined' or if it is a macro. Note that we check here because many
// keywords are pp-identifiers, so we can't check the kind.
@@ -693,7 +710,7 @@ EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
// Peek ahead one token.
Token Tok;
Lex(Tok);
-
+
// C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index ebf606e9406f..9015c278fc92 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@@ -71,6 +72,12 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
+
+ // Microsoft Extensions.
+ if (Features.Microsoft)
+ Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
+ else
+ Ident__pragma = 0;
}
/// isTrivialSingleTokenExpansion - Return true if MI, which has a single token
@@ -323,6 +330,13 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
// an argument value in a macro could expand to ',' or '(' or ')'.
LexUnexpandedToken(Tok);
+ if (Tok.is(tok::code_completion)) {
+ if (CodeComplete)
+ CodeComplete->CodeCompleteMacroArgument(MacroName.getIdentifierInfo(),
+ MI, NumActuals);
+ LexUnexpandedToken(Tok);
+ }
+
if (Tok.is(tok::eof) || Tok.is(tok::eom)) { // "#if f(<eof>" & "#if f(\n"
Diag(MacroName, diag::err_unterm_macro_invoc);
// Do not lose the EOF/EOM. Return it to the client.
@@ -506,6 +520,10 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("cxx_static_assert", LangOpts.CPlusPlus0x)
.Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
.Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
+ .Case("ownership_holds", true)
+ .Case("ownership_returns", true)
+ .Case("ownership_takes", true)
+ .Case("cxx_inline_namespaces", true)
//.Case("cxx_concepts", false)
//.Case("cxx_lambdas", false)
//.Case("cxx_nullptr", false)
@@ -630,10 +648,12 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
IdentifierInfo *II = Tok.getIdentifierInfo();
assert(II && "Can't be a macro without id info!");
- // If this is an _Pragma directive, expand it, invoke the pragma handler, then
- // lex the token after it.
+ // If this is an _Pragma or Microsoft __pragma directive, expand it,
+ // invoke the pragma handler, then lex the token after it.
if (II == Ident_Pragma)
return Handle_Pragma(Tok);
+ else if (II == Ident__pragma) // in non-MS mode this is null
+ return HandleMicrosoft__pragma(Tok);
++NumBuiltinMacroExpanded;
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index 3b949d0ab40a..63b4823cf19e 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -101,16 +101,15 @@ LexNextToken:
// Save the end-of-file token.
EofToken = Tok;
+ // Save 'PP' to 'PPCache' as LexEndOfFile can delete 'this'.
Preprocessor *PPCache = PP;
assert(!ParsingPreprocessorDirective);
assert(!LexingRawMode);
-
- // FIXME: Issue diagnostics similar to Lexer.
- if (PP->HandleEndOfFile(Tok, false))
+
+ if (LexEndOfFile(Tok))
return;
- assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
return PPCache->Lex(Tok);
}
@@ -134,6 +133,29 @@ LexNextToken:
MIOpt.ReadToken();
}
+bool PTHLexer::LexEndOfFile(Token &Result) {
+ // If we hit the end of the file while parsing a preprocessor directive,
+ // end the preprocessor directive first. The next token returned will
+ // then be the end of file.
+ if (ParsingPreprocessorDirective) {
+ ParsingPreprocessorDirective = false; // Done parsing the "line".
+ return true; // Have a token.
+ }
+
+ assert(!LexingRawMode);
+
+ // If we are in a #if directive, emit an error.
+ while (!ConditionalStack.empty()) {
+ if (!PP->isCodeCompletionFile(FileStartLoc))
+ PP->Diag(ConditionalStack.back().IfLoc,
+ diag::err_pp_unterminated_conditional);
+ ConditionalStack.pop_back();
+ }
+
+ // Finally, let the preprocessor handle this.
+ return PP->HandleEndOfFile(Result);
+}
+
// FIXME: We can just grab the last token instead of storing a copy
// into EofToken.
void PTHLexer::getEOF(Token& Tok) {
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 7bf409405ab1..a7b289e137eb 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -16,9 +16,12 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
using namespace clang;
@@ -166,6 +169,62 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
--e;
}
}
+
+ Handle_Pragma(StrVal, PragmaLoc, RParenLoc);
+
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
+
+/// HandleMicrosoft__pragma - Like Handle_Pragma except the pragma text
+/// is not enclosed within a string literal.
+void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
+ // Remember the pragma token location.
+ SourceLocation PragmaLoc = Tok.getLocation();
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(PragmaLoc, diag::err__Pragma_malformed);
+ return;
+ }
+
+ // Get the tokens enclosed within the __pragma().
+ llvm::SmallVector<Token, 32> PragmaToks;
+ int NumParens = 0;
+ Lex(Tok);
+ while (Tok.isNot(tok::eof)) {
+ if (Tok.is(tok::l_paren))
+ NumParens++;
+ else if (Tok.is(tok::r_paren) && NumParens-- == 0)
+ break;
+ PragmaToks.push_back(Tok);
+ Lex(Tok);
+ }
+
+ if (Tok.is(tok::eof)) {
+ Diag(PragmaLoc, diag::err_unterminated___pragma);
+ return;
+ }
+
+ // Build the pragma string.
+ std::string StrVal = " ";
+ for (llvm::SmallVector<Token, 32>::iterator I =
+ PragmaToks.begin(), E = PragmaToks.end(); I != E; ++I) {
+ StrVal += getSpelling(*I);
+ }
+
+ SourceLocation RParenLoc = Tok.getLocation();
+
+ Handle_Pragma(StrVal, PragmaLoc, RParenLoc);
+
+ // Finally, return whatever came after the pragma directive.
+ return Lex(Tok);
+}
+
+void Preprocessor::Handle_Pragma(const std::string &StrVal,
+ SourceLocation PragmaLoc,
+ SourceLocation RParenLoc) {
// Plop the string (including the newline and trailing null) into a buffer
// where we can lex it.
@@ -183,9 +242,6 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
// With everything set up, lex this as a #pragma directive.
HandlePragmaDirective();
-
- // Finally, return whatever came after the pragma directive.
- return Lex(Tok);
}
@@ -328,7 +384,9 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
Lex(DependencyTok);
}
- Message.erase(Message.end()-1);
+ // Remove the trailing ' ' if present.
+ if (!Message.empty())
+ Message.erase(Message.end()-1);
Diag(FilenameTok, diag::pp_out_of_date_dependency) << Message;
}
}
@@ -483,6 +541,109 @@ void Preprocessor::HandlePragmaMessage(Token &Tok) {
Callbacks->PragmaMessage(MessageLoc, MessageString);
}
+/// ParsePragmaPushOrPopMacro - Handle parsing of pragma push_macro/pop_macro.
+/// Return the IdentifierInfo* associated with the macro to push or pop.
+IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
+ // Remember the pragma token location.
+ Token PragmaTok = Tok;
+
+ // Read the '('.
+ Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
+ << getSpelling(PragmaTok);
+ return 0;
+ }
+
+ // Read the macro name string.
+ Lex(Tok);
+ if (Tok.isNot(tok::string_literal)) {
+ Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
+ << getSpelling(PragmaTok);
+ return 0;
+ }
+
+ // Remember the macro string.
+ std::string StrVal = getSpelling(Tok);
+
+ // Read the ')'.
+ Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ Diag(PragmaTok.getLocation(), diag::err_pragma_push_pop_macro_malformed)
+ << getSpelling(PragmaTok);
+ return 0;
+ }
+
+ assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
+ "Invalid string token!");
+
+ // Create a Token from the string.
+ Token MacroTok;
+ MacroTok.startToken();
+ MacroTok.setKind(tok::identifier);
+ CreateString(&StrVal[1], StrVal.size() - 2, MacroTok);
+
+ // Get the IdentifierInfo of MacroToPushTok.
+ return LookUpIdentifierInfo(MacroTok);
+}
+
+/// HandlePragmaPushMacro - Handle #pragma push_macro.
+/// The syntax is:
+/// #pragma push_macro("macro")
+void Preprocessor::HandlePragmaPushMacro(Token &PushMacroTok) {
+ // Parse the pragma directive and get the macro IdentifierInfo*.
+ IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PushMacroTok);
+ if (!IdentInfo) return;
+
+ // Get the MacroInfo associated with IdentInfo.
+ MacroInfo *MI = getMacroInfo(IdentInfo);
+
+ MacroInfo *MacroCopyToPush = 0;
+ if (MI) {
+ // Make a clone of MI.
+ MacroCopyToPush = CloneMacroInfo(*MI);
+
+ // Allow the original MacroInfo to be redefined later.
+ MI->setIsAllowRedefinitionsWithoutWarning(true);
+ }
+
+ // Push the cloned MacroInfo so we can retrieve it later.
+ PragmaPushMacroInfo[IdentInfo].push_back(MacroCopyToPush);
+}
+
+/// HandlePragmaPopMacro - Handle #pragma push_macro.
+/// The syntax is:
+/// #pragma pop_macro("macro")
+void Preprocessor::HandlePragmaPopMacro(Token &PopMacroTok) {
+ SourceLocation MessageLoc = PopMacroTok.getLocation();
+
+ // Parse the pragma directive and get the macro IdentifierInfo*.
+ IdentifierInfo *IdentInfo = ParsePragmaPushOrPopMacro(PopMacroTok);
+ if (!IdentInfo) return;
+
+ // Find the vector<MacroInfo*> associated with the macro.
+ llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> >::iterator iter =
+ PragmaPushMacroInfo.find(IdentInfo);
+ if (iter != PragmaPushMacroInfo.end()) {
+ // Release the MacroInfo currently associated with IdentInfo.
+ MacroInfo *CurrentMI = getMacroInfo(IdentInfo);
+ if (CurrentMI) ReleaseMacroInfo(CurrentMI);
+
+ // Get the MacroInfo we want to reinstall.
+ MacroInfo *MacroToReInstall = iter->second.back();
+
+ // Reinstall the previously pushed macro.
+ setMacroInfo(IdentInfo, MacroToReInstall);
+
+ // Pop PragmaPushMacroInfo stack.
+ iter->second.pop_back();
+ if (iter->second.size() == 0)
+ PragmaPushMacroInfo.erase(iter);
+ } else {
+ Diag(MessageLoc, diag::warn_pragma_pop_macro_no_push)
+ << IdentInfo->getName();
+ }
+}
/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
/// If 'Namespace' is non-null, then it is a token required to exist on the
@@ -582,24 +743,51 @@ struct PragmaDependencyHandler : public PragmaHandler {
}
};
+struct PragmaDebugHandler : public PragmaHandler {
+ PragmaDebugHandler() : PragmaHandler("__debug") {}
+ virtual void HandlePragma(Preprocessor &PP, Token &DepToken) {
+ Token Tok;
+ PP.LexUnexpandedToken(Tok);
+ if (Tok.isNot(tok::identifier)) {
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
+ return;
+ }
+ IdentifierInfo *II = Tok.getIdentifierInfo();
+
+ if (II->isStr("assert")) {
+ assert(0 && "This is an assertion!");
+ } else if (II->isStr("crash")) {
+ *(volatile int*) 0x11 = 0;
+ } else if (II->isStr("llvm_fatal_error")) {
+ llvm::report_fatal_error("#pragma clang __debug llvm_fatal_error");
+ } else if (II->isStr("llvm_unreachable")) {
+ llvm_unreachable("#pragma clang __debug llvm_unreachable");
+ } else if (II->isStr("overflow_stack")) {
+ DebugOverflowStack();
+ } else if (II->isStr("handle_crash")) {
+ llvm::CrashRecoveryContext *CRC =llvm::CrashRecoveryContext::GetCurrent();
+ if (CRC)
+ CRC->HandleCrash();
+ } else {
+ PP.Diag(Tok, diag::warn_pragma_debug_unexpected_command)
+ << II->getName();
+ }
+ }
+
+ void DebugOverflowStack() {
+ DebugOverflowStack();
+ }
+};
+
/// PragmaDiagnosticHandler - e.g. '#pragma GCC diagnostic ignored "-Wformat"'
-/// Since clang's diagnostic supports extended functionality beyond GCC's
-/// the constructor takes a clangMode flag to tell it whether or not to allow
-/// clang's extended functionality, or whether to reject it.
struct PragmaDiagnosticHandler : public PragmaHandler {
-private:
- const bool ClangMode;
public:
- explicit PragmaDiagnosticHandler(const bool clangMode)
- : PragmaHandler("diagnostic"), ClangMode(clangMode) {}
-
+ explicit PragmaDiagnosticHandler() : PragmaHandler("diagnostic") {}
virtual void HandlePragma(Preprocessor &PP, Token &DiagToken) {
Token Tok;
PP.LexUnexpandedToken(Tok);
if (Tok.isNot(tok::identifier)) {
- unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
- : diag::warn_pragma_diagnostic_gcc_invalid;
- PP.Diag(Tok, Diag);
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
return;
}
IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -613,22 +801,16 @@ public:
Map = diag::MAP_IGNORE;
else if (II->isStr("fatal"))
Map = diag::MAP_FATAL;
- else if (ClangMode) {
- if (II->isStr("pop")) {
- if (!PP.getDiagnostics().popMappings())
- PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_cannot_ppp);
- return;
- }
-
- if (II->isStr("push")) {
- PP.getDiagnostics().pushMappings();
- return;
- }
-
- PP.Diag(Tok, diag::warn_pragma_diagnostic_clang_invalid);
+ else if (II->isStr("pop")) {
+ if (!PP.getDiagnostics().popMappings())
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_cannot_pop);
+
+ return;
+ } else if (II->isStr("push")) {
+ PP.getDiagnostics().pushMappings();
return;
} else {
- PP.Diag(Tok, diag::warn_pragma_diagnostic_gcc_invalid);
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
return;
}
@@ -660,9 +842,7 @@ public:
if (Literal.hadError)
return;
if (Literal.Pascal) {
- unsigned Diag = ClangMode ? diag::warn_pragma_diagnostic_clang_invalid
- : diag::warn_pragma_diagnostic_gcc_invalid;
- PP.Diag(Tok, Diag);
+ PP.Diag(Tok, diag::warn_pragma_diagnostic_invalid);
return;
}
@@ -699,6 +879,25 @@ struct PragmaMessageHandler : public PragmaHandler {
}
};
+/// PragmaPushMacroHandler - "#pragma push_macro" saves the value of the
+/// macro on the top of the stack.
+struct PragmaPushMacroHandler : public PragmaHandler {
+ PragmaPushMacroHandler() : PragmaHandler("push_macro") {}
+ virtual void HandlePragma(Preprocessor &PP, Token &PushMacroTok) {
+ PP.HandlePragmaPushMacro(PushMacroTok);
+ }
+};
+
+
+/// PragmaPopMacroHandler - "#pragma pop_macro" sets the value of the
+/// macro to the value on the top of the stack.
+struct PragmaPopMacroHandler : public PragmaHandler {
+ PragmaPopMacroHandler() : PragmaHandler("pop_macro") {}
+ virtual void HandlePragma(Preprocessor &PP, Token &PopMacroTok) {
+ PP.HandlePragmaPopMacro(PopMacroTok);
+ }
+};
+
// Pragma STDC implementations.
enum STDCSetting {
@@ -780,17 +979,20 @@ struct PragmaSTDC_UnknownHandler : public PragmaHandler {
void Preprocessor::RegisterBuiltinPragmas() {
AddPragmaHandler(new PragmaOnceHandler());
AddPragmaHandler(new PragmaMarkHandler());
+ AddPragmaHandler(new PragmaPushMacroHandler());
+ AddPragmaHandler(new PragmaPopMacroHandler());
// #pragma GCC ...
AddPragmaHandler("GCC", new PragmaPoisonHandler());
AddPragmaHandler("GCC", new PragmaSystemHeaderHandler());
AddPragmaHandler("GCC", new PragmaDependencyHandler());
- AddPragmaHandler("GCC", new PragmaDiagnosticHandler(false));
+ AddPragmaHandler("GCC", new PragmaDiagnosticHandler());
// #pragma clang ...
AddPragmaHandler("clang", new PragmaPoisonHandler());
AddPragmaHandler("clang", new PragmaSystemHeaderHandler());
+ AddPragmaHandler("clang", new PragmaDebugHandler());
AddPragmaHandler("clang", new PragmaDependencyHandler());
- AddPragmaHandler("clang", new PragmaDiagnosticHandler(true));
+ AddPragmaHandler("clang", new PragmaDiagnosticHandler());
AddPragmaHandler("STDC", new PragmaSTDC_FP_CONTRACTHandler());
AddPragmaHandler("STDC", new PragmaSTDC_FENV_ACCESSHandler());
diff --git a/lib/Lex/PreprocessingRecord.cpp b/lib/Lex/PreprocessingRecord.cpp
index 6966c38b23d8..c446d96b4527 100644
--- a/lib/Lex/PreprocessingRecord.cpp
+++ b/lib/Lex/PreprocessingRecord.cpp
@@ -118,7 +118,8 @@ void PreprocessingRecord::MacroDefined(const IdentifierInfo *II,
PreprocessedEntities.push_back(Def);
}
-void PreprocessingRecord::MacroUndefined(const IdentifierInfo *II,
+void PreprocessingRecord::MacroUndefined(SourceLocation Loc,
+ const IdentifierInfo *II,
const MacroInfo *MI) {
llvm::DenseMap<const MacroInfo *, MacroDefinition *>::iterator Pos
= MacroDefinitions.find(MI);
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 51f729334cb9..5160acf19e1f 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -34,6 +34,7 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/ScratchBuffer.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -53,8 +54,9 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
SourceMgr(SM), HeaderInfo(Headers), ExternalSource(0),
- Identifiers(opts, IILookup), BuiltinInfo(Target), CodeCompletionFile(0),
- CurPPLexer(0), CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0) {
+ Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0),
+ CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
+ CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0) {
ScratchBuf = new ScratchBuffer(SourceMgr);
CounterValue = 0; // __COUNTER__ starts at 0.
OwnsHeaderSearch = OwnsHeaders;
@@ -110,7 +112,7 @@ Preprocessor::~Preprocessor() {
// will be released when the BumpPtrAllocator 'BP' object gets
// destroyed. We still need to run the dtor, however, to free
// memory alocated by MacroInfo.
- I->second->Destroy(BP);
+ I->second->Destroy();
I->first->setHasMacroDefinition(false);
}
for (std::vector<MacroInfo*>::iterator I = MICache.begin(),
@@ -119,7 +121,7 @@ Preprocessor::~Preprocessor() {
// will be released when the BumpPtrAllocator 'BP' object gets
// destroyed. We still need to run the dtor, however, to free
// memory alocated by MacroInfo.
- (*I)->Destroy(BP);
+ (*I)->Destroy();
}
// Free any cached macro expanders.
@@ -163,7 +165,7 @@ void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const {
llvm::errs() << " [ExpandDisabled]";
if (Tok.needsCleaning()) {
const char *Start = SourceMgr.getCharacterData(Tok.getLocation());
- llvm::errs() << " [UnClean='" << std::string(Start, Start+Tok.getLength())
+ llvm::errs() << " [UnClean='" << llvm::StringRef(Start, Tok.getLength())
<< "']";
}
@@ -282,6 +284,13 @@ bool Preprocessor::isCodeCompletionFile(SourceLocation FileLoc) const {
== CodeCompletionFile;
}
+void Preprocessor::CodeCompleteNaturalLanguage() {
+ SetCodeCompletionPoint(0, 0, 0);
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ if (CodeComplete)
+ CodeComplete->CodeCompleteNaturalLanguage();
+}
+
//===----------------------------------------------------------------------===//
// Token Spelling
//===----------------------------------------------------------------------===//
@@ -508,6 +517,12 @@ void Preprocessor::EnterMainSourceFile() {
// Enter the main file source buffer.
EnterSourceFile(MainFileID, 0, SourceLocation());
+ // If we've been asked to skip bytes in the main file (e.g., as part of a
+ // precompiled preamble), do so now.
+ if (SkipMainFilePreamble.first > 0)
+ CurLexer->SkipBytes(SkipMainFilePreamble.first,
+ SkipMainFilePreamble.second);
+
// Tell the header info that the main file was entered. If the file is later
// #imported, it won't be re-entered.
if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
@@ -516,7 +531,7 @@ void Preprocessor::EnterMainSourceFile() {
// Preprocess Predefines to populate the initial preprocessor state.
llvm::MemoryBuffer *SB =
llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
- assert(SB && "Cannot fail to create predefined source buffer");
+ assert(SB && "Cannot create predefined source buffer");
FileID FID = SourceMgr.createFileIDForMemBuffer(SB);
assert(!FID.isInvalid() && "Could not create FileID for predefines?");
@@ -639,6 +654,8 @@ bool Preprocessor::HandleComment(Token &result, SourceRange Comment) {
CommentHandler::~CommentHandler() { }
+CodeCompletionHandler::~CodeCompletionHandler() { }
+
void Preprocessor::createPreprocessingRecord() {
if (Record)
return;
diff --git a/lib/Lex/TokenLexer.cpp b/lib/Lex/TokenLexer.cpp
index 56bb073e5919..94719b0baa3c 100644
--- a/lib/Lex/TokenLexer.cpp
+++ b/lib/Lex/TokenLexer.cpp
@@ -268,6 +268,13 @@ void TokenLexer::ExpandFunctionArguments() {
// Remove the paste operator, report use of the extension.
PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
ResultToks.pop_back();
+
+ // If the comma was right after another paste (e.g. "X##,##__VA_ARGS__"),
+ // then removal of the comma should produce a placemarker token (in C99
+ // terms) which we model by popping off the previous ##, giving us a plain
+ // "X" when __VA_ARGS__ is empty.
+ if (!ResultToks.empty() && ResultToks.back().is(tok::hashhash))
+ ResultToks.pop_back();
}
continue;
}
@@ -478,7 +485,7 @@ bool TokenLexer::PasteTokens(Token &Tok) {
return true;
}
- // Do not emit the warning when preprocessing assembler code.
+ // Do not emit the error when preprocessing assembler code.
if (!PP.getLangOptions().AsmPreprocessor) {
// Explicitly convert the token location to have proper instantiation
// information so that the user knows where it came from.
@@ -486,8 +493,13 @@ bool TokenLexer::PasteTokens(Token &Tok) {
SourceLocation Loc =
SM.createInstantiationLoc(PasteOpLoc, InstantiateLocStart,
InstantiateLocEnd, 2);
- PP.Diag(Loc, diag::err_pp_bad_paste)
- << std::string(Buffer.begin(), Buffer.end());
+ // If we're in microsoft extensions mode, downgrade this from a hard
+ // error to a warning that defaults to an error. This allows
+ // disabling it.
+ PP.Diag(Loc,
+ PP.getLangOptions().Microsoft ? diag::err_pp_bad_paste_ms
+ : diag::err_pp_bad_paste)
+ << Buffer.str();
}
// Do not consume the RHS.
diff --git a/lib/Makefile b/lib/Makefile
index 4fca6249ba3d..dbd0eb699ee1 100755
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -9,7 +9,7 @@
CLANG_LEVEL := ..
PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \
- Checker Rewrite Frontend Index Driver
+ Checker Rewrite Serialization Frontend FrontendTool Index Driver
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index fafcf77b006c..189af3dc882f 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -1,9 +1,7 @@
set(LLVM_NO_RTTI 1)
add_clang_library(clangParse
- AttributeList.cpp
- DeclSpec.cpp
- MinimalAction.cpp
+ ParseAST.cpp
ParseCXXInlineMethods.cpp
ParseDecl.cpp
ParseDeclCXX.cpp
@@ -18,4 +16,4 @@ add_clang_library(clangParse
Parser.cpp
)
-add_dependencies(clangParse ClangAttrList ClangDiagnosticParse)
+add_dependencies(clangParse ClangAttrClasses ClangAttrList ClangDeclNodes ClangDiagnosticParse ClangStmtNodes)
diff --git a/lib/Parse/Makefile b/lib/Parse/Makefile
index 238e02d9996c..5ec7c333c504 100644
--- a/lib/Parse/Makefile
+++ b/lib/Parse/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangParse
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
deleted file mode 100644
index b7205160c177..000000000000
--- a/lib/Parse/MinimalAction.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-//===--- MinimalAction.cpp - Implement the MinimalAction class ------------===//
-//
-// 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 MinimalAction interface.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Parse/Parser.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Basic/TargetInfo.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/RecyclingAllocator.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace clang;
-
-/// Out-of-line virtual destructor to provide home for ActionBase class.
-ActionBase::~ActionBase() {}
-
-/// Out-of-line virtual destructor to provide home for Action class.
-Action::~Action() {}
-
-Action::ObjCMessageKind Action::getObjCMessageKind(Scope *S,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- bool IsSuper,
- bool HasTrailingDot,
- TypeTy *&ReceiverType) {
- ReceiverType = 0;
-
- if (IsSuper && !HasTrailingDot && S->isInObjcMethodScope())
- return ObjCSuperMessage;
-
- if (TypeTy *TyName = getTypeName(*Name, NameLoc, S)) {
- DeclSpec DS;
- const char *PrevSpec = 0;
- unsigned DiagID = 0;
- if (!DS.SetTypeSpecType(DeclSpec::TST_typename, NameLoc, PrevSpec,
- DiagID, TyName)) {
- DS.SetRangeEnd(NameLoc);
- Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- TypeResult Ty = ActOnTypeName(S, DeclaratorInfo);
- if (!Ty.isInvalid())
- ReceiverType = Ty.get();
- }
- return ObjCClassMessage;
- }
-
- return ObjCInstanceMessage;
-}
-
-// Defined out-of-line here because of dependecy on AttributeList
-Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
- SourceLocation UsingLoc,
- SourceLocation NamespcLoc,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- AttributeList *AttrList) {
-
- // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
- // passed AttributeList, however other actions don't free it, is it
- // temporary state or bug?
- delete AttrList;
- return DeclPtrTy();
-}
-
-// Defined out-of-line here because of dependency on AttributeList
-Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
- AccessSpecifier AS,
- bool HasUsingKeyword,
- SourceLocation UsingLoc,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- AttributeList *AttrList,
- 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
- // temporary state or bug?
- delete AttrList;
- return DeclPtrTy();
-}
-
-
-void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
- if (Loc.isValid()) {
- Loc.print(OS, SM);
- OS << ": ";
- }
- OS << Message;
-
- std::string Name = Actions.getDeclName(TheDecl);
- if (!Name.empty())
- OS << " '" << Name << '\'';
-
- OS << '\n';
-}
-
-/// TypeNameInfo - A link exists here for each scope that an identifier is
-/// defined.
-namespace {
- struct TypeNameInfo {
- TypeNameInfo *Prev;
- bool isTypeName;
-
- TypeNameInfo(bool istypename, TypeNameInfo *prev) {
- isTypeName = istypename;
- Prev = prev;
- }
- };
-
- struct TypeNameInfoTable {
- llvm::RecyclingAllocator<llvm::BumpPtrAllocator, TypeNameInfo> Allocator;
-
- void AddEntry(bool isTypename, IdentifierInfo *II) {
- TypeNameInfo *TI = Allocator.Allocate<TypeNameInfo>();
- new (TI) TypeNameInfo(isTypename, II->getFETokenInfo<TypeNameInfo>());
- II->setFETokenInfo(TI);
- }
-
- void DeleteEntry(TypeNameInfo *Entry) {
- Entry->~TypeNameInfo();
- Allocator.Deallocate(Entry);
- }
- };
-}
-
-static TypeNameInfoTable *getTable(void *TP) {
- return static_cast<TypeNameInfoTable*>(TP);
-}
-
-MinimalAction::MinimalAction(Preprocessor &pp)
- : Idents(pp.getIdentifierTable()), PP(pp) {
- TypeNameInfoTablePtr = new TypeNameInfoTable();
-}
-
-MinimalAction::~MinimalAction() {
- delete getTable(TypeNameInfoTablePtr);
-}
-
-void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
- TUScope = S;
-
- TypeNameInfoTable &TNIT = *getTable(TypeNameInfoTablePtr);
-
- if (PP.getTargetInfo().getPointerWidth(0) >= 64) {
- // Install [u]int128_t for 64-bit targets.
- TNIT.AddEntry(true, &Idents.get("__int128_t"));
- TNIT.AddEntry(true, &Idents.get("__uint128_t"));
- }
-
- if (PP.getLangOptions().ObjC1) {
- // Recognize the ObjC built-in type identifiers as types.
- TNIT.AddEntry(true, &Idents.get("id"));
- TNIT.AddEntry(true, &Idents.get("SEL"));
- TNIT.AddEntry(true, &Idents.get("Class"));
- TNIT.AddEntry(true, &Idents.get("Protocol"));
- }
-}
-
-/// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
-/// determine whether the name is a type name (objc class name or typedef) or
-/// not in this scope.
-///
-/// FIXME: Use the passed CXXScopeSpec for accurate C++ type checking.
-Action::TypeTy *
-MinimalAction::getTypeName(IdentifierInfo &II, SourceLocation Loc,
- Scope *S, CXXScopeSpec *SS,
- bool isClassName, TypeTy *ObjectType) {
- if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
- if (TI->isTypeName)
- return TI;
- return 0;
-}
-
-/// isCurrentClassName - Always returns false, because MinimalAction
-/// does not support C++ classes with constructors.
-bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *,
- const CXXScopeSpec *) {
- return false;
-}
-
-TemplateNameKind
-MinimalAction::isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Name,
- TypeTy *ObjectType,
- bool EnteringScope,
- TemplateTy &TemplateDecl,
- bool &MemberOfUnknownSpecialization) {
- MemberOfUnknownSpecialization = false;
- return TNK_Non_template;
-}
-
-/// ActOnDeclarator - If this is a typedef declarator, we modify the
-/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
-/// popped.
-Action::DeclPtrTy
-MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) {
- IdentifierInfo *II = D.getIdentifier();
-
- // If there is no identifier associated with this declarator, bail out.
- if (II == 0) return DeclPtrTy();
-
- TypeNameInfo *weCurrentlyHaveTypeInfo = II->getFETokenInfo<TypeNameInfo>();
- bool isTypeName =
- D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef;
-
- // this check avoids creating TypeNameInfo objects for the common case.
- // It does need to handle the uncommon case of shadowing a typedef name with a
- // non-typedef name. e.g. { typedef int a; a xx; { int a; } }
- if (weCurrentlyHaveTypeInfo || isTypeName) {
- // Allocate and add the 'TypeNameInfo' "decl".
- getTable(TypeNameInfoTablePtr)->AddEntry(isTypeName, II);
-
- // Remember that this needs to be removed when the scope is popped.
- S->AddDecl(DeclPtrTy::make(II));
- }
- return DeclPtrTy();
-}
-
-Action::DeclPtrTy
-MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs,
- unsigned NumProtocols,
- const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc,
- AttributeList *AttrList) {
- // Allocate and add the 'TypeNameInfo' "decl".
- getTable(TypeNameInfoTablePtr)->AddEntry(true, ClassName);
- return DeclPtrTy();
-}
-
-/// ActOnForwardClassDeclaration -
-/// Scope will always be top level file scope.
-Action::DeclPtrTy
-MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
- 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]);
-
- // Remember that this needs to be removed when the scope is popped.
- TUScope->AddDecl(DeclPtrTy::make(IdentList[i]));
- }
- return DeclPtrTy();
-}
-
-/// ActOnPopScope - When a scope is popped, if any typedefs are now
-/// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
-void MinimalAction::ActOnPopScope(SourceLocation Loc, Scope *S) {
- TypeNameInfoTable &Table = *getTable(TypeNameInfoTablePtr);
-
- for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
- I != E; ++I) {
- IdentifierInfo &II = *(*I).getAs<IdentifierInfo>();
- TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>();
- assert(TI && "This decl didn't get pushed??");
-
- if (TI) {
- TypeNameInfo *Next = TI->Prev;
- Table.DeleteEntry(TI);
-
- II.setFETokenInfo(Next);
- }
- }
-}
diff --git a/lib/Sema/ParseAST.cpp b/lib/Parse/ParseAST.cpp
index bb0bd9e1cb5e..d02787941b0d 100644
--- a/lib/Sema/ParseAST.cpp
+++ b/lib/Parse/ParseAST.cpp
@@ -11,12 +11,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/ParseAST.h"
-#include "Sema.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Sema/Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/Parser.h"
@@ -56,68 +57,56 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
ASTContext &Ctx, bool PrintStats,
bool CompleteTranslationUnit,
CodeCompleteConsumer *CompletionConsumer) {
+ Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer);
+ ParseAST(S, PrintStats);
+}
+
+void clang::ParseAST(Sema &S, bool PrintStats) {
// 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, CompletionConsumer);
- Parser P(PP, S);
- PP.EnterMainSourceFile();
+ ASTConsumer *Consumer = &S.getASTConsumer();
- // Initialize the parser.
+ Parser P(S.getPreprocessor(), S);
+ S.getPreprocessor().EnterMainSourceFile();
P.Initialize();
-
- Consumer->Initialize(Ctx);
-
- if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumer))
- SC->InitializeSema(S);
-
- if (ExternalASTSource *External = Ctx.getExternalSource()) {
- if (ExternalSemaSource *ExternalSema =
- dyn_cast<ExternalSemaSource>(External))
- ExternalSema->InitializeSema(S);
-
+ S.Initialize();
+
+ if (ExternalASTSource *External = S.getASTContext().getExternalSource())
External->StartTranslationUnit(Consumer);
- }
-
+
Parser::DeclGroupPtrTy ADecl;
-
+
while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
// If we got a null return and something *was* parsed, ignore it. This
// is due to a top-level semicolon, an action override, or a parse error
// skipping something.
if (ADecl)
- Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
+ Consumer->HandleTopLevelDecl(ADecl.get());
};
// Check for any pending objective-c implementation decl.
- while ((ADecl = P.RetrievePendingObjCImpDecl()))
- Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
-
+ while ((ADecl = P.FinishPendingObjCActions()))
+ Consumer->HandleTopLevelDecl(ADecl.get());
+
// Process any TopLevelDecls generated by #pragma weak.
for (llvm::SmallVector<Decl*,2>::iterator
- I = S.WeakTopLevelDecls().begin(),
- E = S.WeakTopLevelDecls().end(); I != E; ++I)
+ I = S.WeakTopLevelDecls().begin(),
+ E = S.WeakTopLevelDecls().end(); I != E; ++I)
Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
-
+
// Dump record layouts, if requested.
- if (PP.getLangOptions().DumpRecordLayouts)
- DumpRecordLayouts(Ctx);
-
- Consumer->HandleTranslationUnit(Ctx);
-
- if (ExternalSemaSource *ESS =
- dyn_cast_or_null<ExternalSemaSource>(Ctx.getExternalSource()))
- ESS->ForgetSema();
-
- if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumer))
- SC->ForgetSema();
-
+ if (S.getLangOptions().DumpRecordLayouts)
+ DumpRecordLayouts(S.getASTContext());
+
+ Consumer->HandleTranslationUnit(S.getASTContext());
+
if (PrintStats) {
fprintf(stderr, "\nSTATISTICS:\n");
P.getActions().PrintStats();
- Ctx.PrintStats();
+ S.getASTContext().PrintStats();
Decl::PrintStats();
Stmt::PrintStats();
Consumer->PrintStats();
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 62a7ecd5d490..d327db485c09 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -13,26 +13,25 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
using namespace clang;
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
-Parser::DeclPtrTy
-Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
const ParsedTemplateInfo &TemplateInfo) {
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"This isn't a function declarator!");
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
"Current token not a '{', ':' or 'try'!");
- Action::MultiTemplateParamsArg TemplateParams(Actions,
+ MultiTemplateParamsArg TemplateParams(Actions,
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
- DeclPtrTy FnD;
+ Decl *FnD;
if (D.getDeclSpec().isFriendSpecified())
// FIXME: Friend templates
FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D, true,
@@ -139,12 +138,17 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
assert(Tok.is(tok::equal) && "Default argument not starting with '='");
SourceLocation EqualLoc = ConsumeToken();
- OwningExprResult DefArgResult(ParseAssignmentExpression());
+ ExprResult DefArgResult(ParseAssignmentExpression());
if (DefArgResult.isInvalid())
Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param);
- else
+ else {
+ if (Tok.is(tok::cxx_defaultarg_end))
+ ConsumeToken();
+ else
+ Diag(Tok.getLocation(), diag::err_default_arg_unparsed);
Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
- move(DefArgResult));
+ DefArgResult.take());
+ }
assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
Tok.getLocation()) &&
@@ -227,7 +231,7 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
// Error recovery.
if (!Tok.is(tok::l_brace)) {
- Actions.ActOnFinishFunctionBody(LM.D, Action::StmtArg(Actions));
+ Actions.ActOnFinishFunctionBody(LM.D, 0);
continue;
}
} else
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 62ef3ec0179b..555fcf0dec55 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -13,8 +13,9 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
#include "RAIIObjectsForParser.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -28,7 +29,7 @@ using namespace clang;
/// specifier-qualifier-list abstract-declarator[opt]
///
/// Called type-id in C++.
-Action::TypeResult Parser::ParseTypeName(SourceRange *Range) {
+TypeResult Parser::ParseTypeName(SourceRange *Range) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseSpecifierQualifierList(DS);
@@ -131,7 +132,7 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
// now parse the non-empty comma separated list of expressions
while (1) {
- OwningExprResult ArgExpr(ParseAssignmentExpression());
+ ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
ArgExprsOk = false;
SkipUntil(tok::r_paren);
@@ -174,11 +175,13 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
case tok::kw_double:
case tok::kw_void:
case tok::kw_typeof:
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
+ 0, SourceLocation(), 0, 0, CurrAttr);
+ if (CurrAttr->getKind() == AttributeList::AT_IBOutletCollection)
+ Diag(Tok, diag::err_iboutletcollection_builtintype);
// If it's a builtin type name, eat it and expect a rparen
// __attribute__(( vec_type_hint(char) ))
ConsumeToken();
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
- 0, SourceLocation(), 0, 0, CurrAttr);
if (Tok.is(tok::r_paren))
ConsumeParen();
break;
@@ -189,7 +192,7 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
// now parse the list of expressions
while (1) {
- OwningExprResult ArgExpr(ParseAssignmentExpression());
+ ExprResult ArgExpr(ParseAssignmentExpression());
if (ArgExpr.isInvalid()) {
ArgExprsOk = false;
SkipUntil(tok::r_paren);
@@ -254,9 +257,9 @@ AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
ConsumeParen();
// FIXME: This doesn't parse __declspec(property(get=get_func_name))
// correctly.
- OwningExprResult ArgExpr(ParseAssignmentExpression());
+ ExprResult ArgExpr(ParseAssignmentExpression());
if (!ArgExpr.isInvalid()) {
- ExprTy* ExprList = ArgExpr.take();
+ Expr *ExprList = ArgExpr.take();
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
SourceLocation(), &ExprList, 1,
CurrAttr, true);
@@ -290,6 +293,17 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
return CurrAttr;
}
+AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) {
+ // Treat these like attributes
+ while (Tok.is(tok::kw___pascal)) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
+ SourceLocation(), 0, 0, CurrAttr, true);
+ }
+ return CurrAttr;
+}
+
/// ParseDeclaration - Parse a full 'declaration', which consists of
/// declaration-specifiers, some number of declarators, and a semicolon.
/// 'Context' should be a Declarator::TheContext value. This returns the
@@ -311,7 +325,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
CXX0XAttributeList Attr) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- DeclPtrTy SingleDecl;
+ Decl *SingleDecl = 0;
switch (Tok.getKind()) {
case tok::kw_template:
case tok::kw_export:
@@ -320,6 +334,17 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
<< Attr.Range;
SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
break;
+ case tok::kw_inline:
+ // Could be the start of an inline namespace. Allowed as an ext in C++03.
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
+ if (Attr.HasAttr)
+ Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
+ << Attr.Range;
+ SourceLocation InlineLoc = ConsumeToken();
+ SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
+ break;
+ }
+ return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true);
case tok::kw_namespace:
if (Attr.HasAttr)
Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
@@ -366,7 +391,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
if (RequireSemi) ConsumeToken();
- DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
+ Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
DS);
DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
@@ -410,7 +435,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
DS.ClearStorageClassSpecs();
}
- DeclPtrTy TheDecl = ParseFunctionDefinition(D);
+ Decl *TheDecl = ParseFunctionDefinition(D);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -427,10 +452,10 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
}
}
- llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
- DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+ llvm::SmallVector<Decl *, 8> DeclsInGroup;
+ Decl *FirstDecl = ParseDeclarationAfterDeclarator(D);
D.complete(FirstDecl);
- if (FirstDecl.get())
+ if (FirstDecl)
DeclsInGroup.push_back(FirstDecl);
// If we don't have a comma, it is either the end of the list (a ';') or an
@@ -457,9 +482,9 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
ParseDeclarator(D);
- DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+ Decl *ThisDecl = ParseDeclarationAfterDeclarator(D);
D.complete(ThisDecl);
- if (ThisDecl.get())
+ if (ThisDecl)
DeclsInGroup.push_back(ThisDecl);
}
@@ -507,15 +532,15 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
/// According to the standard grammar, =default and =delete are function
/// definitions, but that definitely doesn't fit with the parser here.
///
-Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
+Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo) {
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
SourceLocation Loc;
- OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid()) {
SkipUntil(tok::semi, true, true);
- return DeclPtrTy();
+ return 0;
}
D.setAsmLabel(AsmLabel.release());
@@ -530,7 +555,7 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
}
// Inform the current actions module that we just parsed this declarator.
- DeclPtrTy ThisDecl;
+ Decl *ThisDecl = 0;
switch (TemplateInfo.Kind) {
case ParsedTemplateInfo::NonTemplate:
ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@@ -539,21 +564,21 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
case ParsedTemplateInfo::Template:
case ParsedTemplateInfo::ExplicitSpecialization:
ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
- Action::MultiTemplateParamsArg(Actions,
+ MultiTemplateParamsArg(Actions,
TemplateInfo.TemplateParams->data(),
TemplateInfo.TemplateParams->size()),
D);
break;
case ParsedTemplateInfo::ExplicitInstantiation: {
- Action::DeclResult ThisRes
+ DeclResult ThisRes
= Actions.ActOnExplicitInstantiation(getCurScope(),
TemplateInfo.ExternLoc,
TemplateInfo.TemplateLoc,
D);
if (ThisRes.isInvalid()) {
SkipUntil(tok::semi, true, true);
- return DeclPtrTy();
+ return 0;
}
ThisDecl = ThisRes.get();
@@ -580,7 +605,7 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
return ThisDecl;
}
- OwningExprResult Init(ParseInitializer());
+ ExprResult Init(ParseInitializer());
if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl);
@@ -591,7 +616,7 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
SkipUntil(tok::comma, true, true);
Actions.ActOnInitializerError(ThisDecl);
} else
- Actions.AddInitializerToDecl(ThisDecl, move(Init));
+ Actions.AddInitializerToDecl(ThisDecl, Init.take());
}
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
@@ -771,7 +796,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// This is almost certainly an invalid type name. Let the action emit a
// diagnostic and attempt to recover.
- Action::TypeTy *T = 0;
+ ParsedType T;
if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc,
getCurScope(), SS, T)) {
// The action emitted a diagnostic, so we don't have to.
@@ -781,8 +806,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// name token, and we're done.
const char *PrevSpec;
unsigned DiagID;
- DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
- false);
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T);
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
@@ -851,21 +875,7 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS,
- DeclSpecContext DSContext) {
- if (Tok.is(tok::code_completion)) {
- Action::CodeCompletionContext CCC = Action::CCC_Namespace;
- if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
- CCC = DSContext == DSC_class? Action::CCC_MemberTemplate
- : Action::CCC_Template;
- else if (DSContext == DSC_class)
- CCC = Action::CCC_Class;
- else if (ObjCImpDecl)
- CCC = Action::CCC_ObjCImplementation;
-
- Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
- ConsumeCodeCompletionToken();
- }
-
+ DeclSpecContext DSContext) {
DS.SetRangeStart(Tok.getLocation());
while (1) {
bool isInvalid = false;
@@ -882,6 +892,38 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.Finish(Diags, PP);
return;
+ case tok::code_completion: {
+ Sema::ParserCompletionContext CCC = Sema::PCC_Namespace;
+ if (DS.hasTypeSpecifier()) {
+ bool AllowNonIdentifiers
+ = (getCurScope()->getFlags() & (Scope::ControlScope |
+ Scope::BlockScope |
+ Scope::TemplateParamScope |
+ Scope::FunctionPrototypeScope |
+ Scope::AtCatchScope)) == 0;
+ bool AllowNestedNameSpecifiers
+ = DSContext == DSC_top_level ||
+ (DSContext == DSC_class && DS.isFriendSpecified());
+
+ Actions.CodeCompleteDeclarator(getCurScope(), AllowNonIdentifiers,
+ AllowNestedNameSpecifiers);
+ ConsumeCodeCompletionToken();
+ return;
+ }
+
+ if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
+ CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate
+ : Sema::PCC_Template;
+ else if (DSContext == DSC_class)
+ CCC = Sema::PCC_Class;
+ else if (ObjCImpDecl)
+ CCC = Sema::PCC_ObjCImplementation;
+
+ Actions.CodeCompleteOrdinaryName(getCurScope(), CCC);
+ ConsumeCodeCompletionToken();
+ return;
+ }
+
case tok::coloncolon: // ::foo::bar
// C++ scope specifier. Annotate and loop, or bail out on error.
if (TryAnnotateCXXScopeToken(true)) {
@@ -898,7 +940,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
CXXScopeSpec SS;
- SS.setScopeRep(Tok.getAnnotationValue());
+ SS.setScopeRep((NestedNameSpecifier*) Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
// We are looking for a qualified typename.
@@ -961,10 +1003,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (Next.is(tok::annot_typename)) {
DS.getTypeSpecScope() = SS;
ConsumeToken(); // The C++ scope.
- if (Tok.getAnnotationValue())
+ if (Tok.getAnnotationValue()) {
+ ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc,
- PrevSpec, DiagID,
- Tok.getAnnotationValue());
+ PrevSpec, DiagID, T);
+ }
else
DS.SetTypeSpecError();
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
@@ -993,8 +1036,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
<< Next.getIdentifierInfo();
}
- TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
- Next.getLocation(), getCurScope(), &SS);
+ ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
+ Next.getLocation(),
+ getCurScope(), &SS);
// If the referenced identifier is not a type, then this declspec is
// erroneous: We already checked about that it has no type specifier, and
@@ -1021,10 +1065,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
case tok::annot_typename: {
- if (Tok.getAnnotationValue())
+ if (Tok.getAnnotationValue()) {
+ ParsedType T = getTypeAnnotation(Tok);
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, Tok.getAnnotationValue());
- else
+ DiagID, T);
+ } else
DS.SetTypeSpecError();
if (isInvalid)
@@ -1041,7 +1086,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
continue;
SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+ llvm::SmallVector<Decl *, 8> ProtocolDecl;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
LAngleLoc, EndProtoLoc);
@@ -1077,12 +1122,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
// It has to be available as a typedef too!
- TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), getCurScope());
+ ParsedType TypeRep =
+ Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), getCurScope());
// If this is not a typedef name, don't parse it as part of the declspec,
// it must be an implicit int or an error.
- if (TypeRep == 0) {
+ if (!TypeRep) {
if (ParseImplicitInt(DS, 0, TemplateInfo, AS)) continue;
goto DoneWithDeclSpec;
}
@@ -1110,7 +1156,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
continue;
SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+ llvm::SmallVector<Decl *, 8> ProtocolDecl;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
LAngleLoc, EndProtoLoc);
@@ -1172,6 +1218,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
+ // Borland single token adornments.
+ case tok::kw___pascal:
+ DS.AddAttributes(ParseBorlandTypeAttributes());
+ continue;
+
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
@@ -1383,7 +1434,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
{
SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+ llvm::SmallVector<Decl *, 8> ProtocolDecl;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
LAngleLoc, EndProtoLoc);
@@ -1403,7 +1454,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
assert(DiagID);
- Diag(Tok, DiagID) << PrevSpec;
+
+ if (DiagID == diag::ext_duplicate_declspec)
+ Diag(Tok, DiagID)
+ << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());
+ else
+ Diag(Tok, DiagID) << PrevSpec;
}
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
@@ -1495,10 +1551,10 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// simple-type-specifier:
case tok::annot_typename: {
- if (Tok.getAnnotationValue())
+ if (ParsedType T = getTypeAnnotation(Tok)) {
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- DiagID, Tok.getAnnotationValue());
- else
+ DiagID, T);
+ } else
DS.SetTypeSpecError();
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeToken(); // The typename
@@ -1511,7 +1567,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
return true;
SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
+ llvm::SmallVector<Decl *, 8> ProtocolDecl;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
LAngleLoc, EndProtoLoc);
@@ -1643,6 +1699,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID);
break;
+
case tok::kw___ptr64:
case tok::kw___w64:
case tok::kw___cdecl:
@@ -1652,6 +1709,10 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
DS.AddAttributes(ParseMicrosoftTypeAttributes());
return true;
+ case tok::kw___pascal:
+ DS.AddAttributes(ParseBorlandTypeAttributes());
+ return true;
+
default:
// Not a type-specifier; do nothing.
return false;
@@ -1728,7 +1789,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
if (Tok.is(tok::colon)) {
ConsumeToken();
- OwningExprResult Res(ParseConstantExpression());
+ ExprResult Res(ParseConstantExpression());
if (Res.isInvalid())
SkipUntil(tok::semi, true, true);
else
@@ -1743,7 +1804,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
}
// We're done with this declarator; invoke the callback.
- DeclPtrTy D = Fields.invoke(DeclaratorInfo);
+ Decl *D = Fields.invoke(DeclaratorInfo);
PD.complete(D);
// If we don't have a comma, it is either the end of the list (a ';')
@@ -1769,10 +1830,9 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
/// [OBC] '@' 'defs' '(' class-name ')'
///
void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
- unsigned TagType, DeclPtrTy TagDecl) {
- PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
- PP.getSourceManager(),
- "parsing struct/union body");
+ unsigned TagType, Decl *TagDecl) {
+ PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ "parsing struct/union body");
SourceLocation LBraceLoc = ConsumeBrace();
@@ -1782,10 +1842,10 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
// C++.
if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
- Diag(Tok, diag::ext_empty_struct_union_enum)
- << DeclSpec::getSpecifierName((DeclSpec::TST)TagType);
+ Diag(Tok, diag::ext_empty_struct_union)
+ << (TagType == TST_union);
- llvm::SmallVector<DeclPtrTy, 32> FieldDecls;
+ llvm::SmallVector<Decl *, 32> FieldDecls;
// While we still have something to read, read the declarations in the struct.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
@@ -1806,16 +1866,16 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
if (!Tok.is(tok::at)) {
struct CFieldCallback : FieldCallback {
Parser &P;
- DeclPtrTy TagDecl;
- llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
+ Decl *TagDecl;
+ llvm::SmallVectorImpl<Decl *> &FieldDecls;
- CFieldCallback(Parser &P, DeclPtrTy TagDecl,
- llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) :
+ CFieldCallback(Parser &P, Decl *TagDecl,
+ llvm::SmallVectorImpl<Decl *> &FieldDecls) :
P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
- virtual DeclPtrTy invoke(FieldDeclarator &FD) {
+ virtual Decl *invoke(FieldDeclarator &FD) {
// Install the declarator into the current TagDecl.
- DeclPtrTy Field = P.Actions.ActOnField(P.getCurScope(), TagDecl,
+ Decl *Field = P.Actions.ActOnField(P.getCurScope(), TagDecl,
FD.D.getDeclSpec().getSourceRange().getBegin(),
FD.D, FD.BitfieldSize);
FieldDecls.push_back(Field);
@@ -1838,7 +1898,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
SkipUntil(tok::semi, true);
continue;
}
- llvm::SmallVector<DeclPtrTy, 16> Fields;
+ llvm::SmallVector<Decl *, 16> Fields;
Actions.ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),
Tok.getIdentifierInfo(), Fields);
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
@@ -1905,7 +1965,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
CXXScopeSpec &SS = DS.getTypeSpecScope();
if (getLang().CPlusPlus) {
- if (ParseOptionalCXXScopeSpecifier(SS, 0, false))
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false))
return;
if (SS.isSet() && Tok.isNot(tok::identifier)) {
@@ -1944,18 +2004,18 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// enum foo {..}; void bar() { enum foo; } <- new foo in bar.
// enum foo {..}; void bar() { enum foo x; } <- use of old foo.
//
- Action::TagUseKind TUK;
+ Sema::TagUseKind TUK;
if (Tok.is(tok::l_brace))
- TUK = Action::TUK_Definition;
+ TUK = Sema::TUK_Definition;
else if (Tok.is(tok::semi))
- TUK = Action::TUK_Declaration;
+ TUK = Sema::TUK_Declaration;
else
- TUK = Action::TUK_Reference;
+ TUK = Sema::TUK_Reference;
// enums cannot be templates, although they can be referenced from a
// template.
if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
- TUK != Action::TUK_Reference) {
+ TUK != Sema::TUK_Reference) {
Diag(Tok, diag::err_enum_template);
// Skip the rest of this declarator, up until the comma or semicolon.
@@ -1968,11 +2028,11 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
const char *PrevSpec = 0;
unsigned DiagID;
- DeclPtrTy TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
- StartLoc, SS, Name, NameLoc, Attr.get(),
- AS,
- Action::MultiTemplateParamsArg(Actions),
- Owned, IsDependent);
+ Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK,
+ StartLoc, SS, Name, NameLoc, Attr.get(),
+ AS,
+ MultiTemplateParamsArg(Actions),
+ Owned, IsDependent);
if (IsDependent) {
// This enum has a dependent nested-name-specifier. Handle it as a
// dependent tag.
@@ -1991,13 +2051,13 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
if (DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc, PrevSpec, DiagID,
- Type.get(), false))
+ Type.get()))
Diag(StartLoc, DiagID) << PrevSpec;
return;
}
- if (!TagDecl.get()) {
+ if (!TagDecl) {
// The action failed to produce an enumeration tag. If this is a
// definition, consume the entire definition.
if (Tok.is(tok::l_brace)) {
@@ -2012,10 +2072,10 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (Tok.is(tok::l_brace))
ParseEnumBody(StartLoc, TagDecl);
- // FIXME: The DeclSpec should keep the locations of both the keyword and the
- // name (if there is one).
+ // FIXME: The DeclSpec should keep the locations of both the keyword
+ // and the name (if there is one).
if (DS.SetTypeSpecType(DeclSpec::TST_enum, TSTLoc, PrevSpec, DiagID,
- TagDecl.getAs<void>(), Owned))
+ TagDecl, Owned))
Diag(StartLoc, DiagID) << PrevSpec;
}
@@ -2029,7 +2089,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
/// enumeration-constant:
/// identifier
///
-void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
+void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
// Enter the scope of the enum body and start the definition.
ParseScope EnumScope(this, Scope::DeclScope);
Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);
@@ -2040,9 +2100,9 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
Diag(Tok, diag::error_empty_enum);
- llvm::SmallVector<DeclPtrTy, 32> EnumConstantDecls;
+ llvm::SmallVector<Decl *, 32> EnumConstantDecls;
- DeclPtrTy LastEnumConstDecl;
+ Decl *LastEnumConstDecl = 0;
// Parse the enumerator-list.
while (Tok.is(tok::identifier)) {
@@ -2050,7 +2110,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
SourceLocation IdentLoc = ConsumeToken();
SourceLocation EqualLoc;
- OwningExprResult AssignedVal(Actions);
+ ExprResult AssignedVal;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
AssignedVal = ParseConstantExpression();
@@ -2059,11 +2119,11 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
}
// Install the enumerator constant into EnumDecl.
- DeclPtrTy EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
- LastEnumConstDecl,
- IdentLoc, Ident,
- EqualLoc,
- AssignedVal.release());
+ Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl,
+ LastEnumConstDecl,
+ IdentLoc, Ident,
+ EqualLoc,
+ AssignedVal.release());
EnumConstantDecls.push_back(EnumConstDecl);
LastEnumConstDecl = EnumConstDecl;
@@ -2229,6 +2289,7 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___thiscall:
case tok::kw___w64:
case tok::kw___ptr64:
+ case tok::kw___pascal:
return true;
}
}
@@ -2337,6 +2398,7 @@ bool Parser::isDeclarationSpecifier() {
case tok::kw___w64:
case tok::kw___ptr64:
case tok::kw___forceinline:
+ case tok::kw___pascal:
return true;
}
}
@@ -2346,7 +2408,7 @@ bool Parser::isConstructorDeclarator() {
// Parse the C++ scope specifier.
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, 0, true)) {
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true)) {
TPA.Revert();
return false;
}
@@ -2388,15 +2450,19 @@ bool Parser::isConstructorDeclarator() {
}
/// ParseTypeQualifierListOpt
-/// type-qualifier-list: [C99 6.7.5]
-/// type-qualifier
-/// [GNU] attributes [ only if AttributesAllowed=true ]
-/// type-qualifier-list type-qualifier
-/// [GNU] type-qualifier-list attributes [ only if AttributesAllowed=true ]
-/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
-/// if CXX0XAttributesAllowed = true
+/// type-qualifier-list: [C99 6.7.5]
+/// type-qualifier
+/// [vendor] attributes
+/// [ only if VendorAttributesAllowed=true ]
+/// type-qualifier-list type-qualifier
+/// [vendor] type-qualifier-list attributes
+/// [ only if VendorAttributesAllowed=true ]
+/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
+/// [ only if CXX0XAttributesAllowed=true ]
+/// Note: vendor can be GNU, MS, etc.
///
-void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
+void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
+ bool VendorAttributesAllowed,
bool CXX0XAttributesAllowed) {
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
SourceLocation Loc = Tok.getLocation();
@@ -2414,6 +2480,11 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
+ case tok::code_completion:
+ Actions.CodeCompleteTypeQualifiers(DS);
+ ConsumeCodeCompletionToken();
+ break;
+
case tok::kw_const:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
getLang());
@@ -2432,13 +2503,19 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
case tok::kw___stdcall:
case tok::kw___fastcall:
case tok::kw___thiscall:
- if (GNUAttributesAllowed) {
+ if (VendorAttributesAllowed) {
DS.AddAttributes(ParseMicrosoftTypeAttributes());
continue;
}
goto DoneWithTypeQuals;
+ case tok::kw___pascal:
+ if (VendorAttributesAllowed) {
+ DS.AddAttributes(ParseBorlandTypeAttributes());
+ continue;
+ }
+ goto DoneWithTypeQuals;
case tok::kw___attribute:
- if (GNUAttributesAllowed) {
+ if (VendorAttributesAllowed) {
DS.AddAttributes(ParseGNUAttributes());
continue; // do *not* consume the next token!
}
@@ -2494,6 +2571,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser) {
if (Diags.hasAllExtensionsSilenced())
D.setExtension();
+
// C++ member pointers start with a '::' or a nested-name.
// Member pointers get special handling, since there's no place for the
// scope spec in the generic path below.
@@ -2501,7 +2579,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
(Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
Tok.is(tok::annot_cxxscope))) {
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); // ignore fail
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true); // ignore fail
if (SS.isNotEmpty()) {
if (Tok.isNot(tok::star)) {
@@ -2660,8 +2738,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
// ParseDeclaratorInternal might already have parsed the scope.
if (D.getCXXScopeSpec().isEmpty()) {
- ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
- true);
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), ParsedType(), true);
}
if (D.getCXXScopeSpec().isValid()) {
@@ -2690,7 +2767,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
/*EnteringContext=*/true,
/*AllowDestructorName=*/true,
AllowConstructorName,
- /*ObjectType=*/0,
+ ParsedType(),
D.getName()) ||
// Once we're past the identifier, if the scope was bad, mark the
// whole declarator bad.
@@ -2724,7 +2801,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// scope when parsing the parenthesized declarator, then exited
// the scope already. Re-enter the scope, if we need to.
if (D.getCXXScopeSpec().isSet()) {
- if (Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
+ // If there was an error parsing parenthesized declarator, declarator
+ // scope may have been enterred before. Don't do it again.
+ if (!D.isInvalidType() &&
+ Actions.ShouldEnterDeclaratorScope(getCurScope(), D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
DeclScopeObj.EnterDeclaratorScope();
@@ -2820,6 +2900,10 @@ void Parser::ParseParenDeclarator(Declarator &D) {
Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) {
AttrList.reset(ParseMicrosoftTypeAttributes(AttrList.take()));
}
+ // Eat any Borland extensions.
+ if (Tok.is(tok::kw___pascal)) {
+ AttrList.reset(ParseBorlandTypeAttributes(AttrList.take()));
+ }
// If we haven't past the identifier yet (or where the identifier would be
// stored, if this is an abstract declarator), then this is probably just
@@ -2922,7 +3006,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
bool hasExceptionSpec = false;
SourceLocation ThrowLoc;
bool hasAnyExceptionSpec = false;
- llvm::SmallVector<TypeTy*, 2> Exceptions;
+ llvm::SmallVector<ParsedType, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
if (getLang().CPlusPlus) {
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
@@ -3061,7 +3145,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
- DeclPtrTy Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
// Parse the default argument, if any. We parse the default
// arguments in all dialects; the semantic analysis in
@@ -3085,21 +3169,29 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
delete DefArgToks;
DefArgToks = 0;
Actions.ActOnParamDefaultArgumentError(Param);
- } else
+ } else {
+ // Mark the end of the default argument so that we know when to
+ // stop when we parse it later on.
+ Token DefArgEnd;
+ DefArgEnd.startToken();
+ DefArgEnd.setKind(tok::cxx_defaultarg_end);
+ DefArgEnd.setLocation(Tok.getLocation());
+ DefArgToks->push_back(DefArgEnd);
Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
(*DefArgToks)[1].getLocation());
+ }
} else {
// Consume the '='.
ConsumeToken();
- OwningExprResult DefArgResult(ParseAssignmentExpression());
+ ExprResult DefArgResult(ParseAssignmentExpression());
if (DefArgResult.isInvalid()) {
Actions.ActOnParamDefaultArgumentError(Param);
SkipUntil(tok::comma, tok::r_paren, true, true);
} else {
// Inform the actions module about the default argument
Actions.ActOnParamDefaultArgument(Param, EqualLoc,
- move(DefArgResult));
+ DefArgResult.take());
}
}
}
@@ -3141,7 +3233,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
bool hasExceptionSpec = false;
SourceLocation ThrowLoc;
bool hasAnyExceptionSpec = false;
- llvm::SmallVector<TypeTy*, 2> Exceptions;
+ llvm::SmallVector<ParsedType, 2> Exceptions;
llvm::SmallVector<SourceRange, 2> ExceptionRanges;
if (getLang().CPlusPlus) {
@@ -3202,8 +3294,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// The first identifier was already read, and is known to be the first
// identifier in the list. Remember this identifier in ParamInfo.
ParamsSoFar.insert(FirstIdent);
- ParamInfo.push_back(DeclaratorChunk::ParamInfo(FirstIdent, FirstIdentLoc,
- DeclPtrTy()));
+ ParamInfo.push_back(DeclaratorChunk::ParamInfo(FirstIdent, FirstIdentLoc, 0));
while (Tok.is(tok::comma)) {
// Eat the comma.
@@ -3229,7 +3320,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// Remember this identifier in ParamInfo.
ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
Tok.getLocation(),
- DeclPtrTy()));
+ 0));
}
// Eat the identifier.
@@ -3271,7 +3362,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
}
// Remember that we parsed the empty array type.
- OwningExprResult NumElements(Actions);
+ ExprResult NumElements;
D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
StartLoc, EndLoc),
EndLoc);
@@ -3279,7 +3370,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
} else if (Tok.getKind() == tok::numeric_constant &&
GetLookAheadToken(1).is(tok::r_square)) {
// [4] is very common. Parse the numeric constant expression.
- OwningExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
+ ExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
ConsumeToken();
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
@@ -3317,7 +3408,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// Handle "direct-declarator [ type-qual-list[opt] * ]".
bool isStar = false;
- OwningExprResult NumElements(Actions);
+ ExprResult NumElements;
// Handle the case where we have '[*]' as the array size. However, a leading
// star could be the start of an expression, for example 'X[*p + 4]'. Verify
@@ -3382,12 +3473,12 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
const bool hasParens = Tok.is(tok::l_paren);
bool isCastExpr;
- TypeTy *CastTy;
+ ParsedType CastTy;
SourceRange CastRange;
- OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
- isCastExpr,
- CastTy,
- CastRange);
+ ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
+ isCastExpr,
+ CastTy,
+ CastRange);
if (hasParens)
DS.setTypeofParensRange(CastRange);
@@ -3422,7 +3513,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
- DiagID, Operand.release()))
+ DiagID, Operand.get()))
Diag(StartLoc, DiagID) << PrevSpec;
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 590ba6c6f8bc..b277156a0d06 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -14,37 +14,42 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
#include "RAIIObjectsForParser.h"
using namespace clang;
/// ParseNamespace - We know that the current token is a namespace keyword. This
-/// may either be a top level namespace or a block-level namespace alias.
+/// may either be a top level namespace or a block-level namespace alias. If
+/// there was an inline keyword, it has already been parsed.
///
/// namespace-definition: [C++ 7.3: basic.namespace]
/// named-namespace-definition
/// unnamed-namespace-definition
///
/// unnamed-namespace-definition:
-/// 'namespace' attributes[opt] '{' namespace-body '}'
+/// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
///
/// named-namespace-definition:
/// original-namespace-definition
/// extension-namespace-definition
///
/// original-namespace-definition:
-/// 'namespace' identifier attributes[opt] '{' namespace-body '}'
+/// 'inline'[opt] 'namespace' identifier attributes[opt]
+/// '{' namespace-body '}'
///
/// extension-namespace-definition:
-/// 'namespace' original-namespace-name '{' namespace-body '}'
+/// 'inline'[opt] 'namespace' original-namespace-name
+/// '{' namespace-body '}'
///
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
///
-Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
- SourceLocation &DeclEnd) {
+Decl *Parser::ParseNamespace(unsigned Context,
+ SourceLocation &DeclEnd,
+ SourceLocation InlineLoc) {
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
@@ -75,6 +80,9 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
if (Tok.is(tok::equal)) {
if (AttrList)
Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
+ if (InlineLoc.isValid())
+ Diag(InlineLoc, diag::err_inline_namespace_alias)
+ << FixItHint::CreateRemoval(InlineLoc);
return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
}
@@ -82,7 +90,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
if (Tok.isNot(tok::l_brace)) {
Diag(Tok, Ident ? diag::err_expected_lbrace :
diag::err_expected_ident_lbrace);
- return DeclPtrTy();
+ return 0;
}
SourceLocation LBrace = ConsumeBrace();
@@ -92,19 +100,22 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
getCurScope()->getFnParent()) {
Diag(LBrace, diag::err_namespace_nonnamespace_scope);
SkipUntil(tok::r_brace, false);
- return DeclPtrTy();
+ return 0;
}
+ // If we're still good, complain about inline namespaces in non-C++0x now.
+ if (!getLang().CPlusPlus0x && InlineLoc.isValid())
+ Diag(InlineLoc, diag::ext_inline_namespace);
+
// Enter a scope for the namespace.
ParseScope NamespaceScope(this, Scope::DeclScope);
- DeclPtrTy NamespcDecl =
- Actions.ActOnStartNamespaceDef(getCurScope(), IdentLoc, Ident, LBrace,
- AttrList.get());
+ Decl *NamespcDecl =
+ Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, IdentLoc, Ident,
+ LBrace, AttrList.get());
- PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
- PP.getSourceManager(),
- "parsing namespace");
+ PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
+ "parsing namespace");
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
CXX0XAttributeList Attr;
@@ -126,7 +137,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
/// ParseNamespaceAlias - Parse the part after the '=' in a namespace
/// alias definition.
///
-Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
+Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceLocation &DeclEnd) {
@@ -141,13 +152,13 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_namespace_name);
// Skip to end of the definition and eat the ';'.
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
// Parse identifier.
@@ -170,7 +181,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
/// 'extern' string-literal '{' declaration-seq[opt] '}'
/// 'extern' string-literal declaration
///
-Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
+Decl *Parser::ParseLinkage(ParsingDeclSpec &DS,
unsigned Context) {
assert(Tok.is(tok::string_literal) && "Not a string literal!");
llvm::SmallString<8> LangBuffer;
@@ -178,12 +189,12 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
bool Invalid = false;
llvm::StringRef Lang = PP.getSpelling(Tok, LangBuffer, &Invalid);
if (Invalid)
- return DeclPtrTy();
+ return 0;
SourceLocation Loc = ConsumeStringToken();
ParseScope LinkageScope(this, Scope::DeclScope);
- DeclPtrTy LinkageSpec
+ Decl *LinkageSpec
= Actions.ActOnStartLinkageSpecification(getCurScope(),
/*FIXME: */SourceLocation(),
Loc, Lang,
@@ -196,7 +207,8 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
}
if (Tok.isNot(tok::l_brace)) {
- ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
+ DS.setExternInLinkageSpec(true);
+ ParseExternalDeclaration(Attr, &DS);
return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
SourceLocation());
}
@@ -221,7 +233,7 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
/// using-directive. Assumes that current token is 'using'.
-Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
+Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
SourceLocation &DeclEnd,
CXX0XAttributeList Attr) {
assert(Tok.is(tok::kw_using) && "Not using token");
@@ -257,7 +269,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
/// namespace-name attributes[opt] ;
///
-Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
+Decl *Parser::ParseUsingDirective(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AttributeList *Attr) {
@@ -273,7 +285,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
IdentifierInfo *NamespcName = 0;
SourceLocation IdentLoc = SourceLocation();
@@ -284,7 +296,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
// If there was invalid namespace name, skip to end of decl, and eat ';'.
SkipUntil(tok::semi);
// FIXME: Are there cases, when we would like to call ActOnUsingDirective?
- return DeclPtrTy();
+ return 0;
}
// Parse identifier.
@@ -316,7 +328,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
/// unqualified-id
/// 'using' :: unqualified-id
///
-Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
+Decl *Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation UsingLoc,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
@@ -335,12 +347,12 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
IsTypeName = false;
// Parse nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
// Check nested-name specifier.
if (SS.isInvalid()) {
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
// Parse the unqualified-id. We allow parsing of both constructor and
@@ -351,10 +363,10 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
/*EnteringContext=*/false,
/*AllowDestructorName=*/true,
/*AllowConstructorName=*/true,
- /*ObjectType=*/0,
+ ParsedType(),
Name)) {
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
// Parse (optional) attributes (most likely GNU strong-using extension).
@@ -377,43 +389,44 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
/// static_assert-declaration:
/// static_assert ( constant-expression , string-literal ) ;
///
-Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
+Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration");
SourceLocation StaticAssertLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren)) {
Diag(Tok, diag::err_expected_lparen);
- return DeclPtrTy();
+ return 0;
}
SourceLocation LParenLoc = ConsumeParen();
- OwningExprResult AssertExpr(ParseConstantExpression());
+ ExprResult AssertExpr(ParseConstantExpression());
if (AssertExpr.isInvalid()) {
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
- return DeclPtrTy();
+ return 0;
if (Tok.isNot(tok::string_literal)) {
Diag(Tok, diag::err_expected_string_literal);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
- OwningExprResult AssertMessage(ParseStringLiteralExpression());
+ ExprResult AssertMessage(ParseStringLiteralExpression());
if (AssertMessage.isInvalid())
- return DeclPtrTy();
+ return 0;
MatchRHSPunctuation(tok::r_paren, LParenLoc);
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert);
- return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr),
- move(AssertMessage));
+ return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc,
+ AssertExpr.take(),
+ AssertMessage.take());
}
/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
@@ -437,8 +450,8 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
// C++0x [dcl.type.simple]p4:
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions,
- Action::Unevaluated);
- OwningExprResult Result = ParseExpression();
+ Sema::Unevaluated);
+ ExprResult Result = ParseExpression();
if (Result.isInvalid()) {
SkipUntil(tok::r_paren);
return;
@@ -483,7 +496,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
AnnotateTemplateIdTokenAsType(SS);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
- TypeTy *Type = Tok.getAnnotationValue();
+ ParsedType Type = getTypeAnnotation(Tok);
EndLocation = Tok.getAnnotationEndLoc();
ConsumeToken();
@@ -536,13 +549,13 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
// Retrieve the type from the annotation token, consume that token, and
// return.
EndLocation = Tok.getAnnotationEndLoc();
- TypeTy *Type = Tok.getAnnotationValue();
+ ParsedType Type = getTypeAnnotation(Tok);
ConsumeToken();
return Type;
}
// We have an identifier; check whether it is actually a type.
- TypeTy *Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), SS, true);
+ ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), SS, true);
if (!Type) {
Diag(IdLoc, diag::err_expected_class_name);
return true;
@@ -550,7 +563,19 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
// Consume the identifier.
EndLocation = IdLoc;
- return Type;
+
+ // Fake up a Declarator to use with ActOnTypeName.
+ DeclSpec DS;
+ DS.SetRangeStart(IdLoc);
+ DS.SetRangeEnd(EndLocation);
+ DS.getTypeSpecScope() = *SS;
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type);
+
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}
/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
@@ -633,7 +658,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
AttrList = ParseGNUAttributes();
// If declspecs exist after tag, parse them.
- if (Tok.is(tok::kw___declspec))
+ while (Tok.is(tok::kw___declspec))
AttrList = ParseMicrosoftDeclSpec(AttrList);
// If C++0x attributes exist here, parse them.
@@ -648,7 +673,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// token sequence "struct __is_pod", make __is_pod into a normal
// identifier rather than a keyword, to allow libstdc++ 4.2 to work
// properly.
- Tok.getIdentifierInfo()->setTokenID(tok::identifier);
+ Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
Tok.setKind(tok::identifier);
}
@@ -658,7 +683,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// token sequence "struct __is_empty", make __is_empty into a normal
// identifier rather than a keyword, to allow libstdc++ 4.2 to work
// properly.
- Tok.getIdentifierInfo()->setTokenID(tok::identifier);
+ Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
Tok.setKind(tok::identifier);
}
@@ -668,7 +693,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// "FOO : BAR" is not a potential typo for "FOO::BAR".
ColonProtectionRAIIObject X(*this);
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), true))
+ DS.SetTypeSpecError();
if (SS.isSet())
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
Diag(Tok, diag::err_expected_ident);
@@ -769,9 +795,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// or
// &T::operator struct s;
// For these, SuppressDeclarations is true.
- Action::TagUseKind TUK;
+ Sema::TagUseKind TUK;
if (SuppressDeclarations)
- TUK = Action::TUK_Reference;
+ TUK = Sema::TUK_Reference;
else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))){
if (DS.isFriendSpecified()) {
// C++ [class.friend]p2:
@@ -782,20 +808,23 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Skip everything up to the semicolon, so that this looks like a proper
// friend class (or template thereof) declaration.
SkipUntil(tok::semi, true, true);
- TUK = Action::TUK_Friend;
+ TUK = Sema::TUK_Friend;
} else {
// Okay, this is a class definition.
- TUK = Action::TUK_Definition;
+ TUK = Sema::TUK_Definition;
}
} else if (Tok.is(tok::semi))
- TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration;
+ TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
else
- TUK = Action::TUK_Reference;
-
- if (!Name && !TemplateId && TUK != Action::TUK_Definition) {
- // We have a declaration or reference to an anonymous class.
- Diag(StartLoc, diag::err_anon_type_definition)
- << DeclSpec::getSpecifierName(TagType);
+ TUK = Sema::TUK_Reference;
+
+ if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error ||
+ TUK != Sema::TUK_Definition)) {
+ if (DS.getTypeSpecType() != DeclSpec::TST_error) {
+ // We have a declaration or reference to an anonymous class.
+ Diag(StartLoc, diag::err_anon_type_definition)
+ << DeclSpec::getSpecifierName(TagType);
+ }
SkipUntil(tok::comma, true);
@@ -805,8 +834,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
// Create the tag portion of the class or class template.
- Action::DeclResult TagOrTempResult = true; // invalid
- Action::TypeResult TypeResult = true; // invalid
+ DeclResult TagOrTempResult = true; // invalid
+ TypeResult TypeResult = true; // invalid
bool Owned = false;
if (TemplateId) {
@@ -816,7 +845,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
- TUK == Action::TUK_Declaration) {
+ TUK == Sema::TUK_Declaration) {
// This is an explicit instantiation of a class template.
TagOrTempResult
= Actions.ActOnExplicitInstantiation(getCurScope(),
@@ -825,7 +854,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TagType,
StartLoc,
SS,
- TemplateTy::make(TemplateId->Template),
+ TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -836,11 +865,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// they have template headers, in which case they're ill-formed
// (FIXME: "template <class T> friend class A<T>::B<int>;").
// We diagnose this error in ActOnClassTemplateSpecialization.
- } else if (TUK == Action::TUK_Reference ||
- (TUK == Action::TUK_Friend &&
+ } else if (TUK == Sema::TUK_Reference ||
+ (TUK == Sema::TUK_Friend &&
TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
TypeResult
- = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ = Actions.ActOnTemplateIdType(TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -862,7 +891,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// but it actually has a definition. Most likely, this was
// meant to be an explicit specialization, but the user forgot
// the '<>' after 'template'.
- assert(TUK == Action::TUK_Definition && "Expected a definition here");
+ assert(TUK == Sema::TUK_Definition && "Expected a definition here");
SourceLocation LAngleLoc
= PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
@@ -887,19 +916,19 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TagOrTempResult
= Actions.ActOnClassTemplateSpecialization(getCurScope(), TagType, TUK,
StartLoc, SS,
- TemplateTy::make(TemplateId->Template),
+ TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc,
AttrList,
- Action::MultiTemplateParamsArg(Actions,
+ MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0));
}
TemplateId->Destroy();
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
- TUK == Action::TUK_Declaration) {
+ TUK == Sema::TUK_Declaration) {
// Explicit instantiation of a member of a class template
// specialization, e.g.,
//
@@ -913,7 +942,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
NameLoc, AttrList);
} else {
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
- TUK == Action::TUK_Definition) {
+ TUK == Sema::TUK_Definition) {
// FIXME: Diagnose this particular error.
}
@@ -922,7 +951,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Declaration or definition of a class type
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc, SS,
Name, NameLoc, AttrList, AS,
- Action::MultiTemplateParamsArg(Actions,
+ MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0),
Owned, IsDependent);
@@ -935,7 +964,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
// If there is a body, parse it and inform the actions module.
- if (TUK == Action::TUK_Definition) {
+ if (TUK == Sema::TUK_Definition) {
assert(Tok.is(tok::l_brace) ||
(getLang().CPlusPlus && Tok.is(tok::colon)));
if (getLang().CPlusPlus)
@@ -944,27 +973,25 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
}
- void *Result;
+ // FIXME: The DeclSpec should keep the locations of both the keyword and the
+ // name (if there is one).
+ SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+ bool Result;
if (!TypeResult.isInvalid()) {
- TagType = DeclSpec::TST_typename;
- Result = TypeResult.get();
- Owned = false;
+ Result = DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc,
+ PrevSpec, DiagID, TypeResult.get());
} else if (!TagOrTempResult.isInvalid()) {
- Result = TagOrTempResult.get().getAs<void>();
+ Result = DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
+ TagOrTempResult.get(), Owned);
} else {
DS.SetTypeSpecError();
return;
}
- const char *PrevSpec = 0;
- unsigned DiagID;
-
- // FIXME: The DeclSpec should keep the locations of both the keyword and the
- // name (if there is one).
- SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
-
- if (DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
- Result, Owned))
+ if (Result)
Diag(StartLoc, DiagID) << PrevSpec;
// At this point, we've successfully parsed a class-specifier in 'definition'
@@ -974,7 +1001,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// the end of the declaration and recover that way.
//
// This switch enumerates the valid "follow" set for definition.
- if (TUK == Action::TUK_Definition) {
+ if (TUK == Sema::TUK_Definition) {
bool ExpectedSemi = true;
switch (Tok.getKind()) {
default: break;
@@ -1048,12 +1075,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
/// base-specifier-list:
/// base-specifier '...'[opt]
/// base-specifier-list ',' base-specifier '...'[opt]
-void Parser::ParseBaseClause(DeclPtrTy ClassDecl) {
+void Parser::ParseBaseClause(Decl *ClassDecl) {
assert(Tok.is(tok::colon) && "Not a base clause");
ConsumeToken();
// Build up an array of parsed base specifiers.
- llvm::SmallVector<BaseTy *, 8> BaseInfo;
+ llvm::SmallVector<CXXBaseSpecifier *, 8> BaseInfo;
while (true) {
// Parse a base-specifier.
@@ -1090,7 +1117,7 @@ void Parser::ParseBaseClause(DeclPtrTy ClassDecl) {
/// class-name
/// access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
/// class-name
-Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
+Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
bool IsVirtual = false;
SourceLocation StartLoc = Tok.getLocation();
@@ -1120,8 +1147,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
// Parse optional '::' and optional nested-name-specifier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
- /*EnteringContext=*/false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
// The location of the base class itself.
SourceLocation BaseLoc = Tok.getLocation();
@@ -1158,7 +1184,7 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
}
void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
- DeclPtrTy ThisDecl) {
+ Decl *ThisDecl) {
// We just declared a member function. If this member function
// has any default arguments, we'll need to parse them later.
LateParsedMethodDeclaration *LateMethod = 0;
@@ -1218,7 +1244,8 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
/// '=' constant-expression
///
void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
- const ParsedTemplateInfo &TemplateInfo) {
+ const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject *TemplateDiags) {
// Access declarations.
if (!TemplateInfo.Kind &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
@@ -1233,11 +1260,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (isAccessDecl) {
// Collect the scope specifier token we annotated earlier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType*/ 0, false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
// Try to parse an unqualified-id.
UnqualifiedId Name;
- if (ParseUnqualifiedId(SS, false, true, true, /*ObjectType*/ 0, Name)) {
+ if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), Name)) {
SkipUntil(tok::semi);
return;
}
@@ -1281,7 +1308,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+ return ParseCXXClassMemberDeclaration(AS, TemplateInfo, TemplateDiags);
}
// Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
@@ -1317,17 +1344,19 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation DSStart = Tok.getLocation();
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
- ParsingDeclSpec DS(*this);
+ ParsingDeclSpec DS(*this, TemplateDiags);
DS.AddAttributes(AttrList.AttrList);
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
- Action::MultiTemplateParamsArg TemplateParams(Actions,
+ MultiTemplateParamsArg TemplateParams(Actions,
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
if (Tok.is(tok::semi)) {
ConsumeToken();
- Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ Decl *TheDecl =
+ Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ DS.complete(TheDecl);
return;
}
@@ -1385,9 +1414,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// member-declarator
// member-declarator-list ',' member-declarator
- llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
- OwningExprResult BitfieldSize(Actions);
- OwningExprResult Init(Actions);
+ llvm::SmallVector<Decl *, 8> DeclsInGroup;
+ ExprResult BitfieldSize;
+ ExprResult Init;
bool Deleted = false;
while (1) {
@@ -1426,7 +1455,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// If a simple-asm-expr is present, parse it.
if (Tok.is(tok::kw_asm)) {
SourceLocation Loc;
- OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid())
SkipUntil(tok::comma, true, true);
@@ -1445,7 +1474,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// this call will *not* return the created decl; It will return null.
// See Sema::ActOnCXXMemberDeclarator for details.
- DeclPtrTy ThisDecl;
+ Decl *ThisDecl = 0;
if (DS.isFriendSpecified()) {
// TODO: handle initializers, bitfields, 'delete'
ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
@@ -1515,14 +1544,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
/// access-specifier ':' member-specification[opt]
///
void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
- unsigned TagType, DeclPtrTy TagDecl) {
+ unsigned TagType, Decl *TagDecl) {
assert((TagType == DeclSpec::TST_struct ||
TagType == DeclSpec::TST_union ||
TagType == DeclSpec::TST_class) && "Invalid TagType!");
- PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
- PP.getSourceManager(),
- "parsing struct/union/class body");
+ PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
+ "parsing struct/union/class body");
// Determine whether this is a non-nested class. Note that local
// classes are *not* considered to be nested classes.
@@ -1681,21 +1709,28 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
/// [C++] mem-initializer-list:
/// mem-initializer
/// mem-initializer , mem-initializer-list
-void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
+void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
SourceLocation ColonLoc = ConsumeToken();
- llvm::SmallVector<MemInitTy*, 4> MemInitializers;
+ llvm::SmallVector<CXXBaseOrMemberInitializer*, 4> MemInitializers;
bool AnyErrors = false;
do {
- MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
- if (!MemInit.isInvalid())
- MemInitializers.push_back(MemInit.get());
- else
- AnyErrors = true;
-
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
+ MemInitializers.data(),
+ MemInitializers.size());
+ ConsumeCodeCompletionToken();
+ } else {
+ MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
+ if (!MemInit.isInvalid())
+ MemInitializers.push_back(MemInit.get());
+ else
+ AnyErrors = true;
+ }
+
if (Tok.is(tok::comma))
ConsumeToken();
else if (Tok.is(tok::l_brace))
@@ -1724,11 +1759,11 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
/// [C++] mem-initializer-id:
/// '::'[opt] nested-name-specifier[opt] class-name
/// identifier
-Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
+Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// parse '::'[opt] nested-name-specifier[opt]
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
- TypeTy *TemplateTypeTy = 0;
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
+ ParsedType TemplateTypeTy;
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
@@ -1736,7 +1771,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
TemplateId->Kind == TNK_Dependent_template_name) {
AnnotateTemplateIdTokenAsType(&SS);
assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
- TemplateTypeTy = Tok.getAnnotationValue();
+ TemplateTypeTy = getTypeAnnotation(Tok);
}
}
if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
@@ -1785,9 +1820,9 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
/// type-id-list ',' type-id
///
bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
- llvm::SmallVector<TypeTy*, 2>
+ llvm::SmallVectorImpl<ParsedType>
&Exceptions,
- llvm::SmallVector<SourceRange, 2>
+ llvm::SmallVectorImpl<SourceRange>
&Ranges,
bool &hasAnyExceptionSpec) {
assert(Tok.is(tok::kw_throw) && "expected throw");
@@ -1831,7 +1866,7 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
/// \brief We have just started parsing the definition of a new class,
/// so push that class onto our stack of classes that is currently
/// being parsed.
-void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool NonNestedClass) {
+void Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass) {
assert((NonNestedClass || !ClassStack.empty()) &&
"Nested class without outer class");
ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
@@ -1997,7 +2032,7 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
}
SourceLocation ParamLoc = ConsumeParen();
- OwningExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
+ ExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
MatchRHSPunctuation(tok::r_paren, ParamLoc);
@@ -2042,15 +2077,14 @@ CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
///
/// [C++0x] 'align' '(' type-id ')'
/// [C++0x] 'align' '(' assignment-expression ')'
-Parser::OwningExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
+ExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
if (isTypeIdInParens()) {
- EnterExpressionEvaluationContext Unevaluated(Actions,
- Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
SourceLocation TypeLoc = Tok.getLocation();
- TypeTy *Ty = ParseTypeName().get();
+ ParsedType Ty = ParseTypeName().get();
SourceRange TypeRange(Start, Tok.getLocation());
- return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, Ty,
- TypeRange);
+ return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true,
+ Ty.getAsOpaquePtr(), TypeRange);
} else
return ParseConstantExpression();
}
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index e7973f73ea15..c4beab191d37 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -20,9 +20,9 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "RAIIObjectsForParser.h"
#include "llvm/ADT/SmallVector.h"
@@ -30,8 +30,7 @@
using namespace clang;
/// getBinOpPrecedence - Return the precedence of the specified binary operator
-/// token. This returns:
-///
+/// token.
static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
bool GreaterThanIsOperator,
bool CPlusPlus0x) {
@@ -176,8 +175,8 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
/// assignment-expression
/// expression ',' assignment-expression
///
-Parser::OwningExprResult Parser::ParseExpression() {
- OwningExprResult LHS(ParseAssignmentExpression());
+ExprResult Parser::ParseExpression() {
+ ExprResult LHS(ParseAssignmentExpression());
if (LHS.isInvalid()) return move(LHS);
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
@@ -188,9 +187,9 @@ Parser::OwningExprResult Parser::ParseExpression() {
/// routine is necessary to disambiguate @try-statement from,
/// for example, @encode-expression.
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
- OwningExprResult LHS(ParseObjCAtExpression(AtLoc));
+ ExprResult LHS(ParseObjCAtExpression(AtLoc));
if (LHS.isInvalid()) return move(LHS);
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
@@ -199,9 +198,9 @@ Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
/// This routine is called when a leading '__extension__' is seen and
/// consumed. This is necessary because the token gets consumed in the
/// process of disambiguating between an expression and a declaration.
-Parser::OwningExprResult
+ExprResult
Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
- OwningExprResult LHS(Actions, true);
+ ExprResult LHS(true);
{
// Silence extension warnings in the sub-expression
ExtensionRAIIObject O(Diags);
@@ -211,27 +210,27 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
}
LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,
- move(LHS));
+ LHS.take());
if (LHS.isInvalid()) return move(LHS);
- return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
+ return ParseRHSOfBinaryExpression(LHS.take(), prec::Comma);
}
/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
///
-Parser::OwningExprResult Parser::ParseAssignmentExpression() {
+ExprResult Parser::ParseAssignmentExpression() {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_Expression);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
ConsumeCodeCompletionToken();
}
if (Tok.is(tok::kw_throw))
return ParseThrowExpression();
- OwningExprResult LHS(ParseCastExpression(false));
+ ExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
- return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
+ return ParseRHSOfBinaryExpression(LHS.take(), prec::Assignment);
}
/// ParseAssignmentExprWithObjCMessageExprStart - Parse an assignment expression
@@ -242,38 +241,38 @@ Parser::OwningExprResult Parser::ParseAssignmentExpression() {
///
/// Since this handles full assignment-expression's, it handles postfix
/// expressions and other binary operators for these expressions as well.
-Parser::OwningExprResult
+ExprResult
Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
SourceLocation SuperLoc,
- TypeTy *ReceiverType,
- ExprArg ReceiverExpr) {
- OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
- ReceiverType,
- move(ReceiverExpr)));
+ ParsedType ReceiverType,
+ Expr *ReceiverExpr) {
+ ExprResult R
+ = ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
+ ReceiverType, ReceiverExpr);
if (R.isInvalid()) return move(R);
- R = ParsePostfixExpressionSuffix(move(R));
+ R = ParsePostfixExpressionSuffix(R.take());
if (R.isInvalid()) return move(R);
- return ParseRHSOfBinaryExpression(move(R), prec::Assignment);
+ return ParseRHSOfBinaryExpression(R.take(), prec::Assignment);
}
-Parser::OwningExprResult Parser::ParseConstantExpression() {
+ExprResult Parser::ParseConstantExpression() {
// C++ [basic.def.odr]p2:
// An expression is potentially evaluated unless it appears where an
// integral constant expression is required (see 5.19) [...].
EnterExpressionEvaluationContext Unevaluated(Actions,
- Action::Unevaluated);
+ Sema::Unevaluated);
- OwningExprResult LHS(ParseCastExpression(false));
+ ExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
- return ParseRHSOfBinaryExpression(move(LHS), prec::Conditional);
+ return ParseRHSOfBinaryExpression(LHS.take(), prec::Conditional);
}
/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
/// LHS and has a precedence of at least MinPrec.
-Parser::OwningExprResult
-Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
+ExprResult
+Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),
GreaterThanIsOperator,
getLang().CPlusPlus0x);
@@ -291,7 +290,7 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
ConsumeToken();
// Special case handling for the ternary operator.
- OwningExprResult TernaryMiddle(Actions, true);
+ ExprResult TernaryMiddle(true);
if (NextTokPrec == prec::Conditional) {
if (Tok.isNot(tok::colon)) {
// Don't parse FOO:BAR as if it were a typo for FOO::BAR.
@@ -358,7 +357,7 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
// Therefore we need some special-casing here.
// Also note that the third operand of the conditional operator is
// an assignment-expression in C++.
- OwningExprResult RHS(Actions);
+ ExprResult RHS;
if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
RHS = ParseAssignmentExpression();
else
@@ -385,7 +384,7 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
// is okay, to bind exactly as tightly. For example, compile A=B=C=D as
// A=(B=(C=D)), where each paren is a level of recursion here.
// The function takes ownership of the RHS.
- RHS = ParseRHSOfBinaryExpression(move(RHS),
+ RHS = ParseRHSOfBinaryExpression(RHS.get(),
static_cast<prec::Level>(ThisPrec + !isRightAssoc));
if (RHS.isInvalid())
return move(RHS);
@@ -408,11 +407,11 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
Actions.getExprRange(RHS.get()).getEnd()));
LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
- OpToken.getKind(), move(LHS), move(RHS));
+ OpToken.getKind(), LHS.take(), RHS.take());
} else
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
- move(LHS), move(TernaryMiddle),
- move(RHS));
+ LHS.take(), TernaryMiddle.take(),
+ RHS.take());
}
}
}
@@ -422,11 +421,11 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
/// id-expression that is the operand of address-of gets special treatment
/// due to member pointers.
///
-Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
- TypeTy *TypeOfCast) {
+ ParsedType TypeOfCast) {
bool NotCastExpr;
- OwningExprResult Res = ParseCastExpression(isUnaryExpression,
+ ExprResult Res = ParseCastExpression(isUnaryExpression,
isAddressOfOperand,
NotCastExpr,
TypeOfCast);
@@ -527,14 +526,14 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
/// '::'[opt] 'delete' '[' ']' cast-expression
///
/// [GNU] unary-type-trait:
-/// '__has_nothrow_assign' [TODO]
-/// '__has_nothrow_copy' [TODO]
-/// '__has_nothrow_constructor' [TODO]
+/// '__has_nothrow_assign'
+/// '__has_nothrow_copy'
+/// '__has_nothrow_constructor'
/// '__has_trivial_assign' [TODO]
/// '__has_trivial_copy' [TODO]
/// '__has_trivial_constructor'
/// '__has_trivial_destructor'
-/// '__has_virtual_destructor' [TODO]
+/// '__has_virtual_destructor'
/// '__is_abstract' [TODO]
/// '__is_class'
/// '__is_empty' [TODO]
@@ -546,11 +545,11 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
/// [GNU] binary-type-trait:
/// '__is_base_of' [TODO]
///
-Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
bool &NotCastExpr,
- TypeTy *TypeOfCast) {
- OwningExprResult Res(Actions);
+ ParsedType TypeOfCast) {
+ ExprResult Res;
tok::TokenKind SavedKind = Tok.getKind();
NotCastExpr = false;
@@ -561,16 +560,17 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// expression, or statement expression.
//
// If the parsed tokens consist of a primary-expression, the cases below
- // call ParsePostfixExpressionSuffix to handle the postfix expression
- // suffixes. Cases that cannot be followed by postfix exprs should
- // return without invoking ParsePostfixExpressionSuffix.
+ // break out of the switch; at the end we call ParsePostfixExpressionSuffix
+ // to handle the postfix expression suffixes. Cases that cannot be followed
+ // by postfix exprs should return without invoking
+ // ParsePostfixExpressionSuffix.
switch (SavedKind) {
case tok::l_paren: {
// If this expression is limited to being a unary-expression, the parent can
// not start a cast expression.
ParenParseOption ParenExprType =
- isUnaryExpression ? CompoundLiteral : CastExpr;
- TypeTy *CastTy;
+ (isUnaryExpression && !getLang().CPlusPlus)? CompoundLiteral : CastExpr;
+ ParsedType CastTy;
SourceLocation LParenLoc = Tok.getLocation();
SourceLocation RParenLoc;
@@ -597,8 +597,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return move(Res);
}
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
}
// primary-expression
@@ -608,9 +607,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = Actions.ActOnNumericConstant(Tok);
ConsumeToken();
-
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::kw_true:
case tok::kw_false:
@@ -661,9 +658,12 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
ILoc, PropertyLoc);
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
}
+
+ // Make sure to pass down the right value for isAddressOfOperand.
+ if (isAddressOfOperand && isPostfixExpressionSuffixStart())
+ isAddressOfOperand = false;
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
// need to know whether or not this identifier is a function designator or
@@ -672,29 +672,23 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
CXXScopeSpec ScopeSpec;
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, Name,
- Tok.is(tok::l_paren), false);
-
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ Tok.is(tok::l_paren), isAddressOfOperand);
+ break;
}
case tok::char_constant: // constant: character-constant
Res = Actions.ActOnCharacterConstant(Tok);
ConsumeToken();
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
ConsumeToken();
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::string_literal: // primary-expression: string-literal
case tok::wide_string_literal:
Res = ParseStringLiteralExpression();
- if (Res.isInvalid()) return move(Res);
- // This can be followed by postfix-expr pieces (e.g. "foo"[1]).
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::kw___builtin_va_arg:
case tok::kw___builtin_offsetof:
case tok::kw___builtin_choose_expr:
@@ -703,12 +697,16 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___null:
return Actions.ActOnGNUNullExpr(ConsumeToken());
break;
- case tok::plusplus: // unary-expression: '++' unary-expression
- case tok::minusminus: { // unary-expression: '--' unary-expression
+ case tok::plusplus: // unary-expression: '++' unary-expression [C99]
+ case tok::minusminus: { // unary-expression: '--' unary-expression [C99]
+ // C++ [expr.unary] has:
+ // unary-expression:
+ // ++ cast-expression
+ // -- cast-expression
SourceLocation SavedLoc = ConsumeToken();
- Res = ParseCastExpression(true);
+ Res = ParseCastExpression(!getLang().CPlusPlus);
if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, move(Res));
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return move(Res);
}
case tok::amp: { // unary-expression: '&' cast-expression
@@ -716,7 +714,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation SavedLoc = ConsumeToken();
Res = ParseCastExpression(false, true);
if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, move(Res));
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return move(Res);
}
@@ -730,7 +728,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation SavedLoc = ConsumeToken();
Res = ParseCastExpression(false);
if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, move(Res));
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return move(Res);
}
@@ -740,7 +738,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation SavedLoc = ConsumeToken();
Res = ParseCastExpression(false);
if (!Res.isInvalid())
- Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, move(Res));
+ Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
return move(Res);
}
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
@@ -766,16 +764,13 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_reinterpret_cast:
case tok::kw_static_cast:
Res = ParseCXXCasts();
- // These can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::kw_typeid:
Res = ParseCXXTypeid();
- // This can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::kw_this:
Res = ParseCXXThis();
- // This can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::kw_char:
case tok::kw_wchar_t:
@@ -814,8 +809,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
<< DS.getSourceRange());
Res = ParseCXXTypeConstructExpression(DS);
- // This can be followed by postfix-expr pieces.
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
}
case tok::annot_cxxscope: { // [C++] id-expression: qualified-id
@@ -836,7 +830,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// type, translate it into a type and continue parsing as a
// cast expression.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
AnnotateTemplateIdTokenAsType(&SS);
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, TypeOfCast);
@@ -845,7 +839,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// Parse as an id-expression.
Res = ParseCXXIdExpression(isAddressOfOperand);
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
}
case tok::annot_template_id: { // [C++] template-id
@@ -865,7 +859,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
Res = ParseCXXIdExpression(isAddressOfOperand);
- return ParsePostfixExpressionSuffix(move(Res));
+ break;
case tok::coloncolon: {
// ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken
@@ -906,6 +900,10 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___has_trivial_copy:
case tok::kw___has_trivial_assign:
case tok::kw___has_trivial_destructor:
+ case tok::kw___has_nothrow_assign:
+ case tok::kw___has_nothrow_copy:
+ case tok::kw___has_nothrow_constructor:
+ case tok::kw___has_virtual_destructor:
return ParseUnaryTypeTrait();
case tok::at: {
@@ -915,7 +913,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::caret:
return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
case tok::code_completion:
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_Expression);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
ConsumeCodeCompletionToken();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, TypeOfCast);
@@ -929,8 +927,9 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ExprError();
}
- // unreachable.
- abort();
+ // These can be followed by postfix-expr pieces.
+ if (Res.isInvalid()) return move(Res);
+ return ParsePostfixExpressionSuffix(Res.get());
}
/// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression
@@ -951,8 +950,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
/// argument-expression
/// argument-expression-list ',' assignment-expression
///
-Parser::OwningExprResult
-Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
+ExprResult
+Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
// Now that the primary-expression piece of the postfix-expression has been
// parsed, see if there are any postfix-expression pieces here.
SourceLocation Loc;
@@ -972,13 +971,13 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
return move(LHS);
Loc = ConsumeBracket();
- OwningExprResult Idx(ParseExpression());
+ ExprResult Idx(ParseExpression());
SourceLocation RLoc = Tok.getLocation();
if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
- LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), move(LHS), Loc,
- move(Idx), RLoc);
+ LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.take(), Loc,
+ Idx.take(), RLoc);
} else
LHS = ExprError();
@@ -1004,7 +1003,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
}
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(ArgExprs, CommaLocs, &Action::CodeCompleteCall,
+ if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
LHS.get())) {
SkipUntil(tok::r_paren);
return ExprError();
@@ -1020,7 +1019,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
if (!LHS.isInvalid()) {
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
- LHS = Actions.ActOnCallExpr(getCurScope(), move(LHS), Loc,
+ LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
move_arg(ArgExprs), CommaLocs.data(),
Tok.getLocation());
}
@@ -1036,10 +1035,10 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
CXXScopeSpec SS;
- Action::TypeTy *ObjectType = 0;
+ ParsedType ObjectType;
bool MayBePseudoDestructor = false;
if (getLang().CPlusPlus && !LHS.isInvalid()) {
- LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), move(LHS),
+ LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), LHS.take(),
OpLoc, OpKind, ObjectType,
MayBePseudoDestructor);
if (LHS.isInvalid())
@@ -1048,7 +1047,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
&MayBePseudoDestructor);
if (SS.isNotEmpty())
- ObjectType = 0;
+ ObjectType = ParsedType();
}
if (Tok.is(tok::code_completion)) {
@@ -1059,8 +1058,8 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ConsumeCodeCompletionToken();
}
- if (MayBePseudoDestructor) {
- LHS = ParseCXXPseudoDestructor(move(LHS), OpLoc, OpKind, SS,
+ if (MayBePseudoDestructor && !LHS.isInvalid()) {
+ LHS = ParseCXXPseudoDestructor(LHS.take(), OpLoc, OpKind, SS,
ObjectType);
break;
}
@@ -1080,7 +1079,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
return ExprError();
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(getCurScope(), move(LHS), OpLoc,
+ LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc,
OpKind, SS, Name, ObjCImpDecl,
Tok.is(tok::l_paren));
break;
@@ -1089,7 +1088,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
case tok::minusminus: // postfix-expression: postfix-expression '--'
if (!LHS.isInvalid()) {
LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),
- Tok.getKind(), move(LHS));
+ Tok.getKind(), LHS.take());
}
ConsumeToken();
break;
@@ -1114,17 +1113,17 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
/// typeof ( type-name )
/// [GNU/C++] typeof unary-expression
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
- TypeTy *&CastTy,
+ ParsedType &CastTy,
SourceRange &CastRange) {
assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
"Not a typeof/sizeof/alignof expression!");
- OwningExprResult Operand(Actions);
+ ExprResult Operand;
// If the operand doesn't start with an '(', it must be an expression.
if (Tok.isNot(tok::l_paren)) {
@@ -1141,7 +1140,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
EnterExpressionEvaluationContext Unevaluated(Actions,
- Action::Unevaluated);
+ Sema::Unevaluated);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
} else {
// If it starts with a '(', we know that it is either a parenthesized
@@ -1158,10 +1157,9 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
EnterExpressionEvaluationContext Unevaluated(Actions,
- Action::Unevaluated);
+ Sema::Unevaluated);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
- 0/*TypeOfCast*/,
- CastTy, RParenLoc);
+ ParsedType(), CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
// If ParseParenExpression parsed a '(typename)' sequence only, then this is
@@ -1171,10 +1169,14 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
return ExprEmpty();
}
- // If this is a parenthesized expression, it is the start of a
- // unary-expression, but doesn't include any postfix pieces. Parse these
- // now if present.
- Operand = ParsePostfixExpressionSuffix(move(Operand));
+ if (getLang().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
+ // GNU typeof in C requires the expression to be parenthesized. Not so for
+ // sizeof/alignof or in C++. Therefore, the parenthesized expression is
+ // the start of a unary-expression, but doesn't include any postfix
+ // pieces. Parse these now if present.
+ if (!Operand.isInvalid())
+ Operand = ParsePostfixExpressionSuffix(Operand.get());
+ }
}
// If we get here, the operand to the typeof/sizeof/alignof was an expresion.
@@ -1190,7 +1192,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
/// [GNU] '__alignof' unary-expression
/// [GNU] '__alignof' '(' type-name ')'
/// [C++0x] 'alignof' '(' type-id ')'
-Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
+ExprResult Parser::ParseSizeofAlignofExpression() {
assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
|| Tok.is(tok::kw_alignof)) &&
"Not a sizeof/alignof expression!");
@@ -1198,9 +1200,9 @@ Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
ConsumeToken();
bool isCastExpr;
- TypeTy *CastTy;
+ ParsedType CastTy;
SourceRange CastRange;
- OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
+ ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
isCastExpr,
CastTy,
CastRange);
@@ -1208,7 +1210,8 @@ Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
if (isCastExpr)
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
OpTok.is(tok::kw_sizeof),
- /*isType=*/true, CastTy,
+ /*isType=*/true,
+ CastTy.getAsOpaquePtr(),
CastRange);
// If we get here, the operand to the sizeof/alignof was an expresion.
@@ -1234,8 +1237,8 @@ Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
/// [GNU] offsetof-member-designator '.' identifier
/// [GNU] offsetof-member-designator '[' expression ']'
///
-Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
- OwningExprResult Res(Actions);
+ExprResult Parser::ParseBuiltinPrimaryExpression() {
+ ExprResult Res;
const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
tok::TokenKind T = Tok.getKind();
@@ -1252,7 +1255,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
switch (T) {
default: assert(0 && "Not a builtin primary expression!");
case tok::kw___builtin_va_arg: {
- OwningExprResult Expr(ParseAssignmentExpression());
+ ExprResult Expr(ParseAssignmentExpression());
if (Expr.isInvalid()) {
SkipUntil(tok::r_paren);
return ExprError();
@@ -1270,7 +1273,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
if (Ty.isInvalid())
Res = ExprError();
else
- Res = Actions.ActOnVAArg(StartLoc, move(Expr), Ty.get(), ConsumeParen());
+ Res = Actions.ActOnVAArg(StartLoc, Expr.take(), Ty.get(), ConsumeParen());
break;
}
case tok::kw___builtin_offsetof: {
@@ -1292,9 +1295,9 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
}
// Keep track of the various subcomponents we see.
- llvm::SmallVector<Action::OffsetOfComponent, 4> Comps;
+ llvm::SmallVector<Sema::OffsetOfComponent, 4> Comps;
- Comps.push_back(Action::OffsetOfComponent());
+ Comps.push_back(Sema::OffsetOfComponent());
Comps.back().isBrackets = false;
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
@@ -1303,7 +1306,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
while (1) {
if (Tok.is(tok::period)) {
// offsetof-member-designator: offsetof-member-designator '.' identifier
- Comps.push_back(Action::OffsetOfComponent());
+ Comps.push_back(Sema::OffsetOfComponent());
Comps.back().isBrackets = false;
Comps.back().LocStart = ConsumeToken();
@@ -1317,7 +1320,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
} else if (Tok.is(tok::l_square)) {
// offsetof-member-designator: offsetof-member-design '[' expression ']'
- Comps.push_back(Action::OffsetOfComponent());
+ Comps.push_back(Sema::OffsetOfComponent());
Comps.back().isBrackets = true;
Comps.back().LocStart = ConsumeBracket();
Res = ParseExpression();
@@ -1346,7 +1349,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
break;
}
case tok::kw___builtin_choose_expr: {
- OwningExprResult Cond(ParseAssignmentExpression());
+ ExprResult Cond(ParseAssignmentExpression());
if (Cond.isInvalid()) {
SkipUntil(tok::r_paren);
return move(Cond);
@@ -1354,7 +1357,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprError();
- OwningExprResult Expr1(ParseAssignmentExpression());
+ ExprResult Expr1(ParseAssignmentExpression());
if (Expr1.isInvalid()) {
SkipUntil(tok::r_paren);
return move(Expr1);
@@ -1362,7 +1365,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprError();
- OwningExprResult Expr2(ParseAssignmentExpression());
+ ExprResult Expr2(ParseAssignmentExpression());
if (Expr2.isInvalid()) {
SkipUntil(tok::r_paren);
return move(Expr2);
@@ -1371,8 +1374,8 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
Diag(Tok, diag::err_expected_rparen);
return ExprError();
}
- Res = Actions.ActOnChooseExpr(StartLoc, move(Cond), move(Expr1),
- move(Expr2), ConsumeParen());
+ Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(),
+ Expr2.take(), ConsumeParen());
break;
}
case tok::kw___builtin_types_compatible_p:
@@ -1396,9 +1399,12 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
break;
}
+ if (Res.isInvalid())
+ return ExprError();
+
// These can be followed by postfix-expr pieces because they are
// primary-expressions.
- return ParsePostfixExpressionSuffix(move(Res));
+ return ParsePostfixExpressionSuffix(Res.take());
}
/// ParseParenExpression - This parses the unit that starts with a '(' token,
@@ -1415,25 +1421,25 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
/// cast-expression: [C99 6.5.4]
/// '(' type-name ')' cast-expression
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
- TypeTy *TypeOfCast, TypeTy *&CastTy,
+ ParsedType TypeOfCast, ParsedType &CastTy,
SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
SourceLocation OpenLoc = ConsumeParen();
- OwningExprResult Result(Actions, true);
+ ExprResult Result(true);
bool isAmbiguousTypeId;
- CastTy = 0;
+ CastTy = ParsedType();
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
Diag(Tok, diag::ext_gnu_statement_expr);
- OwningStmtResult Stmt(ParseCompoundStatement(0, true));
+ StmtResult Stmt(ParseCompoundStatement(0, true));
ExprType = CompoundStmt;
// If the substmt parsed correctly, build the AST node.
if (!Stmt.isInvalid() && Tok.is(tok::r_paren))
- Result = Actions.ActOnStmtExpr(OpenLoc, move(Stmt), Tok.getLocation());
+ Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
} else if (ExprType >= CompoundLiteral &&
isTypeIdInParens(isAmbiguousTypeId)) {
@@ -1473,7 +1479,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Note that this doesn't parse the subsequent cast-expression, it just
// returns the parsed type to the callee.
if (stopIfCastExpr)
- return OwningExprResult(Actions);
+ return ExprResult();
// Reject the cast of super idiom in ObjC.
if (Tok.is(tok::identifier) && getLang().ObjC1 &&
@@ -1490,7 +1496,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Result = ParseCastExpression(false, false, CastTy);
if (!Result.isInvalid())
Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, CastTy, RParenLoc,
- move(Result));
+ Result.take());
return move(Result);
}
@@ -1510,7 +1516,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Result = ParseExpression();
ExprType = SimpleExpr;
if (!Result.isInvalid() && Tok.is(tok::r_paren))
- Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), move(Result));
+ Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take());
}
// Match the ')'.
@@ -1534,16 +1540,16 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
/// '(' type-name ')' '{' initializer-list '}'
/// '(' type-name ')' '{' initializer-list ',' '}'
///
-Parser::OwningExprResult
-Parser::ParseCompoundLiteralExpression(TypeTy *Ty,
+ExprResult
+Parser::ParseCompoundLiteralExpression(ParsedType Ty,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
assert(Tok.is(tok::l_brace) && "Not a compound literal!");
if (!getLang().C99) // Compound literals don't exist in C90.
Diag(LParenLoc, diag::ext_c99_compound_literal);
- OwningExprResult Result = ParseInitializer();
+ ExprResult Result = ParseInitializer();
if (!Result.isInvalid() && Ty)
- return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, move(Result));
+ return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.take());
return move(Result);
}
@@ -1553,7 +1559,7 @@ Parser::ParseCompoundLiteralExpression(TypeTy *Ty,
///
/// primary-expression: [C99 6.5.1]
/// string-literal
-Parser::OwningExprResult Parser::ParseStringLiteralExpression() {
+ExprResult Parser::ParseStringLiteralExpression() {
assert(isTokenStringLiteral() && "Not a string literal!");
// String concat. Note that keywords like __func__ and __FUNCTION__ are not
@@ -1579,12 +1585,13 @@ Parser::OwningExprResult Parser::ParseStringLiteralExpression() {
/// [C++] assignment-expression
/// [C++] expression-list , assignment-expression
///
-bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
- void (Action::*Completer)(Scope *S,
- void *Data,
- ExprTy **Args,
+bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
+ llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
+ void (Sema::*Completer)(Scope *S,
+ Expr *Data,
+ Expr **Args,
unsigned NumArgs),
- void *Data) {
+ Expr *Data) {
while (1) {
if (Tok.is(tok::code_completion)) {
if (Completer)
@@ -1592,7 +1599,7 @@ bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
ConsumeCodeCompletionToken();
}
- OwningExprResult Expr(ParseAssignmentExpression());
+ ExprResult Expr(ParseAssignmentExpression());
if (Expr.isInvalid())
return true;
@@ -1642,7 +1649,7 @@ void Parser::ParseBlockId() {
/// [clang] block-args:
/// [clang] '(' parameter-list ')'
///
-Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
+ExprResult Parser::ParseBlockLiteralExpression() {
assert(Tok.is(tok::caret) && "block literal starts with ^");
SourceLocation CaretLoc = ConsumeToken();
@@ -1717,7 +1724,7 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
}
- OwningExprResult Result(Actions, true);
+ ExprResult Result(true);
if (!Tok.is(tok::l_brace)) {
// Saw something like: ^expr
Diag(Tok, diag::err_expected_expression);
@@ -1725,9 +1732,9 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
return ExprError();
}
- OwningStmtResult Stmt(ParseCompoundStatementBody());
+ StmtResult Stmt(ParseCompoundStatementBody());
if (!Stmt.isInvalid())
- Result = Actions.ActOnBlockStmtExpr(CaretLoc, move(Stmt), getCurScope());
+ Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
else
Actions.ActOnBlockError(CaretLoc, getCurScope());
return move(Result);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 579d3bde4912..5041a212924a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -13,8 +13,8 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@@ -57,14 +57,14 @@ using namespace clang;
///
/// \returns true if there was an error parsing a scope specifier
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
- Action::TypeTy *ObjectType,
+ ParsedType ObjectType,
bool EnteringContext,
bool *MayBePseudoDestructor) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
if (Tok.is(tok::annot_cxxscope)) {
- SS.setScopeRep(Tok.getAnnotationValue());
+ SS.setScopeRep(static_cast<NestedNameSpecifier*>(Tok.getAnnotationValue()));
SS.setRange(Tok.getAnnotationRange());
ConsumeToken();
return false;
@@ -104,7 +104,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
//
// To implement this, we clear out the object type as soon as we've
// seen a leading '::' or part of a nested-name-specifier.
- ObjectType = 0;
+ ObjectType = ParsedType();
if (Tok.is(tok::code_completion)) {
// Code completion for a nested-name-specifier, where the code
@@ -212,13 +212,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
HasScopeSpecifier = true;
}
- if (TypeToken.getAnnotationValue())
- SS.setScopeRep(
- Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS,
- TypeToken.getAnnotationValue(),
+ if (ParsedType T = getTypeAnnotation(TypeToken)) {
+ CXXScopeTy *Scope =
+ Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, T,
TypeToken.getAnnotationRange(),
- CCLoc));
- else
+ CCLoc);
+ SS.setScopeRep(Scope);
+ } else
SS.setScopeRep(0);
SS.setEndLoc(CCLoc);
continue;
@@ -294,6 +294,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
TemplateName.setIdentifier(&II, Tok.getLocation());
bool MemberOfUnknownSpecialization;
if (TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
+ /*hasTemplateKeyword=*/false,
TemplateName,
ObjectType,
EnteringContext,
@@ -396,40 +397,27 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
/// the only place where a qualified-id naming a non-static class member may
/// appear.
///
-Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
+ExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
// qualified-id:
// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
// '::' unqualified-id
//
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
UnqualifiedId Name;
if (ParseUnqualifiedId(SS,
/*EnteringContext=*/false,
/*AllowDestructorName=*/false,
/*AllowConstructorName=*/false,
- /*ObjectType=*/0,
+ /*ObjectType=*/ ParsedType(),
Name))
return ExprError();
// This is only the direct operand of an & operator if it is not
// followed by a postfix-expression suffix.
- if (isAddressOfOperand) {
- switch (Tok.getKind()) {
- case tok::l_square:
- case tok::l_paren:
- case tok::arrow:
- case tok::period:
- case tok::plusplus:
- case tok::minusminus:
- isAddressOfOperand = false;
- break;
-
- default:
- break;
- }
- }
+ if (isAddressOfOperand && isPostfixExpressionSuffixStart())
+ isAddressOfOperand = false;
return Actions.ActOnIdExpression(getCurScope(), SS, Name, Tok.is(tok::l_paren),
isAddressOfOperand);
@@ -445,7 +433,7 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
/// 'const_cast' '<' type-name '>' '(' expression ')'
///
-Parser::OwningExprResult Parser::ParseCXXCasts() {
+ExprResult Parser::ParseCXXCasts() {
tok::TokenKind Kind = Tok.getKind();
const char *CastName = 0; // For error messages
@@ -474,7 +462,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
return ExprError();
- OwningExprResult Result = ParseExpression();
+ ExprResult Result = ParseExpression();
// Match the ')'.
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -483,7 +471,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
LAngleBracketLoc, CastTy.get(),
RAngleBracketLoc,
- LParenLoc, move(Result), RParenLoc);
+ LParenLoc, Result.take(), RParenLoc);
return move(Result);
}
@@ -494,7 +482,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
/// 'typeid' '(' expression ')'
/// 'typeid' '(' type-id ')'
///
-Parser::OwningExprResult Parser::ParseCXXTypeid() {
+ExprResult Parser::ParseCXXTypeid() {
assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
SourceLocation OpLoc = ConsumeToken();
@@ -506,7 +494,7 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
"typeid"))
return ExprError();
- OwningExprResult Result(Actions);
+ ExprResult Result;
if (isTypeIdInParens()) {
TypeResult Ty = ParseTypeName();
@@ -518,7 +506,7 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
return ExprError();
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
- Ty.get(), RParenLoc);
+ Ty.get().getAsOpaquePtr(), RParenLoc);
} else {
// C++0x [expr.typeid]p3:
// When typeid is applied to an expression other than an lvalue of a
@@ -529,7 +517,7 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
// polymorphic class type until after we've parsed the expression, so
// we the expression is potentially potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(Actions,
- Action::PotentiallyPotentiallyEvaluated);
+ Sema::PotentiallyPotentiallyEvaluated);
Result = ParseExpression();
// Match the ')'.
@@ -560,11 +548,11 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
/// ~type-name
/// ::[opt] nested-name-specifier[opt] ~type-name
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
- Action::TypeTy *ObjectType) {
+ ParsedType ObjectType) {
// We're parsing either a pseudo-destructor-name or a dependent
// member access that has the same form as a
// pseudo-destructor-name. We parse both in the same way and let
@@ -612,7 +600,8 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
/*TemplateKWLoc*/SourceLocation()))
return ExprError();
- return Actions.ActOnPseudoDestructorExpr(getCurScope(), move(Base), OpLoc, OpKind,
+ return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base,
+ OpLoc, OpKind,
SS, FirstTypeName, CCLoc,
TildeLoc, SecondTypeName,
Tok.is(tok::l_paren));
@@ -623,7 +612,7 @@ Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
/// boolean-literal: [C++ 2.13.5]
/// 'true'
/// 'false'
-Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
+ExprResult Parser::ParseCXXBoolLiteral() {
tok::TokenKind Kind = Tok.getKind();
return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
}
@@ -632,7 +621,7 @@ Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
///
/// throw-expression: [C++ 15]
/// 'throw' assignment-expression[opt]
-Parser::OwningExprResult Parser::ParseThrowExpression() {
+ExprResult Parser::ParseThrowExpression() {
assert(Tok.is(tok::kw_throw) && "Not throw!");
SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
@@ -646,12 +635,12 @@ Parser::OwningExprResult Parser::ParseThrowExpression() {
case tok::r_brace:
case tok::colon:
case tok::comma:
- return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
+ return Actions.ActOnCXXThrow(ThrowLoc, 0);
default:
- OwningExprResult Expr(ParseAssignmentExpression());
+ ExprResult Expr(ParseAssignmentExpression());
if (Expr.isInvalid()) return move(Expr);
- return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
+ return Actions.ActOnCXXThrow(ThrowLoc, Expr.take());
}
}
@@ -660,7 +649,7 @@ Parser::OwningExprResult Parser::ParseThrowExpression() {
/// C++ 9.3.2: In the body of a non-static member function, the keyword this is
/// a non-lvalue expression whose value is the address of the object for which
/// the function is called.
-Parser::OwningExprResult Parser::ParseCXXThis() {
+ExprResult Parser::ParseCXXThis() {
assert(Tok.is(tok::kw_this) && "Not 'this'!");
SourceLocation ThisLoc = ConsumeToken();
return Actions.ActOnCXXThis(ThisLoc);
@@ -675,10 +664,10 @@ Parser::OwningExprResult Parser::ParseCXXThis() {
/// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
/// typename-specifier '(' expression-list[opt] ')' [TODO]
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
- TypeTy *TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
+ ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
assert(Tok.is(tok::l_paren) && "Expected '('!");
SourceLocation LParenLoc = ConsumeParen();
@@ -728,27 +717,27 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
/// converted to a boolean value.
///
/// \returns true if there was a parsing, false otherwise.
-bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
- DeclPtrTy &DeclResult,
+bool Parser::ParseCXXCondition(ExprResult &ExprOut,
+ Decl *&DeclOut,
SourceLocation Loc,
bool ConvertToBoolean) {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_Condition);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition);
ConsumeCodeCompletionToken();
}
if (!isCXXConditionDeclaration()) {
// Parse the expression.
- ExprResult = ParseExpression(); // expression
- DeclResult = DeclPtrTy();
- if (ExprResult.isInvalid())
+ ExprOut = ParseExpression(); // expression
+ DeclOut = 0;
+ if (ExprOut.isInvalid())
return true;
// If required, convert to a boolean value.
if (ConvertToBoolean)
- ExprResult
- = Actions.ActOnBooleanCondition(getCurScope(), Loc, move(ExprResult));
- return ExprResult.isInvalid();
+ ExprOut
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprOut.get());
+ return ExprOut.isInvalid();
}
// type-specifier-seq
@@ -762,7 +751,7 @@ bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
// simple-asm-expr[opt]
if (Tok.is(tok::kw_asm)) {
SourceLocation Loc;
- OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
+ ExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid()) {
SkipUntil(tok::semi);
return true;
@@ -779,17 +768,17 @@ bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
}
// Type-check the declaration itself.
- Action::DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
+ DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(),
DeclaratorInfo);
- DeclResult = Dcl.get();
- ExprResult = ExprError();
+ DeclOut = Dcl.get();
+ ExprOut = ExprError();
// '=' assignment-expression
if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
- OwningExprResult AssignExpr(ParseAssignmentExpression());
+ ExprResult AssignExpr(ParseAssignmentExpression());
if (!AssignExpr.isInvalid())
- Actions.AddInitializerToDecl(DeclResult, move(AssignExpr));
+ Actions.AddInitializerToDecl(DeclOut, AssignExpr.take());
} else {
// FIXME: C++0x allows a braced-init-list
Diag(Tok, diag::err_expected_equal_after_declarator);
@@ -874,7 +863,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
// type-name
case tok::annot_typename: {
DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
- Tok.getAnnotationValue());
+ getTypeAnnotation(Tok));
break;
}
@@ -1002,7 +991,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Id,
bool AssumeTemplateId,
SourceLocation TemplateKWLoc) {
@@ -1023,8 +1012,9 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
return true;
} else {
bool MemberOfUnknownSpecialization;
- TNK = Actions.isTemplateName(getCurScope(), SS, Id, ObjectType,
- EnteringContext, Template,
+ TNK = Actions.isTemplateName(getCurScope(), SS,
+ TemplateKWLoc.isValid(), Id,
+ ObjectType, EnteringContext, Template,
MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && MemberOfUnknownSpecialization &&
@@ -1059,7 +1049,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
UnqualifiedId TemplateName;
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
- TNK = Actions.isTemplateName(getCurScope(), SS, TemplateName, ObjectType,
+ TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
+ TemplateName, ObjectType,
EnteringContext, Template,
MemberOfUnknownSpecialization);
break;
@@ -1076,11 +1067,12 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
if (TNK == TNK_Non_template)
return true;
} else {
- TNK = Actions.isTemplateName(getCurScope(), SS, TemplateName, ObjectType,
+ TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
+ TemplateName, ObjectType,
EnteringContext, Template,
MemberOfUnknownSpecialization);
- if (TNK == TNK_Non_template && Id.DestructorName == 0) {
+ if (TNK == TNK_Non_template && !Id.DestructorName.get()) {
Diag(NameLoc, diag::err_destructor_template_id)
<< Name << SS.getRange();
return true;
@@ -1124,7 +1116,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateId->TemplateNameLoc = Id.StartLocation;
}
- TemplateId->Template = Template.getAs<void*>();
+ TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
@@ -1142,7 +1134,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
TemplateArgs.size());
// Constructor and destructor names.
- Action::TypeResult Type
+ TypeResult Type
= Actions.ActOnTemplateIdType(Template, NameLoc,
LAngleLoc, TemplateArgsPtr,
RAngleLoc);
@@ -1198,7 +1190,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
///
/// \returns true if parsing fails, false otherwise.
bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Result) {
assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
@@ -1334,7 +1326,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
// Finish up the type.
- Action::TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D);
+ TypeResult Ty = Actions.ActOnTypeName(getCurScope(), D);
if (Ty.isInvalid())
return true;
@@ -1377,7 +1369,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
bool AllowDestructorName,
bool AllowConstructorName,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
UnqualifiedId &Result) {
// Handle 'A::template B'. This is for template-ids which have not
@@ -1511,17 +1503,17 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
SourceLocation ClassNameLoc = ConsumeToken();
if (TemplateSpecified || Tok.is(tok::less)) {
- Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
+ Result.setDestructorName(TildeLoc, ParsedType(), ClassNameLoc);
return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
EnteringContext, ObjectType, Result,
TemplateSpecified, TemplateKWLoc);
}
// Note that this is a destructor name.
- Action::TypeTy *Ty = Actions.getDestructorName(TildeLoc, *ClassName,
- ClassNameLoc, getCurScope(),
- SS, ObjectType,
- EnteringContext);
+ ParsedType Ty = Actions.getDestructorName(TildeLoc, *ClassName,
+ ClassNameLoc, getCurScope(),
+ SS, ObjectType,
+ EnteringContext);
if (!Ty)
return true;
@@ -1561,7 +1553,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
/// '(' expression-list[opt] ')'
/// [C++0x] braced-init-list [TODO]
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
assert(Tok.is(tok::kw_new) && "expected 'new' token");
ConsumeToken(); // Consume 'new'
@@ -1665,7 +1657,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
bool first = true;
while (Tok.is(tok::l_square)) {
SourceLocation LLoc = ConsumeBracket();
- OwningExprResult Size(first ? ParseExpression()
+ ExprResult Size(first ? ParseExpression()
: ParseConstantExpression());
if (Size.isInvalid()) {
// Recover
@@ -1694,7 +1686,8 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
/// new-placement:
/// '(' expression-list ')'
///
-bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
+bool Parser::ParseExpressionListOrTypeId(
+ llvm::SmallVectorImpl<Expr*> &PlacementArgs,
Declarator &D) {
// The '(' was already consumed.
if (isTypeIdInParens()) {
@@ -1721,7 +1714,7 @@ bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
/// delete-expression:
/// '::'[opt] 'delete' cast-expression
/// '::'[opt] 'delete' '[' ']' cast-expression
-Parser::OwningExprResult
+ExprResult
Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
ConsumeToken(); // Consume 'delete'
@@ -1736,11 +1729,11 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
return ExprError();
}
- OwningExprResult Operand(ParseCastExpression(false));
+ ExprResult Operand(ParseCastExpression(false));
if (Operand.isInvalid())
return move(Operand);
- return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
+ return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.take());
}
static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
@@ -1772,7 +1765,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
/// primary-expression:
/// [GNU] unary-type-trait '(' type-id ')'
///
-Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
+ExprResult Parser::ParseUnaryTypeTrait() {
UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
SourceLocation Loc = ConsumeToken();
@@ -1796,17 +1789,17 @@ Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
/// based on the context past the parens.
-Parser::OwningExprResult
+ExprResult
Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
- TypeTy *&CastTy,
+ ParsedType &CastTy,
SourceLocation LParenLoc,
SourceLocation &RParenLoc) {
assert(getLang().CPlusPlus && "Should only be called for C++!");
assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
assert(isTypeIdInParens() && "Not a type-id!");
- OwningExprResult Result(Actions, true);
- CastTy = 0;
+ ExprResult Result(true);
+ CastTy = ParsedType();
// We need to disambiguate a very ugly part of the C++ syntax:
//
@@ -1851,7 +1844,8 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// will be consumed.
Result = ParseCastExpression(false/*isUnaryExpression*/,
false/*isAddressofOperand*/,
- NotCastExpr, 0/*TypeOfCast*/);
+ NotCastExpr,
+ ParsedType()/*TypeOfCast*/);
}
// If we parsed a cast-expression, it's really a type-id, otherwise it's
@@ -1894,7 +1888,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// Result is what ParseCastExpression returned earlier.
if (!Result.isInvalid())
Result = Actions.ActOnCastExpr(getCurScope(), LParenLoc, CastTy, RParenLoc,
- move(Result));
+ Result.take());
return move(Result);
}
@@ -1904,7 +1898,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ExprType = SimpleExpr;
Result = ParseExpression();
if (!Result.isInvalid() && Tok.is(tok::r_paren))
- Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
+ Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), Result.take());
// Match the ')'.
if (Result.isInvalid()) {
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index 8451aebc04bd..4347294141ac 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Designator.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/Scope.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -71,7 +71,7 @@ static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc,
/// initializer (because it is an expression). We need to consider this case
/// when parsing array designators.
///
-Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
+ExprResult Parser::ParseInitializerWithPotentialDesignator() {
// If this is the old-style GNU extension:
// designation ::= identifier ':'
@@ -137,7 +137,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
// [4][foo bar] -> obsolete GNU designation with objc message send.
//
SourceLocation StartLoc = ConsumeBracket();
- OwningExprResult Idx(Actions);
+ ExprResult Idx;
// If Objective-C is enabled and this is a typename (class message
// send) or send to 'super', parse this as a message send
@@ -149,8 +149,9 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) {
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
- ConsumeToken(), 0,
- ExprArg(Actions));
+ ConsumeToken(),
+ ParsedType(),
+ 0);
}
// Parse the receiver, which is either a type or an expression.
@@ -167,35 +168,35 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
- TypeOrExpr,
- ExprArg(Actions));
+ ParsedType::getFromOpaquePtr(TypeOrExpr),
+ 0);
}
// If the receiver was an expression, we still don't know
// whether we have a message send or an array designator; just
// adopt the expression for further analysis below.
// FIXME: potentially-potentially evaluated expression above?
- Idx = OwningExprResult(Actions, TypeOrExpr);
+ Idx = ExprResult(static_cast<Expr*>(TypeOrExpr));
} else if (getLang().ObjC1 && Tok.is(tok::identifier)) {
IdentifierInfo *II = Tok.getIdentifierInfo();
SourceLocation IILoc = Tok.getLocation();
- TypeTy *ReceiverType;
+ ParsedType ReceiverType;
// Three cases. This is a message send to a type: [type foo]
// This is a message send to super: [super foo]
// This is a message sent to an expr: [super.bar foo]
- switch (Action::ObjCMessageKind Kind
+ switch (Sema::ObjCMessageKind Kind
= Actions.getObjCMessageKind(getCurScope(), II, IILoc,
II == Ident_super,
NextToken().is(tok::period),
ReceiverType)) {
- case Action::ObjCSuperMessage:
- case Action::ObjCClassMessage:
+ case Sema::ObjCSuperMessage:
+ case Sema::ObjCClassMessage:
CheckArrayDesignatorSyntax(*this, StartLoc, Desig);
- if (Kind == Action::ObjCSuperMessage)
+ if (Kind == Sema::ObjCSuperMessage)
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
ConsumeToken(),
- 0,
- ExprArg(Actions));
+ ParsedType(),
+ 0);
ConsumeToken(); // the identifier
if (!ReceiverType) {
SkipUntil(tok::r_square);
@@ -205,9 +206,9 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
ReceiverType,
- ExprArg(Actions));
+ 0);
- case Action::ObjCInstanceMessage:
+ case Sema::ObjCInstanceMessage:
// Fall through; we'll just parse the expression and
// (possibly) treat this like an Objective-C message send
// later.
@@ -239,7 +240,8 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig);
return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,
SourceLocation(),
- 0, move(Idx));
+ ParsedType(),
+ Idx.take());
}
// If this is a normal array designator, remember it.
@@ -250,7 +252,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
Diag(Tok, diag::ext_gnu_array_range);
SourceLocation EllipsisLoc = ConsumeToken();
- OwningExprResult RHS(ParseConstantExpression());
+ ExprResult RHS(ParseConstantExpression());
if (RHS.isInvalid()) {
SkipUntil(tok::r_square);
return move(RHS);
@@ -307,7 +309,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
/// designation[opt] initializer
/// initializer-list ',' designation[opt] initializer
///
-Parser::OwningExprResult Parser::ParseBraceInitializer() {
+ExprResult Parser::ParseBraceInitializer() {
SourceLocation LBraceLoc = ConsumeBrace();
/// InitExprs - This is the actual list of expressions contained in the
@@ -319,7 +321,7 @@ Parser::OwningExprResult Parser::ParseBraceInitializer() {
if (!getLang().CPlusPlus)
Diag(LBraceLoc, diag::ext_gnu_empty_initializer);
// Match the '}'.
- return Actions.ActOnInitList(LBraceLoc, Action::MultiExprArg(Actions),
+ return Actions.ActOnInitList(LBraceLoc, MultiExprArg(Actions),
ConsumeBrace());
}
@@ -330,7 +332,7 @@ Parser::OwningExprResult Parser::ParseBraceInitializer() {
// If we know that this cannot be a designation, just parse the nested
// initializer directly.
- OwningExprResult SubElt(Actions);
+ ExprResult SubElt;
if (MayBeDesignationStart(Tok.getKind(), PP))
SubElt = ParseInitializerWithPotentialDesignator();
else
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 68473a551d1a..6861ce940f76 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/Parser.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
@@ -27,7 +28,7 @@ using namespace clang;
/// [OBJC] objc-protocol-definition
/// [OBJC] objc-method-definition
/// [OBJC] '@' 'end'
-Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
+Decl *Parser::ParseObjCAtDirectives() {
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
@@ -55,7 +56,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
}
@@ -63,7 +64,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
/// objc-class-declaration:
/// '@' 'class' identifier-list ';'
///
-Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+Decl *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
llvm::SmallVector<SourceLocation, 8> ClassLocs;
@@ -73,7 +74,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
ClassNames.push_back(Tok.getIdentifierInfo());
ClassLocs.push_back(Tok.getLocation());
@@ -87,7 +88,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
- return DeclPtrTy();
+ return 0;
return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
ClassLocs.data(),
@@ -122,7 +123,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
/// __attribute__((unavailable))
/// __attribute__((objc_exception)) - used by NSException on 64-bit
///
-Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
+Decl *Parser::ParseObjCAtInterfaceDeclaration(
SourceLocation atLoc, AttributeList *attrList) {
assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
"ParseObjCAtInterfaceDeclaration(): Expected @interface");
@@ -136,7 +137,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing class or category name.
- return DeclPtrTy();
+ return 0;
}
// We have a class or category name - consume it.
@@ -159,27 +160,27 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
}
else if (!getLang().ObjC2) {
Diag(Tok, diag::err_expected_ident); // missing category name.
- return DeclPtrTy();
+ return 0;
}
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected_rparen);
SkipUntil(tok::r_paren, false); // don't stop at ';'
- return DeclPtrTy();
+ return 0;
}
rparenLoc = ConsumeParen();
// Next, we need to check for any protocol references.
SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
+ llvm::SmallVector<Decl *, 8> ProtocolRefs;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
- return DeclPtrTy();
+ return 0;
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
- DeclPtrTy CategoryType =
+ Decl *CategoryType =
Actions.ActOnStartCategoryInterface(atLoc,
nameId, nameLoc,
categoryId, categoryLoc,
@@ -209,21 +210,21 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing super class name.
- return DeclPtrTy();
+ return 0;
}
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken();
}
// Next, we need to check for any protocol references.
- llvm::SmallVector<Action::DeclPtrTy, 8> ProtocolRefs;
+ llvm::SmallVector<Decl *, 8> ProtocolRefs;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
SourceLocation LAngleLoc, EndProtoLoc;
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
LAngleLoc, EndProtoLoc))
- return DeclPtrTy();
+ return 0;
- DeclPtrTy ClsType =
+ Decl *ClsType =
Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
superClassId, superClassLoc,
ProtocolRefs.data(), ProtocolRefs.size(),
@@ -241,30 +242,30 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
/// it's used, but instead it's been lifted to here to support VS2005.
struct Parser::ObjCPropertyCallback : FieldCallback {
Parser &P;
- DeclPtrTy IDecl;
- llvm::SmallVectorImpl<DeclPtrTy> &Props;
+ Decl *IDecl;
+ llvm::SmallVectorImpl<Decl *> &Props;
ObjCDeclSpec &OCDS;
SourceLocation AtLoc;
tok::ObjCKeywordKind MethodImplKind;
- ObjCPropertyCallback(Parser &P, DeclPtrTy IDecl,
- llvm::SmallVectorImpl<DeclPtrTy> &Props,
+ ObjCPropertyCallback(Parser &P, Decl *IDecl,
+ llvm::SmallVectorImpl<Decl *> &Props,
ObjCDeclSpec &OCDS, SourceLocation AtLoc,
tok::ObjCKeywordKind MethodImplKind) :
P(P), IDecl(IDecl), Props(Props), OCDS(OCDS), AtLoc(AtLoc),
MethodImplKind(MethodImplKind) {
}
- DeclPtrTy invoke(FieldDeclarator &FD) {
+ Decl *invoke(FieldDeclarator &FD) {
if (FD.D.getIdentifier() == 0) {
P.Diag(AtLoc, diag::err_objc_property_requires_field_name)
<< FD.D.getSourceRange();
- return DeclPtrTy();
+ return 0;
}
if (FD.BitfieldSize) {
P.Diag(AtLoc, diag::err_objc_property_bitfield)
<< FD.D.getSourceRange();
- return DeclPtrTy();
+ return 0;
}
// Install the property declarator into interfaceDecl.
@@ -282,7 +283,7 @@ struct Parser::ObjCPropertyCallback : FieldCallback {
P.PP.getSelectorTable(),
FD.D.getIdentifier());
bool isOverridingProperty = false;
- DeclPtrTy Property =
+ Decl *Property =
P.Actions.ActOnProperty(P.getCurScope(), AtLoc, FD, OCDS,
GetterSel, SetterSel, IDecl,
&isOverridingProperty,
@@ -306,10 +307,10 @@ struct Parser::ObjCPropertyCallback : FieldCallback {
/// @required
/// @optional
///
-void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
+void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
tok::ObjCKeywordKind contextKey) {
- llvm::SmallVector<DeclPtrTy, 32> allMethods;
- llvm::SmallVector<DeclPtrTy, 16> allProperties;
+ llvm::SmallVector<Decl *, 32> allMethods;
+ llvm::SmallVector<Decl *, 16> allProperties;
llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
@@ -318,7 +319,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
while (1) {
// If this is a method prototype, parse it.
if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
- DeclPtrTy methodPrototype =
+ Decl *methodPrototype =
ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
allMethods.push_back(methodPrototype);
// Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
@@ -329,10 +330,10 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
}
if (Tok.is(tok::l_paren)) {
Diag(Tok, diag::err_expected_minus_or_plus);
- DeclPtrTy methodPrototype = ParseObjCMethodDecl(Tok.getLocation(),
- tok::minus,
- interfaceDecl,
- MethodImplKind);
+ ParseObjCMethodDecl(Tok.getLocation(),
+ tok::minus,
+ interfaceDecl,
+ MethodImplKind);
continue;
}
// Ignore excess semicolons.
@@ -348,8 +349,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// Code completion within an Objective-C interface.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
- ObjCImpDecl? Action::CCC_ObjCImplementation
- : Action::CCC_ObjCInterface);
+ ObjCImpDecl? Sema::PCC_ObjCImplementation
+ : Sema::PCC_ObjCInterface);
ConsumeCodeCompletionToken();
}
@@ -468,8 +469,8 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
/// copy
/// nonatomic
///
-void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
+void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl,
+ Decl **Methods,
unsigned NumMethods) {
assert(Tok.getKind() == tok::l_paren);
SourceLocation LHSLoc = ConsumeParen(); // consume '('
@@ -562,14 +563,13 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
/// objc-method-attributes: [OBJC2]
/// __attribute__((deprecated))
///
-Parser::DeclPtrTy Parser::ParseObjCMethodPrototype(DeclPtrTy IDecl,
- tok::ObjCKeywordKind MethodImplKind) {
+Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl,
+ tok::ObjCKeywordKind MethodImplKind) {
assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
tok::TokenKind methodType = Tok.getKind();
SourceLocation mLoc = ConsumeToken();
-
- DeclPtrTy MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind);
+ Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind);
// Since this rule is used for both method declarations and definitions,
// the caller is (optionally) responsible for consuming the ';'.
return MDecl;
@@ -584,9 +584,31 @@ Parser::DeclPtrTy Parser::ParseObjCMethodPrototype(DeclPtrTy IDecl,
/// in out inout bycopy byref oneway int char float double void _Bool
///
IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {
+
switch (Tok.getKind()) {
default:
return 0;
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::amp:
+ case tok::pipe:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::caret:
+ case tok::caretequal: {
+ std::string ThisTok(PP.getSpelling(Tok));
+ if (isalpha(ThisTok[0])) {
+ IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok.data());
+ Tok.setKind(tok::identifier);
+ SelectorLoc = ConsumeToken();
+ return II;
+ }
+ return 0;
+ }
+
case tok::identifier:
case tok::kw_asm:
case tok::kw_auto:
@@ -680,8 +702,13 @@ bool Parser::isTokIdentifier_in() const {
/// objc-type-qualifier
/// objc-type-qualifiers objc-type-qualifier
///
-void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
+void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) {
while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPassingType(getCurScope(), DS);
+ ConsumeCodeCompletionToken();
+ }
+
if (Tok.isNot(tok::identifier))
return;
@@ -715,16 +742,16 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
/// '(' objc-type-qualifiers[opt] type-name ')'
/// '(' objc-type-qualifiers[opt] ')'
///
-Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
+ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) {
assert(Tok.is(tok::l_paren) && "expected (");
SourceLocation LParenLoc = ConsumeParen();
SourceLocation TypeStartLoc = Tok.getLocation();
// Parse type qualifiers, in, inout, etc.
- ParseObjCTypeQualifierList(DS);
+ ParseObjCTypeQualifierList(DS, IsParameter);
- TypeTy *Ty = 0;
+ ParsedType Ty;
if (isTypeSpecifierQualifier()) {
TypeResult TypeSpec = ParseTypeName();
if (!TypeSpec.isInvalid())
@@ -773,23 +800,23 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
/// objc-keyword-attributes: [OBJC2]
/// __attribute__((unused))
///
-Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
- tok::TokenKind mType,
- DeclPtrTy IDecl,
- tok::ObjCKeywordKind MethodImplKind) {
+Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
+ tok::TokenKind mType,
+ Decl *IDecl,
+ tok::ObjCKeywordKind MethodImplKind) {
ParsingDeclRAIIObject PD(*this);
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
- /*ReturnType=*/0, IDecl);
+ /*ReturnType=*/ ParsedType(), IDecl);
ConsumeCodeCompletionToken();
}
// Parse the return type if present.
- TypeTy *ReturnType = 0;
+ ParsedType ReturnType;
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
- ReturnType = ParseObjCTypeName(DSRet);
+ ReturnType = ParseObjCTypeName(DSRet, false);
// If attributes exist before the method, parse them.
llvm::OwningPtr<AttributeList> MethodAttrs;
@@ -812,7 +839,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
<< SourceRange(mLoc, Tok.getLocation());
// Skip until we get a ; or {}.
SkipUntil(tok::r_brace);
- return DeclPtrTy();
+ return 0;
}
llvm::SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
@@ -823,7 +850,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ParseGNUAttributes()));
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
- DeclPtrTy Result
+ Decl *Result
= Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
0,
@@ -835,10 +862,10 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
}
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
- llvm::SmallVector<Action::ObjCArgInfo, 12> ArgInfos;
+ llvm::SmallVector<Sema::ObjCArgInfo, 12> ArgInfos;
while (1) {
- Action::ObjCArgInfo ArgInfo;
+ Sema::ObjCArgInfo ArgInfo;
// Each iteration parses a single keyword argument.
if (Tok.isNot(tok::colon)) {
@@ -847,9 +874,9 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
}
ConsumeToken(); // Eat the ':'.
- ArgInfo.Type = 0;
+ ArgInfo.Type = ParsedType();
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
- ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec);
+ ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, true);
// If attributes exist before the argument name, parse them.
ArgInfo.ArgAttrs = 0;
@@ -918,7 +945,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Declarator ParmDecl(DS, Declarator::PrototypeContext);
ParseDeclarator(ParmDecl);
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
- DeclPtrTy Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
+ Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
ParmDecl.getIdentifierLoc(),
Param,
@@ -933,10 +960,10 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ParseGNUAttributes()));
if (KeyIdents.size() == 0)
- return DeclPtrTy();
+ return 0;
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
&KeyIdents[0]);
- DeclPtrTy Result
+ Decl *Result
= Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
&ArgInfos[0],
@@ -946,7 +973,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
PD.complete(Result);
// Delete referenced AttributeList objects.
- for (llvm::SmallVectorImpl<Action::ObjCArgInfo>::iterator
+ for (llvm::SmallVectorImpl<Sema::ObjCArgInfo>::iterator
I = ArgInfos.begin(), E = ArgInfos.end(); I != E; ++I)
delete I->ArgAttrs;
@@ -957,7 +984,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
/// '<' identifier-list '>'
///
bool Parser::
-ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
+ParseObjCProtocolReferences(llvm::SmallVectorImpl<Decl *> &Protocols,
llvm::SmallVectorImpl<SourceLocation> &ProtocolLocs,
bool WarnOnDeclarations,
SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
@@ -1024,11 +1051,11 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
/// objc-instance-variable-decl:
/// struct-declaration
///
-void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
+void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
tok::ObjCKeywordKind visibility,
SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {");
- llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
+ llvm::SmallVector<Decl *, 32> AllIvarDecls;
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
@@ -1071,24 +1098,24 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
- Action::CCC_ObjCInstanceVariableList);
+ Sema::PCC_ObjCInstanceVariableList);
ConsumeCodeCompletionToken();
}
struct ObjCIvarCallback : FieldCallback {
Parser &P;
- DeclPtrTy IDecl;
+ Decl *IDecl;
tok::ObjCKeywordKind visibility;
- llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls;
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls;
- ObjCIvarCallback(Parser &P, DeclPtrTy IDecl, tok::ObjCKeywordKind V,
- llvm::SmallVectorImpl<DeclPtrTy> &AllIvarDecls) :
+ ObjCIvarCallback(Parser &P, Decl *IDecl, tok::ObjCKeywordKind V,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls) :
P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) {
}
- DeclPtrTy invoke(FieldDeclarator &FD) {
+ Decl *invoke(FieldDeclarator &FD) {
// Install the declarator into the interface decl.
- DeclPtrTy Field
+ Decl *Field
= P.Actions.ActOnIvar(P.getCurScope(),
FD.D.getDeclSpec().getSourceRange().getBegin(),
IDecl, FD.D, FD.BitfieldSize, visibility);
@@ -1097,7 +1124,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
return Field;
}
} Callback(*this, interfaceDecl, visibility, AllIvarDecls);
-
+
// Parse all the comma separated declarators.
DeclSpec DS;
ParseStructDeclaration(DS, Callback);
@@ -1111,6 +1138,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
}
}
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ Actions.ActOnLastBitfield(RBraceLoc, interfaceDecl, AllIvarDecls);
// Call ActOnFields() even if we don't have any decls. This is useful
// for code rewriting tools that need to be aware of the empty list.
Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
@@ -1135,7 +1163,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
/// "@protocol identifier ;" should be resolved as "@protocol
/// identifier-list ;": objc-interface-decl-list may not start with a
/// semicolon in the first alternative if objc-protocol-refs are omitted.
-Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
+Decl *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
AttributeList *attrList) {
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
@@ -1148,7 +1176,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing protocol name.
- return DeclPtrTy();
+ return 0;
}
// Save the protocol name, then consume it.
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
@@ -1171,7 +1199,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
Tok.getLocation()));
@@ -1182,7 +1210,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
}
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
- return DeclPtrTy();
+ return 0;
return Actions.ActOnForwardProtocolDeclaration(AtLoc,
&ProtocolRefs[0],
@@ -1193,14 +1221,14 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
// Last, and definitely not least, parse a protocol declaration.
SourceLocation LAngleLoc, EndProtoLoc;
- llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
+ llvm::SmallVector<Decl *, 8> ProtocolRefs;
llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
LAngleLoc, EndProtoLoc))
- return DeclPtrTy();
+ return 0;
- DeclPtrTy ProtoType =
+ Decl *ProtoType =
Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
@@ -1220,7 +1248,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
///
/// objc-category-implementation-prologue:
/// @implementation identifier ( identifier )
-Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
+Decl *Parser::ParseObjCAtImplementationDeclaration(
SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
"ParseObjCAtImplementationDeclaration(): Expected @implementation");
@@ -1234,7 +1262,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing class or category name.
- return DeclPtrTy();
+ return 0;
}
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
@@ -1256,20 +1284,20 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
categoryLoc = ConsumeToken();
} else {
Diag(Tok, diag::err_expected_ident); // missing category name.
- return DeclPtrTy();
+ return 0;
}
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected_rparen);
SkipUntil(tok::r_paren, false); // don't stop at ';'
- return DeclPtrTy();
+ return 0;
}
rparenLoc = ConsumeParen();
- DeclPtrTy ImplCatType = Actions.ActOnStartCategoryImplementation(
+ Decl *ImplCatType = Actions.ActOnStartCategoryImplementation(
atLoc, nameId, nameLoc, categoryId,
categoryLoc);
ObjCImpDecl = ImplCatType;
PendingObjCImpDecl.push_back(ObjCImpDecl);
- return DeclPtrTy();
+ return 0;
}
// We have a class implementation
SourceLocation superClassLoc;
@@ -1279,12 +1307,12 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
ConsumeToken();
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing super class name.
- return DeclPtrTy();
+ return 0;
}
superClassId = Tok.getIdentifierInfo();
superClassLoc = ConsumeToken(); // Consume super class name
}
- DeclPtrTy ImplClsType = Actions.ActOnStartClassImplementation(
+ Decl *ImplClsType = Actions.ActOnStartClassImplementation(
atLoc, nameId, nameLoc,
superClassId, superClassLoc);
@@ -1294,17 +1322,17 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
ObjCImpDecl = ImplClsType;
PendingObjCImpDecl.push_back(ObjCImpDecl);
- return DeclPtrTy();
+ return 0;
}
-Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
+Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
assert(Tok.isObjCAtKeyword(tok::objc_end) &&
"ParseObjCAtEndDeclaration(): Expected @end");
- DeclPtrTy Result = ObjCImpDecl;
+ Decl *Result = ObjCImpDecl;
ConsumeToken(); // the "end" identifier
if (ObjCImpDecl) {
Actions.ActOnAtEnd(getCurScope(), atEnd, ObjCImpDecl);
- ObjCImpDecl = DeclPtrTy();
+ ObjCImpDecl = 0;
PendingObjCImpDecl.pop_back();
}
else {
@@ -1314,10 +1342,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
return Result;
}
-Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
+Parser::DeclGroupPtrTy Parser::FinishPendingObjCActions() {
+ Actions.DiagnoseUseOfUnimplementedSelectors();
if (PendingObjCImpDecl.empty())
- return Actions.ConvertDeclToDeclGroup(DeclPtrTy());
- DeclPtrTy ImpDecl = PendingObjCImpDecl.pop_back_val();
+ return Actions.ConvertDeclToDeclGroup(0);
+ Decl *ImpDecl = PendingObjCImpDecl.pop_back_val();
Actions.ActOnAtEnd(getCurScope(), SourceRange(), ImpDecl);
return Actions.ConvertDeclToDeclGroup(ImpDecl);
}
@@ -1325,25 +1354,25 @@ Parser::DeclGroupPtrTy Parser::RetrievePendingObjCImpDecl() {
/// compatibility-alias-decl:
/// @compatibility_alias alias-name class-name ';'
///
-Parser::DeclPtrTy Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
+Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
"ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
ConsumeToken(); // consume compatibility_alias
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
- return DeclPtrTy();
+ return 0;
}
IdentifierInfo *aliasId = Tok.getIdentifierInfo();
SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
- return DeclPtrTy();
+ return 0;
}
IdentifierInfo *classId = Tok.getIdentifierInfo();
SourceLocation classLoc = ConsumeToken(); // consume class-name;
if (Tok.isNot(tok::semi)) {
Diag(Tok, diag::err_expected_semi_after) << "@compatibility_alias";
- return DeclPtrTy();
+ return 0;
}
return Actions.ActOnCompatiblityAlias(atLoc, aliasId, aliasLoc,
classId, classLoc);
@@ -1360,7 +1389,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
/// identifier
/// identifier '=' identifier
///
-Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
+Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
"ParseObjCPropertyDynamic(): Expected '@synthesize'");
SourceLocation loc = ConsumeToken(); // consume synthesize
@@ -1374,7 +1403,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_synthesized_property_name);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
IdentifierInfo *propertyIvar = 0;
@@ -1409,7 +1438,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
}
else
ConsumeToken(); // consume ';'
- return DeclPtrTy();
+ return 0;
}
/// property-dynamic:
@@ -1419,7 +1448,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
/// identifier
/// property-list ',' identifier
///
-Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
+Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
"ParseObjCPropertyDynamic(): Expected '@dynamic'");
SourceLocation loc = ConsumeToken(); // consume dynamic
@@ -1432,7 +1461,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
@@ -1450,14 +1479,14 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
}
else
ConsumeToken(); // consume ';'
- return DeclPtrTy();
+ return 0;
}
/// objc-throw-statement:
/// throw expression[opt];
///
-Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
- OwningExprResult Res(Actions);
+StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
+ ExprResult Res;
ConsumeToken(); // consume throw
if (Tok.isNot(tok::semi)) {
Res = ParseExpression();
@@ -1468,13 +1497,13 @@ Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
}
// consume ';'
ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@throw");
- return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), getCurScope());
+ return Actions.ActOnObjCAtThrowStmt(atLoc, Res.take(), getCurScope());
}
/// objc-synchronized-statement:
/// @synchronized '(' expression ')' compound-statement
///
-Parser::OwningStmtResult
+StmtResult
Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
ConsumeToken(); // consume synchronized
if (Tok.isNot(tok::l_paren)) {
@@ -1482,7 +1511,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
return StmtError();
}
ConsumeParen(); // '('
- OwningExprResult Res(ParseExpression());
+ ExprResult Res(ParseExpression());
if (Res.isInvalid()) {
SkipUntil(tok::semi);
return StmtError();
@@ -1500,12 +1529,12 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
// statements can always hold declarations.
ParseScope BodyScope(this, Scope::DeclScope);
- OwningStmtResult SynchBody(ParseCompoundStatementBody());
+ StmtResult SynchBody(ParseCompoundStatementBody());
BodyScope.Exit();
if (SynchBody.isInvalid())
SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
- return Actions.ActOnObjCAtSynchronizedStmt(atLoc, move(Res), move(SynchBody));
+ return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.take(), SynchBody.take());
}
/// objc-try-catch-statement:
@@ -1519,7 +1548,7 @@ Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
/// parameter-declaration
/// '...' [OBJC2]
///
-Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
+StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
bool catch_or_finally_seen = false;
ConsumeToken(); // consume try
@@ -1528,9 +1557,9 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
return StmtError();
}
StmtVector CatchStmts(Actions);
- OwningStmtResult FinallyStmt(Actions);
+ StmtResult FinallyStmt;
ParseScope TryScope(this, Scope::DeclScope);
- OwningStmtResult TryBody(ParseCompoundStatementBody());
+ StmtResult TryBody(ParseCompoundStatementBody());
TryScope.Exit();
if (TryBody.isInvalid())
TryBody = Actions.ActOnNullStmt(Tok.getLocation());
@@ -1546,7 +1575,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
SourceLocation AtCatchFinallyLoc = ConsumeToken();
if (Tok.isObjCAtKeyword(tok::objc_catch)) {
- DeclPtrTy FirstPart;
+ Decl *FirstPart = 0;
ConsumeToken(); // consume catch
if (Tok.is(tok::l_paren)) {
ConsumeParen();
@@ -1573,7 +1602,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
else // Skip over garbage, until we get to ')'. Eat the ')'.
SkipUntil(tok::r_paren, true, false);
- OwningStmtResult CatchBody(Actions, true);
+ StmtResult CatchBody(true);
if (Tok.is(tok::l_brace))
CatchBody = ParseCompoundStatementBody();
else
@@ -1581,10 +1610,10 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (CatchBody.isInvalid())
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
- OwningStmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
+ StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
RParenLoc,
FirstPart,
- move(CatchBody));
+ CatchBody.take());
if (!Catch.isInvalid())
CatchStmts.push_back(Catch.release());
@@ -1599,7 +1628,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
ConsumeToken(); // consume finally
ParseScope FinallyScope(this, Scope::DeclScope);
- OwningStmtResult FinallyBody(Actions, true);
+ StmtResult FinallyBody(true);
if (Tok.is(tok::l_brace))
FinallyBody = ParseCompoundStatementBody();
else
@@ -1607,7 +1636,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (FinallyBody.isInvalid())
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
- move(FinallyBody));
+ FinallyBody.take());
catch_or_finally_seen = true;
break;
}
@@ -1617,19 +1646,18 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
return StmtError();
}
- return Actions.ActOnObjCAtTryStmt(atLoc, move(TryBody),
+ return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.take(),
move_arg(CatchStmts),
- move(FinallyStmt));
+ FinallyStmt.take());
}
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
///
-Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
- DeclPtrTy MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
+Decl *Parser::ParseObjCMethodDefinition() {
+ Decl *MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
- PrettyStackTraceActionsDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
- PP.getSourceManager(),
- "parsing Objective-C method");
+ PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(),
+ "parsing Objective-C method");
// parse optional ';'
if (Tok.is(tok::semi)) {
@@ -1649,7 +1677,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return DeclPtrTy();
+ return 0;
}
SourceLocation BraceLoc = Tok.getLocation();
@@ -1661,7 +1689,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
// specified Declarator for the method.
Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl);
- OwningStmtResult FnBody(ParseCompoundStatementBody());
+ StmtResult FnBody(ParseCompoundStatementBody());
// If the function body could not be parsed, make a bogus compoundstmt.
if (FnBody.isInvalid())
@@ -1669,7 +1697,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
MultiStmtArg(Actions), false);
// TODO: Pass argument information.
- Actions.ActOnFinishFunctionBody(MDecl, move(FnBody));
+ Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
// Leave the function body scope.
BodyScope.Exit();
@@ -1677,7 +1705,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
return MDecl;
}
-Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
+StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtStatement(getCurScope());
ConsumeCodeCompletionToken();
@@ -1693,7 +1721,7 @@ Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
if (Tok.isObjCAtKeyword(tok::objc_synchronized))
return ParseObjCSynchronizedStmt(AtLoc);
- OwningExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
+ ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
if (Res.isInvalid()) {
// If the expression is invalid, skip ahead to the next semicolon. Not
// doing this opens us up to the possibility of infinite loops if
@@ -1704,10 +1732,10 @@ Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
// Otherwise, eat the semicolon.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
- return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
+ return Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.take()));
}
-Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
+ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
switch (Tok.getKind()) {
case tok::code_completion:
Actions.CodeCompleteObjCAtExpression(getCurScope());
@@ -1764,7 +1792,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
if (!isCXXSimpleTypeSpecifier()) {
// objc-receiver:
// expression
- OwningExprResult Receiver = ParseExpression();
+ ExprResult Receiver = ParseExpression();
if (Receiver.isInvalid())
return true;
@@ -1793,11 +1821,11 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
// postfix-expression suffix, followed by the (optional)
// right-hand side of the binary expression. We have an
// instance method.
- OwningExprResult Receiver = ParseCXXTypeConstructExpression(DS);
+ ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
if (!Receiver.isInvalid())
- Receiver = ParsePostfixExpressionSuffix(move(Receiver));
+ Receiver = ParsePostfixExpressionSuffix(Receiver.take());
if (!Receiver.isInvalid())
- Receiver = ParseRHSOfBinaryExpression(move(Receiver), prec::Comma);
+ Receiver = ParseRHSOfBinaryExpression(Receiver.take(), prec::Comma);
if (Receiver.isInvalid())
return true;
@@ -1815,7 +1843,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
return true;
IsExpr = false;
- TypeOrExpr = Type.get();
+ TypeOrExpr = Type.get().getAsOpaquePtr();
return false;
}
@@ -1840,7 +1868,7 @@ bool Parser::isSimpleObjCMessageExpression() {
/// class-name
/// type-name
///
-Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
+ExprResult Parser::ParseObjCMessageExpression() {
assert(Tok.is(tok::l_square) && "'[' expected");
SourceLocation LBracLoc = ConsumeBracket(); // consume '['
@@ -1860,8 +1888,8 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
// get in Objective-C.
if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
- return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), 0,
- ExprArg(Actions));
+ return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
+ ParsedType(), 0);
// Parse the receiver, which is either a type or an expression.
bool IsExpr;
@@ -1872,26 +1900,28 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
}
if (IsExpr)
- return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 0,
- OwningExprResult(Actions, TypeOrExpr));
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ ParsedType(),
+ static_cast<Expr*>(TypeOrExpr));
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
- TypeOrExpr, ExprArg(Actions));
+ ParsedType::getFromOpaquePtr(TypeOrExpr),
+ 0);
}
if (Tok.is(tok::identifier)) {
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = Tok.getLocation();
- TypeTy *ReceiverType;
+ ParsedType ReceiverType;
switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc,
Name == Ident_super,
NextToken().is(tok::period),
ReceiverType)) {
- case Action::ObjCSuperMessage:
- return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), 0,
- ExprArg(Actions));
+ case Sema::ObjCSuperMessage:
+ return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(),
+ ParsedType(), 0);
- case Action::ObjCClassMessage:
+ case Sema::ObjCClassMessage:
if (!ReceiverType) {
SkipUntil(tok::r_square);
return ExprError();
@@ -1900,24 +1930,23 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
ConsumeToken(); // the type name
return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
- ReceiverType,
- ExprArg(Actions));
+ ReceiverType, 0);
- case Action::ObjCInstanceMessage:
+ case Sema::ObjCInstanceMessage:
// Fall through to parse an expression.
break;
}
}
// Otherwise, an arbitrary expression can be the receiver of a send.
- OwningExprResult Res(ParseExpression());
+ ExprResult Res(ParseExpression());
if (Res.isInvalid()) {
SkipUntil(tok::r_square);
return move(Res);
}
- return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), 0,
- move(Res));
+ return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
+ ParsedType(), Res.take());
}
/// \brief Parse the remainder of an Objective-C message following the
@@ -1958,10 +1987,10 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
/// assignment-expression
/// nonempty-expr-list , assignment-expression
///
-Parser::OwningExprResult
+ExprResult
Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
SourceLocation SuperLoc,
- TypeTy *ReceiverType,
+ ParsedType ReceiverType,
ExprArg ReceiverExpr) {
if (Tok.is(tok::code_completion)) {
if (SuperLoc.isValid())
@@ -1969,7 +1998,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
else if (ReceiverType)
Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, 0, 0);
else
- Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr.get(),
+ Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
0, 0);
ConsumeCodeCompletionToken();
}
@@ -1999,7 +2028,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
ConsumeToken(); // Eat the ':'.
/// Parse the expression after ':'
- OwningExprResult Res(ParseAssignmentExpression());
+ ExprResult Res(ParseAssignmentExpression());
if (Res.isInvalid()) {
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
@@ -2022,7 +2051,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
KeyIdents.data(),
KeyIdents.size());
else
- Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr.get(),
+ Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
KeyIdents.data(),
KeyIdents.size());
ConsumeCodeCompletionToken();
@@ -2038,7 +2067,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
while (Tok.is(tok::comma)) {
ConsumeToken(); // Eat the ','.
/// Parse the expression after ','
- OwningExprResult Res(ParseAssignmentExpression());
+ ExprResult Res(ParseAssignmentExpression());
if (Res.isInvalid()) {
// We must manually skip to a ']', otherwise the expression skipper will
// stop at the ']' when it skips to the ';'. We want it to skip beyond
@@ -2082,24 +2111,24 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
if (SuperLoc.isValid())
return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel,
LBracLoc, SelectorLoc, RBracLoc,
- Action::MultiExprArg(Actions,
- KeyExprs.take(),
- KeyExprs.size()));
+ MultiExprArg(Actions,
+ KeyExprs.take(),
+ KeyExprs.size()));
else if (ReceiverType)
return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel,
LBracLoc, SelectorLoc, RBracLoc,
- Action::MultiExprArg(Actions,
- KeyExprs.take(),
- KeyExprs.size()));
- return Actions.ActOnInstanceMessage(getCurScope(), move(ReceiverExpr), Sel,
+ MultiExprArg(Actions,
+ KeyExprs.take(),
+ KeyExprs.size()));
+ return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel,
LBracLoc, SelectorLoc, RBracLoc,
- Action::MultiExprArg(Actions,
- KeyExprs.take(),
- KeyExprs.size()));
+ MultiExprArg(Actions,
+ KeyExprs.take(),
+ KeyExprs.size()));
}
-Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
- OwningExprResult Res(ParseStringLiteralExpression());
+ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
+ ExprResult Res(ParseStringLiteralExpression());
if (Res.isInvalid()) return move(Res);
// @"foo" @"bar" is a valid concatenated string. Eat any subsequent string
@@ -2117,7 +2146,7 @@ Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
if (!isTokenStringLiteral())
return ExprError(Diag(Tok, diag::err_objc_concat_string));
- OwningExprResult Lit(ParseStringLiteralExpression());
+ ExprResult Lit(ParseStringLiteralExpression());
if (Lit.isInvalid())
return move(Lit);
@@ -2130,7 +2159,7 @@ Parser::OwningExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
/// objc-encode-expression:
/// @encode ( type-name )
-Parser::OwningExprResult
+ExprResult
Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");
@@ -2154,7 +2183,7 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
/// objc-protocol-expression
/// @protocol ( protocol-name )
-Parser::OwningExprResult
+ExprResult
Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
SourceLocation ProtoLoc = ConsumeToken();
@@ -2177,8 +2206,7 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
/// objc-selector-expression
/// @selector '(' objc-keyword-selector ')'
-Parser::OwningExprResult
-Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
+ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
SourceLocation SelectorLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren))
@@ -2187,21 +2215,43 @@ Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
SourceLocation LParenLoc = ConsumeParen();
SourceLocation sLoc;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(),
+ KeyIdents.size());
+ ConsumeCodeCompletionToken();
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return ExprError();
+ }
+
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
- if (!SelIdent && Tok.isNot(tok::colon)) // missing selector name.
+ if (!SelIdent && // missing selector name.
+ Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
return ExprError(Diag(Tok, diag::err_expected_ident));
KeyIdents.push_back(SelIdent);
unsigned nColons = 0;
if (Tok.isNot(tok::r_paren)) {
while (1) {
- if (Tok.isNot(tok::colon))
+ if (Tok.is(tok::coloncolon)) { // Handle :: in C++.
+ ++nColons;
+ KeyIdents.push_back(0);
+ } else if (Tok.isNot(tok::colon))
return ExprError(Diag(Tok, diag::err_expected_colon));
- nColons++;
+ ++nColons;
ConsumeToken(); // Eat the ':'.
if (Tok.is(tok::r_paren))
break;
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents.data(),
+ KeyIdents.size());
+ ConsumeCodeCompletionToken();
+ MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ return ExprError();
+ }
+
// Check for another keyword selector.
SourceLocation Loc;
SelIdent = ParseObjCSelectorPiece(Loc);
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 64a4c16b77c3..ddba09ae0f95 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -13,11 +13,63 @@
#include "ParsePragma.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Action.h"
#include "clang/Parse/Parser.h"
+#include "clang/Lex/Preprocessor.h"
using namespace clang;
+
+// #pragma GCC visibility comes in two variants:
+// 'push' '(' [visibility] ')'
+// 'pop'
+void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Token &VisTok) {
+ SourceLocation VisLoc = VisTok.getLocation();
+
+ Token Tok;
+ PP.Lex(Tok);
+
+ const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
+
+ bool IsPush;
+ const IdentifierInfo *VisType;
+ if (PushPop && PushPop->isStr("pop")) {
+ IsPush = false;
+ VisType = 0;
+ } else if (PushPop && PushPop->isStr("push")) {
+ IsPush = true;
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::l_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
+ << "visibility";
+ return;
+ }
+ PP.Lex(Tok);
+ VisType = Tok.getIdentifierInfo();
+ if (!VisType) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "visibility";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
+ << "visibility";
+ return;
+ }
+ } else {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ << "visibility";
+ return;
+ }
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::eom)) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
+ << "visibility";
+ return;
+ }
+
+ Actions.ActOnPragmaVisibility(IsPush, VisType, VisLoc);
+}
+
// #pragma pack(...) comes in the following delicious flavors:
// pack '(' [integer] ')'
// pack '(' 'show' ')'
@@ -32,9 +84,9 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
return;
}
- Action::PragmaPackKind Kind = Action::PPK_Default;
+ Sema::PragmaPackKind Kind = Sema::PPK_Default;
IdentifierInfo *Name = 0;
- Action::OwningExprResult Alignment(Actions);
+ ExprResult Alignment;
SourceLocation LParenLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.is(tok::numeric_constant)) {
@@ -46,13 +98,13 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
} else if (Tok.is(tok::identifier)) {
const IdentifierInfo *II = Tok.getIdentifierInfo();
if (II->isStr("show")) {
- Kind = Action::PPK_Show;
+ Kind = Sema::PPK_Show;
PP.Lex(Tok);
} else {
if (II->isStr("push")) {
- Kind = Action::PPK_Push;
+ Kind = Sema::PPK_Push;
} else if (II->isStr("pop")) {
- Kind = Action::PPK_Pop;
+ Kind = Sema::PPK_Pop;
} else {
PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
return;
@@ -110,46 +162,52 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
LParenLoc, RParenLoc);
}
-// #pragma 'options' 'align' '=' {'native','natural','mac68k','power','reset'}
-void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
- SourceLocation OptionsLoc = OptionsTok.getLocation();
-
+// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
+// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
+static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
+ bool IsOptions) {
Token Tok;
- PP.Lex(Tok);
- if (Tok.isNot(tok::identifier) || !Tok.getIdentifierInfo()->isStr("align")) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
- return;
+
+ if (IsOptions) {
+ PP.Lex(Tok);
+ if (Tok.isNot(tok::identifier) ||
+ !Tok.getIdentifierInfo()->isStr("align")) {
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
+ return;
+ }
}
PP.Lex(Tok);
if (Tok.isNot(tok::equal)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_equal);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
+ << IsOptions;
return;
}
PP.Lex(Tok);
if (Tok.isNot(tok::identifier)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
- << "options";
+ << (IsOptions ? "options" : "align");
return;
}
- Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural;
+ Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
const IdentifierInfo *II = Tok.getIdentifierInfo();
if (II->isStr("native"))
- Kind = Action::POAK_Native;
+ Kind = Sema::POAK_Native;
else if (II->isStr("natural"))
- Kind = Action::POAK_Natural;
+ Kind = Sema::POAK_Natural;
else if (II->isStr("packed"))
- Kind = Action::POAK_Packed;
+ Kind = Sema::POAK_Packed;
else if (II->isStr("power"))
- Kind = Action::POAK_Power;
+ Kind = Sema::POAK_Power;
else if (II->isStr("mac68k"))
- Kind = Action::POAK_Mac68k;
+ Kind = Sema::POAK_Mac68k;
else if (II->isStr("reset"))
- Kind = Action::POAK_Reset;
+ Kind = Sema::POAK_Reset;
else {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option);
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
+ << IsOptions;
return;
}
@@ -157,11 +215,19 @@ void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
PP.Lex(Tok);
if (Tok.isNot(tok::eom)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
- << "options";
+ << (IsOptions ? "options" : "align");
return;
}
- Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc);
+ Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
+}
+
+void PragmaAlignHandler::HandlePragma(Preprocessor &PP, Token &AlignTok) {
+ ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
+}
+
+void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
+ ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
}
// #pragma unused(identifier)
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
index 929ec46c4ff5..0feaa9919e8d 100644
--- a/lib/Parse/ParsePragma.h
+++ b/lib/Parse/ParsePragma.h
@@ -17,41 +17,58 @@
#include "clang/Lex/Pragma.h"
namespace clang {
- class Action;
+ class Sema;
class Parser;
+class PragmaAlignHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaAlignHandler(Sema &A) : PragmaHandler("align"), Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
+
+class PragmaGCCVisibilityHandler : public PragmaHandler {
+ Sema &Actions;
+public:
+ explicit PragmaGCCVisibilityHandler(Sema &A) : PragmaHandler("visibility"),
+ Actions(A) {}
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
+
class PragmaOptionsHandler : public PragmaHandler {
- Action &Actions;
+ Sema &Actions;
public:
- explicit PragmaOptionsHandler(Action &A) : PragmaHandler("options"),
- Actions(A) {}
+ explicit PragmaOptionsHandler(Sema &A) : PragmaHandler("options"),
+ Actions(A) {}
virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
};
class PragmaPackHandler : public PragmaHandler {
- Action &Actions;
+ Sema &Actions;
public:
- explicit PragmaPackHandler(Action &A) : PragmaHandler("pack"),
- Actions(A) {}
+ explicit PragmaPackHandler(Sema &A) : PragmaHandler("pack"),
+ Actions(A) {}
virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
};
class PragmaUnusedHandler : public PragmaHandler {
- Action &Actions;
+ Sema &Actions;
Parser &parser;
public:
- PragmaUnusedHandler(Action &A, Parser& p)
+ PragmaUnusedHandler(Sema &A, Parser& p)
: PragmaHandler("unused"), Actions(A), parser(p) {}
virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
};
class PragmaWeakHandler : public PragmaHandler {
- Action &Actions;
+ Sema &Actions;
public:
- explicit PragmaWeakHandler(Action &A)
+ explicit PragmaWeakHandler(Sema &A)
: PragmaHandler("weak"), Actions(A) {}
virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index c908ed9caec6..6c240e608c2e 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -14,8 +14,9 @@
#include "clang/Parse/Parser.h"
#include "RAIIObjectsForParser.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Basic/SourceManager.h"
@@ -73,10 +74,10 @@ using namespace clang;
/// [OBC] '@' 'throw' expression ';'
/// [OBC] '@' 'throw' ';'
///
-Parser::OwningStmtResult
+StmtResult
Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
const char *SemiError = 0;
- OwningStmtResult Res(Actions);
+ StmtResult Res;
ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -98,7 +99,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
}
case tok::code_completion:
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_Statement);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
ConsumeCodeCompletionToken();
return ParseStatementOrDeclaration(OnlyStatement);
@@ -125,7 +126,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
// FIXME: Use the attributes
// expression[opt] ';'
- OwningExprResult Expr(ParseExpression());
+ ExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
// If the expression is invalid, skip ahead to the next semicolon or '}'.
// Not doing this opens us up to the possibility of infinite loops if
@@ -137,7 +138,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
}
// Otherwise, eat the semicolon.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
- return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr));
+ return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get()));
}
case tok::kw_case: // C99 6.8.1: labeled-statement
@@ -217,7 +218,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
/// identifier ':' statement
/// [GNU] identifier ':' attributes[opt] statement
///
-Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
+StmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
"Not an identifier!");
@@ -234,7 +235,7 @@ Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
if (Tok.is(tok::kw___attribute))
AttrList.reset(addAttributeLists(AttrList.take(), ParseGNUAttributes()));
- OwningStmtResult SubStmt(ParseStatement());
+ StmtResult SubStmt(ParseStatement());
// Broken substmt shouldn't prevent the label from being added to the AST.
if (SubStmt.isInvalid())
@@ -243,7 +244,7 @@ Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
// FIXME: use attributes?
return Actions.ActOnLabelStmt(IdentTok.getLocation(),
IdentTok.getIdentifierInfo(),
- ColonLoc, move(SubStmt));
+ ColonLoc, SubStmt.get());
}
/// ParseCaseStatement
@@ -251,7 +252,7 @@ Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
/// 'case' constant-expression ':' statement
/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
///
-Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
+StmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
assert(Tok.is(tok::kw_case) && "Not a case stmt!");
// FIXME: Use attributes?
delete Attr;
@@ -272,7 +273,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
// TopLevelCase - This is the highest level we have parsed. 'case 1' in the
// example above.
- OwningStmtResult TopLevelCase(Actions, true);
+ StmtResult TopLevelCase(true);
// DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
// gets updated each time a new case is parsed, and whose body is unset so
@@ -293,7 +294,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
/// expression.
ColonProtectionRAIIObject ColonProtection(*this);
- OwningExprResult LHS(ParseConstantExpression());
+ ExprResult LHS(ParseConstantExpression());
if (LHS.isInvalid()) {
SkipUntil(tok::colon);
return StmtError();
@@ -301,7 +302,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
// GNU case range extension.
SourceLocation DotDotDotLoc;
- OwningExprResult RHS(Actions);
+ ExprResult RHS;
if (Tok.is(tok::ellipsis)) {
Diag(Tok, diag::ext_gnu_case_range);
DotDotDotLoc = ConsumeToken();
@@ -323,9 +324,9 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
SourceLocation ColonLoc = ConsumeToken();
- OwningStmtResult Case =
- Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
- move(RHS), ColonLoc);
+ StmtResult Case =
+ Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc,
+ RHS.get(), ColonLoc);
// If we had a sema error parsing this case, then just ignore it and
// continue parsing the sub-stmt.
@@ -336,11 +337,11 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
} else {
// If this is the first case statement we parsed, it becomes TopLevelCase.
// Otherwise we link it into the current chain.
- StmtTy *NextDeepest = Case.get();
+ Stmt *NextDeepest = Case.get();
if (TopLevelCase.isInvalid())
TopLevelCase = move(Case);
else
- Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
+ Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
DeepestParsedCaseStmt = NextDeepest;
}
@@ -350,7 +351,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
// If we found a non-case statement, start by parsing it.
- OwningStmtResult SubStmt(Actions);
+ StmtResult SubStmt;
if (Tok.isNot(tok::r_brace)) {
SubStmt = ParseStatement();
@@ -367,7 +368,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
SubStmt = Actions.ActOnNullStmt(SourceLocation());
// Install the body into the most deeply-nested case.
- Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
+ Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
// Return the top level parsed statement tree.
return move(TopLevelCase);
@@ -378,7 +379,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
/// 'default' ':' statement
/// Note that this does not parse the 'statement' at the end.
///
-Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
+StmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
//FIXME: Use attributes?
delete Attr;
@@ -399,12 +400,12 @@ Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
return StmtError();
}
- OwningStmtResult SubStmt(ParseStatement());
+ StmtResult SubStmt(ParseStatement());
if (SubStmt.isInvalid())
return StmtError();
return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
- move(SubStmt), getCurScope());
+ SubStmt.get(), getCurScope());
}
@@ -435,7 +436,7 @@ Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
/// [OMP] barrier-directive
/// [OMP] flush-directive
///
-Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
+StmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
bool isStmtExpr) {
//FIXME: Use attributes?
delete Attr;
@@ -455,7 +456,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
/// consume the '}' at the end of the block. It does not manipulate the scope
/// stack.
-Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
+StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
Tok.getLocation(),
"in compound statement ('{}')");
@@ -468,7 +469,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
typedef StmtVector StmtsTy;
StmtsTy Stmts(Actions);
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
- OwningStmtResult R(Actions);
+ StmtResult R;
if (Tok.isNot(tok::kw___extension__)) {
R = ParseStatementOrDeclaration(false);
} else {
@@ -496,7 +497,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
} else {
// Otherwise this was a unary __extension__ marker.
- OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
+ ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
if (Res.isInvalid()) {
SkipUntil(tok::semi);
@@ -507,7 +508,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
// Eat the semicolon at the end of stmt and convert the expr into a
// statement.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
- R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
+ R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res.get()));
}
}
@@ -518,6 +519,7 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
// We broke out of the while loop because we found a '}' or EOF.
if (Tok.isNot(tok::r_brace)) {
Diag(Tok, diag::err_expected_rbrace);
+ Diag(LBraceLoc, diag::note_matching) << "{";
return StmtError();
}
@@ -537,8 +539,8 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
/// should try to recover harder. It returns false if the condition is
/// successfully parsed. Note that a successful parse can still have semantic
/// errors in the condition.
-bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
- DeclPtrTy &DeclResult,
+bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
+ Decl *&DeclResult,
SourceLocation Loc,
bool ConvertToBoolean) {
bool ParseError = false;
@@ -549,18 +551,18 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
ConvertToBoolean);
else {
ExprResult = ParseExpression();
- DeclResult = DeclPtrTy();
+ DeclResult = 0;
// If required, convert to a boolean value.
if (!ExprResult.isInvalid() && ConvertToBoolean)
ExprResult
- = Actions.ActOnBooleanCondition(getCurScope(), Loc, move(ExprResult));
+ = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get());
}
// If the parser was confused by the condition and we don't have a ')', try to
// recover by skipping ahead to a semi and bailing out. If condexp is
// semantically invalid but we have well formed code, keep going.
- if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
+ if (ExprResult.isInvalid() && !DeclResult && Tok.isNot(tok::r_paren)) {
SkipUntil(tok::semi);
// Skipping may have stopped if it found the containing ')'. If so, we can
// continue parsing the if statement.
@@ -581,7 +583,7 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
/// [C++] 'if' '(' condition ')' statement
/// [C++] 'if' '(' condition ')' statement 'else' statement
///
-Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
+StmtResult Parser::ParseIfStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -611,12 +613,12 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
// Parse the condition.
- OwningExprResult CondExp(Actions);
- DeclPtrTy CondVar;
+ ExprResult CondExp;
+ Decl *CondVar = 0;
if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
return StmtError();
- FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp));
+ FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get()));
// C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
@@ -641,7 +643,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
// Read the 'then' stmt.
SourceLocation ThenStmtLoc = Tok.getLocation();
- OwningStmtResult ThenStmt(ParseStatement());
+ StmtResult ThenStmt(ParseStatement());
// Pop the 'if' scope if needed.
InnerScope.Exit();
@@ -649,7 +651,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
// If it has an else, parse it.
SourceLocation ElseLoc;
SourceLocation ElseStmtLoc;
- OwningStmtResult ElseStmt(Actions);
+ StmtResult ElseStmt;
if (Tok.is(tok::kw_else)) {
ElseLoc = ConsumeToken();
@@ -667,13 +669,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
ParseScope InnerScope(this, Scope::DeclScope,
C99orCXX && Tok.isNot(tok::l_brace));
- // Regardless of whether or not InnerScope actually pushed a scope, set the
- // ElseScope flag for the innermost scope so we can diagnose use of the if
- // condition variable in C++.
- unsigned OldFlags = getCurScope()->getFlags();
- getCurScope()->setFlags(OldFlags | Scope::ElseScope);
ElseStmt = ParseStatement();
- getCurScope()->setFlags(OldFlags);
// Pop the 'else' scope if needed.
InnerScope.Exit();
@@ -683,7 +679,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
// If the condition was invalid, discard the if statement. We could recover
// better by replacing it with a valid expr, but don't do that yet.
- if (CondExp.isInvalid() && !CondVar.get())
+ if (CondExp.isInvalid() && !CondVar)
return StmtError();
// If the then or else stmt is invalid and the other is valid (and present),
@@ -702,15 +698,15 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
if (ElseStmt.isInvalid())
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
- return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
- ElseLoc, move(ElseStmt));
+ return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(),
+ ElseLoc, ElseStmt.get());
}
/// ParseSwitchStatement
/// switch-statement:
/// 'switch' '(' expression ')' statement
/// [C++] 'switch' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
+StmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -743,13 +739,13 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
ParseScope SwitchScope(this, ScopeFlags);
// Parse the condition.
- OwningExprResult Cond(Actions);
- DeclPtrTy CondVar;
+ ExprResult Cond;
+ Decl *CondVar = 0;
if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false))
return StmtError();
- OwningStmtResult Switch
- = Actions.ActOnStartOfSwitchStmt(SwitchLoc, move(Cond), CondVar);
+ StmtResult Switch
+ = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar);
if (Switch.isInvalid()) {
// Skip the switch body.
@@ -779,7 +775,7 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
C99orCXX && Tok.isNot(tok::l_brace));
// Read the body statement.
- OwningStmtResult Body(ParseStatement());
+ StmtResult Body(ParseStatement());
// Pop the scopes.
InnerScope.Exit();
@@ -789,14 +785,14 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
// FIXME: Remove the case statement list from the Switch statement.
Body = Actions.ActOnNullStmt(Tok.getLocation());
- return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
+ return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
}
/// ParseWhileStatement
/// while-statement: [C99 6.8.5.1]
/// 'while' '(' expression ')' statement
/// [C++] 'while' '(' condition ')' statement
-Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
+StmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -833,12 +829,12 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
ParseScope WhileScope(this, ScopeFlags);
// Parse the condition.
- OwningExprResult Cond(Actions);
- DeclPtrTy CondVar;
+ ExprResult Cond;
+ Decl *CondVar = 0;
if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true))
return StmtError();
- FullExprArg FullCond(Actions.MakeFullExpr(Cond));
+ FullExprArg FullCond(Actions.MakeFullExpr(Cond.get()));
// C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
@@ -855,23 +851,23 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
C99orCXX && Tok.isNot(tok::l_brace));
// Read the body statement.
- OwningStmtResult Body(ParseStatement());
+ StmtResult Body(ParseStatement());
// Pop the body scope if needed.
InnerScope.Exit();
WhileScope.Exit();
- if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
+ if ((Cond.isInvalid() && !CondVar) || Body.isInvalid())
return StmtError();
- return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
+ return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get());
}
/// ParseDoStatement
/// do-statement: [C99 6.8.5.2]
/// 'do' statement 'while' '(' expression ')' ';'
/// Note: this lets the caller parse the end ';'.
-Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
+StmtResult Parser::ParseDoStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -901,7 +897,7 @@ Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
Tok.isNot(tok::l_brace));
// Read the body statement.
- OwningStmtResult Body(ParseStatement());
+ StmtResult Body(ParseStatement());
// Pop the body scope if needed.
InnerScope.Exit();
@@ -924,15 +920,15 @@ Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
// Parse the parenthesized condition.
SourceLocation LPLoc = ConsumeParen();
- OwningExprResult Cond = ParseExpression();
+ ExprResult Cond = ParseExpression();
SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
DoScope.Exit();
if (Cond.isInvalid() || Body.isInvalid())
return StmtError();
- return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
- move(Cond), RPLoc);
+ return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, LPLoc,
+ Cond.get(), RPLoc);
}
/// ParseForStatement
@@ -948,7 +944,7 @@ Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
/// [C++] expression-statement
/// [C++] simple-declaration
///
-Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
+StmtResult Parser::ParseForStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -988,20 +984,20 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
ParseScope ForScope(this, ScopeFlags);
SourceLocation LParenLoc = ConsumeParen();
- OwningExprResult Value(Actions);
+ ExprResult Value;
bool ForEach = false;
- OwningStmtResult FirstPart(Actions);
+ StmtResult FirstPart;
bool SecondPartIsInvalid = false;
FullExprArg SecondPart(Actions);
- OwningExprResult Collection(Actions);
+ ExprResult Collection;
FullExprArg ThirdPart(Actions);
- DeclPtrTy SecondVar;
+ Decl *SecondVar = 0;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(getCurScope(),
- C99orCXXorObjC? Action::CCC_ForInit
- : Action::CCC_Expression);
+ C99orCXXorObjC? Sema::PCC_ForInit
+ : Sema::PCC_Expression);
ConsumeCodeCompletionToken();
}
@@ -1029,6 +1025,11 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
Actions.ActOnForEachDeclStmt(DG);
// ObjC: for (id x in expr)
ConsumeToken(); // consume 'in'
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
+ ConsumeCodeCompletionToken();
+ }
Collection = ParseExpression();
} else {
Diag(Tok, diag::err_expected_semi_for);
@@ -1039,12 +1040,17 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
// Turn the expression into a stmt.
if (!Value.isInvalid())
- FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value));
+ FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value.get()));
if (Tok.is(tok::semi)) {
ConsumeToken();
} else if ((ForEach = isTokIdentifier_in())) {
ConsumeToken(); // consume 'in'
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy());
+ ConsumeCodeCompletionToken();
+ }
Collection = ParseExpression();
} else {
if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
@@ -1052,36 +1058,36 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
}
}
if (!ForEach) {
- assert(!SecondPart->get() && "Shouldn't have a second expression yet.");
+ assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
} else {
- OwningExprResult Second(Actions);
+ ExprResult Second;
if (getLang().CPlusPlus)
ParseCXXCondition(Second, SecondVar, ForLoc, true);
else {
Second = ParseExpression();
if (!Second.isInvalid())
Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc,
- move(Second));
+ Second.get());
}
SecondPartIsInvalid = Second.isInvalid();
- SecondPart = Actions.MakeFullExpr(Second);
+ SecondPart = Actions.MakeFullExpr(Second.get());
}
if (Tok.is(tok::semi)) {
ConsumeToken();
} else {
- if (!SecondPartIsInvalid || SecondVar.get())
+ if (!SecondPartIsInvalid || SecondVar)
Diag(Tok, diag::err_expected_semi_for);
SkipUntil(tok::semi);
}
// Parse the third part of the for specifier.
if (Tok.isNot(tok::r_paren)) { // for (...;...;)
- OwningExprResult Third = ParseExpression();
- ThirdPart = Actions.MakeFullExpr(Third);
+ ExprResult Third = ParseExpression();
+ ThirdPart = Actions.MakeFullExpr(Third.take());
}
}
// Match the ')'.
@@ -1102,7 +1108,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
C99orCXXorObjC && Tok.isNot(tok::l_brace));
// Read the body statement.
- OwningStmtResult Body(ParseStatement());
+ StmtResult Body(ParseStatement());
// Pop the body scope if needed.
InnerScope.Exit();
@@ -1114,14 +1120,14 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
return StmtError();
if (!ForEach)
- return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart), SecondPart,
- SecondVar, ThirdPart, RParenLoc, move(Body));
+ return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart,
+ SecondVar, ThirdPart, RParenLoc, Body.take());
// FIXME: It isn't clear how to communicate the late destruction of
// C++ temporaries used to create the collection.
- return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, move(FirstPart),
- move(Collection), RParenLoc,
- move(Body));
+ return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, FirstPart.take(),
+ Collection.take(), RParenLoc,
+ Body.take());
}
/// ParseGotoStatement
@@ -1131,14 +1137,14 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
+StmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
- OwningStmtResult Res(Actions);
+ StmtResult Res;
if (Tok.is(tok::identifier)) {
Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
Tok.getIdentifierInfo());
@@ -1147,12 +1153,12 @@ Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
// GNU indirect goto extension.
Diag(Tok, diag::ext_gnu_indirect_goto);
SourceLocation StarLoc = ConsumeToken();
- OwningExprResult R(ParseExpression());
+ ExprResult R(ParseExpression());
if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
SkipUntil(tok::semi, false, true);
return StmtError();
}
- Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(R));
+ Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
} else {
Diag(Tok, diag::err_expected_ident);
return StmtError();
@@ -1167,7 +1173,7 @@ Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
+StmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -1181,7 +1187,7 @@ Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
///
/// Note: this lets the caller parse the end ';'.
///
-Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
+StmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
@@ -1192,14 +1198,14 @@ Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
/// ParseReturnStatement
/// jump-statement:
/// 'return' expression[opt] ';'
-Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
+StmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
// FIXME: Use attributes?
delete Attr;
assert(Tok.is(tok::kw_return) && "Not a return stmt!");
SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
- OwningExprResult R(Actions);
+ ExprResult R;
if (Tok.isNot(tok::semi)) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteReturn(getCurScope());
@@ -1214,12 +1220,12 @@ Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
return StmtError();
}
}
- return Actions.ActOnReturnStmt(ReturnLoc, move(R));
+ return Actions.ActOnReturnStmt(ReturnLoc, R.take());
}
/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
/// routine is called to skip/ignore tokens that comprise the MS asm statement.
-Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
+StmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
if (Tok.is(tok::l_brace)) {
unsigned short savedBraceCount = BraceCount;
do {
@@ -1240,16 +1246,16 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
}
Token t;
t.setKind(tok::string_literal);
- t.setLiteralData("\"FIXME: not done\"");
+ t.setLiteralData("\"/*FIXME: not done*/\"");
t.clearFlag(Token::NeedsCleaning);
- t.setLength(17);
- OwningExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
+ t.setLength(21);
+ ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
ExprVector Constraints(Actions);
ExprVector Exprs(Actions);
ExprVector Clobbers(Actions);
return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, 0,
move_arg(Constraints), move_arg(Exprs),
- move(AsmString), move_arg(Clobbers),
+ AsmString.take(), move_arg(Clobbers),
Tok.getLocation(), true);
}
@@ -1280,7 +1286,7 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
/// assembly-instruction ';'[opt]
/// assembly-instruction-list ';' assembly-instruction ';'[opt]
///
-Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
+StmtResult Parser::ParseAsmStatement(bool &msAsm) {
assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
SourceLocation AsmLoc = ConsumeToken();
@@ -1307,7 +1313,7 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
}
Loc = ConsumeParen();
- OwningExprResult AsmString(ParseAsmStringLiteral());
+ ExprResult AsmString(ParseAsmStringLiteral());
if (AsmString.isInvalid())
return StmtError();
@@ -1322,7 +1328,7 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
/*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
move_arg(Constraints), move_arg(Exprs),
- move(AsmString), move_arg(Clobbers),
+ AsmString.take(), move_arg(Clobbers),
RParenLoc);
}
@@ -1367,17 +1373,19 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
if (!AteExtraColon)
ConsumeToken();
- // Parse the asm-string list for clobbers.
- while (1) {
- OwningExprResult Clobber(ParseAsmStringLiteral());
+ // Parse the asm-string list for clobbers if present.
+ if (Tok.isNot(tok::r_paren)) {
+ while (1) {
+ ExprResult Clobber(ParseAsmStringLiteral());
- if (Clobber.isInvalid())
- break;
+ if (Clobber.isInvalid())
+ break;
- Clobbers.push_back(Clobber.release());
+ Clobbers.push_back(Clobber.release());
- if (Tok.isNot(tok::comma)) break;
- ConsumeToken();
+ if (Tok.isNot(tok::comma)) break;
+ ConsumeToken();
+ }
}
}
@@ -1385,7 +1393,7 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
NumOutputs, NumInputs, Names.data(),
move_arg(Constraints), move_arg(Exprs),
- move(AsmString), move_arg(Clobbers),
+ AsmString.take(), move_arg(Clobbers),
RParenLoc);
}
@@ -1428,7 +1436,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
} else
Names.push_back(0);
- OwningExprResult Constraint(ParseAsmStringLiteral());
+ ExprResult Constraint(ParseAsmStringLiteral());
if (Constraint.isInvalid()) {
SkipUntil(tok::r_paren);
return true;
@@ -1443,7 +1451,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
// Read the parenthesized expression.
SourceLocation OpenLoc = ConsumeParen();
- OwningExprResult Res(ParseExpression());
+ ExprResult Res(ParseExpression());
MatchRHSPunctuation(tok::r_paren, OpenLoc);
if (Res.isInvalid()) {
SkipUntil(tok::r_paren);
@@ -1458,25 +1466,24 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
return true;
}
-Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
+Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
- PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
- PP.getSourceManager(),
- "parsing function body");
+ PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
+ "parsing function body");
// Do not enter a scope for the brace, as the arguments are in the same scope
// (the function body) as the body itself. Instead, just read the statement
// list and put it into a CompoundStmt for safe keeping.
- OwningStmtResult FnBody(ParseCompoundStatementBody());
+ StmtResult FnBody(ParseCompoundStatementBody());
// If the function body could not be parsed, make a bogus compoundstmt.
if (FnBody.isInvalid())
FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
MultiStmtArg(Actions), false);
- return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
+ return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
}
/// ParseFunctionTryBlock - Parse a C++ function-try-block.
@@ -1484,27 +1491,26 @@ Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
/// function-try-block:
/// 'try' ctor-initializer[opt] compound-statement handler-seq
///
-Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
+Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
- PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
- PP.getSourceManager(),
- "parsing function try block");
+ PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, TryLoc,
+ "parsing function try block");
// Constructor initializer list?
if (Tok.is(tok::colon))
ParseConstructorInitializer(Decl);
SourceLocation LBraceLoc = Tok.getLocation();
- OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
+ StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
// If we failed to parse the try-catch, we just give the function an empty
// compound statement as the body.
if (FnBody.isInvalid())
FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
MultiStmtArg(Actions), false);
- return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
+ return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
}
/// ParseCXXTryBlock - Parse a C++ try-block.
@@ -1512,7 +1518,7 @@ Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
/// try-block:
/// 'try' compound-statement handler-seq
///
-Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
+StmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
// FIXME: Add attributes?
delete Attr;
@@ -1534,11 +1540,11 @@ Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
/// handler-seq:
/// handler handler-seq[opt]
///
-Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
+StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- OwningStmtResult TryBlock(ParseCompoundStatement(0));
+ StmtResult TryBlock(ParseCompoundStatement(0));
if (TryBlock.isInvalid())
return move(TryBlock);
@@ -1551,7 +1557,7 @@ Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Tok.isNot(tok::kw_catch))
return StmtError(Diag(Tok, diag::err_expected_catch));
while (Tok.is(tok::kw_catch)) {
- OwningStmtResult Handler(ParseCXXCatchBlock());
+ StmtResult Handler(ParseCXXCatchBlock());
if (!Handler.isInvalid())
Handlers.push_back(Handler.release());
}
@@ -1560,7 +1566,7 @@ Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
if (Handlers.empty())
return StmtError();
- return Actions.ActOnCXXTryBlock(TryLoc, move(TryBlock), move_arg(Handlers));
+ return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers));
}
/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
@@ -1574,7 +1580,7 @@ Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
/// type-specifier-seq
/// '...'
///
-Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
+StmtResult Parser::ParseCXXCatchBlock() {
assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
SourceLocation CatchLoc = ConsumeToken();
@@ -1590,7 +1596,7 @@ Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
// exception-declaration is equivalent to '...' or a parameter-declaration
// without default arguments.
- DeclPtrTy ExceptionDecl;
+ Decl *ExceptionDecl = 0;
if (Tok.isNot(tok::ellipsis)) {
DeclSpec DS;
if (ParseCXXTypeSpecifierSeq(DS))
@@ -1608,9 +1614,9 @@ Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
return StmtError(Diag(Tok, diag::err_expected_lbrace));
// FIXME: Possible draft standard bug: attribute-specifier should be allowed?
- OwningStmtResult Block(ParseCompoundStatement(0));
+ StmtResult Block(ParseCompoundStatement(0));
if (Block.isInvalid())
return move(Block);
- return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, move(Block));
+ return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take());
}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index e1aaf91bd658..dfb4785489d0 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -13,15 +13,15 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Scope.h"
#include "RAIIObjectsForParser.h"
using namespace clang;
/// \brief Parse a template declaration, explicit instantiation, or
/// explicit specialization.
-Parser::DeclPtrTy
+Decl *
Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
@@ -70,7 +70,7 @@ namespace {
///
/// explicit-specialization: [ C++ temp.expl.spec]
/// 'template' '<' '>' declaration
-Parser::DeclPtrTy
+Decl *
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
@@ -80,6 +80,10 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// Enter template-parameter scope.
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+ // Tell the action that names should be checked in the context of
+ // the declaration to come.
+ ParsingDeclRAIIObject ParsingTemplateParams(*this);
+
// Parse multiple levels of template headers within this template
// parameter scope, e.g.,
//
@@ -118,19 +122,19 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
TemplateLoc = ConsumeToken();
} else {
Diag(Tok.getLocation(), diag::err_expected_template);
- return DeclPtrTy();
+ return 0;
}
// Parse the '<' template-parameter-list '>'
SourceLocation LAngleLoc, RAngleLoc;
- TemplateParameterList TemplateParams;
+ llvm::SmallVector<Decl*, 4> TemplateParams;
if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
RAngleLoc)) {
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return 0;
}
ParamLists.push_back(
@@ -152,6 +156,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
ParsedTemplateInfo(&ParamLists,
isSpecialization,
LastParamListWasEmpty),
+ ParsingTemplateParams,
DeclEnd, AS);
}
@@ -175,10 +180,11 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
/// declaration. Will be AS_none for namespace-scope declarations.
///
/// \returns the new declaration.
-Parser::DeclPtrTy
+Decl *
Parser::ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
+ ParsingDeclRAIIObject &DiagsFromTParams,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
@@ -186,12 +192,13 @@ Parser::ParseSingleDeclarationAfterTemplate(
if (Context == Declarator::MemberContext) {
// We are parsing a member template.
- ParseCXXClassMemberDeclaration(AS, TemplateInfo);
- return DeclPtrTy::make((void*)0);
+ ParseCXXClassMemberDeclaration(AS, TemplateInfo, &DiagsFromTParams);
+ return 0;
}
- // Parse the declaration specifiers.
- ParsingDeclSpec DS(*this);
+ // Parse the declaration specifiers, stealing the accumulated
+ // diagnostics from the template parameters.
+ ParsingDeclSpec DS(DiagsFromTParams);
if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
DS.AddAttributes(ParseCXX0XAttributes().AttrList);
@@ -201,7 +208,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
if (Tok.is(tok::semi)) {
DeclEnd = ConsumeToken();
- DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ Decl *Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
DS.complete(Decl);
return Decl;
}
@@ -215,14 +222,14 @@ Parser::ParseSingleDeclarationAfterTemplate(
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
ConsumeToken();
- return DeclPtrTy();
+ return 0;
}
// If we have a declaration or declarator list, handle it.
if (isDeclarationAfterDeclarator()) {
// Parse this declaration.
- DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
- TemplateInfo);
+ Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo,
+ TemplateInfo);
if (Tok.is(tok::comma)) {
Diag(Tok, diag::err_multiple_template_declarators)
@@ -251,7 +258,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
} else {
SkipUntil(tok::semi);
}
- return DeclPtrTy();
+ return 0;
}
return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo);
}
@@ -261,7 +268,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
else
Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
SkipUntil(tok::semi);
- return DeclPtrTy();
+ return 0;
}
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
@@ -274,7 +281,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
///
/// \returns true if an error occurred, false otherwise.
bool Parser::ParseTemplateParameters(unsigned Depth,
- TemplateParameterList &TemplateParams,
+ llvm::SmallVectorImpl<Decl*> &TemplateParams,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc) {
// Get the template parameter list.
@@ -307,9 +314,9 @@ bool Parser::ParseTemplateParameters(unsigned Depth,
/// template-parameter-list ',' template-parameter
bool
Parser::ParseTemplateParameterList(unsigned Depth,
- TemplateParameterList &TemplateParams) {
+ llvm::SmallVectorImpl<Decl*> &TemplateParams) {
while (1) {
- if (DeclPtrTy TmpParam
+ if (Decl *TmpParam
= ParseTemplateParameter(Depth, TemplateParams.size())) {
TemplateParams.push_back(TmpParam);
} else {
@@ -414,8 +421,7 @@ bool Parser::isStartOfTemplateTypeParameter() {
/// 'typename' identifier[opt] '=' type-id
/// 'template' ...[opt][C++0x] '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclPtrTy
-Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
+Decl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
if (isStartOfTemplateTypeParameter())
return ParseTypeParameter(Depth, Position);
@@ -437,7 +443,7 @@ Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
/// 'class' identifier[opt] '=' type-id
/// 'typename' ...[opt][C++0x] identifier[opt]
/// 'typename' identifier[opt] '=' type-id
-Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
+Decl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
"A type-parameter starts with 'class' or 'typename'");
@@ -468,14 +474,14 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
// don't consume this token.
} else {
Diag(Tok.getLocation(), diag::err_expected_ident);
- return DeclPtrTy();
+ return 0;
}
// Grab a default argument (if available).
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
// we introduce the type parameter into the local scope.
SourceLocation EqualLoc;
- TypeTy *DefaultArg = 0;
+ ParsedType DefaultArg;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
DefaultArg = ParseTypeName().get();
@@ -492,19 +498,19 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
/// type-parameter: [C++ temp.param]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclPtrTy
+Decl *
Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
// Handle the template <...> part.
SourceLocation TemplateLoc = ConsumeToken();
- TemplateParameterList TemplateParams;
+ llvm::SmallVector<Decl*,8> TemplateParams;
SourceLocation LAngleLoc, RAngleLoc;
{
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
RAngleLoc)) {
- return DeclPtrTy();
+ return 0;
}
}
@@ -513,7 +519,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
if (!Tok.is(tok::kw_class)) {
Diag(Tok.getLocation(), diag::err_expected_class_before)
<< PP.getSpelling(Tok);
- return DeclPtrTy();
+ return 0;
}
SourceLocation ClassLoc = ConsumeToken();
@@ -528,7 +534,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// don't consume this token.
} else {
Diag(Tok.getLocation(), diag::err_expected_ident);
- return DeclPtrTy();
+ return 0;
}
TemplateParamsTy *ParamList =
@@ -568,7 +574,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
/// template-parameter:
/// ...
/// parameter-declaration
-Parser::DeclPtrTy
+Decl *
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
SourceLocation StartLoc = Tok.getLocation();
@@ -581,21 +587,21 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// Parse this as a typename.
Declarator ParamDecl(DS, Declarator::TemplateParamContext);
ParseDeclarator(ParamDecl);
- if (DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
+ if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
// This probably shouldn't happen - and it's more of a Sema thing, but
// basically we didn't parse the type name because we couldn't associate
// it with an AST node. we should just skip to the comma or greater.
// TODO: This is currently a placeholder for some kind of Sema Error.
Diag(Tok.getLocation(), diag::err_parse_error);
SkipUntil(tok::comma, tok::greater, true, true);
- return DeclPtrTy();
+ return 0;
}
// If there is a default value, parse it.
// Per C++0x [basic.scope.pdecl]p9, we parse the default argument before
// we introduce the template parameter into the local scope.
SourceLocation EqualLoc;
- OwningExprResult DefaultArg(Actions);
+ ExprResult DefaultArg;
if (Tok.is(tok::equal)) {
EqualLoc = ConsumeToken();
@@ -614,7 +620,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// Create the parameter.
return Actions.ActOnNonTypeTemplateParameter(getCurScope(), ParamDecl,
Depth, Position, EqualLoc,
- move(DefaultArg));
+ DefaultArg.take());
}
/// \brief Parses a template-id that after the template name has
@@ -766,7 +772,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build the annotation token.
if (TNK == TNK_Type_template && AllowTypeAnnotation) {
- Action::TypeResult Type
+ TypeResult Type
= Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
LAngleLoc, TemplateArgsPtr,
RAngleLoc);
@@ -779,7 +785,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
}
Tok.setKind(tok::annot_typename);
- Tok.setAnnotationValue(Type.get());
+ setTypeAnnotation(Tok, Type.get());
if (SS && SS->isNotEmpty())
Tok.setLocation(SS->getBeginLoc());
else if (TemplateKWLoc.isValid())
@@ -800,7 +806,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateId->Name = 0;
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
}
- TemplateId->Template = Template.getAs<void*>();
+ TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
@@ -844,15 +850,15 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- Action::TypeResult Type
- = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TypeResult Type
+ = Actions.ActOnTemplateIdType(TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->RAngleLoc);
// Create the new "type" annotation token.
Tok.setKind(tok::annot_typename);
- Tok.setAnnotationValue(Type.isInvalid()? 0 : Type.get());
+ setTypeAnnotation(Tok, Type.isInvalid() ? ParsedType() : Type.get());
if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
Tok.setLocation(SS->getBeginLoc());
// End location stays the same
@@ -887,7 +893,7 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
// 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,
+ ParseOptionalCXXScopeSpecifier(SS, ParsedType(),
/*EnteringContext=*/false);
if (SS.isSet() && Tok.is(tok::kw_template)) {
@@ -906,8 +912,9 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
// template argument.
TemplateTy Template;
if (isEndOfTemplateArgument(Tok) &&
- Actions.ActOnDependentTemplateName(getCurScope(), TemplateLoc, SS, Name,
- /*ObjectType=*/0,
+ Actions.ActOnDependentTemplateName(getCurScope(), TemplateLoc,
+ SS, Name,
+ /*ObjectType=*/ ParsedType(),
/*EnteringContext=*/false,
Template))
return ParsedTemplateArgument(SS, Template, Name.StartLocation);
@@ -921,8 +928,10 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
if (isEndOfTemplateArgument(Tok)) {
bool MemberOfUnknownSpecialization;
- TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS, Name,
- /*ObjectType=*/0,
+ TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
+ /*hasTemplateKeyword=*/false,
+ Name,
+ /*ObjectType=*/ ParsedType(),
/*EnteringContext=*/false,
Template,
MemberOfUnknownSpecialization);
@@ -957,7 +966,8 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
if (TypeArg.isInvalid())
return ParsedTemplateArgument();
- return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type,
+ TypeArg.get().getAsOpaquePtr(),
Loc);
}
@@ -978,7 +988,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
// Parse a non-type template argument.
SourceLocation Loc = Tok.getLocation();
- OwningExprResult ExprArg = ParseConstantExpression();
+ ExprResult ExprArg = ParseConstantExpression();
if (ExprArg.isInvalid() || !ExprArg.get())
return ParsedTemplateArgument();
@@ -1053,12 +1063,15 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
/// 'extern' [opt] 'template' declaration
///
/// Note that the 'extern' is a GNU extension and C++0x feature.
-Parser::DeclPtrTy
-Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- SourceLocation &DeclEnd) {
+Decl *Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation &DeclEnd) {
+ // This isn't really required here.
+ ParsingDeclRAIIObject ParsingTemplateParams(*this);
+
return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
ParsedTemplateInfo(ExternLoc,
TemplateLoc),
+ ParsingTemplateParams,
DeclEnd, AS_none);
}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 5e64e6162b73..c22d99fa9d38 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -14,7 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/ParsedTemplate.h"
using namespace clang;
/// isCXXDeclarationStatement - C++-specialized function that disambiguates
@@ -172,14 +172,6 @@ Parser::TPResult Parser::TryParseSimpleDeclaration() {
/// '{' '}'
///
Parser::TPResult Parser::TryParseInitDeclaratorList() {
- // GCC only examines the first declarator for disambiguation:
- // i.e:
- // int(x), ++x; // GCC regards it as ill-formed declaration.
- //
- // Comeau and MSVC will regard the above statement as correct expression.
- // Clang examines all of the declarators and also regards the above statement
- // as correct expression.
-
while (1) {
// declarator
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
@@ -196,15 +188,22 @@ Parser::TPResult Parser::TryParseInitDeclaratorList() {
ConsumeParen();
if (!SkipUntil(tok::r_paren))
return TPResult::Error();
- } else if (Tok.is(tok::equal)) {
- // MSVC won't examine the rest of declarators if '=' is encountered, it
- // will conclude that it is a declaration.
- // Comeau and Clang will examine the rest of declarators.
- // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed
- // expression.
+ } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
+ // MSVC and g++ won't examine the rest of declarators if '=' is
+ // encountered; they just conclude that we have a declaration.
+ // EDG parses the initializer completely, which is the proper behavior
+ // for this case.
//
- // Parse through the initializer-clause.
- SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/);
+ // At present, Clang follows MSVC and g++, since the parser does not have
+ // the ability to parse an expression fully without recording the
+ // results of that parse.
+ // Also allow 'in' after on objective-c declaration as in:
+ // for (int (^b)(void) in array). Ideally this should be done in the
+ // context of parsing for-init-statement of a foreach statement only. But,
+ // in any other context 'in' is invalid after a declaration and parser
+ // issues the error regardless of outcome of this decision.
+ // FIXME. Change if above assumption does not hold.
+ return TPResult::True();
}
if (Tok.isNot(tok::comma))
@@ -758,6 +757,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
case tok::kw___ptr64:
case tok::kw___forceinline:
return TPResult::True();
+
+ // Borland
+ case tok::kw___pascal:
+ return TPResult::True();
// AltiVec
case tok::kw___vector:
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index ac78f114a967..44bd0fbc0c03 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -13,15 +13,15 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "llvm/Support/raw_ostream.h"
#include "RAIIObjectsForParser.h"
#include "ParsePragma.h"
using namespace clang;
-Parser::Parser(Preprocessor &pp, Action &actions)
+Parser::Parser(Preprocessor &pp, Sema &actions)
: CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
GreaterThanIsOperator(true), ColonIsSacred(false),
TemplateParameterDepth(0) {
@@ -29,10 +29,16 @@ Parser::Parser(Preprocessor &pp, Action &actions)
Actions.CurScope = 0;
NumCachedScopes = 0;
ParenCount = BracketCount = BraceCount = 0;
- ObjCImpDecl = DeclPtrTy();
+ ObjCImpDecl = 0;
// Add #pragma handlers. These are removed and destroyed in the
// destructor.
+ AlignHandler.reset(new PragmaAlignHandler(actions));
+ PP.AddPragmaHandler(AlignHandler.get());
+
+ GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler(actions));
+ PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
+
OptionsHandler.reset(new PragmaOptionsHandler(actions));
PP.AddPragmaHandler(OptionsHandler.get());
@@ -44,6 +50,8 @@ Parser::Parser(Preprocessor &pp, Action &actions)
WeakHandler.reset(new PragmaWeakHandler(actions));
PP.AddPragmaHandler(WeakHandler.get());
+
+ PP.setCodeCompletionHandler(*this);
}
/// If a crash happens while the parser is active, print out a line indicating
@@ -298,6 +306,10 @@ Parser::~Parser() {
delete ScopeCache[i];
// Remove the pragma handlers we installed.
+ PP.RemovePragmaHandler(AlignHandler.get());
+ AlignHandler.reset();
+ PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
+ GCCVisibilityHandler.reset();
PP.RemovePragmaHandler(OptionsHandler.get());
OptionsHandler.reset();
PP.RemovePragmaHandler(PackHandler.get());
@@ -306,18 +318,19 @@ Parser::~Parser() {
UnusedHandler.reset();
PP.RemovePragmaHandler(WeakHandler.get());
WeakHandler.reset();
+ PP.clearCodeCompletionHandler();
}
/// Initialize - Warm up the parser.
///
void Parser::Initialize() {
- // Prime the lexer look-ahead.
- ConsumeToken();
-
// Create the translation unit scope. Install it as the current scope.
assert(getCurScope() == 0 && "A scope is already active?");
EnterScope(Scope::DeclScope);
- Actions.ActOnTranslationUnitScope(Tok.getLocation(), getCurScope());
+ Actions.ActOnTranslationUnitScope(getCurScope());
+
+ // Prime the lexer look-ahead.
+ ConsumeToken();
if (Tok.is(tok::eof) &&
!getLang().CPlusPlus) // Empty source file is an extension in C
@@ -395,10 +408,11 @@ void Parser::ParseTranslationUnit() {
/// ';'
///
/// [C++0x/GNU] 'extern' 'template' declaration
-Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr) {
+Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
+ ParsingDeclSpec *DS) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- DeclPtrTy SingleDecl;
+ Decl *SingleDecl = 0;
switch (Tok.getKind()) {
case tok::semi:
if (!getLang().CPlusPlus0x)
@@ -426,14 +440,14 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
<< Attr.Range;
- OwningExprResult Result(ParseSimpleAsm());
+ ExprResult Result(ParseSimpleAsm());
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
"top-level asm block");
if (Result.isInvalid())
return DeclGroupPtrTy();
- SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), move(Result));
+ SingleDecl = Actions.ActOnFileScopeAsmDecl(Tok.getLocation(), Result.get());
break;
}
case tok::at:
@@ -453,8 +467,8 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
break;
case tok::code_completion:
Actions.CodeCompleteOrdinaryName(getCurScope(),
- ObjCImpDecl? Action::CCC_ObjCImplementation
- : Action::CCC_Namespace);
+ ObjCImpDecl? Sema::PCC_ObjCImplementation
+ : Sema::PCC_Namespace);
ConsumeCodeCompletionToken();
return ParseExternalDeclaration(Attr);
case tok::kw_using:
@@ -468,6 +482,15 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
SourceLocation DeclEnd;
return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
}
+
+ case tok::kw_inline:
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
+ // Inline namespaces. Allowed as an extension even in C++03.
+ SourceLocation DeclEnd;
+ return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+ }
+ goto dont_know;
+
case tok::kw_extern:
if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
// Extern templates
@@ -477,14 +500,16 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
return Actions.ConvertDeclToDeclGroup(
ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd));
}
-
// FIXME: Detect C++ linkage specifications here?
-
- // Fall through to handle other declarations or function definitions.
+ goto dont_know;
default:
+ dont_know:
// We can't tell whether this is a function-definition or declaration yet.
- return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
+ if (DS)
+ return ParseDeclarationOrFunctionDefinition(*DS, Attr.AttrList);
+ else
+ return ParseDeclarationOrFunctionDefinition(Attr.AttrList);
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -551,7 +576,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
ConsumeToken();
- DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
DS.complete(TheDecl);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -575,7 +600,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
Diag(AtLoc, DiagID) << PrevSpec;
- DeclPtrTy TheDecl;
+ Decl *TheDecl = 0;
if (Tok.isObjCAtKeyword(tok::objc_protocol))
TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
else
@@ -589,7 +614,7 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS,
if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
- DeclPtrTy TheDecl = ParseLinkage(DS, Declarator::FileContext);
+ Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
@@ -617,7 +642,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr,
/// [C++] function-definition: [C++ 8.4]
/// decl-specifier-seq[opt] declarator function-try-block
///
-Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
+Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo) {
const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
@@ -653,7 +678,7 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return DeclPtrTy();
+ return 0;
}
// Enter a scope for the function body.
@@ -661,9 +686,9 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
- DeclPtrTy Res = TemplateInfo.TemplateParams?
+ Decl *Res = TemplateInfo.TemplateParams?
Actions.ActOnStartOfFunctionTemplateDef(getCurScope(),
- Action::MultiTemplateParamsArg(Actions,
+ MultiTemplateParamsArg(Actions,
TemplateInfo.TemplateParams->data(),
TemplateInfo.TemplateParams->size()),
D)
@@ -686,7 +711,7 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
// Recover from error.
if (!Tok.is(tok::l_brace)) {
- Actions.ActOnFinishFunctionBody(Res, Action::StmtArg(Actions));
+ Actions.ActOnFinishFunctionBody(Res, 0);
return Res;
}
} else
@@ -752,7 +777,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
}
// Ask the actions module to compute the type for this declarator.
- Action::DeclPtrTy Param =
+ Decl *Param =
Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);
if (Param &&
@@ -819,13 +844,13 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
/// [GNU] asm-string-literal:
/// string-literal
///
-Parser::OwningExprResult Parser::ParseAsmStringLiteral() {
+Parser::ExprResult Parser::ParseAsmStringLiteral() {
if (!isTokenStringLiteral()) {
Diag(Tok, diag::err_expected_string_literal);
return ExprError();
}
- OwningExprResult Res(ParseStringLiteralExpression());
+ ExprResult Res(ParseStringLiteralExpression());
if (Res.isInvalid()) return move(Res);
// TODO: Diagnose: wide string literal in 'asm'
@@ -838,7 +863,7 @@ Parser::OwningExprResult Parser::ParseAsmStringLiteral() {
/// [GNU] simple-asm-expr:
/// 'asm' '(' asm-string-literal ')'
///
-Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
+Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
assert(Tok.is(tok::kw_asm) && "Not an asm!");
SourceLocation Loc = ConsumeToken();
@@ -859,7 +884,7 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
Loc = ConsumeParen();
- OwningExprResult Result(ParseAsmStringLiteral());
+ ExprResult Result(ParseAsmStringLiteral());
if (Result.isInvalid()) {
SkipUntil(tok::r_paren, true, true);
@@ -911,7 +936,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// simple-template-id
SourceLocation TypenameLoc = ConsumeToken();
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false))
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false))
return true;
if (!SS.isSet()) {
Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
@@ -939,7 +964,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
if (Tok.getAnnotationValue())
Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS,
SourceLocation(),
- Tok.getAnnotationValue());
+ getTypeAnnotation(Tok));
else
Ty = true;
} else {
@@ -950,7 +975,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
SourceLocation EndLoc = Tok.getLastLoc();
Tok.setKind(tok::annot_typename);
- Tok.setAnnotationValue(Ty.isInvalid()? 0 : Ty.get());
+ setTypeAnnotation(Tok, Ty.isInvalid() ? ParsedType() : Ty.get());
Tok.setAnnotationEndLoc(EndLoc);
Tok.setLocation(TypenameLoc);
PP.AnnotateCachedTokens(Tok);
@@ -962,17 +987,18 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
CXXScopeSpec SS;
if (getLang().CPlusPlus)
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
return true;
if (Tok.is(tok::identifier)) {
// Determine whether the identifier is a type name.
- if (TypeTy *Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), getCurScope(), &SS)) {
+ if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), getCurScope(),
+ &SS)) {
// This is a typename. Replace the current token in-place with an
// annotation type token.
Tok.setKind(tok::annot_typename);
- Tok.setAnnotationValue(Ty);
+ setTypeAnnotation(Tok, Ty);
Tok.setAnnotationEndLoc(Tok.getLocation());
if (SS.isNotEmpty()) // it was a C++ qualified type name.
Tok.setLocation(SS.getBeginLoc());
@@ -997,9 +1023,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
bool MemberOfUnknownSpecialization;
if (TemplateNameKind TNK
- = Actions.isTemplateName(getCurScope(), SS, TemplateName,
- /*ObjectType=*/0, EnteringContext,
- Template, MemberOfUnknownSpecialization)) {
+ = Actions.isTemplateName(getCurScope(), SS,
+ /*hasTemplateKeyword=*/false, TemplateName,
+ /*ObjectType=*/ ParsedType(),
+ EnteringContext,
+ Template, MemberOfUnknownSpecialization)) {
// Consume the identifier.
ConsumeToken();
if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName)) {
@@ -1066,7 +1094,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
"Cannot be a type or scope token!");
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+ if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext))
return true;
if (SS.isEmpty())
return false;
@@ -1090,17 +1118,17 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
void Parser::CodeCompletionRecovery() {
for (Scope *S = getCurScope(); S; S = S->getParent()) {
if (S->getFlags() & Scope::FnScope) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_RecoveryInFunction);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_RecoveryInFunction);
return;
}
if (S->getFlags() & Scope::ClassScope) {
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_Class);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class);
return;
}
}
- Actions.CodeCompleteOrdinaryName(getCurScope(), Action::CCC_Namespace);
+ Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace);
}
// Anchor the Parser::FieldCallback vtable to this translation unit.
@@ -1109,3 +1137,32 @@ void Parser::CodeCompletionRecovery() {
// performance-sensitive.
void Parser::FieldCallback::_anchor() {
}
+
+// Code-completion pass-through functions
+
+void Parser::CodeCompleteDirective(bool InConditional) {
+ Actions.CodeCompletePreprocessorDirective(InConditional);
+}
+
+void Parser::CodeCompleteInConditionalExclusion() {
+ Actions.CodeCompleteInPreprocessorConditionalExclusion(getCurScope());
+}
+
+void Parser::CodeCompleteMacroName(bool IsDefinition) {
+ Actions.CodeCompletePreprocessorMacroName(IsDefinition);
+}
+
+void Parser::CodeCompletePreprocessorExpression() {
+ Actions.CodeCompletePreprocessorExpression();
+}
+
+void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) {
+ Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo,
+ ArgumentIndex);
+}
+
+void Parser::CodeCompleteNaturalLanguage() {
+ Actions.CodeCompleteNaturalLanguage();
+}
diff --git a/lib/Rewrite/CMakeLists.txt b/lib/Rewrite/CMakeLists.txt
index ce728afea850..ffeb3e66ebcb 100644
--- a/lib/Rewrite/CMakeLists.txt
+++ b/lib/Rewrite/CMakeLists.txt
@@ -13,3 +13,9 @@ add_clang_library(clangRewrite
Rewriter.cpp
TokenRewriter.cpp
)
+
+add_dependencies(clangBasic
+ ClangAttrClasses
+ ClangAttrList
+ ClangDeclNodes
+ ClangStmtNodes)
diff --git a/lib/Rewrite/DeltaTree.cpp b/lib/Rewrite/DeltaTree.cpp
index 35e888bcf595..085dfd89ef15 100644
--- a/lib/Rewrite/DeltaTree.cpp
+++ b/lib/Rewrite/DeltaTree.cpp
@@ -116,7 +116,7 @@ namespace {
void Destroy();
- static inline bool classof(const DeltaTreeNode *) { return true; }
+ //static inline bool classof(const DeltaTreeNode *) { return true; }
};
} // end anonymous namespace
@@ -133,12 +133,6 @@ namespace {
public:
DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
- DeltaTreeInteriorNode(DeltaTreeNode *FirstChild)
- : DeltaTreeNode(false /*nonleaf*/) {
- FullDelta = FirstChild->FullDelta;
- Children[0] = FirstChild;
- }
-
DeltaTreeInteriorNode(const InsertResult &IR)
: DeltaTreeNode(false /*nonleaf*/) {
Children[0] = IR.LHS;
@@ -157,7 +151,7 @@ namespace {
return Children[i];
}
- static inline bool classof(const DeltaTreeInteriorNode *) { return true; }
+ //static inline bool classof(const DeltaTreeInteriorNode *) { return true; }
static inline bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
};
}
diff --git a/lib/Rewrite/FixItRewriter.cpp b/lib/Rewrite/FixItRewriter.cpp
index 29ac7e380bfe..582096978d7b 100644
--- a/lib/Rewrite/FixItRewriter.cpp
+++ b/lib/Rewrite/FixItRewriter.cpp
@@ -27,16 +27,17 @@ using namespace clang;
FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr,
const LangOptions &LangOpts,
- FixItPathRewriter *PathRewriter)
+ FixItOptions *FixItOpts)
: Diags(Diags),
Rewrite(SourceMgr, LangOpts),
- PathRewriter(PathRewriter),
+ FixItOpts(FixItOpts),
NumFailures(0) {
- Client = Diags.getClient();
+ Client = Diags.takeClient();
Diags.setClient(this);
}
FixItRewriter::~FixItRewriter() {
+ Diags.takeClient();
Diags.setClient(Client);
}
@@ -49,16 +50,14 @@ bool FixItRewriter::WriteFixedFile(FileID ID, llvm::raw_ostream &OS) {
}
bool FixItRewriter::WriteFixedFiles() {
- if (NumFailures > 0) {
+ if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) {
Diag(FullSourceLoc(), diag::warn_fixit_no_changes);
return true;
}
for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
- std::string Filename = Entry->getName();
- if (PathRewriter)
- Filename = PathRewriter->RewriteFilename(Filename);
+ std::string Filename = FixItOpts->RewriteFilename(Entry->getName());
std::string Err;
llvm::raw_fd_ostream OS(Filename.c_str(), Err,
llvm::raw_fd_ostream::F_Binary);
@@ -98,12 +97,6 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
CanRewrite = false;
break;
}
-
- if (Hint.InsertionLoc.isValid() &&
- !Rewrite.isRewritable(Hint.InsertionLoc)) {
- CanRewrite = false;
- break;
- }
}
if (!CanRewrite) {
@@ -122,12 +115,6 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
for (unsigned Idx = 0, Last = Info.getNumFixItHints();
Idx < Last; ++Idx) {
const FixItHint &Hint = Info.getFixItHint(Idx);
- if (!Hint.RemoveRange.isValid()) {
- // We're adding code.
- if (Rewrite.InsertTextBefore(Hint.InsertionLoc, Hint.CodeToInsert))
- Failed = true;
- continue;
- }
if (Hint.CodeToInsert.empty()) {
// We're removing code.
@@ -158,10 +145,12 @@ void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
// When producing this diagnostic, we temporarily bypass ourselves,
// clear out any current diagnostic, and let the downstream client
// format the diagnostic.
+ Diags.takeClient();
Diags.setClient(Client);
Diags.Clear();
Diags.Report(Loc, DiagID);
+ Diags.takeClient();
Diags.setClient(this);
}
-FixItPathRewriter::~FixItPathRewriter() {}
+FixItOptions::~FixItOptions() {}
diff --git a/lib/Rewrite/FrontendActions.cpp b/lib/Rewrite/FrontendActions.cpp
index 6da3b4bf519c..977e0cfba6d0 100644
--- a/lib/Rewrite/FrontendActions.cpp
+++ b/lib/Rewrite/FrontendActions.cpp
@@ -42,12 +42,19 @@ ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
return new ASTConsumer();
}
-class FixItActionSuffixInserter : public FixItPathRewriter {
+class FixItRewriteInPlace : public FixItOptions {
+public:
+ std::string RewriteFilename(const std::string &Filename) { return Filename; }
+};
+
+class FixItActionSuffixInserter : public FixItOptions {
std::string NewSuffix;
public:
- explicit FixItActionSuffixInserter(std::string NewSuffix)
- : NewSuffix(NewSuffix) {}
+ FixItActionSuffixInserter(std::string NewSuffix, bool FixWhatYouCan)
+ : NewSuffix(NewSuffix) {
+ this->FixWhatYouCan = FixWhatYouCan;
+ }
std::string RewriteFilename(const std::string &Filename) {
llvm::sys::Path Path(Filename);
@@ -62,12 +69,14 @@ bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,
llvm::StringRef Filename) {
const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts();
if (!FEOpts.FixItSuffix.empty()) {
- PathRewriter.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix));
+ FixItOpts.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix,
+ FEOpts.FixWhatYouCan));
} else {
- PathRewriter.reset();
+ FixItOpts.reset(new FixItRewriteInPlace);
+ FixItOpts->FixWhatYouCan = FEOpts.FixWhatYouCan;
}
Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(),
- CI.getLangOpts(), PathRewriter.get()));
+ CI.getLangOpts(), FixItOpts.get()));
return true;
}
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 5fe064990e96..b461df462e2e 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -486,8 +486,7 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// Temporarily change the diagnostics object so that we ignore any generated
// diagnostics from this pass.
- IgnoringDiagClient TmpDC;
- Diagnostic TmpDiags(&TmpDC);
+ Diagnostic TmpDiags(new IgnoringDiagClient);
// FIXME: This is a huge hack; we reuse the input preprocessor because we want
// its state, but we aren't actually changing it (we hope). This should really
diff --git a/lib/Rewrite/Makefile b/lib/Rewrite/Makefile
index 1c5b8a8117c2..5fef9b2c0d38 100644
--- a/lib/Rewrite/Makefile
+++ b/lib/Rewrite/Makefile
@@ -13,7 +13,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangRewrite
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp
index 489fec9be0e5..578a063614a1 100644
--- a/lib/Rewrite/RewriteObjC.cpp
+++ b/lib/Rewrite/RewriteObjC.cpp
@@ -229,14 +229,6 @@ namespace {
Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
}
- void RemoveText(SourceLocation Loc, unsigned StrLen) {
- // If removal succeeded or warning disabled return with no warning.
- if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning)
- return;
-
- Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
- }
-
void ReplaceText(SourceLocation Start, unsigned OrigLength,
llvm::StringRef Str) {
// If removal succeeded or warning disabled return with no warning.
@@ -248,9 +240,7 @@ namespace {
}
// Syntactic Rewriting.
- void RewritePrologue(SourceLocation Loc);
void RewriteInclude();
- void RewriteTabs();
void RewriteForwardClassDecl(ObjCClassDecl *Dcl);
void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
ObjCImplementationDecl *IMD,
@@ -275,7 +265,6 @@ namespace {
void RewriteTypeOfDecl(VarDecl *VD);
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
bool needToScanForQualifiers(QualType T);
- bool isSuperReceiver(Expr *recExpr);
QualType getSuperStructType();
QualType getConstantStringStructType();
QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
@@ -305,8 +294,6 @@ namespace {
void RewriteSyncReturnStmts(Stmt *S, std::string buf);
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
- Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
- Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S);
Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
SourceLocation OrigEnd);
@@ -343,17 +330,17 @@ namespace {
void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
MethodIterator MethodEnd,
bool IsInstanceMethod,
- const char *prefix,
- const char *ClassName,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
std::string &Result);
void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
- const char *prefix,
- const char *ClassName,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
std::string &Result);
void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
- const char *prefix,
- const char *ClassName,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
std::string &Result);
void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result);
@@ -371,7 +358,6 @@ namespace {
void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
// Block specific rewrite rules.
- void RewriteBlockCall(CallExpr *Exp);
void RewriteBlockPointerDecl(NamedDecl *VD);
void RewriteByRefVar(VarDecl *VD);
std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
@@ -380,18 +366,18 @@ namespace {
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
- const char *funcName, std::string Tag);
+ llvm::StringRef funcName, std::string Tag);
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
- const char *funcName, std::string Tag);
+ llvm::StringRef funcName, std::string Tag);
std::string SynthesizeBlockImpl(BlockExpr *CE,
std::string Tag, std::string Desc);
std::string SynthesizeBlockDescriptor(std::string DescTag,
std::string ImplTag,
- int i, const char *funcName,
+ int i, llvm::StringRef funcName,
unsigned hasCopy);
Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
void SynthesizeBlockLiterals(SourceLocation FunLocStart,
- const char *FunName);
+ llvm::StringRef FunName);
void RewriteRecordBody(RecordDecl *RD);
void CollectBlockDeclRefInfo(BlockExpr *Exp);
@@ -441,7 +427,7 @@ namespace {
const char *&RParen);
void RewriteCastExpr(CStyleCastExpr *CE);
- FunctionDecl *SynthBlockInitFunctionDecl(const char *name);
+ FunctionDecl *SynthBlockInitFunctionDecl(llvm::StringRef name);
Stmt *SynthBlockInitExpr(BlockExpr *Exp,
const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs);
@@ -457,10 +443,10 @@ namespace {
// Helper function: create a CStyleCastExpr with trivial type source info.
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
- CastExpr::CastKind Kind, Expr *E) {
+ CastKind Kind, Expr *E) {
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
- return new (Ctx) CStyleCastExpr(Ty, Kind, E, CXXBaseSpecifierArray(), TInfo,
- SourceLocation(), SourceLocation());
+ return CStyleCastExpr::Create(*Ctx, Ty, Kind, E, 0, TInfo,
+ SourceLocation(), SourceLocation());
}
}
@@ -692,7 +678,7 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
RewriteFunctionDecl(FD);
} else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
// declared in <Foundation/NSString.h>
- if (strcmp(FVD->getNameAsCString(), "_NSConstantStringClassReference") == 0) {
+ if (FVD->getName() == "_NSConstantStringClassReference") {
ConstantStringClassReference = FVD;
return;
}
@@ -747,36 +733,6 @@ void RewriteObjC::RewriteInclude() {
}
}
-void RewriteObjC::RewriteTabs() {
- llvm::StringRef MainBuf = SM->getBufferData(MainFileID);
- const char *MainBufStart = MainBuf.begin();
- const char *MainBufEnd = MainBuf.end();
-
- // Loop over the whole file, looking for tabs.
- for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
- if (*BufPtr != '\t')
- continue;
-
- // Okay, we found a tab. This tab will turn into at least one character,
- // but it depends on which 'virtual column' it is in. Compute that now.
- unsigned VCol = 0;
- while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
- BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
- ++VCol;
-
- // Okay, now that we know the virtual column, we know how many spaces to
- // insert. We assume 8-character tab-stops.
- unsigned Spaces = 8-(VCol & 7);
-
- // Get the location of the tab.
- SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID);
- TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart);
-
- // Rewrite the single tab character into a sequence of spaces.
- ReplaceText(TabLoc, 1, llvm::StringRef(" ", Spaces));
- }
-}
-
static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
ObjCIvarDecl *OID) {
std::string S;
@@ -885,7 +841,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
Setr += "objc_setProperty (self, _cmd, ";
SynthesizeIvarOffsetComputation(ClassDecl, OID, Setr);
Setr += ", (id)";
- Setr += PD->getNameAsCString();
+ Setr += PD->getName();
Setr += ", ";
if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic)
Setr += "0, ";
@@ -898,7 +854,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
}
else {
Setr += getIvarAccessString(ClassDecl, OID) + " = ";
- Setr += PD->getNameAsCString();
+ Setr += PD->getName();
}
Setr += "; }";
InsertText(onePastSemiLoc, Setr);
@@ -1374,7 +1330,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
- CastExpr::CK_Unknown,
+ CK_Unknown,
IV->getBase());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
@@ -1419,7 +1375,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
- CastExpr::CK_Unknown,
+ CK_Unknown,
IV->getBase());
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
@@ -1553,7 +1509,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
SourceLocation startLoc = S->getLocStart();
const char *startBuf = SM->getCharacterData(startLoc);
- const char *elementName;
+ llvm::StringRef elementName;
std::string elementTypeAsString;
std::string buf;
buf = "\n{\n\t";
@@ -1569,13 +1525,13 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
elementTypeAsString = ElementType.getAsString(Context->PrintingPolicy);
buf += elementTypeAsString;
buf += " ";
- elementName = D->getNameAsCString();
+ elementName = D->getName();
buf += elementName;
buf += ";\n\t";
}
else {
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
- elementName = DR->getDecl()->getNameAsCString();
+ elementName = DR->getDecl()->getName();
ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
if (VD->getType()->isObjCQualifiedIdType() ||
VD->getType()->isObjCQualifiedInterfaceType())
@@ -1755,7 +1711,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
std::string syncBuf;
syncBuf += " objc_sync_exit(";
Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CastExpr::CK_Unknown,
+ CK_Unknown,
S->getSynchExpr());
std::string syncExprBufS;
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
@@ -2024,14 +1980,6 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
return 0;
}
-Stmt *RewriteObjC::RewriteObjCCatchStmt(ObjCAtCatchStmt *S) {
- return 0;
-}
-
-Stmt *RewriteObjC::RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S) {
- return 0;
-}
-
// This can't be done with ReplaceStmt(S, ThrowExpr), since
// the throw expression is typically a message expression that's already
// been rewritten! (which implies the SourceLocation's are invalid).
@@ -2106,9 +2054,8 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
// Now, we cast the reference to a pointer to the objc_msgSend type.
QualType pToFunc = Context->getPointerType(msgSendType);
ImplicitCastExpr *ICE =
- new (Context) ImplicitCastExpr(pToFunc, CastExpr::CK_Unknown,
- DRE, CXXBaseSpecifierArray(),
- /*isLvalue=*/false);
+ ImplicitCastExpr::Create(*Context, pToFunc, CK_Unknown,
+ DRE, 0, VK_RValue);
const FunctionType *FT = msgSendType->getAs<FunctionType>();
@@ -2318,14 +2265,14 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() {
SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
SelGetUidIdent, getFuncType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
// declared in <objc/objc.h>
if (FD->getIdentifier() &&
- strcmp(FD->getNameAsCString(), "sel_registerName") == 0) {
+ FD->getName() == "sel_registerName") {
SelGetUidFunctionDecl = FD;
return;
}
@@ -2385,7 +2332,7 @@ void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
QualType Type = proto->getResultType();
std::string FdStr = Type.getAsString(Context->PrintingPolicy);
FdStr += " ";
- FdStr += FD->getNameAsCString();
+ FdStr += FD->getName();
FdStr += "(";
unsigned numArgs = proto->getNumArgs();
for (unsigned i = 0; i < numArgs; i++) {
@@ -2417,8 +2364,8 @@ void RewriteObjC::SynthSuperContructorFunctionDecl() {
SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
msgSendIdent, msgSendType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
@@ -2439,8 +2386,8 @@ void RewriteObjC::SynthMsgSendFunctionDecl() {
MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
msgSendIdent, msgSendType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
@@ -2464,8 +2411,8 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
msgSendIdent, msgSendType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
@@ -2486,8 +2433,8 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() {
MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
msgSendIdent, msgSendType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthMsgSendSuperStretFunctionDecl -
@@ -2513,8 +2460,8 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
msgSendIdent, msgSendType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
@@ -2535,8 +2482,8 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
msgSendIdent, msgSendType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
@@ -2552,8 +2499,8 @@ void RewriteObjC::SynthGetClassFunctionDecl() {
GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
getClassIdent, getClassType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
@@ -2571,8 +2518,8 @@ void RewriteObjC::SynthGetSuperClassFunctionDecl() {
SourceLocation(),
getSuperClassIdent,
getClassType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None,
+ SC_Extern,
+ SC_None,
false);
}
@@ -2589,8 +2536,8 @@ void RewriteObjC::SynthGetMetaClassFunctionDecl() {
GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
getClassIdent, getClassType, 0,
- FunctionDecl::Extern,
- FunctionDecl::None, false);
+ SC_Extern,
+ SC_None, false);
}
Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
@@ -2624,25 +2571,19 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
&Context->Idents.get(S), strType, 0,
- VarDecl::Static, VarDecl::None);
+ SC_Static, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation());
- Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
+ Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()),
SourceLocation());
// cast to NSConstantString *
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
- CastExpr::CK_Unknown, Unop);
+ CK_Unknown, Unop);
ReplaceStmt(Exp, cast);
// delete Exp; leak for now, see RewritePropertySetter() usage for more info.
return cast;
}
-bool RewriteObjC::isSuperReceiver(Expr *recExpr) {
- // check if we are sending a message to 'super'
- if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return false;
- return isa<ObjCSuperExpr>(recExpr);
-}
-
// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
QualType RewriteObjC::getSuperStructType() {
if (!SuperStructDecl) {
@@ -2751,7 +2692,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// set the receiver to self, the first argument to all methods.
InitExprs.push_back(
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CastExpr::CK_Unknown,
+ CK_Unknown,
new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
Context->getObjCIdType(),
SourceLocation()))
@@ -2772,7 +2713,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
- CastExpr::CK_Unknown, Cls);
+ CK_Unknown, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
@@ -2784,7 +2725,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back( // set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context,
Context->getObjCIdType(),
- CastExpr::CK_Unknown, Cls));
+ CK_Unknown, Cls));
// struct objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
@@ -2803,12 +2744,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// we need the cast below. For example:
// (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
//
- SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+ SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
SourceLocation());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
- CastExpr::CK_Unknown, SuperRep);
+ CK_Unknown, SuperRep);
} else {
// (struct objc_super) { <exprs from above> }
InitListExpr *ILE =
@@ -2820,7 +2761,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
superType, ILE, false);
// struct objc_super *
- SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+ SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
SourceLocation());
}
@@ -2857,7 +2798,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back(
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CastExpr::CK_Unknown,
+ CK_Unknown,
new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
Context->getObjCIdType(),
SourceLocation()))
@@ -2877,7 +2818,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
- CastExpr::CK_Unknown, Cls);
+ CK_Unknown, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
@@ -2889,7 +2830,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
InitExprs.push_back(
// set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CastExpr::CK_Unknown, Cls));
+ CK_Unknown, Cls));
// struct objc_super
QualType superType = getSuperStructType();
Expr *SuperRep;
@@ -2908,12 +2849,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// we need the cast below. For example:
// (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
//
- SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+ SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf,
Context->getPointerType(SuperRep->getType()),
SourceLocation());
SuperRep = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(superType),
- CastExpr::CK_Unknown, SuperRep);
+ CK_Unknown, SuperRep);
} else {
// (struct objc_super) { <exprs from above> }
InitListExpr *ILE =
@@ -2936,7 +2877,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
recExpr = CE->getSubExpr();
recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CastExpr::CK_Unknown, recExpr);
+ CK_Unknown, recExpr);
MsgExprs.push_back(recExpr);
break;
}
@@ -2966,7 +2907,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
: ICE->getType();
// Make sure we convert "type (^)(...)" to "type (*)(...)".
(void)convertBlockPointerToFunctionPointer(type);
- userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown,
+ userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK_Unknown,
userExpr);
}
// Make id<P...> cast into an 'id' cast.
@@ -2975,7 +2916,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
userExpr = CE->getSubExpr();
userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
- CastExpr::CK_Unknown, userExpr);
+ CK_Unknown, userExpr);
}
}
MsgExprs.push_back(userExpr);
@@ -3025,7 +2966,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// xx.m:13: note: if this code is reached, the program will abort
cast = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidTy),
- CastExpr::CK_Unknown, DRE);
+ CK_Unknown, DRE);
// Now do the "normal" pointer to function cast.
QualType castType = Context->getFunctionType(returnType,
@@ -3035,7 +2976,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
false, false, 0, 0,
FunctionType::ExtInfo());
castType = Context->getPointerType(castType);
- cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
+ cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_Unknown,
cast);
// Don't forget the parens to enforce the proper binding.
@@ -3058,7 +2999,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// Need to cast objc_msgSend_stret to "void *" (see above comment).
cast = NoTypeInfoCStyleCastExpr(Context,
Context->getPointerType(Context->VoidTy),
- CastExpr::CK_Unknown, STDRE);
+ CK_Unknown, STDRE);
// Now do the "normal" pointer to function cast.
castType = Context->getFunctionType(returnType,
&ArgTypes[0], ArgTypes.size(),
@@ -3066,7 +3007,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
false, false, 0, 0,
FunctionType::ExtInfo());
castType = Context->getPointerType(castType);
- cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
+ cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_Unknown,
cast);
// Don't forget the parens to enforce the proper binding.
@@ -3088,19 +3029,22 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
// is needed to decide what to do.
unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
- IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8),
- Context->IntTy,
- SourceLocation());
+ IntegerLiteral *limit = IntegerLiteral::Create(*Context,
+ llvm::APInt(IntSize, 8),
+ Context->IntTy,
+ SourceLocation());
BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit,
- BinaryOperator::LE,
+ BO_LE,
Context->IntTy,
SourceLocation());
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
ConditionalOperator *CondExpr =
new (Context) ConditionalOperator(lessThanExpr,
SourceLocation(), CE,
- SourceLocation(), STCE, returnType);
- ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
+ SourceLocation(), STCE, (Expr*)0,
+ returnType);
+ ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ CondExpr);
}
// delete Exp; leak for now, see RewritePropertySetter() usage for more info.
return ReplacingStmt;
@@ -3139,13 +3083,13 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
IdentifierInfo *ID = &Context->Idents.get(Name);
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
ID, getProtocolType(), 0,
- VarDecl::Extern, VarDecl::None);
+ SC_Extern, SC_None);
DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation());
- Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
+ Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf,
Context->getPointerType(DRE->getType()),
SourceLocation());
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
- CastExpr::CK_Unknown,
+ CK_Unknown,
DerefExpr);
ReplaceStmt(Exp, castExpr);
ProtocolExprDecls.insert(Exp->getProtocol());
@@ -3185,7 +3129,7 @@ bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result) {
assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
- assert(CDecl->getNameAsCString() &&
+ assert(CDecl->getName() != "" &&
"Name missing in SynthesizeObjCInternalStruct");
// Do not synthesize more than once.
if (ObjCSynthesizedStructs.count(CDecl))
@@ -3318,8 +3262,8 @@ template<typename MethodIterator>
void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
MethodIterator MethodEnd,
bool IsInstanceMethod,
- const char *prefix,
- const char *ClassName,
+ llvm::StringRef prefix,
+ llvm::StringRef ClassName,
std::string &Result) {
if (MethodBegin == MethodEnd) return;
@@ -3388,8 +3332,8 @@ void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
void RewriteObjC::
-RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix,
- const char *ClassName, std::string &Result) {
+RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, llvm::StringRef prefix,
+ llvm::StringRef ClassName, std::string &Result) {
static bool objc_protocol_methods = false;
// Output struct protocol_methods holder of method selector and type.
@@ -3435,7 +3379,7 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix,
Result += "\t ,{{(struct objc_selector *)\"";
else
Result += "\t ,{(struct objc_selector *)\"";
- Result += (*I)->getSelector().getAsString().c_str();
+ Result += (*I)->getSelector().getAsString();
std::string MethodTypeString;
Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
Result += "\", \"";
@@ -3473,7 +3417,7 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix,
Result += "\t ,{{(struct objc_selector *)\"";
else
Result += "\t ,{(struct objc_selector *)\"";
- Result += (*I)->getSelector().getAsString().c_str();
+ Result += (*I)->getSelector().getAsString();
std::string MethodTypeString;
Context->getObjCEncodingForMethodDecl((*I), MethodTypeString);
Result += "\", \"";
@@ -3536,7 +3480,7 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix,
void RewriteObjC::
RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols,
- const char *prefix, const char *ClassName,
+ llvm::StringRef prefix, llvm::StringRef ClassName,
std::string &Result) {
if (Protocols.empty()) return;
@@ -3629,7 +3573,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
// Null CDecl is case of a category implementation with no category interface
if (CDecl)
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
- FullCategoryName.c_str(), Result);
+ FullCategoryName, Result);
/* struct _objc_category {
char *category_name;
char *class_name;
@@ -3827,15 +3771,15 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
InstanceMethods.push_back(Setter);
}
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
- true, "", IDecl->getNameAsCString(), Result);
+ true, "", IDecl->getName(), Result);
// Build _objc_method_list for class's class methods if needed
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
- false, "", IDecl->getNameAsCString(), Result);
+ false, "", IDecl->getName(), Result);
// Protocols referenced in class declaration?
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
- "CLASS", CDecl->getNameAsCString(), Result);
+ "CLASS", CDecl->getName(), Result);
// Declaration of class/meta-class metadata
/* struct _objc_class {
@@ -4101,13 +4045,13 @@ static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
}
std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
- const char *funcName,
+ llvm::StringRef funcName,
std::string Tag) {
const FunctionType *AFT = CE->getFunctionType();
QualType RT = AFT->getResultType();
std::string StructRef = "struct " + Tag;
std::string S = "static " + RT.getAsString(Context->PrintingPolicy) + " __" +
- funcName + "_" + "block_func_" + utostr(i);
+ funcName.str() + "_" + "block_func_" + utostr(i);
BlockDecl *BD = CE->getBlockDecl();
@@ -4195,7 +4139,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
}
std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
- const char *funcName,
+ llvm::StringRef funcName,
std::string Tag) {
std::string StructRef = "struct " + Tag;
std::string S = "static void __";
@@ -4309,37 +4253,48 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
S += FieldName + "; // by ref\n";
}
// Finish writing the constructor.
- Constructor += ", int flags=0) {\n";
- if (GlobalVarDecl)
- Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
- else
- Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
- Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
-
- Constructor += " Desc = desc;\n";
-
+ Constructor += ", int flags=0)";
// Initialize all "by copy" arguments.
+ bool firsTime = true;
for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(),
E = BlockByCopyDecls.end(); I != E; ++I) {
std::string Name = (*I)->getNameAsString();
- Constructor += " ";
- if (isTopLevelBlockPointerType((*I)->getType()))
- Constructor += Name + " = (struct __block_impl *)_";
- else
- Constructor += Name + " = _";
- Constructor += Name + ";\n";
+ if (firsTime) {
+ Constructor += " : ";
+ firsTime = false;
+ }
+ else
+ Constructor += ", ";
+ if (isTopLevelBlockPointerType((*I)->getType()))
+ Constructor += Name + "((struct __block_impl *)_" + Name + ")";
+ else
+ Constructor += Name + "(_" + Name + ")";
}
// Initialize all "by ref" arguments.
for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(),
E = BlockByRefDecls.end(); I != E; ++I) {
std::string Name = (*I)->getNameAsString();
- Constructor += " ";
+ if (firsTime) {
+ Constructor += " : ";
+ firsTime = false;
+ }
+ else
+ Constructor += ", ";
if (isTopLevelBlockPointerType((*I)->getType()))
- Constructor += Name + " = (struct __block_impl *)_";
+ Constructor += Name + "((struct __block_impl *)_"
+ + Name + "->__forwarding)";
else
- Constructor += Name + " = _";
- Constructor += Name + "->__forwarding;\n";
+ Constructor += Name + "(_" + Name + "->__forwarding)";
}
+
+ Constructor += " {\n";
+ if (GlobalVarDecl)
+ Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
+ else
+ Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
+ Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
+
+ Constructor += " Desc = desc;\n";
} else {
// Finish writing the constructor.
Constructor += ", int flags=0) {\n";
@@ -4359,7 +4314,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
std::string ImplTag, int i,
- const char *FunName,
+ llvm::StringRef FunName,
unsigned hasCopy) {
std::string S = "\nstatic struct " + DescTag;
@@ -4378,21 +4333,21 @@ std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
S += DescTag + "_DATA = { 0, sizeof(struct ";
S += ImplTag + ")";
if (hasCopy) {
- S += ", __" + std::string(FunName) + "_block_copy_" + utostr(i);
- S += ", __" + std::string(FunName) + "_block_dispose_" + utostr(i);
+ S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
+ S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
}
S += "};\n";
return S;
}
void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
- const char *FunName) {
+ llvm::StringRef FunName) {
// Insert declaration for the function in which block literal is used.
if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
bool RewriteSC = (GlobalVarDecl &&
!Blocks.empty() &&
- GlobalVarDecl->getStorageClass() == VarDecl::Static &&
+ GlobalVarDecl->getStorageClass() == SC_Static &&
GlobalVarDecl->getType().getCVRQualifiers());
if (RewriteSC) {
std::string SC(" void __");
@@ -4420,8 +4375,8 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
}
}
- std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
- std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i);
+ std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
+ std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
@@ -4450,7 +4405,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
// Must insert any 'const/volatile/static here. Since it has been
// removed as result of rewriting of block literals.
std::string SC;
- if (GlobalVarDecl->getStorageClass() == VarDecl::Static)
+ if (GlobalVarDecl->getStorageClass() == SC_Static)
SC = "static ";
if (GlobalVarDecl->getType().isConstQualified())
SC += "const ";
@@ -4469,7 +4424,7 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
- const char *FuncName = FD->getNameAsCString();
+ llvm::StringRef FuncName = FD->getName();
SynthesizeBlockLiterals(FunLocStart, FuncName);
}
@@ -4477,7 +4432,7 @@ void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
static void BuildUniqueMethodName(std::string &Name,
ObjCMethodDecl *MD) {
ObjCInterfaceDecl *IFace = MD->getClassInterface();
- Name = IFace->getNameAsCString();
+ Name = IFace->getName();
Name += "__" + MD->getSelector().getAsString();
// Convert colons to underscores.
std::string::size_type loc = 0;
@@ -4491,7 +4446,7 @@ void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
SourceLocation FunLocStart = MD->getLocStart();
std::string FuncName;
BuildUniqueMethodName(FuncName, MD);
- SynthesizeBlockLiterals(FunLocStart, FuncName.c_str());
+ SynthesizeBlockLiterals(FunLocStart, FuncName);
}
void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
@@ -4613,7 +4568,8 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
ConditionalOperator *CondExpr =
new (Context) ConditionalOperator(CONDExp,
SourceLocation(), cast<Expr>(LHSStmt),
- SourceLocation(), cast<Expr>(RHSStmt),
+ SourceLocation(), cast<Expr>(RHSStmt),
+ (Expr*)0,
Exp->getType());
return CondExpr;
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
@@ -4655,7 +4611,7 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
- CastExpr::CK_Unknown,
+ CK_Unknown,
const_cast<Expr*>(BlockExp));
// Don't forget the parens to enforce the proper binding.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
@@ -4669,7 +4625,7 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
FD->getType());
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
- CastExpr::CK_Unknown, ME);
+ CK_Unknown, ME);
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
llvm::SmallVector<Expr*, 8> BlkExprs;
@@ -4686,11 +4642,6 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
return CE;
}
-void RewriteObjC::RewriteBlockCall(CallExpr *Exp) {
- Stmt *BlockCall = SynthesizeBlockCall(Exp, Exp->getCallee());
- ReplaceStmt(Exp, BlockCall);
-}
-
// We need to return the rewritten expression to handle cases where the
// BlockDeclRefExpr is embedded in another expression being rewritten.
// For example:
@@ -4724,7 +4675,7 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) {
FD, SourceLocation(),
FD->getType());
- const char *Name = VD->getNameAsCString();
+ llvm::StringRef Name = VD->getName();
FD = FieldDecl::Create(*Context, 0, SourceLocation(),
&Context->Idents.get(Name),
Context->VoidPtrTy, 0,
@@ -4749,7 +4700,7 @@ Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
if (!ImportedLocalExternalDecls.count(Var))
return DRE;
- Expr *Exp = new (Context) UnaryOperator(DRE, UnaryOperator::Deref,
+ Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref,
DRE->getType(), DRE->getLocation());
// Need parens to enforce precedence.
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
@@ -5098,7 +5049,6 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
startLoc = E->getLocStart();
startLoc = SM->getInstantiationLoc(startLoc);
endBuf = SM->getCharacterData(startLoc);
-
ByrefType += " " + Name;
ByrefType += " = {(void*)";
ByrefType += utostr(isa);
@@ -5125,11 +5075,11 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
//
// double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
//
- const char *startBuf = SM->getCharacterData(startLoc);
- const char *semiBuf = strchr(startBuf, ';');
+ const char *startInitializerBuf = SM->getCharacterData(startLoc);
+ const char *semiBuf = strchr(startInitializerBuf, ';');
assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
SourceLocation semiLoc =
- startLoc.getFileLocWithOffset(semiBuf-startBuf);
+ startLoc.getFileLocWithOffset(semiBuf-startInitializerBuf);
InsertText(semiLoc, "}");
}
@@ -5165,12 +5115,12 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
}
}
-FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(const char *name) {
+FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(llvm::StringRef name) {
IdentifierInfo *ID = &Context->Idents.get(name);
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
return FunctionDecl::Create(*Context, TUDecl,SourceLocation(),
- ID, FType, 0, FunctionDecl::Extern,
- FunctionDecl::None, false, false);
+ ID, FType, 0, SC_Extern,
+ SC_None, false, false);
}
Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
@@ -5232,17 +5182,17 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
Expr *NewRep;
// Simulate a contructor call...
- FD = SynthBlockInitFunctionDecl(Tag.c_str());
+ FD = SynthBlockInitFunctionDecl(Tag);
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, SourceLocation());
llvm::SmallVector<Expr*, 4> InitExprs;
// Initialize the block function.
- FD = SynthBlockInitFunctionDecl(Func.c_str());
+ FD = SynthBlockInitFunctionDecl(Func);
DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(),
SourceLocation());
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg);
+ CK_Unknown, Arg);
InitExprs.push_back(castExpr);
// Initialize the block descriptor.
@@ -5251,11 +5201,11 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
&Context->Idents.get(DescData.c_str()),
Context->VoidPtrTy, 0,
- VarDecl::Static, VarDecl::None);
+ SC_Static, SC_None);
UnaryOperator *DescRefExpr = new (Context) UnaryOperator(
new (Context) DeclRefExpr(NewVD,
Context->VoidPtrTy, SourceLocation()),
- UnaryOperator::AddrOf,
+ UO_AddrOf,
Context->getPointerType(Context->VoidPtrTy),
SourceLocation());
InitExprs.push_back(DescRefExpr);
@@ -5268,26 +5218,26 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
E = BlockByCopyDecls.end(); I != E; ++I) {
if (isObjCType((*I)->getType())) {
// FIXME: Conform to ABI ([[obj retain] autorelease]).
- FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
- Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, QT,
+ Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT,
SourceLocation());
}
} else if (isTopLevelBlockPointerType((*I)->getType())) {
- FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
- CastExpr::CK_Unknown, Arg);
+ CK_Unknown, Arg);
} else {
- FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
if (HasLocalVariableExternalStorage(*I)) {
QualType QT = (*I)->getType();
QT = Context->getPointerType(QT);
- Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, QT,
+ Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT,
SourceLocation());
}
@@ -5308,12 +5258,12 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
- FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
+ FD = SynthBlockInitFunctionDecl((*I)->getName());
Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
- Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf,
+ Exp = new (Context) UnaryOperator(Exp, UO_AddrOf,
Context->getPointerType(Exp->getType()),
SourceLocation());
- Exp = NoTypeInfoCStyleCastExpr(Context, castT, CastExpr::CK_Unknown, Exp);
+ Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_Unknown, Exp);
InitExprs.push_back(Exp);
}
}
@@ -5322,16 +5272,16 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
unsigned IntSize =
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
- Expr *FlagExp = new (Context) IntegerLiteral(llvm::APInt(IntSize, flag),
- Context->IntTy, SourceLocation());
+ Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
+ Context->IntTy, SourceLocation());
InitExprs.push_back(FlagExp);
}
NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
FType, SourceLocation());
- NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf,
+ NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
Context->getPointerType(NewRep->getType()),
SourceLocation());
- NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CastExpr::CK_Unknown,
+ NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_Unknown,
NewRep);
BlockDeclRefs.clear();
BlockByRefDecls.clear();
@@ -5609,7 +5559,9 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
}
#if 0
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
- CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
+ CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
+ ICE->getSubExpr(),
+ SourceLocation());
// Get the new text.
std::string SStr;
llvm::raw_string_ostream Buf(SStr);
@@ -5722,7 +5674,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) {
PropParentMap = 0;
}
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(),
- VD->getNameAsCString());
+ VD->getName());
GlobalVarDecl = 0;
// This is needed for blocks.
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 448d16116a39..cfebed6a05b2 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -13,9 +13,11 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "AnalysisBasedWarnings.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtObjC.h"
@@ -197,6 +199,8 @@ static ControlFlowKind CheckFallThrough(AnalysisContext &AC) {
return AlwaysFallThrough;
}
+namespace {
+
struct CheckFallThroughDiagnostics {
unsigned diag_MaybeFallThrough_HasNoReturn;
unsigned diag_MaybeFallThrough_ReturnsNonVoid;
@@ -266,6 +270,8 @@ struct CheckFallThroughDiagnostics {
}
};
+}
+
/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
/// function that should return a value. Check that we don't fall off the end
/// of a noreturn function. We assume that functions and blocks not marked
@@ -375,19 +381,16 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
S.SourceMgr.isInSystemHeader(D->getLocation()))
return;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // For function templates, class templates and member function templates
- // we'll do the analysis at instantiation time.
- if (FD->isDependentContext())
- return;
- }
+ // For code in dependent contexts, we'll do this at instantiation time.
+ if (cast<DeclContext>(D)->isDependentContext())
+ return;
const Stmt *Body = D->getBody();
assert(Body);
// Don't generate EH edges for CallExprs as we'd like to avoid the n^2
// explosion for destrutors that can result and the compile time hit.
- AnalysisContext AC(D, false);
+ AnalysisContext AC(D, 0, false);
// Warning: check missing 'return'
if (P.enableCheckFallThrough) {
@@ -401,3 +404,21 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
if (P.enableCheckUnreachable)
CheckUnreachable(S, AC);
}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const BlockExpr *E) {
+ return IssueWarnings(P, E->getBlockDecl(), E->getType());
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const ObjCMethodDecl *D) {
+ return IssueWarnings(P, D, QualType());
+}
+
+void clang::sema::
+AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
+ const FunctionDecl *D) {
+ return IssueWarnings(P, D, QualType());
+}
diff --git a/lib/Parse/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index 98d5d07e151e..8ccb2ca586eb 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/AttributeList.h"
+#include "clang/Sema/AttributeList.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -19,7 +19,7 @@ using namespace clang;
AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
IdentifierInfo *sName, SourceLocation sLoc,
IdentifierInfo *pName, SourceLocation pLoc,
- ActionBase::ExprTy **ExprList, unsigned numArgs,
+ Expr **ExprList, unsigned numArgs,
AttributeList *n, bool declspec, bool cxx0x)
: AttrName(aName), AttrLoc(aLoc), ScopeName(sName), ScopeLoc(sLoc),
ParmName(pName), ParmLoc(pLoc), NumArgs(numArgs), Next(n),
@@ -28,7 +28,7 @@ AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
if (numArgs == 0)
Args = 0;
else {
- Args = new ActionBase::ExprTy*[numArgs];
+ Args = new Expr*[numArgs];
memcpy(Args, ExprList, numArgs*sizeof(Args[0]));
}
}
@@ -100,6 +100,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("format_arg", AT_format_arg)
.Case("gnu_inline", AT_gnu_inline)
.Case("weak_import", AT_weak_import)
+ .Case("vecreturn", AT_vecreturn)
.Case("vector_size", AT_vector_size)
.Case("constructor", AT_constructor)
.Case("unavailable", AT_unavailable)
@@ -118,13 +119,18 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("ns_returns_retained", AT_ns_returns_retained)
.Case("cf_returns_not_retained", AT_cf_returns_not_retained)
.Case("cf_returns_retained", AT_cf_returns_retained)
+ .Case("ownership_returns", AT_ownership_returns)
+ .Case("ownership_holds", AT_ownership_holds)
+ .Case("ownership_takes", AT_ownership_takes)
.Case("reqd_work_group_size", AT_reqd_wg_size)
.Case("init_priority", AT_init_priority)
.Case("no_instrument_function", AT_no_instrument_function)
.Case("thiscall", AT_thiscall)
+ .Case("pascal", AT_pascal)
.Case("__cdecl", AT_cdecl)
.Case("__stdcall", AT_stdcall)
.Case("__fastcall", AT_fastcall)
.Case("__thiscall", AT_thiscall)
+ .Case("__pascal", AT_pascal)
.Default(UnknownAttribute);
}
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 70b4792f3ba5..e65bb227f159 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -2,10 +2,11 @@ set(LLVM_NO_RTTI 1)
add_clang_library(clangSema
AnalysisBasedWarnings.cpp
+ AttributeList.cpp
CodeCompleteConsumer.cpp
+ DeclSpec.cpp
IdentifierResolver.cpp
JumpDiagnostics.cpp
- ParseAST.cpp
Sema.cpp
SemaAccess.cpp
SemaAttr.cpp
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 6cefc61f6640..58a1627b478a 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -11,11 +11,13 @@
//
//===----------------------------------------------------------------------===//
#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Sema.h"
#include "clang/AST/DeclCXX.h"
-#include "clang/Parse/Scope.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/Lex/Preprocessor.h"
#include "clang-c/Index.h"
-#include "Sema.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -234,8 +236,7 @@ std::string CodeCompletionString::getAsString() const {
default: OS << C->Text; break;
}
}
- OS.flush();
- return Result;
+ return OS.str();
}
const char *CodeCompletionString::getTypedText() const {
@@ -246,8 +247,10 @@ const char *CodeCompletionString::getTypedText() const {
return 0;
}
-CodeCompletionString *CodeCompletionString::Clone() const {
- CodeCompletionString *Result = new CodeCompletionString;
+CodeCompletionString *
+CodeCompletionString::Clone(CodeCompletionString *Result) const {
+ if (!Result)
+ Result = new CodeCompletionString;
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
Result->AddChunk(C->Clone());
return Result;
@@ -373,19 +376,19 @@ bool CodeCompletionString::Deserialize(const char *&Str, const char *StrEnd) {
return true;
}
-void CodeCompleteConsumer::Result::Destroy() {
+void CodeCompletionResult::Destroy() {
if (Kind == RK_Pattern) {
delete Pattern;
Pattern = 0;
}
}
-unsigned CodeCompleteConsumer::Result::getPriorityFromDecl(NamedDecl *ND) {
+unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
if (!ND)
return CCP_Unlikely;
// Context-based decisions.
- DeclContext *DC = ND->getDeclContext()->getLookupContext();
+ DeclContext *DC = ND->getDeclContext()->getRedeclContext();
if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC))
return CCP_LocalDeclaration;
if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
@@ -437,13 +440,16 @@ CodeCompleteConsumer::~CodeCompleteConsumer() { }
void
PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
- Result *Results,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults) {
+ std::stable_sort(Results, Results + NumResults);
+
// Print the results.
for (unsigned I = 0; I != NumResults; ++I) {
OS << "COMPLETION: ";
switch (Results[I].Kind) {
- case Result::RK_Declaration:
+ case CodeCompletionResult::RK_Declaration:
OS << Results[I].Declaration;
if (Results[I].Hidden)
OS << " (Hidden)";
@@ -456,11 +462,11 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << '\n';
break;
- case Result::RK_Keyword:
+ case CodeCompletionResult::RK_Keyword:
OS << Results[I].Keyword << '\n';
break;
- case Result::RK_Macro: {
+ case CodeCompletionResult::RK_Macro: {
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef)) {
@@ -471,7 +477,7 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
break;
}
- case Result::RK_Pattern: {
+ case CodeCompletionResult::RK_Pattern: {
OS << "Pattern : "
<< Results[I].Pattern->getAsString() << '\n';
break;
@@ -494,116 +500,104 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
}
}
+void CodeCompletionResult::computeCursorKindAndAvailability() {
+ switch (Kind) {
+ case RK_Declaration:
+ // Set the availability based on attributes.
+ Availability = CXAvailability_Available;
+ if (Declaration->getAttr<UnavailableAttr>())
+ Availability = CXAvailability_NotAvailable;
+ else if (Declaration->getAttr<DeprecatedAttr>())
+ Availability = CXAvailability_Deprecated;
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
+ if (Function->isDeleted())
+ Availability = CXAvailability_NotAvailable;
+
+ CursorKind = getCursorKindForDecl(Declaration);
+ if (CursorKind == CXCursor_UnexposedDecl)
+ CursorKind = CXCursor_NotImplemented;
+ break;
+
+ case RK_Macro:
+ Availability = CXAvailability_Available;
+ CursorKind = CXCursor_MacroDefinition;
+ break;
+
+ case RK_Keyword:
+ Availability = CXAvailability_Available;
+ CursorKind = CXCursor_NotImplemented;
+ break;
+
+ case RK_Pattern:
+ // Do nothing: Patterns can come with cursor kinds!
+ break;
+ }
+}
+
+/// \brief Retrieve the name that should be used to order a result.
+///
+/// If the name needs to be constructed as a string, that string will be
+/// saved into Saved and the returned StringRef will refer to it.
+static llvm::StringRef getOrderedName(const CodeCompletionResult &R,
+ std::string &Saved) {
+ switch (R.Kind) {
+ case CodeCompletionResult::RK_Keyword:
+ return R.Keyword;
+
+ case CodeCompletionResult::RK_Pattern:
+ return R.Pattern->getTypedText();
+
+ case CodeCompletionResult::RK_Macro:
+ return R.Macro->getName();
+
+ case CodeCompletionResult::RK_Declaration:
+ // Handle declarations below.
+ break;
+ }
+
+ DeclarationName Name = R.Declaration->getDeclName();
+
+ // If the name is a simple identifier (by far the common case), or a
+ // zero-argument selector, just return a reference to that identifier.
+ if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
+ return Id->getName();
+ if (Name.isObjCZeroArgSelector())
+ if (IdentifierInfo *Id
+ = Name.getObjCSelector().getIdentifierInfoForSlot(0))
+ return Id->getName();
+
+ Saved = Name.getAsString();
+ return Saved;
+}
+
+bool clang::operator<(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ std::string XSaved, YSaved;
+ llvm::StringRef XStr = getOrderedName(X, XSaved);
+ llvm::StringRef YStr = getOrderedName(Y, YSaved);
+ int cmp = XStr.compare_lower(YStr);
+ if (cmp)
+ return cmp < 0;
+
+ // If case-insensitive comparison fails, try case-sensitive comparison.
+ cmp = XStr.compare(YStr);
+ if (cmp)
+ return cmp < 0;
+
+ return false;
+}
+
void
CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
- Result *Results,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
unsigned NumResults) {
// Print the results.
for (unsigned I = 0; I != NumResults; ++I) {
- CXCursorKind Kind = CXCursor_NotImplemented;
-
- switch (Results[I].Kind) {
- case Result::RK_Declaration:
- switch (Results[I].Declaration->getKind()) {
- case Decl::Record:
- case Decl::CXXRecord:
- case Decl::ClassTemplateSpecialization: {
- RecordDecl *Record = cast<RecordDecl>(Results[I].Declaration);
- if (Record->isStruct())
- Kind = CXCursor_StructDecl;
- else if (Record->isUnion())
- Kind = CXCursor_UnionDecl;
- else
- Kind = CXCursor_ClassDecl;
- break;
- }
-
- case Decl::ObjCMethod: {
- ObjCMethodDecl *Method = cast<ObjCMethodDecl>(Results[I].Declaration);
- if (Method->isInstanceMethod())
- Kind = CXCursor_ObjCInstanceMethodDecl;
- else
- Kind = CXCursor_ObjCClassMethodDecl;
- break;
- }
-
- case Decl::Typedef:
- Kind = CXCursor_TypedefDecl;
- break;
-
- case Decl::Enum:
- Kind = CXCursor_EnumDecl;
- break;
-
- case Decl::Field:
- Kind = CXCursor_FieldDecl;
- break;
-
- case Decl::EnumConstant:
- Kind = CXCursor_EnumConstantDecl;
- break;
-
- case Decl::Function:
- case Decl::CXXMethod:
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- case Decl::CXXConversion:
- Kind = CXCursor_FunctionDecl;
- break;
-
- case Decl::Var:
- Kind = CXCursor_VarDecl;
- break;
-
- case Decl::ParmVar:
- Kind = CXCursor_ParmDecl;
- break;
-
- case Decl::ObjCInterface:
- Kind = CXCursor_ObjCInterfaceDecl;
- break;
-
- case Decl::ObjCCategory:
- Kind = CXCursor_ObjCCategoryDecl;
- break;
-
- case Decl::ObjCProtocol:
- Kind = CXCursor_ObjCProtocolDecl;
- break;
-
- case Decl::ObjCProperty:
- Kind = CXCursor_ObjCPropertyDecl;
- break;
-
- case Decl::ObjCIvar:
- Kind = CXCursor_ObjCIvarDecl;
- break;
-
- case Decl::ObjCImplementation:
- Kind = CXCursor_ObjCImplementationDecl;
- break;
-
- case Decl::ObjCCategoryImpl:
- Kind = CXCursor_ObjCCategoryImplDecl;
- break;
-
- default:
- break;
- }
- break;
-
- case Result::RK_Macro:
- Kind = CXCursor_MacroDefinition;
- break;
-
- case Result::RK_Keyword:
- case Result::RK_Pattern:
- Kind = CXCursor_NotImplemented;
- break;
- }
-
- WriteUnsigned(OS, Kind);
+ WriteUnsigned(OS, Results[I].CursorKind);
WriteUnsigned(OS, Results[I].Priority);
+ WriteUnsigned(OS, Results[I].Availability);
CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
assert(CCS && "No code-completion string?");
CCS->Serialize(OS);
@@ -618,7 +612,8 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
unsigned NumCandidates) {
for (unsigned I = 0; I != NumCandidates; ++I) {
WriteUnsigned(OS, CXCursor_NotImplemented);
- WriteUnsigned(OS, /*Priority=*/0);
+ WriteUnsigned(OS, /*Priority=*/I);
+ WriteUnsigned(OS, /*Availability=*/CXAvailability_Available);
CodeCompletionString *CCS
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
assert(CCS && "No code-completion string?");
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index d2cd74418af0..b46e8af9db86 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -11,9 +11,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/ParseDiagnostic.h"
-#include "clang/Parse/Template.h"
+#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
@@ -54,7 +54,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
bool hasExceptionSpec,
SourceLocation ThrowLoc,
bool hasAnyExceptionSpec,
- ActionBase::TypeTy **Exceptions,
+ ParsedType *Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
SourceLocation LPLoc,
@@ -219,8 +219,15 @@ const char *DeclSpec::getSpecifierName(TQ T) {
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID) {
- if (StorageClassSpec != SCS_unspecified)
- return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
+ if (StorageClassSpec != SCS_unspecified) {
+ // Changing storage class is allowed only if the previous one
+ // was the 'extern' that is part of a linkage specification and
+ // the new storage class is 'typedef'.
+ if (!(SCS_extern_in_linkage_spec &&
+ StorageClassSpec == SCS_extern &&
+ S == SCS_typedef))
+ return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
+ }
StorageClassSpec = S;
StorageClassSpecLoc = Loc;
assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
@@ -240,7 +247,6 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
return false;
}
-
/// These methods set the specified attribute of the DeclSpec, but return true
/// and ignore the request if invalid (e.g. "extern" then "auto" is
/// specified).
@@ -285,7 +291,63 @@ bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
const char *&PrevSpec,
unsigned &DiagID,
- void *Rep, bool Owned) {
+ ParsedType Rep) {
+ assert(isTypeRep(T) && "T does not store a type");
+ assert(Rep && "no type provided!");
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ TypeSpecType = T;
+ TypeRep = Rep;
+ TSTLoc = Loc;
+ TypeSpecOwned = false;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ Expr *Rep) {
+ assert(isExprRep(T) && "T does not store an expr");
+ assert(Rep && "no expression provided!");
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ TypeSpecType = T;
+ ExprRep = Rep;
+ TSTLoc = Loc;
+ TypeSpecOwned = false;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ Decl *Rep, bool Owned) {
+ assert(isDeclRep(T) && "T does not store a decl");
+ // Unlike the other cases, we don't assert that we actually get a decl.
+
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
+ TypeSpecType = T;
+ DeclRep = Rep;
+ TSTLoc = Loc;
+ TypeSpecOwned = Owned;
+ return false;
+}
+
+bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) &&
+ "rep required for these type-spec kinds!");
if (TypeSpecType != TST_unspecified) {
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
DiagID = diag::err_invalid_decl_spec_combination;
@@ -297,9 +359,8 @@ bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
return false;
}
TypeSpecType = T;
- TypeRep = Rep;
TSTLoc = Loc;
- TypeSpecOwned = Owned;
+ TypeSpecOwned = false;
if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) {
PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
DiagID = diag::err_invalid_vector_decl_spec;
@@ -335,7 +396,7 @@ bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
bool DeclSpec::SetTypeSpecError() {
TypeSpecType = TST_error;
- TypeRep = 0;
+ TypeSpecOwned = false;
TSTLoc = SourceLocation();
return false;
}
@@ -401,14 +462,14 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
return false;
}
-void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos,
+void DeclSpec::setProtocolQualifiers(Decl * const *Protos,
unsigned NP,
SourceLocation *ProtoLocs,
SourceLocation LAngleLoc) {
if (NP == 0) return;
- ProtocolQualifiers = new ActionBase::DeclPtrTy[NP];
+ ProtocolQualifiers = new Decl*[NP];
ProtocolLocs = new SourceLocation[NP];
- memcpy((void*)ProtocolQualifiers, Protos, sizeof(ActionBase::DeclPtrTy)*NP);
+ memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP);
memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
NumProtocolQualifiers = NP;
ProtocolLAngleLoc = LAngleLoc;
@@ -430,6 +491,15 @@ void DeclSpec::SaveWrittenBuiltinSpecs() {
}
}
+void DeclSpec::SaveStorageSpecifierAsWritten() {
+ if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
+ // If 'extern' is part of a linkage specification,
+ // then it is not a storage class "as written".
+ StorageClassSpecAsWritten = SCS_unspecified;
+ else
+ StorageClassSpecAsWritten = StorageClassSpec;
+}
+
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
@@ -475,6 +545,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
TypeSpecType = TST_int;
TypeSpecSign = TSS_unsigned;
TypeSpecWidth = TSW_short;
+ TypeSpecOwned = false;
}
}
@@ -504,6 +575,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
: diag::err_invalid_longlong_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecType = TST_int;
+ TypeSpecOwned = false;
}
break;
case TSW_long: // long double, long int
@@ -513,6 +585,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
Diag(D, TSWLoc, SrcMgr, diag::err_invalid_long_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecType = TST_int;
+ TypeSpecOwned = false;
}
break;
}
@@ -553,6 +626,8 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
ClearStorageClassSpecs();
}
+ assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType));
+
// Okay, now we can infer the real type.
// TODO: return "auto function" and other bad things based on the real type.
@@ -562,11 +637,8 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
bool DeclSpec::isMissingDeclaratorOk() {
TST tst = getTypeSpecType();
- return (tst == TST_union
- || tst == TST_struct
- || tst == TST_class
- || tst == TST_enum
- ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
+ return isDeclRep(tst) && getRepAsDecl() != 0 &&
+ StorageClassSpec != DeclSpec::SCS_typedef;
}
void UnqualifiedId::clear() {
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index b09526e097b6..3f16ed772352 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -12,7 +12,9 @@
//
//===----------------------------------------------------------------------===//
-#include "IdentifierResolver.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/Scope.h"
+#include "clang/AST/Decl.h"
#include "clang/Basic/LangOptions.h"
using namespace clang;
@@ -103,7 +105,7 @@ IdentifierResolver::~IdentifierResolver() {
/// true if 'D' belongs to the given declaration context.
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
ASTContext &Context, Scope *S) const {
- Ctx = Ctx->getLookupContext();
+ Ctx = Ctx->getRedeclContext();
if (Ctx->isFunctionOrMethod()) {
// Ignore the scopes associated within transparent declaration contexts.
@@ -111,7 +113,7 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
((DeclContext *)S->getEntity())->isTransparentContext())
S = S->getParent();
- if (S->isDeclScope(Action::DeclPtrTy::make(D)))
+ if (S->isDeclScope(D))
return true;
if (LangOpt.CPlusPlus) {
// C++ 3.3.2p3:
@@ -128,17 +130,20 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
//
assert(S->getParent() && "No TUScope?");
if (S->getParent()->getFlags() & Scope::ControlScope)
- return S->getParent()->isDeclScope(Action::DeclPtrTy::make(D));
+ return S->getParent()->isDeclScope(D);
}
return false;
}
- return D->getDeclContext()->getLookupContext()->Equals(Ctx);
+ return D->getDeclContext()->getRedeclContext()->Equals(Ctx);
}
/// AddDecl - Link the decl to its shadowed decl chain.
void IdentifierResolver::AddDecl(NamedDecl *D) {
DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) {
@@ -164,6 +169,9 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
assert(D && "null param passed");
DeclarationName Name = D->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
void *Ptr = Name.getFETokenInfo<void>();
assert(Ptr && "Didn't find this decl on its identifier's chain!");
@@ -182,6 +190,9 @@ bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
"Cannot replace a decl with another decl of a different name");
DeclarationName Name = Old->getDeclName();
+ if (IdentifierInfo *II = Name.getAsIdentifierInfo())
+ II->setIsFromAST(false);
+
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr)
@@ -218,6 +229,7 @@ IdentifierResolver::begin(DeclarationName Name) {
void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II,
NamedDecl *D) {
+ II->setIsFromAST(false);
void *Ptr = II->getFETokenInfo<void>();
if (!Ptr) {
@@ -261,3 +273,16 @@ IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
++CurIndex;
return *IDI;
}
+
+void IdentifierResolver::iterator::incrementSlowCase() {
+ NamedDecl *D = **this;
+ void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
+ assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
+ IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
+
+ BaseIter I = getIterator();
+ if (I != Info->decls_begin())
+ *this = iterator(I-1);
+ else // No more decls.
+ *this = iterator();
+}
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 3431ac611886..b23f615af7b7 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -12,11 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/BitVector.h"
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
+#include "llvm/ADT/BitVector.h"
using namespace clang;
namespace {
@@ -180,12 +181,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
// If we found a label, remember that it is in ParentScope scope.
switch (S->getStmtClass()) {
- case Stmt::LabelStmtClass:
- case Stmt::DefaultStmtClass:
- case Stmt::CaseStmtClass:
- LabelAndGotoScopes[S] = ParentScope;
- break;
-
case Stmt::AddrLabelExprClass:
IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
break;
@@ -225,6 +220,24 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
Stmt *SubStmt = *CI;
if (SubStmt == 0) continue;
+ // Cases, labels, and defaults aren't "scope parents". It's also
+ // important to handle these iteratively instead of recursively in
+ // order to avoid blowing out the stack.
+ while (true) {
+ Stmt *Next;
+ if (isa<CaseStmt>(SubStmt))
+ Next = cast<CaseStmt>(SubStmt)->getSubStmt();
+ else if (isa<DefaultStmt>(SubStmt))
+ Next = cast<DefaultStmt>(SubStmt)->getSubStmt();
+ else if (isa<LabelStmt>(SubStmt))
+ Next = cast<LabelStmt>(SubStmt)->getSubStmt();
+ else
+ break;
+
+ LabelAndGotoScopes[SubStmt] = ParentScope;
+ SubStmt = Next;
+ }
+
// If this is a declstmt with a VLA definition, it defines a scope from here
// to the end of the containing context.
if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
diff --git a/lib/Sema/Makefile b/lib/Sema/Makefile
index 90f2dffa0f1b..2c02739d268f 100644
--- a/lib/Sema/Makefile
+++ b/lib/Sema/Makefile
@@ -14,7 +14,6 @@
CLANG_LEVEL := ../..
LIBRARYNAME := clangSema
-BUILD_ARCHIVE = 1
include $(CLANG_LEVEL)/Makefile
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index cddc84eeedff..17817d41691b 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -12,26 +12,36 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
#include "TargetAttributesSema.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/APFloat.h"
+#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/ExternalSemaSource.h"
-#include "clang/AST/ASTConsumer.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
using namespace clang;
+using namespace sema;
FunctionScopeInfo::~FunctionScopeInfo() { }
void FunctionScopeInfo::Clear(unsigned NumErrors) {
- NeedsScopeChecking = false;
+ HasBranchProtectedScope = false;
+ HasBranchIntoScope = false;
+ HasIndirectGoto = false;
+
LabelMap.clear();
SwitchStack.clear();
Returns.clear();
@@ -40,13 +50,13 @@ void FunctionScopeInfo::Clear(unsigned NumErrors) {
BlockScopeInfo::~BlockScopeInfo() { }
-void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
+void Sema::ActOnTranslationUnitScope(Scope *S) {
TUScope = S;
PushDeclContext(S, Context.getTranslationUnitDecl());
VAListTagName = PP.getIdentifierInfo("__va_list_tag");
- if (!Context.isInt128Installed() && // May be set by PCHReader.
+ if (!Context.isInt128Installed() && // May be set by ASTReader.
PP.getTargetInfo().getPointerWidth(0) >= 64) {
TypeSourceInfo *TInfo;
@@ -68,7 +78,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
if (!PP.getLangOptions().ObjC1) return;
- // Built-in ObjC types may already be set by PCHReader (hence isNull checks).
+ // Built-in ObjC types may already be set by ASTReader (hence isNull checks).
if (Context.getObjCSelType().isNull()) {
// Create the built-in typedef for 'SEL'.
QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy);
@@ -113,7 +123,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
PushOnScopeChains(ClassTypedef, TUScope);
Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
Context.ObjCClassRedefinitionType = Context.getObjCClassType();
- }
+ }
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
@@ -123,9 +133,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
- PackContext(0), TopFunctionScope(0), ParsingDeclDepth(0),
- IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
- GlobalNewDeleteDeclared(false),
+ PackContext(0), VisContext(0), ParsingDeclDepth(0),
+ IdResolver(pp.getLangOptions()), GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), SuppressAccessChecking(false),
NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0),
@@ -140,22 +149,52 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
&Context);
ExprEvalContexts.push_back(
- ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
+ ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
+
+ FunctionScopes.push_back(new FunctionScopeInfo(Diags.getNumErrors()));
+}
+
+void Sema::Initialize() {
+ // Tell the AST consumer about this Sema object.
+ Consumer.Initialize(Context);
+
+ // FIXME: Isn't this redundant with the initialization above?
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
+ SC->InitializeSema(*this);
+
+ // Tell the external Sema source about this Sema object.
+ if (ExternalSemaSource *ExternalSema
+ = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
+ ExternalSema->InitializeSema(*this);
}
Sema::~Sema() {
if (PackContext) FreePackedContext();
+ if (VisContext) FreeVisContext();
delete TheTargetAttributesSema;
- while (!FunctionScopes.empty())
- PopFunctionOrBlockScope();
+
+ // Kill all the active scopes.
+ for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
+ delete FunctionScopes[I];
+ if (FunctionScopes.size() == 1)
+ delete FunctionScopes[0];
+
+ // Tell the SemaConsumer to forget about us; we're going out of scope.
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
+ SC->ForgetSema();
+
+ // Detach from the external Sema source.
+ if (ExternalSemaSource *ExternalSema
+ = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
+ ExternalSema->ForgetSema();
}
/// 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.
+/// The result is of the given category.
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
- CastExpr::CastKind Kind,
- bool isLvalue, CXXBaseSpecifierArray BasePath) {
+ CastKind Kind, ExprValueKind VK,
+ const CXXCastPath *BasePath) {
QualType ExprTy = Context.getCanonicalType(Expr->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
@@ -173,8 +212,8 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
// If this is a derived-to-base cast to a through a virtual base, we
// need a vtable.
- if (Kind == CastExpr::CK_DerivedToBase &&
- BasePathInvolvesVirtualBase(BasePath)) {
+ if (Kind == CK_DerivedToBase &&
+ BasePathInvolvesVirtualBase(*BasePath)) {
QualType T = Expr->getType();
if (const PointerType *Pointer = T->getAs<PointerType>())
T = Pointer->getPointeeType();
@@ -184,53 +223,96 @@ void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
}
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
- if (ImpCast->getCastKind() == Kind && BasePath.empty()) {
+ if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);
- ImpCast->setLvalueCast(isLvalue);
+ ImpCast->setValueKind(VK);
return;
}
}
- Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, BasePath, isLvalue);
+ Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, VK);
}
-void Sema::DeleteExpr(ExprTy *E) {
- if (E) static_cast<Expr*>(E)->Destroy(Context);
+ExprValueKind Sema::CastCategory(Expr *E) {
+ Expr::Classification Classification = E->Classify(Context);
+ return Classification.isRValue() ? VK_RValue :
+ (Classification.isLValue() ? VK_LValue : VK_XValue);
}
-void Sema::DeleteStmt(StmtTy *S) {
- if (S) static_cast<Stmt*>(S)->Destroy(Context);
+
+/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
+static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
+ if (D->isUsed())
+ return true;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // UnusedFileScopedDecls stores the first declaration.
+ // The declaration may have become definition so check again.
+ const FunctionDecl *DeclToCheck;
+ if (FD->hasBody(DeclToCheck))
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+ // Later redecls may add new information resulting in not having to warn,
+ // so check again.
+ DeclToCheck = FD->getMostRecentDeclaration();
+ if (DeclToCheck != FD)
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ // UnusedFileScopedDecls stores the first declaration.
+ // The declaration may have become definition so check again.
+ const VarDecl *DeclToCheck = VD->getDefinition();
+ if (DeclToCheck)
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+
+ // Later redecls may add new information resulting in not having to warn,
+ // so check again.
+ DeclToCheck = VD->getMostRecentDeclaration();
+ if (DeclToCheck != VD)
+ return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
+ }
+
+ return false;
}
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
-void Sema::ActOnEndOfTranslationUnit() {
- while (1) {
- // C++: Perform implicit template instantiations.
- //
- // FIXME: When we perform these implicit instantiations, we do not carefully
- // keep track of the point of instantiation (C++ [temp.point]). This means
- // that name lookup that occurs within the template instantiation will
- // always happen at the end of the translation unit, so it will find
- // some names that should not be found. Although this is common behavior
- // for C++ compilers, it is technically wrong. In the future, we either need
- // to be able to filter the results of name lookup or we need to perform
- // template instantiations earlier.
- PerformPendingImplicitInstantiations();
-
- /// If DefinedUsedVTables ends up marking any virtual member
- /// functions it might lead to more pending template
- /// instantiations, which is why we need to loop here.
- if (!DefineUsedVTables())
- break;
- }
+void Sema::ActOnEndOfTranslationUnit() {
+ // At PCH writing, implicit instantiations and VTable handling info are
+ // stored and performed when the PCH is included.
+ if (CompleteTranslationUnit)
+ while (1) {
+ // C++: Perform implicit template instantiations.
+ //
+ // FIXME: When we perform these implicit instantiations, we do not
+ // carefully keep track of the point of instantiation (C++ [temp.point]).
+ // This means that name lookup that occurs within the template
+ // instantiation will always happen at the end of the translation unit,
+ // so it will find some names that should not be found. Although this is
+ // common behavior for C++ compilers, it is technically wrong. In the
+ // future, we either need to be able to filter the results of name lookup
+ // or we need to perform template instantiations earlier.
+ PerformPendingInstantiations();
+
+ /// If DefinedUsedVTables ends up marking any virtual member
+ /// functions it might lead to more pending template
+ /// instantiations, which is why we need to loop here.
+ if (!DefineUsedVTables())
+ break;
+ }
- // Remove functions that turned out to be used.
- UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(),
- UnusedStaticFuncs.end(),
- std::bind2nd(std::mem_fun(&FunctionDecl::isUsed),
- true)),
- UnusedStaticFuncs.end());
+ // Remove file scoped decls that turned out to be used.
+ UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(),
+ UnusedFileScopedDecls.end(),
+ std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
+ this)),
+ UnusedFileScopedDecls.end());
+
+ if (!CompleteTranslationUnit) {
+ TUScope = 0;
+ return;
+ }
// Check for #pragma weak identifiers that were never declared
// FIXME: This will cause diagnostics to be emitted in a non-determinstic
@@ -244,9 +326,6 @@ void Sema::ActOnEndOfTranslationUnit() {
<< I->first;
}
- if (!CompleteTranslationUnit)
- return;
-
// C99 6.9.2p2:
// A declaration of an identifier for an object that has file
// scope without an initializer, and without a storage-class
@@ -293,14 +372,28 @@ void Sema::ActOnEndOfTranslationUnit() {
}
- // Output warning for unused functions.
- for (std::vector<FunctionDecl*>::iterator
- F = UnusedStaticFuncs.begin(),
- FEnd = UnusedStaticFuncs.end();
- F != FEnd;
- ++F)
- Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName();
-
+ // Output warning for unused file scoped decls.
+ for (llvm::SmallVectorImpl<const DeclaratorDecl*>::iterator
+ I = UnusedFileScopedDecls.begin(),
+ E = UnusedFileScopedDecls.end(); I != E; ++I) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
+ const FunctionDecl *DiagD;
+ if (!FD->hasBody(DiagD))
+ DiagD = FD;
+ Diag(DiagD->getLocation(),
+ isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
+ : diag::warn_unused_function)
+ << DiagD->getDeclName();
+ } else {
+ const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
+ if (!DiagD)
+ DiagD = cast<VarDecl>(*I);
+ Diag(DiagD->getLocation(), diag::warn_unused_variable)
+ << DiagD->getDeclName();
+ }
+ }
+
+ TUScope = 0;
}
@@ -418,11 +511,11 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
/// \brief Enter a new function scope
void Sema::PushFunctionScope() {
- if (FunctionScopes.empty()) {
- // Use the "top" function scope rather than having to allocate memory for
- // a new scope.
- TopFunctionScope.Clear(getDiagnostics().getNumErrors());
- FunctionScopes.push_back(&TopFunctionScope);
+ if (FunctionScopes.size() == 1) {
+ // Use the "top" function scope rather than having to allocate
+ // memory for a new scope.
+ FunctionScopes.back()->Clear(getDiagnostics().getNumErrors());
+ FunctionScopes.push_back(FunctionScopes.back());
return;
}
@@ -436,21 +529,17 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
}
void Sema::PopFunctionOrBlockScope() {
- if (FunctionScopes.back() != &TopFunctionScope)
- delete FunctionScopes.back();
- else
- TopFunctionScope.Clear(getDiagnostics().getNumErrors());
-
- FunctionScopes.pop_back();
+ FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
+ assert(!FunctionScopes.empty() && "mismatched push/pop!");
+ if (FunctionScopes.back() != Scope)
+ delete Scope;
}
/// \brief Determine whether any errors occurred within this function/method/
/// block.
bool Sema::hasAnyErrorsInThisFunction() const {
- unsigned NumErrors = TopFunctionScope.NumErrorsAtStartOfFunction;
- if (!FunctionScopes.empty())
- NumErrors = FunctionScopes.back()->NumErrorsAtStartOfFunction;
- return NumErrors != getDiagnostics().getNumErrors();
+ return getCurFunction()->NumErrorsAtStartOfFunction
+ != getDiagnostics().getNumErrors();
}
BlockScopeInfo *Sema::getCurBlock() {
@@ -462,3 +551,21 @@ BlockScopeInfo *Sema::getCurBlock() {
// Pin this vtable to this file.
ExternalSemaSource::~ExternalSemaSource() {}
+
+void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const {
+ SourceLocation Loc = this->Loc;
+ if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
+ if (Loc.isValid()) {
+ Loc.print(OS, S.getSourceManager());
+ OS << ": ";
+ }
+ OS << Message;
+
+ if (TheDecl && isa<NamedDecl>(TheDecl)) {
+ std::string Name = cast<NamedDecl>(TheDecl)->getNameAsString();
+ if (!Name.empty())
+ OS << " '" << Name << '\'';
+ }
+
+ OS << '\n';
+}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index e110e3dfa471..e629f0fd35bf 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -11,9 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
@@ -22,6 +23,7 @@
#include "clang/AST/ExprCXX.h"
using namespace clang;
+using namespace sema;
/// A copy of Sema's enum without AR_delayed.
enum AccessResult {
@@ -132,10 +134,10 @@ struct EffectiveContext {
bool Dependent;
};
-/// Like Sema's AccessedEntity, but kindly lets us scribble all over
+/// Like sema:;AccessedEntity, but kindly lets us scribble all over
/// it.
-struct AccessTarget : public Sema::AccessedEntity {
- AccessTarget(const Sema::AccessedEntity &Entity)
+struct AccessTarget : public AccessedEntity {
+ AccessTarget(const AccessedEntity &Entity)
: AccessedEntity(Entity) {
initialize();
}
@@ -562,6 +564,130 @@ static AccessResult GetFriendKind(Sema &S,
return OnFailure;
}
+namespace {
+
+/// A helper class for checking for a friend which will grant access
+/// to a protected instance member.
+struct ProtectedFriendContext {
+ Sema &S;
+ const EffectiveContext &EC;
+ const CXXRecordDecl *NamingClass;
+ bool CheckDependent;
+ bool EverDependent;
+
+ /// The path down to the current base class.
+ llvm::SmallVector<const CXXRecordDecl*, 20> CurPath;
+
+ ProtectedFriendContext(Sema &S, const EffectiveContext &EC,
+ const CXXRecordDecl *InstanceContext,
+ const CXXRecordDecl *NamingClass)
+ : S(S), EC(EC), NamingClass(NamingClass),
+ CheckDependent(InstanceContext->isDependentContext() ||
+ NamingClass->isDependentContext()),
+ EverDependent(false) {}
+
+ /// Check classes in the current path for friendship, starting at
+ /// the given index.
+ bool checkFriendshipAlongPath(unsigned I) {
+ assert(I < CurPath.size());
+ for (unsigned E = CurPath.size(); I != E; ++I) {
+ switch (GetFriendKind(S, EC, CurPath[I])) {
+ case AR_accessible: return true;
+ case AR_inaccessible: continue;
+ case AR_dependent: EverDependent = true; continue;
+ }
+ }
+ return false;
+ }
+
+ /// Perform a search starting at the given class.
+ ///
+ /// PrivateDepth is the index of the last (least derived) class
+ /// along the current path such that a notional public member of
+ /// the final class in the path would have access in that class.
+ bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {
+ // If we ever reach the naming class, check the current path for
+ // friendship. We can also stop recursing because we obviously
+ // won't find the naming class there again.
+ if (Cur == NamingClass)
+ return checkFriendshipAlongPath(PrivateDepth);
+
+ if (CheckDependent && MightInstantiateTo(Cur, NamingClass))
+ EverDependent = true;
+
+ // Recurse into the base classes.
+ for (CXXRecordDecl::base_class_const_iterator
+ I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) {
+
+ // If this is private inheritance, then a public member of the
+ // base will not have any access in classes derived from Cur.
+ unsigned BasePrivateDepth = PrivateDepth;
+ if (I->getAccessSpecifier() == AS_private)
+ BasePrivateDepth = CurPath.size() - 1;
+
+ const CXXRecordDecl *RD;
+
+ QualType T = I->getType();
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ RD = cast<CXXRecordDecl>(RT->getDecl());
+ } else if (const InjectedClassNameType *IT
+ = T->getAs<InjectedClassNameType>()) {
+ RD = IT->getDecl();
+ } else {
+ assert(T->isDependentType() && "non-dependent base wasn't a record?");
+ EverDependent = true;
+ continue;
+ }
+
+ // Recurse. We don't need to clean up if this returns true.
+ CurPath.push_back(RD);
+ if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))
+ return true;
+ CurPath.pop_back();
+ }
+
+ return false;
+ }
+
+ bool findFriendship(const CXXRecordDecl *Cur) {
+ assert(CurPath.empty());
+ CurPath.push_back(Cur);
+ return findFriendship(Cur, 0);
+ }
+};
+}
+
+/// Search for a class P that EC is a friend of, under the constraint
+/// InstanceContext <= P <= NamingClass
+/// and with the additional restriction that a protected member of
+/// NamingClass would have some natural access in P.
+///
+/// That second condition isn't actually quite right: the condition in
+/// the standard is whether the target would have some natural access
+/// in P. The difference is that the target might be more accessible
+/// along some path not passing through NamingClass. Allowing that
+/// introduces two problems:
+/// - It breaks encapsulation because you can suddenly access a
+/// forbidden base class's members by subclassing it elsewhere.
+/// - It makes access substantially harder to compute because it
+/// breaks the hill-climbing algorithm: knowing that the target is
+/// accessible in some base class would no longer let you change
+/// the question solely to whether the base class is accessible,
+/// because the original target might have been more accessible
+/// because of crazy subclassing.
+/// So we don't implement that.
+static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC,
+ const CXXRecordDecl *InstanceContext,
+ const CXXRecordDecl *NamingClass) {
+ assert(InstanceContext->getCanonicalDecl() == InstanceContext);
+ assert(NamingClass->getCanonicalDecl() == NamingClass);
+
+ ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);
+ if (PRC.findFriendship(InstanceContext)) return AR_accessible;
+ if (PRC.EverDependent) return AR_dependent;
+ return AR_inaccessible;
+}
+
static AccessResult HasAccess(Sema &S,
const EffectiveContext &EC,
const CXXRecordDecl *NamingClass,
@@ -629,20 +755,25 @@ static AccessResult HasAccess(Sema &S,
}
}
- if (!NamingClass->hasFriends())
- return OnFailure;
-
- // Don't consider friends if we're under the [class.protected]
- // restriction, above.
+ // [M3] and [B3] say that, if the target is protected in N, we grant
+ // access if the access occurs in a friend or member of some class P
+ // that's a subclass of N and where the target has some natural
+ // access in P. The 'member' aspect is easy to handle because P
+ // would necessarily be one of the effective-context records, and we
+ // address that above. The 'friend' aspect is completely ridiculous
+ // to implement because there are no restrictions at all on P
+ // *unless* the [class.protected] restriction applies. If it does,
+ // however, we should ignore whether the naming class is a friend,
+ // and instead rely on whether any potential P is a friend.
if (Access == AS_protected && Target.hasInstanceContext()) {
const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
if (!InstanceContext) return AR_dependent;
-
- switch (IsDerivedFromInclusive(InstanceContext, NamingClass)) {
- case AR_accessible: break;
+ switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) {
+ case AR_accessible: return AR_accessible;
case AR_inaccessible: return OnFailure;
case AR_dependent: return AR_dependent;
}
+ llvm_unreachable("impossible friendship kind");
}
switch (GetFriendKind(S, EC, NamingClass)) {
@@ -799,6 +930,57 @@ static CXXBasePath *FindBestPath(Sema &S,
return BestPath;
}
+/// Given that an entity has protected natural access, check whether
+/// access might be denied because of the protected member access
+/// restriction.
+///
+/// \return true if a note was emitted
+static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
+ AccessTarget &Target) {
+ // Only applies to instance accesses.
+ if (!Target.hasInstanceContext())
+ return false;
+ assert(Target.isMemberAccess());
+ NamedDecl *D = Target.getTargetDecl();
+
+ const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass();
+ DeclaringClass = DeclaringClass->getCanonicalDecl();
+
+ for (EffectiveContext::record_iterator
+ I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
+ const CXXRecordDecl *ECRecord = *I;
+ switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) {
+ case AR_accessible: break;
+ case AR_inaccessible: continue;
+ case AR_dependent: continue;
+ }
+
+ // The effective context is a subclass of the declaring class.
+ // If that class isn't a superclass of the instance context,
+ // then the [class.protected] restriction applies.
+
+ // To get this exactly right, this might need to be checked more
+ // holistically; it's not necessarily the case that gaining
+ // access here would grant us access overall.
+
+ const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);
+ assert(InstanceContext && "diagnosing dependent access");
+
+ switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) {
+ case AR_accessible: continue;
+ case AR_dependent: continue;
+ case AR_inaccessible:
+ S.Diag(D->getLocation(), diag::note_access_protected_restricted)
+ << (InstanceContext != Target.getNamingClass()->getCanonicalDecl())
+ << S.Context.getTypeDeclType(InstanceContext)
+ << S.Context.getTypeDeclType(ECRecord);
+ return true;
+ }
+ }
+
+ return false;
+}
+
/// Diagnose the path which caused the given declaration or base class
/// to become inaccessible.
static void DiagnoseAccessPath(Sema &S,
@@ -817,6 +999,10 @@ static void DiagnoseAccessPath(Sema &S,
if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) {
switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) {
case AR_inaccessible: {
+ if (Access == AS_protected &&
+ TryDiagnoseProtectedAccess(S, EC, Entity))
+ return;
+
S.Diag(D->getLocation(), diag::note_access_natural)
<< (unsigned) (Access == AS_protected)
<< /*FIXME: not implicitly*/ 0;
@@ -1033,7 +1219,7 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
// access control.
if (S.CurContext->isFileContext() && S.ParsingDeclDepth) {
S.DelayedDiagnostics.push_back(
- Sema::DelayedDiagnostic::makeAccess(Loc, Entity));
+ DelayedDiagnostic::makeAccess(Loc, Entity));
return Sema::AR_delayed;
}
@@ -1266,7 +1452,7 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
Found.getAccess() == AS_public)
return AR_accessible;
- OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
+ OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression;
CXXRecordDecl *NamingClass = Ovl->getNamingClass();
AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 69f27b0ada7d..0921156b932f 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -12,8 +12,9 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/AST/Attr.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -62,18 +63,30 @@ namespace {
/// alignment to the previous value. If \arg Name is non-zero then
/// the first such named record is popped, otherwise the top record
/// is popped. Returns true if the pop succeeded.
- bool pop(IdentifierInfo *Name);
+ bool pop(IdentifierInfo *Name, bool IsReset);
};
} // end anonymous namespace.
-bool PragmaPackStack::pop(IdentifierInfo *Name) {
- if (Stack.empty())
- return false;
-
+bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
// If name is empty just pop top.
if (!Name) {
- Alignment = Stack.back().Alignment;
- Stack.pop_back();
+ // An empty stack is a special case...
+ if (Stack.empty()) {
+ // If this isn't a reset, it is always an error.
+ if (!IsReset)
+ return false;
+
+ // Otherwise, it is an error only if some alignment has been set.
+ if (!Alignment)
+ return false;
+
+ // Otherwise, reset to the default alignment.
+ Alignment = 0;
+ } else {
+ Alignment = Stack.back().Alignment;
+ Stack.pop_back();
+ }
+
return true;
}
@@ -108,9 +121,11 @@ void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
// Otherwise, check to see if we need a max field alignment attribute.
if (unsigned Alignment = Stack->getAlignment()) {
if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
- RD->addAttr(::new (Context) AlignMac68kAttr());
+ RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
else
- RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
+ RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
+ Context,
+ Alignment * 8));
}
}
@@ -122,13 +137,10 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
- // Reset just pops the top of the stack.
- if (Kind == Action::POAK_Reset) {
- // Do the pop.
- if (!Context->pop(0)) {
- // If a name was specified then failure indicates the name
- // wasn't found. Otherwise failure indicates the stack was
- // empty.
+ // Reset just pops the top of the stack, or resets the current alignment to
+ // default.
+ if (Kind == Sema::POAK_Reset) {
+ if (!Context->pop(0, /*IsReset=*/true)) {
Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
<< "stack empty";
}
@@ -188,7 +200,6 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
!(Val == 0 || Val.isPowerOf2()) ||
Val.getZExtValue() > 16) {
Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
- Alignment->Destroy(Context);
return; // Ignore
}
@@ -201,11 +212,11 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
switch (Kind) {
- case Action::PPK_Default: // pack([n])
+ case Sema::PPK_Default: // pack([n])
Context->setAlignment(AlignmentVal);
break;
- case Action::PPK_Show: // pack(show)
+ case Sema::PPK_Show: // pack(show)
// Show the current alignment, making sure to show the right value
// for the default.
AlignmentVal = Context->getAlignment();
@@ -218,21 +229,21 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
break;
- case Action::PPK_Push: // pack(push [, id] [, [n])
+ case Sema::PPK_Push: // pack(push [, id] [, [n])
Context->push(Name);
// Set the new alignment if specified.
if (Alignment)
Context->setAlignment(AlignmentVal);
break;
- case Action::PPK_Pop: // pack(pop [, id] [, n])
+ case Sema::PPK_Pop: // pack(pop [, id] [, n])
// MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
// "#pragma pack(pop, identifier, n) is undefined"
if (Alignment && Name)
Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
// Do the pop.
- if (!Context->pop(Name)) {
+ if (!Context->pop(Name, /*IsReset=*/false)) {
// If a name was specified then failure indicates the name
// wasn't found. Otherwise failure indicates the stack was
// empty.
@@ -277,6 +288,80 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
continue;
}
- VD->addAttr(::new (Context) UnusedAttr());
+ VD->addAttr(::new (Context) UnusedAttr(Tok.getLocation(), Context));
+ }
+}
+
+typedef std::vector<std::pair<VisibilityAttr::VisibilityType,
+ SourceLocation> > VisStack;
+
+void Sema::AddPushedVisibilityAttribute(Decl *D) {
+ if (!VisContext)
+ return;
+
+ if (D->hasAttr<VisibilityAttr>())
+ return;
+
+ VisStack *Stack = static_cast<VisStack*>(VisContext);
+ VisibilityAttr::VisibilityType type = Stack->back().first;
+ SourceLocation loc = Stack->back().second;
+
+ D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
+}
+
+/// FreeVisContext - Deallocate and null out VisContext.
+void Sema::FreeVisContext() {
+ delete static_cast<VisStack*>(VisContext);
+ VisContext = 0;
+}
+
+static void PushPragmaVisibility(Sema &S, VisibilityAttr::VisibilityType type,
+ SourceLocation loc) {
+ // Put visibility on stack.
+ if (!S.VisContext)
+ S.VisContext = new VisStack;
+
+ VisStack *Stack = static_cast<VisStack*>(S.VisContext);
+ Stack->push_back(std::make_pair(type, loc));
+}
+
+void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc) {
+ if (IsPush) {
+ // Compute visibility to use.
+ VisibilityAttr::VisibilityType type;
+ if (VisType->isStr("default"))
+ type = VisibilityAttr::Default;
+ else if (VisType->isStr("hidden"))
+ type = VisibilityAttr::Hidden;
+ else if (VisType->isStr("internal"))
+ type = VisibilityAttr::Hidden; // FIXME
+ else if (VisType->isStr("protected"))
+ type = VisibilityAttr::Protected;
+ else {
+ Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
+ VisType->getName();
+ return;
+ }
+ PushPragmaVisibility(*this, type, PragmaLoc);
+ } else {
+ PopPragmaVisibility();
+ }
+}
+
+void Sema::PushVisibilityAttr(const VisibilityAttr *Attr) {
+ PushPragmaVisibility(*this, Attr->getVisibility(), Attr->getLocation());
+}
+
+void Sema::PopPragmaVisibility() {
+ // Pop visibility from stack, if there is one on the stack.
+ if (VisContext) {
+ VisStack *Stack = static_cast<VisStack*>(VisContext);
+
+ Stack->pop_back();
+ // To simplify the implementation, never keep around an empty stack.
+ if (Stack->empty())
+ FreeVisContext();
}
+ // FIXME: Add diag for pop without push.
}
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index b8e27e7b7285..21b1a73aa3bc 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -43,16 +43,16 @@ static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange,
- CastExpr::CastKind &Kind);
+ CastKind &Kind);
static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
@@ -73,54 +73,54 @@ static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
CanQualType DestType, bool CStyle,
const SourceRange &OpRange,
QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr,
QualType SrcType,
QualType DestType,bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind);
+ CastKind &Kind);
static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath);
+ CastKind &Kind,
+ CXXCastPath &BasePath);
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind);
+ CastKind &Kind);
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
-Action::OwningExprResult
+ExprResult
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc, TypeTy *Ty,
+ SourceLocation LAngleBracketLoc, ParsedType Ty,
SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc, ExprArg E,
+ SourceLocation LParenLoc, Expr *E,
SourceLocation RParenLoc) {
TypeSourceInfo *DestTInfo;
@@ -133,11 +133,10 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
SourceRange(LParenLoc, RParenLoc));
}
-Action::OwningExprResult
+ExprResult
Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
- TypeSourceInfo *DestTInfo, ExprArg E,
+ TypeSourceInfo *DestTInfo, Expr *Ex,
SourceRange AngleBrackets, SourceRange Parens) {
- Expr *Ex = E.takeAs<Expr>();
QualType DestType = DestTInfo->getType();
SourceRange OpRange(OpLoc, Parens.getEnd());
@@ -153,39 +152,39 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
case tok::kw_const_cast:
if (!TypeDependent)
CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
- return Owned(new (Context) CXXConstCastExpr(
+ return Owned(CXXConstCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Ex, DestTInfo, OpLoc));
+ Ex, DestTInfo, OpLoc));
case tok::kw_dynamic_cast: {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (!TypeDependent)
CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath);
- return Owned(new (Context)CXXDynamicCastExpr(
+ return Owned(CXXDynamicCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, BasePath, DestTInfo,
- OpLoc));
+ Kind, Ex, &BasePath, DestTInfo,
+ OpLoc));
}
case tok::kw_reinterpret_cast: {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+ CastKind Kind = CK_Unknown;
if (!TypeDependent)
CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
- return Owned(new (Context) CXXReinterpretCastExpr(
+ return Owned(CXXReinterpretCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, CXXBaseSpecifierArray(),
+ Kind, Ex, 0,
DestTInfo, OpLoc));
}
case tok::kw_static_cast: {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (!TypeDependent)
CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath);
- return Owned(new (Context) CXXStaticCastExpr(
+ return Owned(CXXStaticCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, BasePath,
- DestTInfo, OpLoc));
+ Kind, Ex, &BasePath,
+ DestTInfo, OpLoc));
}
}
@@ -197,7 +196,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
/// the same kind of pointer (plain or to-member). Unlike the Sema function,
/// this one doesn't care if the two pointers-to-member don't point into the
/// same class. This is because CastsAwayConstness doesn't care.
-bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
+static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
const PointerType *T1PtrType = T1->getAs<PointerType>(),
*T2PtrType = T2->getAs<PointerType>();
if (T1PtrType && T2PtrType) {
@@ -307,8 +306,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
static void
CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
- const SourceRange &DestRange, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ const SourceRange &DestRange, CastKind &Kind,
+ CXXCastPath &BasePath) {
QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
DestType = Self.Context.getCanonicalType(DestType);
@@ -396,6 +395,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
// C++ 5.2.7p3: If the type of v is the same as the required result type,
// [except for cv].
if (DestRecord == SrcRecord) {
+ Kind = CK_NoOp;
return;
}
@@ -407,7 +407,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
&BasePath))
return;
- Kind = CastExpr::CK_DerivedToBase;
+ Kind = CK_DerivedToBase;
// If we are casting to or through a virtual base class, we need a
// vtable.
@@ -428,7 +428,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
cast<CXXRecordDecl>(SrcRecord->getDecl()));
// Done. Everything else is run-time checks.
- Kind = CastExpr::CK_Dynamic;
+ Kind = CK_Dynamic;
}
/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
@@ -457,7 +457,7 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
void
CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange, const SourceRange &DestRange,
- CastExpr::CastKind &Kind) {
+ CastKind &Kind) {
if (!DestType->isLValueReferenceType())
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
@@ -475,13 +475,13 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// implicit conversions explicit and getting rid of data loss warnings.
void
CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
- const SourceRange &OpRange, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ const SourceRange &OpRange, CastKind &Kind,
+ CXXCastPath &BasePath) {
// This test is outside everything else because it's the only case where
// 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;
+ Kind = CK_ToVoid;
return;
}
@@ -493,6 +493,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
Kind, BasePath) != TC_Success && msg != 0)
Self.Diag(OpRange.getBegin(), msg) << CT_Static
<< SrcExpr->getType() << DestType << OpRange;
+ else if (Kind == CK_Unknown || Kind == CK_BitCast)
+ Self.CheckCastAlign(SrcExpr, DestType, OpRange);
}
/// TryStaticCast - Check if a static cast can be performed, and do so if
@@ -501,8 +503,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange, unsigned &msg,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ CastKind &Kind,
+ CXXCastPath &BasePath) {
// The order the tests is not entirely arbitrary. There is one conversion
// that can be handled in two different ways. Given:
// struct A {};
@@ -532,7 +534,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg);
if (tcr != TC_NotApplicable) {
- Kind = CastExpr::CK_NoOp;
+ Kind = CK_NoOp;
return tcr;
}
@@ -567,7 +569,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
if (SrcType->isComplexType() || SrcType->isVectorType()) {
// Fall through - these cannot be converted.
} else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) {
- Kind = CastExpr::CK_IntegralCast;
+ Kind = CK_IntegralCast;
return TC_Success;
}
}
@@ -602,19 +604,19 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
msg = diag::err_bad_cxx_cast_const_away;
return TC_Failed;
}
- Kind = CastExpr::CK_BitCast;
+ Kind = CK_BitCast;
return TC_Success;
}
}
else if (DestType->isObjCObjectPointerType()) {
// allow both c-style cast and static_cast of objective-c pointers as
// they are pervasive.
- Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
+ Kind = CK_AnyPointerToObjCPointerCast;
return TC_Success;
}
else if (CStyle && DestType->isBlockPointerType()) {
// allow c-style cast of void * to block pointers.
- Kind = CastExpr::CK_AnyPointerToBlockPointerCast;
+ Kind = CK_AnyPointerToBlockPointerCast;
return TC_Success;
}
}
@@ -645,9 +647,10 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
// this is the only cast possibility, so we issue an error if we fail now.
// FIXME: Should allow casting away constness if CStyle.
bool DerivedToBase;
+ bool ObjCConversion;
if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
SrcExpr->getType(), R->getPointeeType(),
- DerivedToBase) <
+ DerivedToBase, ObjCConversion) <
Sema::Ref_Compatible_With_Added_Qualification) {
msg = diag::err_bad_lvalue_to_rvalue_cast;
return TC_Failed;
@@ -662,8 +665,8 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
TryCastResult
TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
bool CStyle, const SourceRange &OpRange,
- unsigned &msg, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath) {
// 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"
@@ -697,8 +700,8 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
TryCastResult
TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
bool CStyle, const SourceRange &OpRange,
- unsigned &msg, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath) {
// 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
@@ -732,7 +735,7 @@ TryCastResult
TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,
QualType OrigDestType, unsigned &msg,
- CastExpr::CastKind &Kind, CXXBaseSpecifierArray &BasePath) {
+ CastKind &Kind, CXXCastPath &BasePath) {
// We can only work with complete types. But don't complain if it doesn't work
if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) ||
Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0)))
@@ -824,7 +827,7 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
}
Self.BuildBasePathArray(Paths, BasePath);
- Kind = CastExpr::CK_BaseToDerived;
+ Kind = CK_BaseToDerived;
return TC_Success;
}
@@ -839,8 +842,8 @@ TryCastResult
TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
- unsigned &msg, CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath) {
+ unsigned &msg, CastKind &Kind,
+ CXXCastPath &BasePath) {
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
if (!DestMemPtr)
return TC_NotApplicable;
@@ -900,7 +903,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
}
if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(),
- DestType, SrcType,
+ DestClass, SrcClass,
Paths.front(),
diag::err_upcast_to_inaccessible_base)) {
msg = 0;
@@ -927,7 +930,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
}
Self.BuildBasePathArray(Paths, BasePath);
- Kind = CastExpr::CK_DerivedToBaseMemberPointer;
+ Kind = CK_DerivedToBaseMemberPointer;
return TC_Success;
}
@@ -939,7 +942,7 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
TryCastResult
TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
bool CStyle, const SourceRange &OpRange, unsigned &msg,
- CastExpr::CastKind &Kind) {
+ CastKind &Kind) {
if (DestType->isRecordType()) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
diag::err_bad_dynamic_cast_incomplete)) {
@@ -961,18 +964,17 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
(CStyle || !DestType->isReferenceType()))
return TC_NotApplicable;
- Sema::OwningExprResult Result
- = InitSeq.Perform(Self, Entity, InitKind,
- Action::MultiExprArg(Self, (void**)&SrcExpr, 1));
+ ExprResult Result
+ = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExpr, 1));
if (Result.isInvalid()) {
msg = 0;
return TC_Failed;
}
if (InitSeq.isConstructorInitialization())
- Kind = CastExpr::CK_ConstructorConversion;
+ Kind = CK_ConstructorConversion;
else
- Kind = CastExpr::CK_NoOp;
+ Kind = CK_NoOp;
SrcExpr = Result.takeAs<Expr>();
return TC_Success;
@@ -1051,7 +1053,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
unsigned &msg,
- CastExpr::CastKind &Kind) {
+ CastKind &Kind) {
bool IsLValueCast = false;
DestType = Self.Context.getCanonicalType(DestType);
@@ -1097,8 +1099,15 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
return TC_Failed;
}
+ // Don't allow casting between member pointers of different sizes.
+ if (Self.Context.getTypeSize(DestMemPtr) !=
+ Self.Context.getTypeSize(SrcMemPtr)) {
+ msg = diag::err_bad_cxx_cast_member_pointer_size;
+ return TC_Failed;
+ }
+
// A valid member pointer cast.
- Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast;
+ Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast;
return TC_Success;
}
@@ -1113,7 +1122,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
msg = diag::err_bad_reinterpret_cast_small_int;
return TC_Failed;
}
- Kind = CastExpr::CK_PointerToIntegral;
+ Kind = CK_PointerToIntegral;
return TC_Success;
}
@@ -1132,7 +1141,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// If both types have the same size, we can successfully cast.
if (Self.Context.getTypeSize(SrcType)
== Self.Context.getTypeSize(DestType)) {
- Kind = CastExpr::CK_BitCast;
+ Kind = CK_BitCast;
return TC_Success;
}
@@ -1163,7 +1172,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// to the same type. However, the behavior of compilers is pretty consistent
// on this point: allow same-type conversion if the involved types are
// pointers, disallow otherwise.
- Kind = CastExpr::CK_NoOp;
+ Kind = CK_NoOp;
return TC_Success;
}
@@ -1176,7 +1185,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
msg = diag::err_bad_reinterpret_cast_small_int;
return TC_Failed;
}
- Kind = CastExpr::CK_PointerToIntegral;
+ Kind = CK_PointerToIntegral;
return TC_Success;
}
@@ -1184,7 +1193,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
assert(destIsPtr && "One type must be a pointer");
// C++ 5.2.10p5: A value of integral or enumeration type can be explicitly
// converted to a pointer.
- Kind = CastExpr::CK_IntegralToPointer;
+ Kind = CK_IntegralToPointer;
return TC_Success;
}
@@ -1209,13 +1218,13 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// Any pointer can be cast to an Objective-C pointer type with a C-style
// cast.
if (CStyle && DestType->isObjCObjectPointerType()) {
- Kind = CastExpr::CK_AnyPointerToObjCPointerCast;
+ Kind = CK_AnyPointerToObjCPointerCast;
return TC_Success;
}
// Not casting away constness, so the only remaining check is for compatible
// pointer categories.
- Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast;
+ Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast;
if (SrcType->isFunctionPointerType()) {
if (DestType->isFunctionPointerType()) {
@@ -1252,14 +1261,14 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
bool
Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind,
- CXXBaseSpecifierArray &BasePath,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
bool FunctionalStyle) {
// This test is outside everything else because it's the only case where
// 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 (CastTy->isVoidType()) {
- Kind = CastExpr::CK_ToVoid;
+ Kind = CK_ToVoid;
return false;
}
@@ -1285,7 +1294,7 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,
msg);
if (tcr == TC_Success)
- Kind = CastExpr::CK_NoOp;
+ Kind = CK_NoOp;
if (tcr == TC_NotApplicable) {
// ... or if that is not possible, a static_cast, ignoring const, ...
@@ -1301,6 +1310,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
if (tcr != TC_Success && msg != 0)
Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle)
<< CastExpr->getType() << CastTy << R;
+ else if (Kind == CK_Unknown || Kind == CK_BitCast)
+ CheckCastAlign(CastExpr, CastTy, R);
return tcr != TC_Success;
}
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index f56573a8de26..631308eebb04 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -11,14 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -283,7 +283,7 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
SourceLocation IdLoc,
IdentifierInfo &II,
- TypeTy *ObjectTypePtr) {
+ ParsedType ObjectTypePtr) {
QualType ObjectType = GetTypeFromParser(ObjectTypePtr);
LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName);
@@ -416,7 +416,17 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
ObjectTypeSearchedInScope = true;
}
- } else if (isDependent) {
+ } else if (!isDependent) {
+ // Perform unqualified name lookup in the current scope.
+ LookupName(Found, S);
+ }
+
+ // If we performed lookup into a dependent context and did not find anything,
+ // that's fine: just build a dependent nested-name-specifier.
+ if (Found.empty() && isDependent &&
+ !(LookupCtx && LookupCtx->isRecord() &&
+ (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() ||
+ !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) {
// Don't speculate if we're just trying to improve error recovery.
if (ErrorRecoveryLookup)
return 0;
@@ -429,11 +439,8 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S,
return NestedNameSpecifier::Create(Context, &II);
return NestedNameSpecifier::Create(Context, Prefix, &II);
- } else {
- // Perform unqualified name lookup in the current scope.
- LookupName(Found, S);
- }
-
+ }
+
// FIXME: Deal with ambiguities cleanly.
if (Found.empty() && !ErrorRecoveryLookup) {
@@ -560,10 +567,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II,
- TypeTy *ObjectTypePtr,
+ ParsedType ObjectTypePtr,
bool EnteringContext) {
return BuildCXXNestedNameSpecifier(S, SS, IdLoc, CCLoc, II,
- QualType::getFromOpaquePtr(ObjectTypePtr),
+ GetTypeFromParser(ObjectTypePtr),
/*ScopeLookupResult=*/0, EnteringContext,
false);
}
@@ -575,21 +582,20 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
///
/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier.
bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- IdentifierInfo &II, TypeTy *ObjectType,
+ IdentifierInfo &II, ParsedType ObjectType,
bool EnteringContext) {
return BuildCXXNestedNameSpecifier(S, SS, SourceLocation(), SourceLocation(),
- II, QualType::getFromOpaquePtr(ObjectType),
+ II, GetTypeFromParser(ObjectType),
/*ScopeLookupResult=*/0, EnteringContext,
true);
}
Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
const CXXScopeSpec &SS,
- TypeTy *Ty,
+ ParsedType Ty,
SourceRange TypeRange,
SourceLocation CCLoc) {
- NestedNameSpecifier *Prefix
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
+ NestedNameSpecifier *Prefix = SS.getScopeRep();
QualType T = GetTypeFromParser(Ty);
return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
T.getTypePtr());
@@ -620,7 +626,7 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
case NestedNameSpecifier::Namespace:
// These are always namespace scopes. We never want to enter a
// namespace scope from anything but a file context.
- return CurContext->getLookupContext()->isFileContext();
+ return CurContext->getRedeclContext()->isFileContext();
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::TypeSpec:
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 7a39f058c5ec..a0b4b988dbeb 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -12,10 +12,13 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "clang/Analysis/Analyses/PrintfFormatString.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Analysis/Analyses/FormatString.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -26,12 +29,12 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include <limits>
using namespace clang;
+using namespace sema;
/// getLocationOfStringLiteralByte - Return a source location that points to the
/// specified byte of the specified string literal.
@@ -122,9 +125,9 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) {
return false;
}
-Action::OwningExprResult
+ExprResult
Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
- OwningExprResult TheCallResult(Owned(TheCall));
+ ExprResult TheCallResult(Owned(TheCall));
switch (BuiltinID) {
case Builtin::BI__builtin___CFStringMakeConstantString:
@@ -298,6 +301,10 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
switch (BuiltinID) {
default: return false;
+ case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break;
+ case ARM::BI__builtin_arm_usat: i = 1; u = 31; break;
+ case ARM::BI__builtin_arm_vcvtr_f:
+ case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break;
#define GET_NEON_IMMEDIATE_CHECK
#include "clang/Basic/arm_neon.inc"
#undef GET_NEON_IMMEDIATE_CHECK
@@ -311,9 +318,9 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
unsigned Val = Result.getZExtValue();
if (Val < l || Val > (u + l))
return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range)
- << llvm::utostr(l) << llvm::utostr(u+l)
- << TheCall->getArg(i)->getSourceRange();
+ << l << u+l << TheCall->getArg(i)->getSourceRange();
+ // FIXME: VFP Intrinsics should error if VFP not present.
return false;
}
@@ -334,16 +341,22 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
// Printf checking.
if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) {
- if (CheckablePrintfAttr(Format, TheCall)) {
+ const bool b = Format->getType() == "scanf";
+ if (b || CheckablePrintfAttr(Format, TheCall)) {
bool HasVAListArg = Format->getFirstArg() == 0;
- CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
- HasVAListArg ? 0 : Format->getFirstArg() - 1);
+ CheckPrintfScanfArguments(TheCall, HasVAListArg,
+ Format->getFormatIdx() - 1,
+ HasVAListArg ? 0 : Format->getFirstArg() - 1,
+ !b);
}
}
- for (const NonNullAttr *NonNull = FDecl->getAttr<NonNullAttr>(); NonNull;
- NonNull = NonNull->getNext<NonNullAttr>())
- CheckNonNullArguments(NonNull, TheCall);
+ specific_attr_iterator<NonNullAttr>
+ i = FDecl->specific_attr_begin<NonNullAttr>(),
+ e = FDecl->specific_attr_end<NonNullAttr>();
+
+ for (; i != e; ++i)
+ CheckNonNullArguments(*i, TheCall);
return false;
}
@@ -362,12 +375,13 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
if (!Ty->isBlockPointerType())
return false;
- if (!CheckablePrintfAttr(Format, TheCall))
+ const bool b = Format->getType() == "scanf";
+ if (!b && !CheckablePrintfAttr(Format, TheCall))
return false;
bool HasVAListArg = Format->getFirstArg() == 0;
- CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
- HasVAListArg ? 0 : Format->getFirstArg() - 1);
+ CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
+ HasVAListArg ? 0 : Format->getFirstArg() - 1, !b);
return false;
}
@@ -380,8 +394,8 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) {
///
/// This function goes through and does final semantic checking for these
/// builtins,
-Sema::OwningExprResult
-Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
+ExprResult
+Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
CallExpr *TheCall = (CallExpr *)TheCallResult.get();
DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
@@ -415,6 +429,10 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
return ExprError();
}
+ // The majority of builtins return a value, but a few have special return
+ // types, so allow them to override appropriately below.
+ QualType ResultType = ValType;
+
// We need to figure out which concrete builtin this maps onto. For example,
// __sync_fetch_and_add with a 2 byte object turns into
// __sync_fetch_and_add_2.
@@ -483,11 +501,13 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
case Builtin::BI__sync_bool_compare_and_swap:
BuiltinIndex = 11;
NumFixed = 2;
+ ResultType = Context.BoolTy;
break;
case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 12; break;
case Builtin::BI__sync_lock_release:
BuiltinIndex = 13;
NumFixed = 0;
+ ResultType = Context.VoidTy;
break;
}
@@ -508,19 +528,10 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
FunctionDecl *NewBuiltinDecl =
cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID,
TUScope, false, DRE->getLocStart()));
- const FunctionProtoType *BuiltinFT =
- NewBuiltinDecl->getType()->getAs<FunctionProtoType>();
-
- QualType OrigValType = ValType;
- ValType = BuiltinFT->getArgType(0)->getAs<PointerType>()->getPointeeType();
-
- // If the first type needs to be converted (e.g. void** -> int*), do it now.
- if (BuiltinFT->getArgType(0) != FirstArg->getType()) {
- ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_BitCast);
- TheCall->setArg(0, FirstArg);
- }
- // Next, walk the valid ones promoting to the right type.
+ // The first argument --- the pointer --- has a fixed type; we
+ // deduce the types of the rest of the arguments accordingly. Walk
+ // the remaining arguments, converting them to the deduced value type.
for (unsigned i = 0; i != NumFixed; ++i) {
Expr *Arg = TheCall->getArg(i+1);
@@ -529,14 +540,13 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
Arg = ICE->getSubExpr();
ICE->setSubExpr(0);
- ICE->Destroy(Context);
TheCall->setArg(i+1, Arg);
}
// GCC does an implicit conversion to the pointer or integer ValType. This
// can fail in some cases (1i -> int**), check for this error case now.
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
return ExprError();
@@ -546,7 +556,7 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
// pass in 42. The 42 gets converted to char. This is even more strange
// for things like 45.123 -> char, etc.
// FIXME: Do this check.
- ImpCastExprToType(Arg, ValType, Kind);
+ ImpCastExprToType(Arg, ValType, Kind, VK_RValue, &BasePath);
TheCall->setArg(i+1, Arg);
}
@@ -560,28 +570,10 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) {
UsualUnaryConversions(PromotedCall);
TheCall->setCallee(PromotedCall);
- // Change the result type of the call to match the result type of the decl.
- TheCall->setType(NewBuiltinDecl->getCallResultType());
-
- // If the value type was converted to an integer when processing the
- // arguments (e.g. void* -> int), we need to convert the result back.
- if (!Context.hasSameUnqualifiedType(ValType, OrigValType)) {
- Expr *E = TheCallResult.takeAs<Expr>();
-
- assert(ValType->isIntegerType() &&
- "We always convert atomic operation values to integers.");
- // FIXME: Handle floating point value type here too.
- CastExpr::CastKind Kind;
- if (OrigValType->isIntegerType())
- Kind = CastExpr::CK_IntegralCast;
- else if (OrigValType->hasPointerRepresentation())
- Kind = CastExpr::CK_IntegralToPointer;
- else
- llvm_unreachable("Unhandled original value type!");
-
- ImpCastExprToType(E, OrigValType, Kind);
- return Owned(E);
- }
+ // Change the result type of the call to match the original value type. This
+ // is arbitrary, but the codegen for these builtins ins design to handle it
+ // gracefully.
+ TheCall->setType(ResultType);
return move(TheCallResult);
}
@@ -604,16 +596,11 @@ bool Sema::CheckObjCString(Expr *Arg) {
return true;
}
- const char *Data = Literal->getStrData();
- unsigned Length = Literal->getByteLength();
-
- for (unsigned i = 0; i < Length; ++i) {
- if (!Data[i]) {
- Diag(getLocationOfStringLiteralByte(Literal, i),
- diag::warn_cfstring_literal_contains_nul_character)
- << Arg->getSourceRange();
- break;
- }
+ size_t NulPos = Literal->getString().find('\0');
+ if (NulPos != llvm::StringRef::npos) {
+ Diag(getLocationOfStringLiteralByte(Literal, NulPos),
+ diag::warn_cfstring_literal_contains_nul_character)
+ << Arg->getSourceRange();
}
return false;
@@ -753,7 +740,6 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) &&
"promotion from float to double is the only expected cast here");
Cast->setSubExpr(0);
- Cast->Destroy(Context);
TheCall->setArg(NumArgs-1, CastArg);
OrigArg = CastArg;
}
@@ -764,7 +750,7 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) {
/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything.
-Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
+ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
if (TheCall->getNumArgs() < 2)
return ExprError(Diag(TheCall->getLocEnd(),
diag::err_typecheck_call_too_few_args_at_least)
@@ -797,7 +783,7 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
// with mask. If so, verify that RHS is an integer vector type with the
// same number of elts as lhs.
if (TheCall->getNumArgs() == 2) {
- if (!RHSType->isIntegerType() ||
+ if (!RHSType->hasIntegerRepresentation() ||
RHSType->getAs<VectorType>()->getNumElements() != numElements)
Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector)
<< SourceRange(TheCall->getArg(1)->getLocStart(),
@@ -941,29 +927,31 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) {
// Handle i > 1 ? "x" : "y", recursivelly
bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg) {
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf) {
+
if (E->isTypeDependent() || E->isValueDependent())
return false;
switch (E->getStmtClass()) {
case Stmt::ConditionalOperatorClass: {
const ConditionalOperator *C = cast<ConditionalOperator>(E);
- return SemaCheckStringLiteral(C->getTrueExpr(), TheCall,
- HasVAListArg, format_idx, firstDataArg)
- && SemaCheckStringLiteral(C->getRHS(), TheCall,
- HasVAListArg, format_idx, firstDataArg);
+ return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg,
+ format_idx, firstDataArg, isPrintf)
+ && SemaCheckStringLiteral(C->getRHS(), TheCall, HasVAListArg,
+ format_idx, firstDataArg, isPrintf);
}
case Stmt::ImplicitCastExprClass: {
const ImplicitCastExpr *Expr = cast<ImplicitCastExpr>(E);
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
- format_idx, firstDataArg);
+ format_idx, firstDataArg, isPrintf);
}
case Stmt::ParenExprClass: {
const ParenExpr *Expr = cast<ParenExpr>(E);
return SemaCheckStringLiteral(Expr->getSubExpr(), TheCall, HasVAListArg,
- format_idx, firstDataArg);
+ format_idx, firstDataArg, isPrintf);
}
case Stmt::DeclRefExprClass: {
@@ -985,7 +973,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
if (isConstant) {
if (const Expr *Init = VD->getAnyInitializer())
return SemaCheckStringLiteral(Init, TheCall,
- HasVAListArg, format_idx, firstDataArg);
+ HasVAListArg, format_idx, firstDataArg,
+ isPrintf);
}
// For vprintf* functions (i.e., HasVAListArg==true), we add a
@@ -1025,7 +1014,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
const Expr *Arg = CE->getArg(ArgIndex - 1);
return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg,
- format_idx, firstDataArg);
+ format_idx, firstDataArg, isPrintf);
}
}
}
@@ -1043,8 +1032,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
StrE = cast<StringLiteral>(E);
if (StrE) {
- CheckPrintfString(StrE, E, TheCall, HasVAListArg, format_idx,
- firstDataArg);
+ CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx,
+ firstDataArg, isPrintf);
return true;
}
@@ -1059,7 +1048,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
void
Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
const CallExpr *TheCall) {
- for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end();
+ for (NonNullAttr::args_iterator i = NonNull->args_begin(),
+ e = NonNull->args_end();
i != e; ++i) {
const Expr *ArgExpr = TheCall->getArg(*i);
if (ArgExpr->isNullPointerConstant(Context,
@@ -1069,55 +1059,13 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull,
}
}
-/// CheckPrintfArguments - Check calls to printf (and similar functions) for
-/// correct use of format strings.
-///
-/// HasVAListArg - A predicate indicating whether the printf-like
-/// function is passed an explicit va_arg argument (e.g., vprintf)
-///
-/// format_idx - The index into Args for the format string.
-///
-/// Improper format strings to functions in the printf family can be
-/// the source of bizarre bugs and very serious security holes. A
-/// good source of information is available in the following paper
-/// (which includes additional references):
-///
-/// FormatGuard: Automatic Protection From printf Format String
-/// Vulnerabilities, Proceedings of the 10th USENIX Security Symposium, 2001.
-///
-/// TODO:
-/// Functionality implemented:
-///
-/// We can statically check the following properties for string
-/// literal format strings for non v.*printf functions (where the
-/// arguments are passed directly):
-//
-/// (1) Are the number of format conversions equal to the number of
-/// data arguments?
-///
-/// (2) Does each format conversion correctly match the type of the
-/// corresponding data argument?
-///
-/// Moreover, for all printf functions we can:
-///
-/// (3) Check for a missing format string (when not caught by type checking).
-///
-/// (4) Check for no-operation flags; e.g. using "#" with format
-/// conversion 'c' (TODO)
-///
-/// (5) Check the use of '%n', a major source of security holes.
-///
-/// (6) Check for malformed format conversions that don't specify anything.
-///
-/// (7) Check for empty format strings. e.g: printf("");
-///
-/// (8) Check that the format string is a wide literal.
-///
-/// All of these checks can be done by parsing the format string.
-///
+/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar
+/// functions) for correct use of format strings.
void
-Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg) {
+Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg,
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf) {
+
const Expr *Fn = TheCall->getCallee();
// The way the format attribute works in GCC, the implicit this argument
@@ -1132,9 +1080,9 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
--firstDataArg;
}
- // CHECK: printf-like function is called with no format string.
+ // CHECK: printf/scanf-like function is called with no format string.
if (format_idx >= TheCall->getNumArgs()) {
- Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string)
+ Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string)
<< Fn->getSourceRange();
return;
}
@@ -1154,23 +1102,24 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg,
// ObjC string uses the same format specifiers as C string, so we can use
// the same format string checking logic for both ObjC and C strings.
if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx,
- firstDataArg))
+ firstDataArg, isPrintf))
return; // Literal format string found, check done!
// If there are no arguments specified, warn with -Wformat-security, otherwise
// warn only with -Wformat-nonliteral.
if (TheCall->getNumArgs() == format_idx+1)
Diag(TheCall->getArg(format_idx)->getLocStart(),
- diag::warn_printf_nonliteral_noargs)
+ diag::warn_format_nonliteral_noargs)
<< OrigFormatExpr->getSourceRange();
else
Diag(TheCall->getArg(format_idx)->getLocStart(),
- diag::warn_printf_nonliteral)
+ diag::warn_format_nonliteral)
<< OrigFormatExpr->getSourceRange();
}
namespace {
-class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
+class CheckFormatHandler : public analyze_format_string::FormatStringHandler {
+protected:
Sema &S;
const StringLiteral *FExpr;
const Expr *OrigFormatExpr;
@@ -1185,7 +1134,7 @@ class CheckPrintfHandler : public analyze_printf::FormatStringHandler {
bool usesPositionalArgs;
bool atFirstArg;
public:
- CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+ CheckFormatHandler(Sema &s, const StringLiteral *fexpr,
const Expr *origFormatExpr, unsigned firstDataArg,
unsigned numDataArgs, bool isObjCLiteral,
const char *beg, bool hasVAListArg,
@@ -1203,55 +1152,43 @@ public:
void DoneProcessing();
- void HandleIncompleteFormatSpecifier(const char *startSpecifier,
- unsigned specifierLen);
-
- bool
- HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen);
-
+ void HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen);
+
virtual void HandleInvalidPosition(const char *startSpecifier,
unsigned specifierLen,
- analyze_printf::PositionContext p);
+ analyze_format_string::PositionContext p);
virtual void HandleZeroPosition(const char *startPos, unsigned posLen);
void HandleNullChar(const char *nullCharacter);
- bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen);
-private:
+protected:
+ bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc,
+ const char *startSpec,
+ unsigned specifierLen,
+ const char *csStart, unsigned csLen);
+
SourceRange getFormatStringRange();
- CharSourceRange getFormatSpecifierRange(const char *startSpecifier,
- unsigned specifierLen);
+ CharSourceRange getSpecifierRange(const char *startSpecifier,
+ unsigned specifierLen);
SourceLocation getLocationOfByte(const char *x);
- bool HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned k,
- const char *startSpecifier, unsigned specifierLen);
- void HandleInvalidAmount(const analyze_printf::FormatSpecifier &FS,
- const analyze_printf::OptionalAmount &Amt,
- unsigned type,
- const char *startSpecifier, unsigned specifierLen);
- void HandleFlag(const analyze_printf::FormatSpecifier &FS,
- const analyze_printf::OptionalFlag &flag,
- const char *startSpecifier, unsigned specifierLen);
- void HandleIgnoredFlag(const analyze_printf::FormatSpecifier &FS,
- const analyze_printf::OptionalFlag &ignoredFlag,
- const analyze_printf::OptionalFlag &flag,
- const char *startSpecifier, unsigned specifierLen);
-
const Expr *getDataArg(unsigned i) const;
+
+ bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS,
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen,
+ unsigned argIndex);
};
}
-SourceRange CheckPrintfHandler::getFormatStringRange() {
+SourceRange CheckFormatHandler::getFormatStringRange() {
return OrigFormatExpr->getSourceRange();
}
-CharSourceRange CheckPrintfHandler::
-getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
+CharSourceRange CheckFormatHandler::
+getSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
SourceLocation Start = getLocationOfByte(startSpecifier);
SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1);
@@ -1261,39 +1198,67 @@ getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
return CharSourceRange::getCharRange(Start, End);
}
-SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) {
+SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) {
return S.getLocationOfStringLiteralByte(FExpr, x - Beg);
}
-void CheckPrintfHandler::
-HandleIncompleteFormatSpecifier(const char *startSpecifier,
- unsigned specifierLen) {
+void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier,
+ unsigned specifierLen){
SourceLocation Loc = getLocationOfByte(startSpecifier);
S.Diag(Loc, diag::warn_printf_incomplete_specifier)
- << getFormatSpecifierRange(startSpecifier, specifierLen);
+ << getSpecifierRange(startSpecifier, specifierLen);
}
void
-CheckPrintfHandler::HandleInvalidPosition(const char *startPos, unsigned posLen,
- analyze_printf::PositionContext p) {
+CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen,
+ analyze_format_string::PositionContext p) {
SourceLocation Loc = getLocationOfByte(startPos);
- S.Diag(Loc, diag::warn_printf_invalid_positional_specifier)
- << (unsigned) p << getFormatSpecifierRange(startPos, posLen);
+ S.Diag(Loc, diag::warn_format_invalid_positional_specifier)
+ << (unsigned) p << getSpecifierRange(startPos, posLen);
}
-void CheckPrintfHandler::HandleZeroPosition(const char *startPos,
+void CheckFormatHandler::HandleZeroPosition(const char *startPos,
unsigned posLen) {
SourceLocation Loc = getLocationOfByte(startPos);
- S.Diag(Loc, diag::warn_printf_zero_positional_specifier)
- << getFormatSpecifierRange(startPos, posLen);
+ S.Diag(Loc, diag::warn_format_zero_positional_specifier)
+ << getSpecifierRange(startPos, posLen);
+}
+
+void CheckFormatHandler::HandleNullChar(const char *nullCharacter) {
+ // The presence of a null character is likely an error.
+ S.Diag(getLocationOfByte(nullCharacter),
+ diag::warn_printf_format_string_contains_null_char)
+ << getFormatStringRange();
}
-bool CheckPrintfHandler::
-HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
- const char *startSpecifier,
- unsigned specifierLen) {
+const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
+ return TheCall->getArg(FirstDataArg + i);
+}
- unsigned argIndex = FS.getArgIndex();
+void CheckFormatHandler::DoneProcessing() {
+ // Does the number of data arguments exceed the number of
+ // format conversions in the format string?
+ if (!HasVAListArg) {
+ // Find any arguments that weren't covered.
+ CoveredArgs.flip();
+ signed notCoveredArg = CoveredArgs.find_first();
+ if (notCoveredArg >= 0) {
+ assert((unsigned)notCoveredArg < NumDataArgs);
+ S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(),
+ diag::warn_printf_data_arg_not_used)
+ << getFormatStringRange();
+ }
+ }
+}
+
+bool
+CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
+ SourceLocation Loc,
+ const char *startSpec,
+ unsigned specifierLen,
+ const char *csStart,
+ unsigned csLen) {
+
bool keepGoing = true;
if (argIndex < NumDataArgs) {
// Consider the argument coverered, even though the specifier doesn't
@@ -1308,32 +1273,95 @@ HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
// gibberish when trying to match arguments.
keepGoing = false;
}
+
+ S.Diag(Loc, diag::warn_format_invalid_conversion)
+ << llvm::StringRef(csStart, csLen)
+ << getSpecifierRange(startSpec, specifierLen);
+
+ return keepGoing;
+}
- const analyze_printf::ConversionSpecifier &CS =
- FS.getConversionSpecifier();
- SourceLocation Loc = getLocationOfByte(CS.getStart());
- S.Diag(Loc, diag::warn_printf_invalid_conversion)
- << llvm::StringRef(CS.getStart(), CS.getLength())
- << getFormatSpecifierRange(startSpecifier, specifierLen);
+bool
+CheckFormatHandler::CheckNumArgs(
+ const analyze_format_string::FormatSpecifier &FS,
+ const analyze_format_string::ConversionSpecifier &CS,
+ const char *startSpecifier, unsigned specifierLen, unsigned argIndex) {
- return keepGoing;
+ if (argIndex >= NumDataArgs) {
+ if (FS.usesPositionalArg()) {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_positional_arg_exceeds_data_args)
+ << (argIndex+1) << NumDataArgs
+ << getSpecifierRange(startSpecifier, specifierLen);
+ }
+ else {
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_printf_insufficient_data_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ }
+
+ return false;
+ }
+ return true;
}
-void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) {
- // The presence of a null character is likely an error.
- S.Diag(getLocationOfByte(nullCharacter),
- diag::warn_printf_format_string_contains_null_char)
- << getFormatStringRange();
+//===--- CHECK: Printf format string checking ------------------------------===//
+
+namespace {
+class CheckPrintfHandler : public CheckFormatHandler {
+public:
+ CheckPrintfHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, isObjCLiteral, beg, hasVAListArg,
+ theCall, formatIdx) {}
+
+
+ bool HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalAmount &Amt,
+ unsigned type,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleFlag(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier, unsigned specifierLen);
+ void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS,
+ const analyze_printf::OptionalFlag &ignoredFlag,
+ const analyze_printf::OptionalFlag &flag,
+ const char *startSpecifier, unsigned specifierLen);
+};
}
-const Expr *CheckPrintfHandler::getDataArg(unsigned i) const {
- return TheCall->getArg(FirstDataArg + i);
+bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
+ const analyze_printf::PrintfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+ const analyze_printf::PrintfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+
+ return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+ getLocationOfByte(CS.getStart()),
+ startSpecifier, specifierLen,
+ CS.getStart(), CS.getLength());
}
-bool
-CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
- unsigned k, const char *startSpecifier,
- unsigned specifierLen) {
+bool CheckPrintfHandler::HandleAmount(
+ const analyze_format_string::OptionalAmount &Amt,
+ unsigned k, const char *startSpecifier,
+ unsigned specifierLen) {
if (Amt.hasDataArgument()) {
if (!HasVAListArg) {
@@ -1341,7 +1369,7 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
if (argIndex >= NumDataArgs) {
S.Diag(getLocationOfByte(Amt.getStart()),
diag::warn_printf_asterisk_missing_arg)
- << k << getFormatSpecifierRange(startSpecifier, specifierLen);
+ << k << getSpecifierRange(startSpecifier, specifierLen);
// Don't do any more checking. We will just emit
// spurious errors.
return false;
@@ -1363,7 +1391,7 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
diag::warn_printf_asterisk_wrong_type)
<< k
<< ATR.getRepresentativeType(S.Context) << T
- << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << getSpecifierRange(startSpecifier, specifierLen)
<< Arg->getSourceRange();
// Don't do any more checking. We will just emit
// spurious errors.
@@ -1375,20 +1403,21 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt,
}
void CheckPrintfHandler::HandleInvalidAmount(
- const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::PrintfSpecifier &FS,
const analyze_printf::OptionalAmount &Amt,
unsigned type,
const char *startSpecifier,
unsigned specifierLen) {
- const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+ const analyze_printf::PrintfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
switch (Amt.getHowSpecified()) {
case analyze_printf::OptionalAmount::Constant:
S.Diag(getLocationOfByte(Amt.getStart()),
diag::warn_printf_nonsensical_optional_amount)
<< type
<< CS.toString()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
- << FixItHint::CreateRemoval(getFormatSpecifierRange(Amt.getStart(),
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(),
Amt.getConstantLength()));
break;
@@ -1397,26 +1426,27 @@ void CheckPrintfHandler::HandleInvalidAmount(
diag::warn_printf_nonsensical_optional_amount)
<< type
<< CS.toString()
- << getFormatSpecifierRange(startSpecifier, specifierLen);
+ << getSpecifierRange(startSpecifier, specifierLen);
break;
}
}
-void CheckPrintfHandler::HandleFlag(const analyze_printf::FormatSpecifier &FS,
+void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS,
const analyze_printf::OptionalFlag &flag,
const char *startSpecifier,
unsigned specifierLen) {
// Warn about pointless flag with a fixit removal.
- const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier();
+ const analyze_printf::PrintfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
S.Diag(getLocationOfByte(flag.getPosition()),
diag::warn_printf_nonsensical_flag)
<< flag.toString() << CS.toString()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
- << FixItHint::CreateRemoval(getFormatSpecifierRange(flag.getPosition(), 1));
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(flag.getPosition(), 1));
}
void CheckPrintfHandler::HandleIgnoredFlag(
- const analyze_printf::FormatSpecifier &FS,
+ const analyze_printf::PrintfSpecifier &FS,
const analyze_printf::OptionalFlag &ignoredFlag,
const analyze_printf::OptionalFlag &flag,
const char *startSpecifier,
@@ -1425,30 +1455,33 @@ void CheckPrintfHandler::HandleIgnoredFlag(
S.Diag(getLocationOfByte(ignoredFlag.getPosition()),
diag::warn_printf_ignored_flag)
<< ignoredFlag.toString() << flag.toString()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
- << FixItHint::CreateRemoval(getFormatSpecifierRange(
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(
ignoredFlag.getPosition(), 1));
}
bool
-CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
+CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
&FS,
const char *startSpecifier,
unsigned specifierLen) {
+ using namespace analyze_format_string;
using namespace analyze_printf;
- const ConversionSpecifier &CS = FS.getConversionSpecifier();
+ const PrintfConversionSpecifier &CS = FS.getConversionSpecifier();
- if (atFirstArg) {
- atFirstArg = false;
- usesPositionalArgs = FS.usesPositionalArg();
- }
- else if (usesPositionalArgs != FS.usesPositionalArg()) {
- // Cannot mix-and-match positional and non-positional arguments.
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_mix_positional_nonpositional_args)
- << getFormatSpecifierRange(startSpecifier, specifierLen);
- return false;
+ if (FS.consumesDataArgument()) {
+ if (atFirstArg) {
+ atFirstArg = false;
+ usesPositionalArgs = FS.usesPositionalArg();
+ }
+ else if (usesPositionalArgs != FS.usesPositionalArg()) {
+ // Cannot mix-and-match positional and non-positional arguments.
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_format_mix_positional_nonpositional_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ return false;
+ }
}
// First check if the field width, precision, and conversion specifier
@@ -1481,7 +1514,8 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
// Check for using an Objective-C specific conversion specifier
// in a non-ObjC literal.
if (!IsObjCLiteral && CS.isObjCArg()) {
- return HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen);
+ return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
+ specifierLen);
}
// Check for invalid use of field width
@@ -1520,17 +1554,17 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
const LengthModifier &LM = FS.getLengthModifier();
if (!FS.hasValidLengthModifier())
S.Diag(getLocationOfByte(LM.getStart()),
- diag::warn_printf_nonsensical_length)
+ diag::warn_format_nonsensical_length)
<< LM.toString() << CS.toString()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
- << FixItHint::CreateRemoval(getFormatSpecifierRange(LM.getStart(),
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(),
LM.getLength()));
// Are we using '%n'?
- if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) {
+ if (CS.getKind() == ConversionSpecifier::nArg) {
// Issue a warning about this being a possible security issue.
S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back)
- << getFormatSpecifierRange(startSpecifier, specifierLen);
+ << getSpecifierRange(startSpecifier, specifierLen);
// Continue checking the other format specifiers.
return true;
}
@@ -1539,22 +1573,8 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
if (HasVAListArg)
return true;
- if (argIndex >= NumDataArgs) {
- if (FS.usesPositionalArg()) {
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_positional_arg_exceeds_data_args)
- << (argIndex+1) << NumDataArgs
- << getFormatSpecifierRange(startSpecifier, specifierLen);
- }
- else {
- S.Diag(getLocationOfByte(CS.getStart()),
- diag::warn_printf_insufficient_data_args)
- << getFormatSpecifierRange(startSpecifier, specifierLen);
- }
-
- // Don't do any more checking.
+ if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
return false;
- }
// Now type check the data expression that matches the
// format specifier.
@@ -1570,7 +1590,7 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
return true;
// We may be able to offer a FixItHint if it is a supported type.
- FormatSpecifier fixedFS = FS;
+ PrintfSpecifier fixedFS = FS;
bool success = fixedFS.fixType(Ex->getType());
if (success) {
@@ -1579,20 +1599,23 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
llvm::raw_svector_ostream os(buf);
fixedFS.toString(os);
+ // FIXME: getRepresentativeType() perhaps should return a string
+ // instead of a QualType to better handle when the representative
+ // type is 'wint_t' (which is defined in the system headers).
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_conversion_argument_type_mismatch)
<< ATR.getRepresentativeType(S.Context) << Ex->getType()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << getSpecifierRange(startSpecifier, specifierLen)
<< Ex->getSourceRange()
<< FixItHint::CreateReplacement(
- getFormatSpecifierRange(startSpecifier, specifierLen),
+ getSpecifierRange(startSpecifier, specifierLen),
os.str());
}
else {
S.Diag(getLocationOfByte(CS.getStart()),
diag::warn_printf_conversion_argument_type_mismatch)
<< ATR.getRepresentativeType(S.Context) << Ex->getType()
- << getFormatSpecifierRange(startSpecifier, specifierLen)
+ << getSpecifierRange(startSpecifier, specifierLen)
<< Ex->getSourceRange();
}
}
@@ -1600,54 +1623,173 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier
return true;
}
-void CheckPrintfHandler::DoneProcessing() {
- // Does the number of data arguments exceed the number of
- // format conversions in the format string?
- if (!HasVAListArg) {
- // Find any arguments that weren't covered.
- CoveredArgs.flip();
- signed notCoveredArg = CoveredArgs.find_first();
- if (notCoveredArg >= 0) {
- assert((unsigned)notCoveredArg < NumDataArgs);
- S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(),
- diag::warn_printf_data_arg_not_used)
- << getFormatStringRange();
+//===--- CHECK: Scanf format string checking ------------------------------===//
+
+namespace {
+class CheckScanfHandler : public CheckFormatHandler {
+public:
+ CheckScanfHandler(Sema &s, const StringLiteral *fexpr,
+ const Expr *origFormatExpr, unsigned firstDataArg,
+ unsigned numDataArgs, bool isObjCLiteral,
+ const char *beg, bool hasVAListArg,
+ const CallExpr *theCall, unsigned formatIdx)
+ : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg,
+ numDataArgs, isObjCLiteral, beg, hasVAListArg,
+ theCall, formatIdx) {}
+
+ bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ bool HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen);
+
+ void HandleIncompleteScanList(const char *start, const char *end);
+};
+}
+
+void CheckScanfHandler::HandleIncompleteScanList(const char *start,
+ const char *end) {
+ S.Diag(getLocationOfByte(end), diag::warn_scanf_scanlist_incomplete)
+ << getSpecifierRange(start, end - start);
+}
+
+bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ const analyze_scanf::ScanfConversionSpecifier &CS =
+ FS.getConversionSpecifier();
+
+ return HandleInvalidConversionSpecifier(FS.getArgIndex(),
+ getLocationOfByte(CS.getStart()),
+ startSpecifier, specifierLen,
+ CS.getStart(), CS.getLength());
+}
+
+bool CheckScanfHandler::HandleScanfSpecifier(
+ const analyze_scanf::ScanfSpecifier &FS,
+ const char *startSpecifier,
+ unsigned specifierLen) {
+
+ using namespace analyze_scanf;
+ using namespace analyze_format_string;
+
+ const ScanfConversionSpecifier &CS = FS.getConversionSpecifier();
+
+ // Handle case where '%' and '*' don't consume an argument. These shouldn't
+ // be used to decide if we are using positional arguments consistently.
+ if (FS.consumesDataArgument()) {
+ if (atFirstArg) {
+ atFirstArg = false;
+ usesPositionalArgs = FS.usesPositionalArg();
+ }
+ else if (usesPositionalArgs != FS.usesPositionalArg()) {
+ // Cannot mix-and-match positional and non-positional arguments.
+ S.Diag(getLocationOfByte(CS.getStart()),
+ diag::warn_format_mix_positional_nonpositional_args)
+ << getSpecifierRange(startSpecifier, specifierLen);
+ return false;
+ }
+ }
+
+ // Check if the field with is non-zero.
+ const OptionalAmount &Amt = FS.getFieldWidth();
+ if (Amt.getHowSpecified() == OptionalAmount::Constant) {
+ if (Amt.getConstantAmount() == 0) {
+ const CharSourceRange &R = getSpecifierRange(Amt.getStart(),
+ Amt.getConstantLength());
+ S.Diag(getLocationOfByte(Amt.getStart()),
+ diag::warn_scanf_nonzero_width)
+ << R << FixItHint::CreateRemoval(R);
}
}
+
+ if (!FS.consumesDataArgument()) {
+ // FIXME: Technically specifying a precision or field width here
+ // makes no sense. Worth issuing a warning at some point.
+ return true;
+ }
+
+ // Consume the argument.
+ unsigned argIndex = FS.getArgIndex();
+ if (argIndex < NumDataArgs) {
+ // The check to see if the argIndex is valid will come later.
+ // We set the bit here because we may exit early from this
+ // function if we encounter some other error.
+ CoveredArgs.set(argIndex);
+ }
+
+ // Check the length modifier is valid with the given conversion specifier.
+ const LengthModifier &LM = FS.getLengthModifier();
+ if (!FS.hasValidLengthModifier()) {
+ S.Diag(getLocationOfByte(LM.getStart()),
+ diag::warn_format_nonsensical_length)
+ << LM.toString() << CS.toString()
+ << getSpecifierRange(startSpecifier, specifierLen)
+ << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(),
+ LM.getLength()));
+ }
+
+ // The remaining checks depend on the data arguments.
+ if (HasVAListArg)
+ return true;
+
+ if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
+ return false;
+
+ // FIXME: Check that the argument type matches the format specifier.
+
+ return true;
}
-void Sema::CheckPrintfString(const StringLiteral *FExpr,
+void Sema::CheckFormatString(const StringLiteral *FExpr,
const Expr *OrigFormatExpr,
const CallExpr *TheCall, bool HasVAListArg,
- unsigned format_idx, unsigned firstDataArg) {
-
+ unsigned format_idx, unsigned firstDataArg,
+ bool isPrintf) {
+
// CHECK: is the format string a wide literal?
if (FExpr->isWide()) {
Diag(FExpr->getLocStart(),
- diag::warn_printf_format_string_is_wide_literal)
+ diag::warn_format_string_is_wide_literal)
<< OrigFormatExpr->getSourceRange();
return;
}
-
+
// Str - The format string. NOTE: this is NOT null-terminated!
- const char *Str = FExpr->getStrData();
-
+ llvm::StringRef StrRef = FExpr->getString();
+ const char *Str = StrRef.data();
+ unsigned StrLen = StrRef.size();
+
// CHECK: empty format string?
- unsigned StrLen = FExpr->getByteLength();
-
if (StrLen == 0) {
- Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string)
+ Diag(FExpr->getLocStart(), diag::warn_empty_format_string)
<< OrigFormatExpr->getSourceRange();
return;
}
-
- CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
- TheCall->getNumArgs() - firstDataArg,
- isa<ObjCStringLiteral>(OrigFormatExpr), Str,
- HasVAListArg, TheCall, format_idx);
-
- if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen))
- H.DoneProcessing();
+
+ if (isPrintf) {
+ CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
+ TheCall->getNumArgs() - firstDataArg,
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+ HasVAListArg, TheCall, format_idx);
+
+ if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen))
+ H.DoneProcessing();
+ }
+ else {
+ CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg,
+ TheCall->getNumArgs() - firstDataArg,
+ isa<ObjCStringLiteral>(OrigFormatExpr), Str,
+ HasVAListArg, TheCall, format_idx);
+
+ if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen))
+ H.DoneProcessing();
+ }
}
//===--- CHECK: Return Address of Stack Variable --------------------------===//
@@ -1729,7 +1871,7 @@ static DeclRefExpr* EvalAddr(Expr *E) {
// is AddrOf. All others don't make sense as pointers.
UnaryOperator *U = cast<UnaryOperator>(E);
- if (U->getOpcode() == UnaryOperator::AddrOf)
+ if (U->getOpcode() == UO_AddrOf)
return EvalVal(U->getSubExpr());
else
return NULL;
@@ -1739,9 +1881,9 @@ static DeclRefExpr* EvalAddr(Expr *E) {
// Handle pointer arithmetic. All other binary operators are not valid
// in this context.
BinaryOperator *B = cast<BinaryOperator>(E);
- BinaryOperator::Opcode op = B->getOpcode();
+ BinaryOperatorKind op = B->getOpcode();
- if (op != BinaryOperator::Add && op != BinaryOperator::Sub)
+ if (op != BO_Add && op != BO_Sub)
return NULL;
Expr *Base = B->getLHS();
@@ -1814,7 +1956,7 @@ static DeclRefExpr* EvalAddr(Expr *E) {
/// EvalVal - This function is complements EvalAddr in the mutual recursion.
/// See the comments for EvalAddr for more details.
static DeclRefExpr* EvalVal(Expr *E) {
-
+do {
// We should only be called for evaluating non-pointer expressions, or
// expressions with a pointer type that are not used as references but instead
// are l-values (e.g., DeclRefExpr with a pointer type).
@@ -1823,6 +1965,15 @@ static DeclRefExpr* EvalVal(Expr *E) {
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
switch (E->getStmtClass()) {
+ case Stmt::ImplicitCastExprClass: {
+ ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
+ if (IE->getValueKind() == VK_LValue) {
+ E = IE->getSubExpr();
+ continue;
+ }
+ return NULL;
+ }
+
case Stmt::DeclRefExprClass: {
// DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking
// at code that refers to a variable's name. We check if it has local
@@ -1835,9 +1986,11 @@ static DeclRefExpr* EvalVal(Expr *E) {
return NULL;
}
- case Stmt::ParenExprClass:
+ case Stmt::ParenExprClass: {
// Ignore parentheses.
- return EvalVal(cast<ParenExpr>(E)->getSubExpr());
+ E = cast<ParenExpr>(E)->getSubExpr();
+ continue;
+ }
case Stmt::UnaryOperatorClass: {
// The only unary operator that make sense to handle here
@@ -1845,7 +1998,7 @@ static DeclRefExpr* EvalVal(Expr *E) {
// handling all sorts of rvalues passed to a unary operator.
UnaryOperator *U = cast<UnaryOperator>(E);
- if (U->getOpcode() == UnaryOperator::Deref)
+ if (U->getOpcode() == UO_Deref)
return EvalAddr(U->getSubExpr());
return NULL;
@@ -1876,16 +2029,22 @@ static DeclRefExpr* EvalVal(Expr *E) {
MemberExpr *M = cast<MemberExpr>(E);
// Check for indirect access. We only want direct field accesses.
- if (!M->isArrow())
- return EvalVal(M->getBase());
- else
+ if (M->isArrow())
return NULL;
+
+ // Check whether the member type is itself a reference, in which case
+ // we're not going to refer to the member, but to what the member refers to.
+ if (M->getMemberDecl()->getType()->isReferenceType())
+ return NULL;
+
+ return EvalVal(M->getBase());
}
// Everything else: we simply don't reason about them.
default:
return NULL;
}
+} while (true);
}
//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
@@ -1954,7 +2113,6 @@ struct IntRange {
/// True if the int is known not to have negative values.
bool NonNegative;
- IntRange() {}
IntRange(unsigned Width, bool NonNegative)
: Width(Width), NonNegative(NonNegative)
{}
@@ -2063,13 +2221,13 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
// user has an explicit widening cast, we should treat the value as
// being of the new, wider type.
if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
- if (CE->getCastKind() == CastExpr::CK_NoOp)
+ if (CE->getCastKind() == CK_NoOp)
return GetExprRange(C, CE->getSubExpr(), MaxWidth);
IntRange OutputTypeRange = IntRange::forType(C, CE->getType());
- bool isIntegerCast = (CE->getCastKind() == CastExpr::CK_IntegralCast);
- if (!isIntegerCast && CE->getCastKind() == CastExpr::CK_Unknown)
+ bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast);
+ if (!isIntegerCast && CE->getCastKind() == CK_Unknown)
isIntegerCast = CE->getSubExpr()->getType()->isIntegerType();
// Assume that non-integer casts can span the full range of the type.
@@ -2108,38 +2266,38 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
switch (BO->getOpcode()) {
// Boolean-valued operations are single-bit and positive.
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr:
- case BinaryOperator::LT:
- case BinaryOperator::GT:
- case BinaryOperator::LE:
- case BinaryOperator::GE:
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
return IntRange::forBoolType();
// The type of these compound assignments is the type of the LHS,
// so the RHS is not necessarily an integer.
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
- case BinaryOperator::RemAssign:
- case BinaryOperator::AddAssign:
- case BinaryOperator::SubAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
+ case BO_RemAssign:
+ case BO_AddAssign:
+ case BO_SubAssign:
return IntRange::forType(C, E->getType());
// Operations with opaque sources are black-listed.
- case BinaryOperator::PtrMemD:
- case BinaryOperator::PtrMemI:
+ case BO_PtrMemD:
+ case BO_PtrMemI:
return IntRange::forType(C, E->getType());
// Bitwise-and uses the *infinum* of the two source ranges.
- case BinaryOperator::And:
- case BinaryOperator::AndAssign:
+ case BO_And:
+ case BO_AndAssign:
return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth),
GetExprRange(C, BO->getRHS(), MaxWidth));
// Left shift gets black-listed based on a judgement call.
- case BinaryOperator::Shl:
+ case BO_Shl:
// ...except that we want to treat '1 << (blah)' as logically
// positive. It's an important idiom.
if (IntegerLiteral *I
@@ -2151,12 +2309,12 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
}
// fallthrough
- case BinaryOperator::ShlAssign:
+ case BO_ShlAssign:
return IntRange::forType(C, E->getType());
// Right shift by a constant can narrow its left argument.
- case BinaryOperator::Shr:
- case BinaryOperator::ShrAssign: {
+ case BO_Shr:
+ case BO_ShrAssign: {
IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth);
// If the shift amount is a positive constant, drop the width by
@@ -2175,11 +2333,11 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
}
// Comma acts as its right operand.
- case BinaryOperator::Comma:
+ case BO_Comma:
return GetExprRange(C, BO->getRHS(), MaxWidth);
// Black-list pointer subtractions.
- case BinaryOperator::Sub:
+ case BO_Sub:
if (BO->getLHS()->getType()->isPointerType())
return IntRange::forType(C, E->getType());
// fallthrough
@@ -2198,13 +2356,12 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) {
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
switch (UO->getOpcode()) {
// Boolean-valued operations are white-listed.
- case UnaryOperator::LNot:
+ case UO_LNot:
return IntRange::forBoolType();
// Operations with opaque sources are black-listed.
- case UnaryOperator::Deref:
- case UnaryOperator::AddrOf: // should be impossible
- case UnaryOperator::OffsetOf:
+ case UO_Deref:
+ case UO_AddrOf: // should be impossible
return IntRange::forType(C, E->getType());
default:
@@ -2277,20 +2434,20 @@ bool IsZero(Sema &S, Expr *E) {
}
void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) {
- BinaryOperator::Opcode op = E->getOpcode();
- if (op == BinaryOperator::LT && IsZero(S, E->getRHS())) {
+ BinaryOperatorKind op = E->getOpcode();
+ if (op == BO_LT && IsZero(S, E->getRHS())) {
S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
<< "< 0" << "false"
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (op == BinaryOperator::GE && IsZero(S, E->getRHS())) {
+ } else if (op == BO_GE && IsZero(S, E->getRHS())) {
S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison)
<< ">= 0" << "true"
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (op == BinaryOperator::GT && IsZero(S, E->getLHS())) {
+ } else if (op == BO_GT && IsZero(S, E->getLHS())) {
S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
<< "0 >" << "false"
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
- } else if (op == BinaryOperator::LE && IsZero(S, E->getLHS())) {
+ } else if (op == BO_LE && IsZero(S, E->getLHS())) {
S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison)
<< "0 <=" << "true"
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
@@ -2319,7 +2476,7 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
// We don't do anything special if this isn't an unsigned integral
// comparison: we're only interested in integral comparisons, and
// signed comparisons only happen in cases we don't care to warn about.
- if (!T->isUnsignedIntegerType())
+ if (!T->hasUnsignedIntegerRepresentation())
return AnalyzeImpConvsInComparison(S, E);
Expr *lex = E->getLHS()->IgnoreParenImpCasts();
@@ -2328,12 +2485,12 @@ void AnalyzeComparison(Sema &S, BinaryOperator *E) {
// Check to see if one of the (unmodified) operands is of different
// signedness.
Expr *signedOperand, *unsignedOperand;
- if (lex->getType()->isSignedIntegerType()) {
- assert(!rex->getType()->isSignedIntegerType() &&
+ if (lex->getType()->hasSignedIntegerRepresentation()) {
+ assert(!rex->getType()->hasSignedIntegerRepresentation() &&
"unsigned comparison between two signed integer expressions?");
signedOperand = lex;
unsignedOperand = rex;
- } else if (rex->getType()->isSignedIntegerType()) {
+ } else if (rex->getType()->hasSignedIntegerRepresentation()) {
signedOperand = rex;
unsignedOperand = lex;
} else {
@@ -2648,3 +2805,48 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
return HasInvalidParm;
}
+
+/// CheckCastAlign - Implements -Wcast-align, which warns when a
+/// pointer cast increases the alignment requirements.
+void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
+ // This is actually a lot of work to potentially be doing on every
+ // cast; don't do it if we're ignoring -Wcast_align (as is the default).
+ if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align)
+ == Diagnostic::Ignored)
+ return;
+
+ // Ignore dependent types.
+ if (T->isDependentType() || Op->getType()->isDependentType())
+ return;
+
+ // Require that the destination be a pointer type.
+ const PointerType *DestPtr = T->getAs<PointerType>();
+ if (!DestPtr) return;
+
+ // If the destination has alignment 1, we're done.
+ QualType DestPointee = DestPtr->getPointeeType();
+ if (DestPointee->isIncompleteType()) return;
+ CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee);
+ if (DestAlign.isOne()) return;
+
+ // Require that the source be a pointer type.
+ const PointerType *SrcPtr = Op->getType()->getAs<PointerType>();
+ if (!SrcPtr) return;
+ QualType SrcPointee = SrcPtr->getPointeeType();
+
+ // Whitelist casts from cv void*. We already implicitly
+ // whitelisted casts to cv void*, since they have alignment 1.
+ // Also whitelist casts involving incomplete types, which implicitly
+ // includes 'void'.
+ if (SrcPointee->isIncompleteType()) return;
+
+ CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee);
+ if (SrcAlign >= DestAlign) return;
+
+ Diag(TRange.getBegin(), diag::warn_cast_align)
+ << Op->getType() << T
+ << static_cast<unsigned>(SrcAlign.getQuantity())
+ << static_cast<unsigned>(DestAlign.getQuantity())
+ << TRange << Op->getSourceRange();
+}
+
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 55288750fd5f..f00d1cd20f1e 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -10,10 +10,14 @@
// This file defines the code-completion semantic actions.
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/MacroInfo.h"
@@ -21,11 +25,13 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
#include <list>
#include <map>
#include <vector>
using namespace clang;
+using namespace sema;
namespace {
/// \brief A container of code-completion results.
@@ -37,7 +43,7 @@ namespace {
/// filtered out (returns false).
typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
private:
/// \brief The actual results we have found.
@@ -130,17 +136,28 @@ namespace {
/// different levels of, e.g., the inheritance hierarchy.
std::list<ShadowMap> ShadowMaps;
+ /// \brief If we're potentially referring to a C++ member function, the set
+ /// of qualifiers applied to the object type.
+ Qualifiers ObjectTypeQualifiers;
+
+ /// \brief Whether the \p ObjectTypeQualifiers field is active.
+ bool HasObjectTypeQualifiers;
+
+ /// \brief The selector that we prefer.
+ Selector PreferredSelector;
+
void AdjustResultPriorityForPreferredType(Result &R);
public:
explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
- : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { }
+ : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false),
+ HasObjectTypeQualifiers(false) { }
/// \brief Whether we should include code patterns in the completion
/// results.
bool includeCodePatterns() const {
return SemaRef.CodeCompleter &&
- SemaRef.CodeCompleter->includeCodePatterns();
+ SemaRef.CodeCompleter->includeCodePatterns();
}
/// \brief Set the filter used for code-completion results.
@@ -161,6 +178,27 @@ namespace {
PreferredType = SemaRef.Context.getCanonicalType(T);
}
+ /// \brief Set the cv-qualifiers on the object type, for us in filtering
+ /// calls to member functions.
+ ///
+ /// When there are qualifiers in this set, they will be used to filter
+ /// out member functions that aren't available (because there will be a
+ /// cv-qualifier mismatch) or prefer functions with an exact qualifier
+ /// match.
+ void setObjectTypeQualifiers(Qualifiers Quals) {
+ ObjectTypeQualifiers = Quals;
+ HasObjectTypeQualifiers = true;
+ }
+
+ /// \brief Set the preferred selector.
+ ///
+ /// When an Objective-C method declaration result is added, and that
+ /// method's selector matches this preferred selector, we give that method
+ /// a slight priority boost.
+ void setPreferredSelector(Selector Sel) {
+ PreferredSelector = Sel;
+ }
+
/// \brief Specify whether nested-name-specifiers are allowed.
void allowNestedNameSpecifiers(bool Allow = true) {
AllowNestedNameSpecifiers = Allow;
@@ -227,6 +265,7 @@ namespace {
//@{
bool IsOrdinaryName(NamedDecl *ND) const;
bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
+ bool IsIntegralConstantValue(NamedDecl *ND) const;
bool IsOrdinaryNonValueName(NamedDecl *ND) const;
bool IsNestedNameSpecifier(NamedDecl *ND) const;
bool IsEnum(NamedDecl *ND) const;
@@ -238,6 +277,7 @@ namespace {
bool IsMember(NamedDecl *ND) const;
bool IsObjCIvar(NamedDecl *ND) const;
bool IsObjCMessageReceiver(NamedDecl *ND) const;
+ bool IsObjCCollection(NamedDecl *ND) const;
//@}
};
}
@@ -365,8 +405,12 @@ getRequiredQualification(ASTContext &Context,
DeclContext *Parent = TargetParents.back();
TargetParents.pop_back();
- if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent))
+ if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
+ if (!Namespace->getIdentifier())
+ continue;
+
Result = NestedNameSpecifier::Create(Context, Result, Namespace);
+ }
else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
Result = NestedNameSpecifier::Create(Context, Result,
false,
@@ -425,6 +469,12 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
if (isa<CXXConstructorDecl>(ND))
return false;
+ if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
+ ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
+ Filter != &ResultBuilder::IsNamespace &&
+ Filter != &ResultBuilder::IsNamespaceOrAlias))
+ AsNestedNameSpecifier = true;
+
// Filter out any unwanted results.
if (Filter && !(this->*Filter)(ND)) {
// Check whether it is interesting as a nested-name-specifier.
@@ -438,11 +488,7 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
}
return false;
- }
-
- if (Filter == &ResultBuilder::IsNestedNameSpecifier)
- AsNestedNameSpecifier = true;
-
+ }
// ... then it must be interesting!
return true;
}
@@ -455,13 +501,13 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
if (!SemaRef.getLangOptions().CPlusPlus)
return true;
- DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getLookupContext();
+ DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
return true;
- if (HiddenCtx == Hiding->getDeclContext()->getLookupContext())
+ if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
return true;
// We can refer to the result with the appropriate qualification. Do it.
@@ -475,21 +521,9 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
return false;
}
-enum SimplifiedTypeClass {
- STC_Arithmetic,
- STC_Array,
- STC_Block,
- STC_Function,
- STC_ObjectiveC,
- STC_Other,
- STC_Pointer,
- STC_Record,
- STC_Void
-};
-
/// \brief A simplified classification of types used to determine whether two
/// types are "similar enough" when adjusting priorities.
-static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) {
+SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (T->getTypeClass()) {
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
@@ -560,7 +594,7 @@ static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) {
/// \brief Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
-static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
+QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
@@ -594,9 +628,12 @@ void ResultBuilder::AdjustResultPriorityForPreferredType(Result &R) {
CanQualType TC = SemaRef.Context.getCanonicalType(T);
// Check for exactly-matching types (modulo qualifiers).
- if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
- R.Priority /= CCF_ExactTypeMatch;
- // Check for nearly-matching types, based on classification of each.
+ if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) {
+ if (PreferredType->isVoidType())
+ R.Priority += CCD_VoidMatch;
+ else
+ R.Priority /= CCF_ExactTypeMatch;
+ } // Check for nearly-matching types, based on classification of each.
else if ((getSimplifiedTypeClass(PreferredType)
== getSimplifiedTypeClass(TC)) &&
!(PreferredType->isEnumeralType() && TC->isEnumeralType()))
@@ -681,7 +718,14 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(CanonDecl))
return;
-
+
+ // If this is an Objective-C method declaration whose selector matches our
+ // preferred selector, give it a priority boost.
+ if (!PreferredSelector.isNull())
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
+ if (PreferredSelector == Method->getSelector())
+ R.Priority += CCD_SelectorMatch;
+
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
if (AsNestedNameSpecifier) {
@@ -689,7 +733,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
R.Priority = CCP_NestedNameSpecifier;
} else if (!PreferredType.isNull())
AdjustResultPriorityForPreferredType(R);
-
+
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
@@ -742,7 +786,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
}
else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
isa<CXXRecordDecl>(R.Declaration->getDeclContext()
- ->getLookupContext()))
+ ->getRedeclContext()))
R.QualifierIsInformative = true;
// If this result is supposed to have an informative qualifier, add one.
@@ -762,9 +806,30 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
if (InBaseClass)
R.Priority += CCD_InBaseClass;
+ // If this is an Objective-C method declaration whose selector matches our
+ // preferred selector, give it a priority boost.
+ if (!PreferredSelector.isNull())
+ if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
+ if (PreferredSelector == Method->getSelector())
+ R.Priority += CCD_SelectorMatch;
+
if (!PreferredType.isNull())
AdjustResultPriorityForPreferredType(R);
+ if (HasObjectTypeQualifiers)
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
+ if (Method->isInstance()) {
+ Qualifiers MethodQuals
+ = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
+ if (ObjectTypeQualifiers == MethodQuals)
+ R.Priority += CCD_ObjectQualifierMatch;
+ else if (ObjectTypeQualifiers - MethodQuals) {
+ // The method cannot be invoked, because doing so would drop
+ // qualifiers.
+ return;
+ }
+ }
+
// Insert this result into the set of results.
Results.push_back(R);
}
@@ -821,6 +886,17 @@ bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
return ND->getIdentifierNamespace() & IDNS;
}
+bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
+ if (!IsOrdinaryNonTypeName(ND))
+ return 0;
+
+ if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
+ if (VD->getType()->isIntegralOrEnumerationType())
+ return true;
+
+ return false;
+}
+
/// \brief Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
@@ -888,7 +964,10 @@ bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
/// \brief Determines whether the given declaration is a type.
bool ResultBuilder::IsType(NamedDecl *ND) const {
- return isa<TypeDecl>(ND);
+ if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
+ ND = Using->getTargetDecl();
+
+ return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
}
/// \brief Determines which members of a class should be visible via
@@ -944,6 +1023,20 @@ bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
return isObjCReceiverType(SemaRef.Context, T);
}
+bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
+ if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
+ (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
+ return false;
+
+ QualType T = getDeclUsageType(SemaRef.Context, ND);
+ if (T.isNull())
+ return false;
+
+ T = SemaRef.Context.getBaseElementType(T);
+ return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
+ T->isObjCIdType() ||
+ (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
+}
/// \rief Determines whether the given declaration is an Objective-C
/// instance variable.
@@ -971,7 +1064,7 @@ namespace {
/// \brief Add type specifiers for the current language as keyword results.
static void AddTypeSpecifierResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
Results.AddResult(Result("short", CCP_Type));
Results.AddResult(Result("long", CCP_Type));
Results.AddResult(Result("signed", CCP_Type));
@@ -1046,10 +1139,10 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
}
}
-static void AddStorageSpecifiers(Action::CodeCompletionContext CCC,
+static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
const LangOptions &LangOpts,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Note: we don't suggest either "auto" or "register", because both
// are pointless as storage specifiers. Elsewhere, we suggest "auto"
// in C++0x as a type specifier.
@@ -1057,13 +1150,13 @@ static void AddStorageSpecifiers(Action::CodeCompletionContext CCC,
Results.AddResult(Result("static"));
}
-static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC,
+static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
const LangOptions &LangOpts,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
switch (CCC) {
- case Action::CCC_Class:
- case Action::CCC_MemberTemplate:
+ case Sema::PCC_Class:
+ case Sema::PCC_MemberTemplate:
if (LangOpts.CPlusPlus) {
Results.AddResult(Result("explicit"));
Results.AddResult(Result("friend"));
@@ -1072,20 +1165,21 @@ static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC,
}
// Fall through
- case Action::CCC_ObjCInterface:
- case Action::CCC_ObjCImplementation:
- case Action::CCC_Namespace:
- case Action::CCC_Template:
+ case Sema::PCC_ObjCInterface:
+ case Sema::PCC_ObjCImplementation:
+ case Sema::PCC_Namespace:
+ case Sema::PCC_Template:
if (LangOpts.CPlusPlus || LangOpts.C99)
Results.AddResult(Result("inline"));
break;
- case Action::CCC_ObjCInstanceVariableList:
- case Action::CCC_Expression:
- case Action::CCC_Statement:
- case Action::CCC_ForInit:
- case Action::CCC_Condition:
- case Action::CCC_RecoveryInFunction:
+ case Sema::PCC_ObjCInstanceVariableList:
+ case Sema::PCC_Expression:
+ case Sema::PCC_Statement:
+ case Sema::PCC_ForInit:
+ case Sema::PCC_Condition:
+ case Sema::PCC_RecoveryInFunction:
+ case Sema::PCC_Type:
break;
}
}
@@ -1110,31 +1204,32 @@ static void AddTypedefResult(ResultBuilder &Results) {
Pattern->AddPlaceholderChunk("type");
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
Pattern->AddPlaceholderChunk("name");
- Results.AddResult(CodeCompleteConsumer::Result(Pattern));
+ Results.AddResult(CodeCompletionResult(Pattern));
}
-static bool WantTypesInContext(Action::CodeCompletionContext CCC,
+static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
const LangOptions &LangOpts) {
if (LangOpts.CPlusPlus)
return true;
switch (CCC) {
- case Action::CCC_Namespace:
- case Action::CCC_Class:
- case Action::CCC_ObjCInstanceVariableList:
- case Action::CCC_Template:
- case Action::CCC_MemberTemplate:
- case Action::CCC_Statement:
- case Action::CCC_RecoveryInFunction:
+ case Sema::PCC_Namespace:
+ case Sema::PCC_Class:
+ case Sema::PCC_ObjCInstanceVariableList:
+ case Sema::PCC_Template:
+ case Sema::PCC_MemberTemplate:
+ case Sema::PCC_Statement:
+ case Sema::PCC_RecoveryInFunction:
+ case Sema::PCC_Type:
return true;
- case Action::CCC_ObjCInterface:
- case Action::CCC_ObjCImplementation:
- case Action::CCC_Expression:
- case Action::CCC_Condition:
+ case Sema::PCC_ObjCInterface:
+ case Sema::PCC_ObjCImplementation:
+ case Sema::PCC_Expression:
+ case Sema::PCC_Condition:
return false;
- case Action::CCC_ForInit:
+ case Sema::PCC_ForInit:
return LangOpts.ObjC1 || LangOpts.C99;
}
@@ -1142,13 +1237,13 @@ static bool WantTypesInContext(Action::CodeCompletionContext CCC,
}
/// \brief Add language constructs that show up for "ordinary" names.
-static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
+static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Scope *S,
Sema &SemaRef,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
switch (CCC) {
- case Action::CCC_Namespace:
+ case Sema::PCC_Namespace:
if (SemaRef.getLangOptions().CPlusPlus) {
CodeCompletionString *Pattern = 0;
@@ -1207,7 +1302,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
AddTypedefResult(Results);
// Fall through
- case Action::CCC_Class:
+ case Sema::PCC_Class:
if (SemaRef.getLangOptions().CPlusPlus) {
// Using declaration
CodeCompletionString *Pattern = new CodeCompletionString;
@@ -1231,7 +1326,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
Results.AddResult(Result(Pattern));
}
- if (CCC == Action::CCC_Class) {
+ if (CCC == Sema::PCC_Class) {
AddTypedefResult(Results);
// public:
@@ -1255,8 +1350,8 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
}
// Fall through
- case Action::CCC_Template:
- case Action::CCC_MemberTemplate:
+ case Sema::PCC_Template:
+ case Sema::PCC_MemberTemplate:
if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
// template < parameters >
CodeCompletionString *Pattern = new CodeCompletionString;
@@ -1271,24 +1366,24 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
break;
- case Action::CCC_ObjCInterface:
+ case Sema::PCC_ObjCInterface:
AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
break;
- case Action::CCC_ObjCImplementation:
+ case Sema::PCC_ObjCImplementation:
AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
break;
- case Action::CCC_ObjCInstanceVariableList:
+ case Sema::PCC_ObjCInstanceVariableList:
AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
break;
- case Action::CCC_RecoveryInFunction:
- case Action::CCC_Statement: {
+ case Sema::PCC_RecoveryInFunction:
+ case Sema::PCC_Statement: {
AddTypedefResult(Results);
CodeCompletionString *Pattern = 0;
@@ -1344,7 +1439,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
}
// Switch-specific statements.
- if (!SemaRef.getSwitchStack().empty()) {
+ if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
// case expression:
Pattern = new CodeCompletionString;
Pattern->AddTypedTextChunk("case");
@@ -1460,12 +1555,12 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
}
// Fall through (for statement expressions).
- case Action::CCC_ForInit:
- case Action::CCC_Condition:
+ case Sema::PCC_ForInit:
+ case Sema::PCC_Condition:
AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
// Fall through: conditions and statements can have expressions.
- case Action::CCC_Expression: {
+ case Sema::PCC_Expression: {
CodeCompletionString *Pattern = 0;
if (SemaRef.getLangOptions().CPlusPlus) {
// 'this', if we're in a non-static member function.
@@ -1600,12 +1695,15 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
Results.AddResult(Result(Pattern));
break;
}
+
+ case Sema::PCC_Type:
+ break;
}
if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
- if (SemaRef.getLangOptions().CPlusPlus)
+ if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Results.AddResult(Result("operator"));
}
@@ -1645,6 +1743,117 @@ static void AddResultTypeChunk(ASTContext &Context,
Result->AddResultTypeChunk(TypeStr);
}
+static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
+ CodeCompletionString *Result) {
+ if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
+ if (Sentinel->getSentinel() == 0) {
+ if (Context.getLangOptions().ObjC1 &&
+ Context.Idents.get("nil").hasMacroDefinition())
+ Result->AddTextChunk(", nil");
+ else if (Context.Idents.get("NULL").hasMacroDefinition())
+ Result->AddTextChunk(", NULL");
+ else
+ Result->AddTextChunk(", (void*)0");
+ }
+}
+
+static std::string FormatFunctionParameter(ASTContext &Context,
+ ParmVarDecl *Param,
+ bool SuppressName = false) {
+ bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
+ if (Param->getType()->isDependentType() ||
+ !Param->getType()->isBlockPointerType()) {
+ // The argument for a dependent or non-block parameter is a placeholder
+ // containing that parameter's type.
+ std::string Result;
+
+ if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
+ Result = Param->getIdentifier()->getName();
+
+ Param->getType().getAsStringInternal(Result,
+ Context.PrintingPolicy);
+
+ if (ObjCMethodParam) {
+ Result = "(" + Result;
+ Result += ")";
+ if (Param->getIdentifier() && !SuppressName)
+ Result += Param->getIdentifier()->getName();
+ }
+ return Result;
+ }
+
+ // The argument for a block pointer parameter is a block literal with
+ // the appropriate type.
+ FunctionProtoTypeLoc *Block = 0;
+ TypeLoc TL;
+ if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
+ TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
+ while (true) {
+ // Look through typedefs.
+ if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
+ if (TypeSourceInfo *InnerTSInfo
+ = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
+ TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
+ continue;
+ }
+ }
+
+ // Look through qualified types
+ if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+ TL = QualifiedTL->getUnqualifiedLoc();
+ continue;
+ }
+
+ // Try to get the function prototype behind the block pointer type,
+ // then we're done.
+ if (BlockPointerTypeLoc *BlockPtr
+ = dyn_cast<BlockPointerTypeLoc>(&TL)) {
+ TL = BlockPtr->getPointeeLoc();
+ Block = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ }
+ break;
+ }
+ }
+
+ if (!Block) {
+ // We were unable to find a FunctionProtoTypeLoc with parameter names
+ // for the block; just use the parameter type as a placeholder.
+ std::string Result;
+ Param->getType().getUnqualifiedType().
+ getAsStringInternal(Result, Context.PrintingPolicy);
+
+ if (ObjCMethodParam) {
+ Result = "(" + Result;
+ Result += ")";
+ if (Param->getIdentifier())
+ Result += Param->getIdentifier()->getName();
+ }
+
+ return Result;
+ }
+
+ // We have the function prototype behind the block pointer type, as it was
+ // written in the source.
+ std::string Result = "(^)(";
+ for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
+ if (I)
+ Result += ", ";
+ Result += FormatFunctionParameter(Context, Block->getArg(I));
+
+ if (I == N - 1 && Block->getTypePtr()->isVariadic())
+ Result += ", ...";
+ }
+ if (Block->getTypePtr()->isVariadic() && Block->getNumArgs() == 0)
+ Result += "...";
+ else if (Block->getNumArgs() == 0 && !Context.getLangOptions().CPlusPlus)
+ Result += "void";
+
+ Result += ")";
+ Block->getTypePtr()->getResultType().getAsStringInternal(Result,
+ Context.PrintingPolicy);
+ return Result;
+}
+
/// \brief Add function parameter chunks to the given code completion string.
static void AddFunctionParameterChunks(ASTContext &Context,
FunctionDecl *Function,
@@ -1668,21 +1877,23 @@ static void AddFunctionParameterChunks(ASTContext &Context,
CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
// Format the placeholder string.
- std::string PlaceholderStr;
- if (Param->getIdentifier())
- PlaceholderStr = Param->getIdentifier()->getName();
-
- Param->getType().getAsStringInternal(PlaceholderStr,
- Context.PrintingPolicy);
-
+ std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
+
+ if (Function->isVariadic() && P == N - 1)
+ PlaceholderStr += ", ...";
+
// Add the placeholder string.
CCStr->AddPlaceholderChunk(PlaceholderStr);
}
if (const FunctionProtoType *Proto
= Function->getType()->getAs<FunctionProtoType>())
- if (Proto->isVariadic())
- CCStr->AddPlaceholderChunk(", ...");
+ if (Proto->isVariadic()) {
+ if (Proto->getNumArgs() == 0)
+ CCStr->AddPlaceholderChunk("...");
+
+ MaybeAddSentinel(Context, Function, CCStr);
+ }
}
/// \brief Add template parameter chunks to the given code completion string.
@@ -1799,13 +2010,15 @@ static void AddFunctionTypeQualsToCompletionString(CodeCompletionString *Result,
/// how to use this result, or NULL to indicate that the string or name of the
/// result is all that is needed.
CodeCompletionString *
-CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
+CodeCompletionResult::CreateCodeCompletionString(Sema &S,
+ CodeCompletionString *Result) {
typedef CodeCompletionString::Chunk Chunk;
if (Kind == RK_Pattern)
- return Pattern->Clone();
+ return Pattern->Clone(Result);
- CodeCompletionString *Result = new CodeCompletionString;
+ if (!Result)
+ Result = new CodeCompletionString;
if (Kind == RK_Keyword) {
Result->AddTypedTextChunk(Keyword);
@@ -1978,10 +2191,20 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
continue;
std::string Arg;
- (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
- Arg = "(" + Arg + ")";
- if (IdentifierInfo *II = (*P)->getIdentifier())
- Arg += II->getName().str();
+
+ if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
+ Arg = FormatFunctionParameter(S.Context, *P, true);
+ else {
+ (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
+ Arg = "(" + Arg + ")";
+ if (IdentifierInfo *II = (*P)->getIdentifier())
+ if (DeclaringEntity || AllParametersAreInformative)
+ Arg += II->getName().str();
+ }
+
+ if (Method->isVariadic() && (P + 1) == PEnd)
+ Arg += ", ...";
+
if (DeclaringEntity)
Result->AddTextChunk(Arg);
else if (AllParametersAreInformative)
@@ -1991,12 +2214,16 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) {
}
if (Method->isVariadic()) {
- if (DeclaringEntity)
- Result->AddTextChunk(", ...");
- else if (AllParametersAreInformative)
- Result->AddInformativeChunk(", ...");
- else
- Result->AddPlaceholderChunk(", ...");
+ if (Method->param_size() == 0) {
+ if (DeclaringEntity)
+ Result->AddTextChunk(", ...");
+ else if (AllParametersAreInformative)
+ Result->AddInformativeChunk(", ...");
+ else
+ Result->AddPlaceholderChunk(", ...");
+ }
+
+ MaybeAddSentinel(S.Context, Method, Result);
}
return Result;
@@ -2076,226 +2303,421 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
return Result;
}
-namespace {
- struct SortCodeCompleteResult {
- typedef CodeCompleteConsumer::Result Result;
-
- bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const {
- Selector XSel = X.getObjCSelector();
- Selector YSel = Y.getObjCSelector();
- if (!XSel.isNull() && !YSel.isNull()) {
- // We are comparing two selectors.
- unsigned N = std::min(XSel.getNumArgs(), YSel.getNumArgs());
- if (N == 0)
- ++N;
- for (unsigned I = 0; I != N; ++I) {
- IdentifierInfo *XId = XSel.getIdentifierInfoForSlot(I);
- IdentifierInfo *YId = YSel.getIdentifierInfoForSlot(I);
- if (!XId || !YId)
- return XId && !YId;
-
- switch (XId->getName().compare_lower(YId->getName())) {
- case -1: return true;
- case 1: return false;
- default: break;
- }
- }
-
- return XSel.getNumArgs() < YSel.getNumArgs();
- }
+unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
+ bool PreferredTypeIsPointer) {
+ unsigned Priority = CCP_Macro;
+
+ // Treat the "nil" and "NULL" macros as null pointer constants.
+ if (MacroName.equals("nil") || MacroName.equals("NULL")) {
+ Priority = CCP_Constant;
+ if (PreferredTypeIsPointer)
+ Priority = Priority / CCF_SimilarTypeMatch;
+ }
+
+ return Priority;
+}
- // For non-selectors, order by kind.
- if (X.getNameKind() != Y.getNameKind())
- return X.getNameKind() < Y.getNameKind();
-
- // Order identifiers by comparison of their lowercased names.
- if (IdentifierInfo *XId = X.getAsIdentifierInfo())
- return XId->getName().compare_lower(
- Y.getAsIdentifierInfo()->getName()) < 0;
-
- // Order overloaded operators by the order in which they appear
- // in our list of operators.
- if (OverloadedOperatorKind XOp = X.getCXXOverloadedOperator())
- return XOp < Y.getCXXOverloadedOperator();
-
- // Order C++0x user-defined literal operators lexically by their
- // lowercased suffixes.
- if (IdentifierInfo *XLit = X.getCXXLiteralIdentifier())
- return XLit->getName().compare_lower(
- Y.getCXXLiteralIdentifier()->getName()) < 0;
-
- // The only stable ordering we have is to turn the name into a
- // string and then compare the lower-case strings. This is
- // inefficient, but thankfully does not happen too often.
- return llvm::StringRef(X.getAsString()).compare_lower(
- Y.getAsString()) < 0;
- }
-
- /// \brief Retrieve the name that should be used to order a result.
- ///
- /// If the name needs to be constructed as a string, that string will be
- /// saved into Saved and the returned StringRef will refer to it.
- static llvm::StringRef getOrderedName(const Result &R,
- std::string &Saved) {
- switch (R.Kind) {
- case Result::RK_Keyword:
- return R.Keyword;
-
- case Result::RK_Pattern:
- return R.Pattern->getTypedText();
-
- case Result::RK_Macro:
- return R.Macro->getName();
-
- case Result::RK_Declaration:
- // Handle declarations below.
- break;
- }
-
- DeclarationName Name = R.Declaration->getDeclName();
-
- // If the name is a simple identifier (by far the common case), or a
- // zero-argument selector, just return a reference to that identifier.
- if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
- return Id->getName();
- if (Name.isObjCZeroArgSelector())
- if (IdentifierInfo *Id
- = Name.getObjCSelector().getIdentifierInfoForSlot(0))
- return Id->getName();
-
- Saved = Name.getAsString();
- return Saved;
- }
-
- bool operator()(const Result &X, const Result &Y) const {
- std::string XSaved, YSaved;
- llvm::StringRef XStr = getOrderedName(X, XSaved);
- llvm::StringRef YStr = getOrderedName(Y, YSaved);
- int cmp = XStr.compare_lower(YStr);
- if (cmp)
- return cmp < 0;
-
- // Non-hidden names precede hidden names.
- if (X.Hidden != Y.Hidden)
- return !X.Hidden;
+CXCursorKind clang::getCursorKindForDecl(Decl *D) {
+ if (!D)
+ return CXCursor_UnexposedDecl;
+
+ switch (D->getKind()) {
+ case Decl::Enum: return CXCursor_EnumDecl;
+ case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
+ case Decl::Field: return CXCursor_FieldDecl;
+ case Decl::Function:
+ return CXCursor_FunctionDecl;
+ case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
+ case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
+ case Decl::ObjCClass:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCForwardProtocol:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
+ case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
+ case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
+ case Decl::ObjCMethod:
+ return cast<ObjCMethodDecl>(D)->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
+ case Decl::CXXMethod: return CXCursor_CXXMethod;
+ case Decl::CXXConstructor: return CXCursor_Constructor;
+ case Decl::CXXDestructor: return CXCursor_Destructor;
+ case Decl::CXXConversion: return CXCursor_ConversionFunction;
+ case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
+ case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
+ case Decl::ParmVar: return CXCursor_ParmDecl;
+ case Decl::Typedef: return CXCursor_TypedefDecl;
+ case Decl::Var: return CXCursor_VarDecl;
+ case Decl::Namespace: return CXCursor_Namespace;
+ case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
+ case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
+ case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
+ case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
+ case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
+ case Decl::ClassTemplate: return CXCursor_ClassTemplate;
+ case Decl::ClassTemplatePartialSpecialization:
+ return CXCursor_ClassTemplatePartialSpecialization;
+ case Decl::UsingDirective: return CXCursor_UsingDirective;
- // Non-nested-name-specifiers precede nested-name-specifiers.
- if (X.StartsNestedNameSpecifier != Y.StartsNestedNameSpecifier)
- return !X.StartsNestedNameSpecifier;
+ case Decl::Using:
+ case Decl::UnresolvedUsingValue:
+ case Decl::UnresolvedUsingTypename:
+ return CXCursor_UsingDeclaration;
- return false;
- }
- };
+ default:
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ switch (TD->getTagKind()) {
+ case TTK_Struct: return CXCursor_StructDecl;
+ case TTK_Class: return CXCursor_ClassDecl;
+ case TTK_Union: return CXCursor_UnionDecl;
+ case TTK_Enum: return CXCursor_EnumDecl;
+ }
+ }
+ }
+
+ return CXCursor_UnexposedDecl;
}
static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
bool TargetTypeIsPointer = false) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
Results.EnterNewScope();
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
- unsigned Priority = CCP_Macro;
-
- // Treat the "nil" and "NULL" macros as null pointer constants.
- if (M->first->isStr("nil") || M->first->isStr("NULL")) {
- Priority = CCP_Constant;
- if (TargetTypeIsPointer)
- Priority = Priority / CCF_SimilarTypeMatch;
- }
-
- Results.AddResult(Result(M->first, Priority));
+ Results.AddResult(Result(M->first,
+ getMacroUsagePriority(M->first->getName(),
+ TargetTypeIsPointer)));
}
Results.ExitScope();
}
+static void AddPrettyFunctionResults(const LangOptions &LangOpts,
+ ResultBuilder &Results) {
+ typedef CodeCompletionResult Result;
+
+ Results.EnterNewScope();
+ Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
+ Results.AddResult(Result("__FUNCTION__", CCP_Constant));
+ if (LangOpts.C99 || LangOpts.CPlusPlus0x)
+ Results.AddResult(Result("__func__", CCP_Constant));
+ Results.ExitScope();
+}
+
static void HandleCodeCompleteResults(Sema *S,
CodeCompleteConsumer *CodeCompleter,
- CodeCompleteConsumer::Result *Results,
- unsigned NumResults) {
- std::stable_sort(Results, Results + NumResults, SortCodeCompleteResult());
-
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {
if (CodeCompleter)
- CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
+ CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
for (unsigned I = 0; I != NumResults; ++I)
Results[I].Destroy();
}
+static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
+ Sema::ParserCompletionContext PCC) {
+ switch (PCC) {
+ case Sema::PCC_Namespace:
+ return CodeCompletionContext::CCC_TopLevel;
+
+ case Sema::PCC_Class:
+ return CodeCompletionContext::CCC_ClassStructUnion;
+
+ case Sema::PCC_ObjCInterface:
+ return CodeCompletionContext::CCC_ObjCInterface;
+
+ case Sema::PCC_ObjCImplementation:
+ return CodeCompletionContext::CCC_ObjCImplementation;
+
+ case Sema::PCC_ObjCInstanceVariableList:
+ return CodeCompletionContext::CCC_ObjCIvarList;
+
+ case Sema::PCC_Template:
+ case Sema::PCC_MemberTemplate:
+ case Sema::PCC_RecoveryInFunction:
+ return CodeCompletionContext::CCC_Other;
+
+ case Sema::PCC_Expression:
+ case Sema::PCC_ForInit:
+ case Sema::PCC_Condition:
+ return CodeCompletionContext::CCC_Expression;
+
+ case Sema::PCC_Statement:
+ return CodeCompletionContext::CCC_Statement;
+
+ case Sema::PCC_Type:
+ return CodeCompletionContext::CCC_Type;
+ }
+
+ return CodeCompletionContext::CCC_Other;
+}
+
+/// \brief If we're in a C++ virtual member function, add completion results
+/// that invoke the functions we override, since it's common to invoke the
+/// overridden function as well as adding new functionality.
+///
+/// \param S The semantic analysis object for which we are generating results.
+///
+/// \param InContext This context in which the nested-name-specifier preceding
+/// the code-completion point
+static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
+ ResultBuilder &Results) {
+ // Look through blocks.
+ DeclContext *CurContext = S.CurContext;
+ while (isa<BlockDecl>(CurContext))
+ CurContext = CurContext->getParent();
+
+
+ CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
+ if (!Method || !Method->isVirtual())
+ return;
+
+ // We need to have names for all of the parameters, if we're going to
+ // generate a forwarding call.
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd;
+ ++P) {
+ if (!(*P)->getDeclName())
+ return;
+ }
+
+ for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
+ MEnd = Method->end_overridden_methods();
+ M != MEnd; ++M) {
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
+ if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
+ continue;
+
+ // If we need a nested-name-specifier, add one now.
+ if (!InContext) {
+ NestedNameSpecifier *NNS
+ = getRequiredQualification(S.Context, CurContext,
+ Overridden->getDeclContext());
+ if (NNS) {
+ std::string Str;
+ llvm::raw_string_ostream OS(Str);
+ NNS->print(OS, S.Context.PrintingPolicy);
+ Pattern->AddTextChunk(OS.str());
+ }
+ } else if (!InContext->Equals(Overridden->getDeclContext()))
+ continue;
+
+ Pattern->AddTypedTextChunk(Overridden->getNameAsString());
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ bool FirstParam = true;
+ for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+ PEnd = Method->param_end();
+ P != PEnd; ++P) {
+ if (FirstParam)
+ FirstParam = false;
+ else
+ Pattern->AddChunk(CodeCompletionString::CK_Comma);
+
+ Pattern->AddPlaceholderChunk((*P)->getIdentifier()->getName());
+ }
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Pattern,
+ CCP_SuperCompletion,
+ CXCursor_CXXMethod));
+ Results.Ignore(Overridden);
+ }
+}
+
void Sema::CodeCompleteOrdinaryName(Scope *S,
- CodeCompletionContext CompletionContext) {
- typedef CodeCompleteConsumer::Result Result;
- ResultBuilder Results(*this);
+ ParserCompletionContext CompletionContext) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
// Determine how to filter results, e.g., so that the names of
// values (functions, enumerators, function templates, etc.) are
// only allowed where we can have an expression.
switch (CompletionContext) {
- case CCC_Namespace:
- case CCC_Class:
- case CCC_ObjCInterface:
- case CCC_ObjCImplementation:
- case CCC_ObjCInstanceVariableList:
- case CCC_Template:
- case CCC_MemberTemplate:
+ case PCC_Namespace:
+ case PCC_Class:
+ case PCC_ObjCInterface:
+ case PCC_ObjCImplementation:
+ case PCC_ObjCInstanceVariableList:
+ case PCC_Template:
+ case PCC_MemberTemplate:
+ case PCC_Type:
Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
break;
- case CCC_Expression:
- case CCC_Statement:
- case CCC_ForInit:
- case CCC_Condition:
+ case PCC_Statement:
+ // For statements that are expressions, we prefer to call 'void' functions
+ // rather than functions that return a result, since then the result would
+ // be ignored.
+ Results.setPreferredType(Context.VoidTy);
+ // Fall through
+
+ case PCC_Expression:
+ case PCC_ForInit:
+ case PCC_Condition:
if (WantTypesInContext(CompletionContext, getLangOptions()))
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
+
+ if (getLangOptions().CPlusPlus)
+ MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
break;
- case CCC_RecoveryInFunction:
+ case PCC_RecoveryInFunction:
// Unfiltered
break;
}
+ // If we are in a C++ non-static member function, check the qualifiers on
+ // the member function to filter/prioritize the results list.
+ if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
+ if (CurMethod->isInstance())
+ Results.setObjectTypeQualifiers(
+ Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
+
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
- Results.EnterNewScope();
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Results.ExitScope();
+ switch (CompletionContext) {
+ case PCC_Expression:
+ case PCC_Statement:
+ case PCC_RecoveryInFunction:
+ if (S->getFnParent())
+ AddPrettyFunctionResults(PP.getLangOptions(), Results);
+ break;
+
+ case PCC_Namespace:
+ case PCC_Class:
+ case PCC_ObjCInterface:
+ case PCC_ObjCImplementation:
+ case PCC_ObjCInstanceVariableList:
+ case PCC_Template:
+ case PCC_MemberTemplate:
+ case PCC_ForInit:
+ case PCC_Condition:
+ case PCC_Type:
+ break;
+ }
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results);
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ mapCodeCompletionContext(*this, CompletionContext),
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteDeclarator(Scope *S,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Type qualifiers can come after names.
+ Results.AddResult(Result("const"));
+ Results.AddResult(Result("volatile"));
+ if (getLangOptions().C99)
+ Results.AddResult(Result("restrict"));
+
+ if (getLangOptions().CPlusPlus) {
+ if (AllowNonIdentifiers) {
+ Results.AddResult(Result("operator"));
+ }
+
+ // Add nested-name-specifiers.
+ if (AllowNestedNameSpecifiers) {
+ Results.allowNestedNameSpecifiers();
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
+ CodeCompleter->includeGlobals());
+ }
+ }
+ Results.ExitScope();
+
+ // Note that we intentionally suppress macro results here, since we do not
+ // encourage using macros to produce the names of entities.
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ AllowNestedNameSpecifiers
+ ? CodeCompletionContext::CCC_PotentiallyQualifiedName
+ : CodeCompletionContext::CCC_Name,
+ Results.data(), Results.size());
}
+struct Sema::CodeCompleteExpressionData {
+ CodeCompleteExpressionData(QualType PreferredType = QualType())
+ : PreferredType(PreferredType), IntegralConstantExpression(false),
+ ObjCCollection(false) { }
+
+ QualType PreferredType;
+ bool IntegralConstantExpression;
+ bool ObjCCollection;
+ llvm::SmallVector<Decl *, 4> IgnoreDecls;
+};
+
/// \brief Perform code-completion in an expression context when we know what
/// type we're looking for.
-void Sema::CodeCompleteExpression(Scope *S, QualType T) {
- typedef CodeCompleteConsumer::Result Result;
+///
+/// \param IntegralConstantExpression Only permit integral constant
+/// expressions.
+void Sema::CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data) {
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
- if (WantTypesInContext(CCC_Expression, getLangOptions()))
+ if (Data.ObjCCollection)
+ Results.setFilter(&ResultBuilder::IsObjCCollection);
+ else if (Data.IntegralConstantExpression)
+ Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
+ else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
- Results.setPreferredType(T.getNonReferenceType());
+
+ if (!Data.PreferredType.isNull())
+ Results.setPreferredType(Data.PreferredType.getNonReferenceType());
+
+ // Ignore any declarations that we were told that we don't care about.
+ for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
+ Results.Ignore(Data.IgnoreDecls[I]);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
Results.EnterNewScope();
- AddOrdinaryNameResults(CCC_Expression, S, *this, Results);
+ AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Results.ExitScope();
bool PreferredTypeIsPointer = false;
- if (!T.isNull())
- PreferredTypeIsPointer = T->isAnyPointerType() ||
- T->isMemberPointerType() || T->isBlockPointerType();
+ if (!Data.PreferredType.isNull())
+ PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
+ || Data.PreferredType->isMemberPointerType()
+ || Data.PreferredType->isBlockPointerType();
+ if (S->getFnParent() &&
+ !Data.ObjCCollection &&
+ !Data.IntegralConstantExpression)
+ AddPrettyFunctionResults(PP.getLangOptions(), Results);
+
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, PreferredTypeIsPointer);
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext(CodeCompletionContext::CCC_Expression,
+ Data.PreferredType),
+ Results.data(),Results.size());
}
@@ -2303,7 +2725,7 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
bool AllowCategories,
DeclContext *CurContext,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Add properties in this container.
for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
@@ -2327,9 +2749,9 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
}
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
- E = IFace->protocol_end();
- I != E; ++I)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = IFace->all_referenced_protocol_begin(),
+ E = IFace->all_referenced_protocol_end(); I != E; ++I)
AddObjCProperties(*I, AllowCategories, CurContext, Results);
// Look in the superclass.
@@ -2339,8 +2761,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
} else if (const ObjCCategoryDecl *Category
= dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
- for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
- PEnd = Category->protocol_end();
+ for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
P != PEnd; ++P)
AddObjCProperties(*P, AllowCategories, CurContext, Results);
}
@@ -2352,7 +2774,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
if (!BaseE || !CodeCompleter)
return;
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
Expr *Base = static_cast<Expr *>(BaseE);
QualType BaseType = Base->getType();
@@ -2361,7 +2783,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
if (const PointerType *Ptr = BaseType->getAs<PointerType>())
BaseType = Ptr->getPointeeType();
else if (BaseType->isObjCObjectPointerType())
- /*Do nothing*/ ;
+ /*Do nothing*/ ;
else
return;
}
@@ -2369,10 +2791,15 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
ResultBuilder Results(*this, &ResultBuilder::IsMember);
Results.EnterNewScope();
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+ // Indicate that we are performing a member access, and the cv-qualifiers
+ // for the base object type.
+ Results.setObjectTypeQualifiers(BaseType.getQualifiers());
+
// Access to a C/C++ class, struct, or union.
Results.allowNestedNameSpecifiers();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer);
+ LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
+ CodeCompleter->includeGlobals());
if (getLangOptions().CPlusPlus) {
if (!Results.empty()) {
@@ -2420,7 +2847,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
if (Class) {
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.setFilter(&ResultBuilder::IsObjCIvar);
- LookupVisibleDecls(Class, LookupMemberName, Consumer);
+ LookupVisibleDecls(Class, LookupMemberName, Consumer,
+ CodeCompleter->includeGlobals());
}
}
@@ -2429,27 +2857,35 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
Results.ExitScope();
// Hand off the results found for code completion.
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
+ BaseType),
+ Results.data(),Results.size());
}
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
if (!CodeCompleter)
return;
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder::LookupFilter Filter = 0;
+ enum CodeCompletionContext::Kind ContextKind
+ = CodeCompletionContext::CCC_Other;
switch ((DeclSpec::TST)TagSpec) {
case DeclSpec::TST_enum:
Filter = &ResultBuilder::IsEnum;
+ ContextKind = CodeCompletionContext::CCC_EnumTag;
break;
case DeclSpec::TST_union:
Filter = &ResultBuilder::IsUnion;
+ ContextKind = CodeCompletionContext::CCC_UnionTag;
break;
case DeclSpec::TST_struct:
case DeclSpec::TST_class:
Filter = &ResultBuilder::IsClassOrStruct;
+ ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
break;
default:
@@ -2462,22 +2898,46 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
// First pass: look for tags.
Results.setFilter(Filter);
- LookupVisibleDecls(S, LookupTagName, Consumer);
+ LookupVisibleDecls(S, LookupTagName, Consumer,
+ CodeCompleter->includeGlobals());
- // Second pass: look for nested name specifiers.
- Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+ if (CodeCompleter->includeGlobals()) {
+ // Second pass: look for nested name specifiers.
+ Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+ LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
+ }
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter, ContextKind,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+ if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
+ Results.AddResult("const");
+ if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
+ Results.AddResult("volatile");
+ if (getLangOptions().C99 &&
+ !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
+ Results.AddResult("restrict");
+ Results.ExitScope();
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_TypeQualifiers,
+ Results.data(), Results.size());
}
void Sema::CodeCompleteCase(Scope *S) {
- if (getSwitchStack().empty() || !CodeCompleter)
+ if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
return;
- SwitchStmt *Switch = getSwitchStack().back();
- if (!Switch->getCond()->getType()->isEnumeralType())
+ SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
+ if (!Switch->getCond()->getType()->isEnumeralType()) {
+ CodeCompleteExpressionData Data(Switch->getCond()->getType());
+ Data.IntegralConstantExpression = true;
+ CodeCompleteExpression(S, Data);
return;
+ }
// Code-complete the cases of a switch statement over an enumeration type
// by providing the list of
@@ -2541,14 +3001,16 @@ void Sema::CodeCompleteCase(Scope *S) {
if (EnumeratorsSeen.count(*E))
continue;
- Results.AddResult(CodeCompleteConsumer::Result(*E, Qualifier),
+ Results.AddResult(CodeCompletionResult(*E, Qualifier),
CurContext, 0, false);
}
Results.ExitScope();
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results);
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Expression,
+ Results.data(),Results.size());
}
namespace {
@@ -2562,7 +3024,7 @@ namespace {
bool
operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
- return S.isBetterOverloadCandidate(X, Y, Loc);
+ return isBetterOverloadCandidate(S, X, Y, Loc);
}
};
}
@@ -2594,7 +3056,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
// Ignore type-dependent call expressions entirely.
if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
- CodeCompleteOrdinaryName(S, CCC_Expression);
+ CodeCompleteOrdinaryName(S, PCC_Expression);
return;
}
@@ -2678,7 +3140,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
}
if (ParamType.isNull())
- CodeCompleteOrdinaryName(S, CCC_Expression);
+ CodeCompleteOrdinaryName(S, PCC_Expression);
else
CodeCompleteExpression(S, ParamType);
@@ -2687,10 +3149,10 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
Results.size());
}
-void Sema::CodeCompleteInitializer(Scope *S, DeclPtrTy D) {
- ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D.getAs<Decl>());
+void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
+ ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
if (!VD) {
- CodeCompleteOrdinaryName(S, CCC_Expression);
+ CodeCompleteOrdinaryName(S, PCC_Expression);
return;
}
@@ -2708,7 +3170,7 @@ void Sema::CodeCompleteReturn(Scope *S) {
ResultType = Method->getResultType();
if (ResultType.isNull())
- CodeCompleteOrdinaryName(S, CCC_Expression);
+ CodeCompleteOrdinaryName(S, PCC_Expression);
else
CodeCompleteExpression(S, ResultType);
}
@@ -2717,7 +3179,7 @@ void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
if (LHS)
CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
else
- CodeCompleteOrdinaryName(S, CCC_Expression);
+ CodeCompleteOrdinaryName(S, PCC_Expression);
}
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
@@ -2735,16 +3197,29 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
return;
ResultBuilder Results(*this);
- CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+ Results.EnterNewScope();
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
if (!Results.empty() && NNS->isDependent())
Results.AddResult("template");
+
+ // Add calls to overridden virtual functions, if there are any.
+ //
+ // FIXME: This isn't wonderful, because we don't know whether we're actually
+ // in a context that permits expressions. This is a general issue with
+ // qualified-id completions.
+ if (!EnteringContext)
+ MaybeAddOverrideCalls(*this, Ctx, Results);
+ Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Name,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteUsing(Scope *S) {
@@ -2756,15 +3231,18 @@ void Sema::CodeCompleteUsing(Scope *S) {
// If we aren't in class scope, we could see the "namespace" keyword.
if (!S->isClassScope())
- Results.AddResult(CodeCompleteConsumer::Result("namespace"));
+ Results.AddResult(CodeCompletionResult("namespace"));
// After "using", we can see anything that would start a
// nested-name-specifier.
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteUsingDirective(Scope *S) {
@@ -2776,9 +3254,12 @@ void Sema::CodeCompleteUsingDirective(Scope *S) {
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
Results.EnterNewScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Namespace,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteNamespaceDecl(Scope *S) {
@@ -2807,12 +3288,14 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
- Results.AddResult(CodeCompleteConsumer::Result(NS->second, 0),
+ Results.AddResult(CodeCompletionResult(NS->second, 0),
CurContext, 0, false);
Results.ExitScope();
}
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
@@ -2822,15 +3305,18 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Namespace,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteOperatorName(Scope *S) {
if (!CodeCompleter)
return;
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this, &ResultBuilder::IsType);
Results.EnterNewScope();
@@ -2843,13 +3329,122 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
// Add any type names visible from the current scope
Results.allowNestedNameSpecifiers();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
// Add any type specifiers
AddTypeSpecifierResults(getLangOptions(), Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Type,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
+ CXXBaseOrMemberInitializer** Initializers,
+ unsigned NumInitializers) {
+ CXXConstructorDecl *Constructor
+ = static_cast<CXXConstructorDecl *>(ConstructorD);
+ if (!Constructor)
+ return;
+
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Fill in any already-initialized fields or base classes.
+ llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
+ llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
+ for (unsigned I = 0; I != NumInitializers; ++I) {
+ if (Initializers[I]->isBaseInitializer())
+ InitializedBases.insert(
+ Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
+ else
+ InitializedFields.insert(cast<FieldDecl>(Initializers[I]->getMember()));
+ }
+
+ // Add completions for base classes.
+ bool SawLastInitializer = (NumInitializers == 0);
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
+ BaseEnd = ClassDecl->bases_end();
+ Base != BaseEnd; ++Base) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ SawLastInitializer
+ = NumInitializers > 0 &&
+ Initializers[NumInitializers - 1]->isBaseInitializer() &&
+ Context.hasSameUnqualifiedType(Base->getType(),
+ QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+ continue;
+ }
+
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(
+ Base->getType().getAsString(Context.PrintingPolicy));
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("args");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Pattern,
+ SawLastInitializer? CCP_NextInitializer
+ : CCP_MemberDeclaration));
+ SawLastInitializer = false;
+ }
+
+ // Add completions for virtual base classes.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
+ BaseEnd = ClassDecl->vbases_end();
+ Base != BaseEnd; ++Base) {
+ if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
+ SawLastInitializer
+ = NumInitializers > 0 &&
+ Initializers[NumInitializers - 1]->isBaseInitializer() &&
+ Context.hasSameUnqualifiedType(Base->getType(),
+ QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
+ continue;
+ }
+
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(
+ Base->getType().getAsString(Context.PrintingPolicy));
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("args");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Pattern,
+ SawLastInitializer? CCP_NextInitializer
+ : CCP_MemberDeclaration));
+ SawLastInitializer = false;
+ }
+
+ // Add completions for members.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+ FieldEnd = ClassDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
+ SawLastInitializer
+ = NumInitializers > 0 &&
+ Initializers[NumInitializers - 1]->isMemberInitializer() &&
+ Initializers[NumInitializers - 1]->getMember() == *Field;
+ continue;
+ }
+
+ if (!Field->getDeclName())
+ continue;
+
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(Field->getIdentifier()->getName());
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("args");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(CodeCompletionResult(Pattern,
+ SawLastInitializer? CCP_NextInitializer
+ : CCP_MemberDeclaration));
+ SawLastInitializer = false;
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Name,
+ Results.data(), Results.size());
}
// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
@@ -2858,7 +3453,7 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
static void AddObjCImplementationResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Since we have an implementation, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
@@ -2883,7 +3478,7 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts,
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Since we have an interface or protocol, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
@@ -2901,7 +3496,7 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts,
}
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
CodeCompletionString *Pattern = 0;
// @class name ;
@@ -2946,9 +3541,9 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
Results.AddResult(Result(Pattern));
}
-void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
+void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
bool InInterface) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
Results.EnterNewScope();
if (ObjCImpDecl)
@@ -2958,11 +3553,13 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl,
else
AddObjCTopLevelResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
CodeCompletionString *Pattern = 0;
// @encode ( type-name )
@@ -2991,7 +3588,7 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
}
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
CodeCompletionString *Pattern = 0;
if (Results.includeCodePatterns()) {
@@ -3041,7 +3638,7 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
ResultBuilder &Results,
bool NeedAt) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
@@ -3054,7 +3651,9 @@ void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Results.EnterNewScope();
AddObjCVisibilityResults(getLangOptions(), Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCAtStatement(Scope *S) {
@@ -3063,7 +3662,9 @@ void Sema::CodeCompleteObjCAtStatement(Scope *S) {
AddObjCStatementResults(Results, false);
AddObjCExpressionResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCAtExpression(Scope *S) {
@@ -3071,7 +3672,9 @@ void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Results.EnterNewScope();
AddObjCExpressionResults(Results, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
/// \brief Determine whether the addition of the given flag to an Objective-C
@@ -3110,37 +3713,39 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
unsigned Attributes = ODS.getPropertyAttributes();
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
Results.EnterNewScope();
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
- Results.AddResult(CodeCompleteConsumer::Result("readonly"));
+ Results.AddResult(CodeCompletionResult("readonly"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
- Results.AddResult(CodeCompleteConsumer::Result("assign"));
+ Results.AddResult(CodeCompletionResult("assign"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
- Results.AddResult(CodeCompleteConsumer::Result("readwrite"));
+ Results.AddResult(CodeCompletionResult("readwrite"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
- Results.AddResult(CodeCompleteConsumer::Result("retain"));
+ Results.AddResult(CodeCompletionResult("retain"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
- Results.AddResult(CodeCompleteConsumer::Result("copy"));
+ Results.AddResult(CodeCompletionResult("copy"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
- Results.AddResult(CodeCompleteConsumer::Result("nonatomic"));
+ Results.AddResult(CodeCompletionResult("nonatomic"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
CodeCompletionString *Setter = new CodeCompletionString;
Setter->AddTypedTextChunk("setter");
Setter->AddTextChunk(" = ");
Setter->AddPlaceholderChunk("method");
- Results.AddResult(CodeCompleteConsumer::Result(Setter));
+ Results.AddResult(CodeCompletionResult(Setter));
}
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
CodeCompletionString *Getter = new CodeCompletionString;
Getter->AddTypedTextChunk("getter");
Getter->AddTextChunk(" = ");
Getter->AddPlaceholderChunk("method");
- Results.AddResult(CodeCompleteConsumer::Result(Getter));
+ Results.AddResult(CodeCompletionResult(Getter));
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
/// \brief Descripts the kind of Objective-C method that we want to find
@@ -3151,26 +3756,33 @@ enum ObjCMethodKind {
MK_OneArgSelector //< One-argument selector.
};
-static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
- ObjCMethodKind WantKind,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents) {
- Selector Sel = Method->getSelector();
+static bool isAcceptableObjCSelector(Selector Sel,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
if (NumSelIdents > Sel.getNumArgs())
return false;
-
+
switch (WantKind) {
- case MK_Any: break;
- case MK_ZeroArgSelector: return Sel.isUnarySelector();
- case MK_OneArgSelector: return Sel.getNumArgs() == 1;
+ case MK_Any: break;
+ case MK_ZeroArgSelector: return Sel.isUnarySelector();
+ case MK_OneArgSelector: return Sel.getNumArgs() == 1;
}
-
+
for (unsigned I = 0; I != NumSelIdents; ++I)
if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
return false;
-
+
return true;
}
+
+static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
+ ObjCMethodKind WantKind,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
+ return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
+ NumSelIdents);
+}
/// \brief Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
@@ -3195,8 +3807,9 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
IdentifierInfo **SelIdents,
unsigned NumSelIdents,
DeclContext *CurContext,
- ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder &Results,
+ bool InOriginalClass = true) {
+ typedef CodeCompletionResult Result;
for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
MEnd = Container->meth_end();
M != MEnd; ++M) {
@@ -3209,6 +3822,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
Result R = Result(*M, 0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = (WantKind != MK_Any);
+ if (!InOriginalClass)
+ R.Priority += CCD_InBaseClass;
Results.MaybeAddResult(R, CurContext);
}
}
@@ -3223,13 +3838,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
- CurContext, Results);
+ CurContext, Results, false);
// Add methods in categories.
for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
CatDecl = CatDecl->getNextClassCategory()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results);
+ NumSelIdents, CurContext, Results, InOriginalClass);
// Add a categories protocol methods.
const ObjCList<ObjCProtocolDecl> &Protocols
@@ -3238,37 +3853,36 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results);
+ NumSelIdents, CurContext, Results, false);
// Add methods in category implementations.
if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results);
+ NumSelIdents, CurContext, Results, InOriginalClass);
}
// Add methods in superclass.
if (IFace->getSuperClass())
AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
- SelIdents, NumSelIdents, CurContext, Results);
+ SelIdents, NumSelIdents, CurContext, Results, false);
// Add methods in our implementation, if any.
if (ObjCImplementationDecl *Impl = IFace->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
- NumSelIdents, CurContext, Results);
+ NumSelIdents, CurContext, Results, InOriginalClass);
}
-void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
- DeclPtrTy *Methods,
+void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl,
+ Decl **Methods,
unsigned NumMethods) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Try to find the interface where getters might live.
- ObjCInterfaceDecl *Class
- = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl.getAs<Decl>());
+ ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl);
if (!Class) {
if (ObjCCategoryDecl *Category
- = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl.getAs<Decl>()))
+ = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl))
Class = Category->getClassInterface();
if (!Class)
@@ -3283,7 +3897,7 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
// pushed into DeclContexts early enough. Argh!
for (unsigned I = 0; I != NumMethods; ++I) {
if (ObjCMethodDecl *Method
- = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>()))
+ = dyn_cast_or_null<ObjCMethodDecl>(Methods[I]))
if (Method->isInstanceMethod() &&
isAcceptableObjCMethod(Method, MK_ZeroArgSelector, 0, 0)) {
Result R = Result(Method, 0);
@@ -3294,20 +3908,22 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S, DeclPtrTy ClassDecl,
AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
-void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl,
- DeclPtrTy *Methods,
+void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl,
+ Decl **Methods,
unsigned NumMethods) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Try to find the interface where setters might live.
ObjCInterfaceDecl *Class
- = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl.getAs<Decl>());
+ = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl);
if (!Class) {
if (ObjCCategoryDecl *Category
- = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl.getAs<Decl>()))
+ = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl))
Class = Category->getClassInterface();
if (!Class)
@@ -3322,7 +3938,7 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl,
// pushed into DeclContexts early enough. Argh!
for (unsigned I = 0; I != NumMethods; ++I) {
if (ObjCMethodDecl *Method
- = dyn_cast_or_null<ObjCMethodDecl>(Methods[I].getAs<Decl>()))
+ = dyn_cast_or_null<ObjCMethodDecl>(Methods[I]))
if (Method->isInstanceMethod() &&
isAcceptableObjCMethod(Method, MK_OneArgSelector, 0, 0)) {
Result R = Result(Method, 0);
@@ -3334,7 +3950,54 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ObjCImplDecl,
AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter,Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) {
+ typedef CodeCompletionResult Result;
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // Add context-sensitive, Objective-C parameter-passing keywords.
+ bool AddedInOut = false;
+ if ((DS.getObjCDeclQualifier() &
+ (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
+ Results.AddResult("in");
+ Results.AddResult("inout");
+ AddedInOut = true;
+ }
+ if ((DS.getObjCDeclQualifier() &
+ (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
+ Results.AddResult("out");
+ if (!AddedInOut)
+ Results.AddResult("inout");
+ }
+ if ((DS.getObjCDeclQualifier() &
+ (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
+ ObjCDeclSpec::DQ_Oneway)) == 0) {
+ Results.AddResult("bycopy");
+ Results.AddResult("byref");
+ Results.AddResult("oneway");
+ }
+
+ // Add various builtin type names and specifiers.
+ AddOrdinaryNameResults(PCC_Type, S, *this, Results);
+ Results.ExitScope();
+
+ // Add the various type names
+ Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+ CodeCompletionDeclConsumer Consumer(Results, CurContext);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
+
+ if (CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Type,
+ Results.data(), Results.size());
}
/// \brief When we have an expression with type "id", we may assume
@@ -3407,28 +4070,138 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
.Default(0);
}
+// Add a special completion for a message send to "super", which fills in the
+// most likely case of forwarding all of our arguments to the superclass
+// function.
+///
+/// \param S The semantic analysis object.
+///
+/// \param S NeedSuperKeyword Whether we need to prefix this completion with
+/// the "super" keyword. Otherwise, we just need to provide the arguments.
+///
+/// \param SelIdents The identifiers in the selector that have already been
+/// provided as arguments for a send to "super".
+///
+/// \param NumSelIdents The number of identifiers in \p SelIdents.
+///
+/// \param Results The set of results to augment.
+///
+/// \returns the Objective-C method declaration that would be invoked by
+/// this "super" completion. If NULL, no completion was added.
+static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ ResultBuilder &Results) {
+ ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
+ if (!CurMethod)
+ return 0;
+
+ ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
+ if (!Class)
+ return 0;
+
+ // Try to find a superclass method with the same selector.
+ ObjCMethodDecl *SuperMethod = 0;
+ while ((Class = Class->getSuperClass()) && !SuperMethod)
+ SuperMethod = Class->getMethod(CurMethod->getSelector(),
+ CurMethod->isInstanceMethod());
+
+ if (!SuperMethod)
+ return 0;
+
+ // Check whether the superclass method has the same signature.
+ if (CurMethod->param_size() != SuperMethod->param_size() ||
+ CurMethod->isVariadic() != SuperMethod->isVariadic())
+ return 0;
+
+ for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
+ CurPEnd = CurMethod->param_end(),
+ SuperP = SuperMethod->param_begin();
+ CurP != CurPEnd; ++CurP, ++SuperP) {
+ // Make sure the parameter types are compatible.
+ if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
+ (*SuperP)->getType()))
+ return 0;
+
+ // Make sure we have a parameter name to forward!
+ if (!(*CurP)->getIdentifier())
+ return 0;
+ }
+
+ // We have a superclass method. Now, form the send-to-super completion.
+ CodeCompletionString *Pattern = new CodeCompletionString;
+
+ // Give this completion a return type.
+ AddResultTypeChunk(S.Context, SuperMethod, Pattern);
+
+ // If we need the "super" keyword, add it (plus some spacing).
+ if (NeedSuperKeyword) {
+ Pattern->AddTypedTextChunk("super");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ }
+
+ Selector Sel = CurMethod->getSelector();
+ if (Sel.isUnarySelector()) {
+ if (NeedSuperKeyword)
+ Pattern->AddTextChunk(Sel.getIdentifierInfoForSlot(0)->getName());
+ else
+ Pattern->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName());
+ } else {
+ ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
+ for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
+ if (I > NumSelIdents)
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+
+ if (I < NumSelIdents)
+ Pattern->AddInformativeChunk(
+ Sel.getIdentifierInfoForSlot(I)->getName().str() + ":");
+ else if (NeedSuperKeyword || I > NumSelIdents) {
+ Pattern->AddTextChunk(
+ Sel.getIdentifierInfoForSlot(I)->getName().str() + ":");
+ Pattern->AddPlaceholderChunk((*CurP)->getIdentifier()->getName());
+ } else {
+ Pattern->AddTypedTextChunk(
+ Sel.getIdentifierInfoForSlot(I)->getName().str() + ":");
+ Pattern->AddPlaceholderChunk((*CurP)->getIdentifier()->getName());
+ }
+ }
+ }
+
+ Results.AddResult(CodeCompletionResult(Pattern, CCP_SuperCompletion,
+ SuperMethod->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl
+ : CXCursor_ObjCClassMethodDecl));
+ return SuperMethod;
+}
+
void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
// Find anything that looks like it could be a message receiver.
Results.setFilter(&ResultBuilder::IsObjCMessageReceiver);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.EnterNewScope();
- LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
+ LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
+ CodeCompleter->includeGlobals());
// If we are in an Objective-C method inside a class that has a superclass,
// add "super" as an option.
if (ObjCMethodDecl *Method = getCurMethodDecl())
if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
- if (Iface->getSuperClass())
+ if (Iface->getSuperClass()) {
Results.AddResult(Result("super"));
+
+ AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
+ }
Results.ExitScope();
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results);
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_ObjCMessageReceiver,
+ Results.data(), Results.size());
}
@@ -3454,10 +4227,11 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// an instance method.
QualType SuperTy = Context.getObjCInterfaceType(CDecl);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
- OwningExprResult Super
+ ExprResult Super
= Owned(new (Context) ObjCSuperExpr(SuperLoc, SuperTy));
return CodeCompleteObjCInstanceMessage(S, (Expr *)Super.get(),
- SelIdents, NumSelIdents);
+ SelIdents, NumSelIdents,
+ /*IsSuper=*/true);
}
// Fall through to send to the superclass in CDecl.
@@ -3480,7 +4254,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
CXXScopeSpec SS;
UnqualifiedId id;
id.setIdentifier(Super, SuperLoc);
- OwningExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
+ ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
SelIdents, NumSelIdents);
}
@@ -3488,17 +4262,24 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
// Fall through
}
- TypeTy *Receiver = 0;
+ ParsedType Receiver;
if (CDecl)
- Receiver = Context.getObjCInterfaceType(CDecl).getAsOpaquePtr();
+ Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
- NumSelIdents);
+ NumSelIdents, /*IsSuper=*/true);
}
-void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
+void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) {
- typedef CodeCompleteConsumer::Result Result;
+ CodeCompleteObjCClassMessage(S, Receiver, SelIdents, NumSelIdents, false);
+}
+
+void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool IsSuper) {
+ typedef CodeCompletionResult Result;
ObjCInterfaceDecl *CDecl = 0;
// If the given name refers to an interface type, retrieve the
@@ -3515,6 +4296,20 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
ResultBuilder Results(*this);
Results.EnterNewScope();
+ // If this is a send-to-super, try to add the special "super" send
+ // completion.
+ if (IsSuper) {
+ if (ObjCMethodDecl *SuperMethod
+ = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
+ Results))
+ Results.Ignore(SuperMethod);
+ }
+
+ // If we're inside an Objective-C method definition, prefer its selector to
+ // others.
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+ Results.setPreferredSelector(CurMethod->getSelector());
+
if (CDecl)
AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, CurContext,
Results);
@@ -3522,25 +4317,23 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
// We're messaging "id" as a type; provide all class/factory methods.
// If we have an external source, load the entire class method
- // pool from the PCH file.
+ // pool from the AST file.
if (ExternalSource) {
for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
- if (Sel.isNull() || FactoryMethodPool.count(Sel) ||
- InstanceMethodPool.count(Sel))
+ if (Sel.isNull() || MethodPool.count(Sel))
continue;
- ReadMethodPool(Sel, /*isInstance=*/false);
+ ReadMethodPool(Sel);
}
}
- for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
- M = FactoryMethodPool.begin(),
- MEnd = FactoryMethodPool.end();
- M != MEnd;
- ++M) {
- for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method;
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+ for (ObjCMethodList *MethList = &M->second.second;
+ MethList && MethList->Method;
MethList = MethList->Next) {
if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
NumSelIdents))
@@ -3555,13 +4348,22 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(), Results.size());
}
void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) {
- typedef CodeCompleteConsumer::Result Result;
+ CodeCompleteObjCInstanceMessage(S, Receiver, SelIdents, NumSelIdents, false);
+}
+
+void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
+ IdentifierInfo **SelIdents,
+ unsigned NumSelIdents,
+ bool IsSuper) {
+ typedef CodeCompletionResult Result;
Expr *RecExpr = static_cast<Expr *>(Receiver);
@@ -3574,6 +4376,20 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
ResultBuilder Results(*this);
Results.EnterNewScope();
+ // If this is a send-to-super, try to add the special "super" send
+ // completion.
+ if (IsSuper) {
+ if (ObjCMethodDecl *SuperMethod
+ = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
+ Results))
+ Results.Ignore(SuperMethod);
+ }
+
+ // If we're inside an Objective-C method definition, prefer its selector to
+ // others.
+ if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
+ Results.setPreferredSelector(CurMethod->getSelector());
+
// If we're messaging an expression with type "id" or "Class", check
// whether we know something special about the receiver that allows
// us to assume a more-specific receiver type.
@@ -3623,25 +4439,23 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
// about as code-completion results.
// If we have an external source, load the entire class method
- // pool from the PCH file.
+ // pool from the AST file.
if (ExternalSource) {
for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
- if (Sel.isNull() || InstanceMethodPool.count(Sel) ||
- FactoryMethodPool.count(Sel))
+ if (Sel.isNull() || MethodPool.count(Sel))
continue;
- ReadMethodPool(Sel, /*isInstance=*/true);
+ ReadMethodPool(Sel);
}
}
- for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
- M = InstanceMethodPool.begin(),
- MEnd = InstanceMethodPool.end();
- M != MEnd;
- ++M) {
- for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method;
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+ for (ObjCMethodList *MethList = &M->second.first;
+ MethList && MethList->Method;
MethList = MethList->Next) {
if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
NumSelIdents))
@@ -3656,7 +4470,79 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar) {
+ CodeCompleteExpressionData Data;
+ Data.ObjCCollection = true;
+
+ if (IterationVar.getAsOpaquePtr()) {
+ DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
+ for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
+ if (*I)
+ Data.IgnoreDecls.push_back(*I);
+ }
+ }
+
+ CodeCompleteExpression(S, Data);
+}
+
+void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
+ unsigned NumSelIdents) {
+ // If we have an external source, load the entire class method
+ // pool from the AST file.
+ if (ExternalSource) {
+ for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
+ I != N; ++I) {
+ Selector Sel = ExternalSource->GetExternalSelector(I);
+ if (Sel.isNull() || MethodPool.count(Sel))
+ continue;
+
+ ReadMethodPool(Sel);
+ }
+ }
+
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+
+ Selector Sel = M->first;
+ if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
+ continue;
+
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ if (Sel.isUnarySelector()) {
+ Pattern->AddTypedTextChunk(Sel.getIdentifierInfoForSlot(0)->getName());
+ Results.AddResult(Pattern);
+ continue;
+ }
+
+ std::string Accumulator;
+ for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
+ if (I == NumSelIdents) {
+ if (!Accumulator.empty()) {
+ Pattern->AddInformativeChunk(Accumulator);
+ Accumulator.clear();
+ }
+ }
+
+ Accumulator += Sel.getIdentifierInfoForSlot(I)->getName().str();
+ Accumulator += ':';
+ }
+ Pattern->AddTypedTextChunk(Accumulator);
+ Results.AddResult(Pattern);
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_SelectorName,
+ Results.data(), Results.size());
}
/// \brief Add all of the protocol declarations that we find in the given
@@ -3664,7 +4550,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
for (DeclContext::decl_iterator D = Ctx->decls_begin(),
DEnd = Ctx->decls_end();
@@ -3704,7 +4590,9 @@ void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_ObjCProtocolName,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
@@ -3716,7 +4604,9 @@ void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_ObjCProtocolName,
+ Results.data(),Results.size());
}
/// \brief Add all of the Objective-C interface declarations that we find in
@@ -3725,7 +4615,7 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
bool OnlyUnimplemented,
ResultBuilder &Results) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
for (DeclContext::decl_iterator D = Ctx->decls_begin(),
DEnd = Ctx->decls_end();
@@ -3757,7 +4647,9 @@ void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
false, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
@@ -3776,7 +4668,9 @@ void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
false, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
@@ -3788,13 +4682,15 @@ void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
true, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
@@ -3819,13 +4715,15 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Results.AddResult(Result(Category, 0), CurContext, 0, false);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
// Find the corresponding interface. If we couldn't find the interface, the
// program itself is ill-formed. However, we'll try to be helpful still by
@@ -3856,16 +4754,18 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
-void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) {
- typedef CodeCompleteConsumer::Result Result;
+void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
- = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
if (!Container ||
(!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
@@ -3889,18 +4789,20 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, DeclPtrTy ObjCImpDecl) {
false, CurContext, Results);
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
IdentifierInfo *PropertyName,
- DeclPtrTy ObjCImpDecl) {
- typedef CodeCompleteConsumer::Result Result;
+ Decl *ObjCImpDecl) {
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container
- = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
if (!Container ||
(!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
@@ -3927,10 +4829,15 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
-typedef llvm::DenseMap<Selector, ObjCMethodDecl *> KnownMethodsMap;
+// Mapping from selectors to the methods that implement that selector, along
+// with the "in original class" flag.
+typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
+ KnownMethodsMap;
/// \brief Find all of the methods that reside in the given container
/// (and its superclasses, protocols, etc.) that meet the given
@@ -3941,7 +4848,8 @@ static void FindImplementableMethods(ASTContext &Context,
bool WantInstanceMethods,
QualType ReturnType,
bool IsInImplementation,
- KnownMethodsMap &KnownMethods) {
+ KnownMethodsMap &KnownMethods,
+ bool InOriginalClass = true) {
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
// Recurse into protocols.
const ObjCList<ObjCProtocolDecl> &Protocols
@@ -3950,14 +4858,16 @@ static void FindImplementableMethods(ASTContext &Context,
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
- IsInImplementation, KnownMethods);
+ IsInImplementation, KnownMethods,
+ InOriginalClass);
// If we're not in the implementation of a class, also visit the
// superclass.
if (!IsInImplementation && IFace->getSuperClass())
FindImplementableMethods(Context, IFace->getSuperClass(),
WantInstanceMethods, ReturnType,
- IsInImplementation, KnownMethods);
+ IsInImplementation, KnownMethods,
+ false);
// Add methods from any class extensions (but not from categories;
// those should go into category implementations).
@@ -3965,7 +4875,8 @@ static void FindImplementableMethods(ASTContext &Context,
Cat = Cat->getNextClassExtension())
FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
WantInstanceMethods, ReturnType,
- IsInImplementation, KnownMethods);
+ IsInImplementation, KnownMethods,
+ InOriginalClass);
}
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
@@ -3976,7 +4887,8 @@ static void FindImplementableMethods(ASTContext &Context,
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
- IsInImplementation, KnownMethods);
+ IsInImplementation, KnownMethods,
+ InOriginalClass);
}
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
@@ -3987,7 +4899,7 @@ static void FindImplementableMethods(ASTContext &Context,
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
- IsInImplementation, KnownMethods);
+ IsInImplementation, KnownMethods, false);
}
// Add methods in this container. This operation occurs last because
@@ -4001,15 +4913,15 @@ static void FindImplementableMethods(ASTContext &Context,
!Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
continue;
- KnownMethods[(*M)->getSelector()] = *M;
+ KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
}
}
}
void Sema::CodeCompleteObjCMethodDecl(Scope *S,
bool IsInstanceMethod,
- TypeTy *ReturnTy,
- DeclPtrTy IDecl) {
+ ParsedType ReturnTy,
+ Decl *IDecl) {
// Determine the return type of the method we're declaring, if
// provided.
QualType ReturnType = GetTypeFromParser(ReturnTy);
@@ -4017,7 +4929,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
// Determine where we should start searching for methods, and where we
ObjCContainerDecl *SearchDecl = 0, *CurrentDecl = 0;
bool IsInImplementation = false;
- if (Decl *D = IDecl.getAs<Decl>()) {
+ if (Decl *D = IDecl) {
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
SearchDecl = Impl->getClassInterface();
CurrentDecl = Impl;
@@ -4041,7 +4953,9 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
}
if (!SearchDecl || !CurrentDecl) {
- HandleCodeCompleteResults(this, CodeCompleter, 0, 0);
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ 0, 0);
return;
}
@@ -4064,7 +4978,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
}
// Add declarations or definitions for each of the known methods.
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
Results.EnterNewScope();
PrintingPolicy Policy(Context.PrintingPolicy);
@@ -4072,7 +4986,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M) {
- ObjCMethodDecl *Method = M->second;
+ ObjCMethodDecl *Method = M->second.first;
CodeCompletionString *Pattern = new CodeCompletionString;
// If the result type was not already provided, add it to the
@@ -4100,7 +5014,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
Pattern->AddChunk(CodeCompletionString::CK_Colon);
else if (I < Sel.getNumArgs()) {
Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
- Pattern->AddTextChunk(Sel.getIdentifierInfoForSlot(1)->getName());
+ Pattern->AddTextChunk(Sel.getIdentifierInfoForSlot(I)->getName());
Pattern->AddChunk(CodeCompletionString::CK_Colon);
} else
break;
@@ -4113,14 +5027,14 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
Pattern->AddChunk(CodeCompletionString::CK_RightParen);
if (IdentifierInfo *Id = (*P)->getIdentifier())
- Pattern->AddTextChunk(Id->getName());
+ Pattern->AddTextChunk(Id->getName());
}
if (Method->isVariadic()) {
if (Method->param_size() > 0)
Pattern->AddChunk(CodeCompletionString::CK_Comma);
Pattern->AddTextChunk("...");
- }
+ }
if (IsInImplementation && Results.includeCodePatterns()) {
// We will be defining the method here, so add a compound statement.
@@ -4140,50 +5054,56 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
}
- Results.AddResult(Result(Pattern));
+ unsigned Priority = CCP_CodePattern;
+ if (!M->second.second)
+ Priority += CCD_InBaseClass;
+
+ Results.AddResult(Result(Pattern, Priority,
+ Method->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl
+ : CXCursor_ObjCClassMethodDecl));
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
}
void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
bool AtParameterName,
- TypeTy *ReturnTy,
+ ParsedType ReturnTy,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) {
- llvm::DenseMap<Selector, ObjCMethodList> &Pool
- = IsInstanceMethod? InstanceMethodPool : FactoryMethodPool;
-
// If we have an external source, load the entire class method
- // pool from the PCH file.
+ // pool from the AST file.
if (ExternalSource) {
for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
- if (Sel.isNull() || InstanceMethodPool.count(Sel) ||
- FactoryMethodPool.count(Sel))
+ if (Sel.isNull() || MethodPool.count(Sel))
continue;
-
- ReadMethodPool(Sel, IsInstanceMethod);
+
+ ReadMethodPool(Sel);
}
}
// Build the set of methods we can see.
- typedef CodeCompleteConsumer::Result Result;
+ typedef CodeCompletionResult Result;
ResultBuilder Results(*this);
if (ReturnTy)
Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
-
+
Results.EnterNewScope();
- for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = Pool.begin(),
- MEnd = Pool.end();
- M != MEnd;
- ++M) {
- for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method;
+ for (GlobalMethodPool::iterator M = MethodPool.begin(),
+ MEnd = MethodPool.end();
+ M != MEnd; ++M) {
+ for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
+ &M->second.second;
+ MethList && MethList->Method;
MethList = MethList->Next) {
if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
NumSelIdents))
@@ -4212,5 +5132,270 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
}
Results.ExitScope();
- HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_Other,
+ Results.data(),Results.size());
+}
+
+void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ // #if <condition>
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("if");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("condition");
+ Results.AddResult(Pattern);
+
+ // #ifdef <macro>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("ifdef");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("macro");
+ Results.AddResult(Pattern);
+
+ // #ifndef <macro>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("ifndef");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("macro");
+ Results.AddResult(Pattern);
+
+ if (InConditional) {
+ // #elif <condition>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("elif");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("condition");
+ Results.AddResult(Pattern);
+
+ // #else
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("else");
+ Results.AddResult(Pattern);
+
+ // #endif
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("endif");
+ Results.AddResult(Pattern);
+ }
+
+ // #include "header"
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("include");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("\"");
+ Pattern->AddPlaceholderChunk("header");
+ Pattern->AddTextChunk("\"");
+ Results.AddResult(Pattern);
+
+ // #include <header>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("include");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("<");
+ Pattern->AddPlaceholderChunk("header");
+ Pattern->AddTextChunk(">");
+ Results.AddResult(Pattern);
+
+ // #define <macro>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("define");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("macro");
+ Results.AddResult(Pattern);
+
+ // #define <macro>(<args>)
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("define");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("macro");
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("args");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Pattern);
+
+ // #undef <macro>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("undef");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("macro");
+ Results.AddResult(Pattern);
+
+ // #line <number>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("line");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("number");
+ Results.AddResult(Pattern);
+
+ // #line <number> "filename"
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("line");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("number");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("\"");
+ Pattern->AddPlaceholderChunk("filename");
+ Pattern->AddTextChunk("\"");
+ Results.AddResult(Pattern);
+
+ // #error <message>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("error");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("message");
+ Results.AddResult(Pattern);
+
+ // #pragma <arguments>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("pragma");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("arguments");
+ Results.AddResult(Pattern);
+
+ if (getLangOptions().ObjC1) {
+ // #import "header"
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("import");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("\"");
+ Pattern->AddPlaceholderChunk("header");
+ Pattern->AddTextChunk("\"");
+ Results.AddResult(Pattern);
+
+ // #import <header>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("import");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("<");
+ Pattern->AddPlaceholderChunk("header");
+ Pattern->AddTextChunk(">");
+ Results.AddResult(Pattern);
+ }
+
+ // #include_next "header"
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("include_next");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("\"");
+ Pattern->AddPlaceholderChunk("header");
+ Pattern->AddTextChunk("\"");
+ Results.AddResult(Pattern);
+
+ // #include_next <header>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("include_next");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddTextChunk("<");
+ Pattern->AddPlaceholderChunk("header");
+ Pattern->AddTextChunk(">");
+ Results.AddResult(Pattern);
+
+ // #warning <message>
+ Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("warning");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddPlaceholderChunk("message");
+ Results.AddResult(Pattern);
+
+ // Note: #ident and #sccs are such crazy anachronisms that we don't provide
+ // completions for them. And __include_macros is a Clang-internal extension
+ // that we don't want to encourage anyone to use.
+
+ // FIXME: we don't support #assert or #unassert, so don't suggest them.
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_PreprocessorDirective,
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
+ CodeCompleteOrdinaryName(S,
+ S->getFnParent()? Sema::PCC_RecoveryInFunction
+ : Sema::PCC_Namespace);
+}
+
+void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
+ ResultBuilder Results(*this);
+ if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
+ // Add just the names of macros, not their arguments.
+ Results.EnterNewScope();
+ for (Preprocessor::macro_iterator M = PP.macro_begin(),
+ MEnd = PP.macro_end();
+ M != MEnd; ++M) {
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(M->first->getName());
+ Results.AddResult(Pattern);
+ }
+ Results.ExitScope();
+ } else if (IsDefinition) {
+ // FIXME: Can we detect when the user just wrote an include guard above?
+ }
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ IsDefinition? CodeCompletionContext::CCC_MacroName
+ : CodeCompletionContext::CCC_MacroNameUse,
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompletePreprocessorExpression() {
+ ResultBuilder Results(*this);
+
+ if (!CodeCompleter || CodeCompleter->includeMacros())
+ AddMacroResults(PP, Results);
+
+ // defined (<macro>)
+ Results.EnterNewScope();
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk("defined");
+ Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+ Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+ Pattern->AddPlaceholderChunk("macro");
+ Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+ Results.AddResult(Pattern);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_PreprocessorExpression,
+ Results.data(), Results.size());
+}
+
+void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
+ IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned Argument) {
+ // FIXME: In the future, we could provide "overload" results, much like we
+ // do for function calls.
+
+ CodeCompleteOrdinaryName(S,
+ S->getFnParent()? Sema::PCC_RecoveryInFunction
+ : Sema::PCC_Namespace);
+}
+
+void Sema::CodeCompleteNaturalLanguage() {
+ HandleCodeCompleteResults(this, CodeCompleter,
+ CodeCompletionContext::CCC_NaturalLanguage,
+ 0, 0);
+}
+
+void Sema::GatherGlobalCodeCompletions(
+ llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
+ ResultBuilder Builder(*this);
+
+ if (!CodeCompleter || CodeCompleter->includeGlobals()) {
+ CodeCompletionDeclConsumer Consumer(Builder,
+ Context.getTranslationUnitDecl());
+ LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
+ Consumer);
+ }
+
+ if (!CodeCompleter || CodeCompleter->includeMacros())
+ AddMacroResults(PP, Builder);
+
+ Results.clear();
+ Results.insert(Results.end(),
+ Builder.data(), Builder.data() + Builder.size());
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c1c898fac5f9..f5e045a722a0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -11,19 +11,24 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.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"
@@ -35,18 +40,10 @@
#include <cstring>
#include <functional>
using namespace clang;
+using namespace sema;
-/// getDeclName - Return a pretty name for the specified decl if possible, or
-/// an empty string if not. This is used for pretty crash reporting.
-std::string Sema::getDeclName(DeclPtrTy d) {
- Decl *D = d.getAs<Decl>();
- if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(D))
- return DN->getQualifiedNameAsString();
- return "";
-}
-
-Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
- return DeclGroupPtrTy::make(DeclGroupRef(Ptr.getAs<Decl>()));
+Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) {
+ return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
}
/// \brief If the identifier refers to a type name within this scope,
@@ -60,14 +57,14 @@ Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(DeclPtrTy Ptr) {
///
/// If name lookup results in an ambiguity, this routine will complain
/// and then return NULL.
-Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
- Scope *S, CXXScopeSpec *SS,
- bool isClassName,
- TypeTy *ObjectTypePtr) {
+ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS,
+ bool isClassName,
+ ParsedType ObjectTypePtr) {
// Determine where we will perform name lookup.
DeclContext *LookupCtx = 0;
if (ObjectTypePtr) {
- QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+ QualType ObjectType = ObjectTypePtr.get();
if (ObjectType->isRecordType())
LookupCtx = computeDeclContext(ObjectType);
} else if (SS && SS->isNotEmpty()) {
@@ -85,22 +82,22 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// We therefore do not perform any name lookup if the result would
// refer to a member of an unknown specialization.
if (!isClassName)
- return 0;
+ return ParsedType();
// We know from the grammar that this name refers to a type,
// so build a dependent node to describe the type.
- return CheckTypenameType(ETK_None,
- (NestedNameSpecifier *)SS->getScopeRep(), II,
- SourceLocation(), SS->getRange(), NameLoc
- ).getAsOpaquePtr();
+ QualType T =
+ CheckTypenameType(ETK_None, SS->getScopeRep(), II,
+ SourceLocation(), SS->getRange(), NameLoc);
+ return ParsedType::make(T);
}
- return 0;
+ return ParsedType();
}
if (!LookupCtx->isDependentContext() &&
RequireCompleteDeclContext(*SS, LookupCtx))
- return 0;
+ return ParsedType();
}
// FIXME: LookupNestedNameSpecifierName isn't the right kind of
@@ -136,7 +133,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
case LookupResult::FoundOverloaded:
case LookupResult::FoundUnresolvedValue:
Result.suppressDiagnostics();
- return 0;
+ return ParsedType();
case LookupResult::Ambiguous:
// Recover from type-hiding ambiguities by hiding the type. We'll
@@ -146,7 +143,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// that only makes sense if the identifier was treated like a type.
if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) {
Result.suppressDiagnostics();
- return 0;
+ return ParsedType();
}
// Look to see if we have a type anywhere in the list of results.
@@ -168,7 +165,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
// will produce the ambiguity, or will complain that it expected
// a type name.
Result.suppressDiagnostics();
- return 0;
+ return ParsedType();
}
// We found a type within the ambiguous lookup; diagnose the
@@ -199,10 +196,10 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
} else {
// If it's not plausibly a type, suppress diagnostics.
Result.suppressDiagnostics();
- return 0;
+ return ParsedType();
}
- return T.getAsOpaquePtr();
+ return ParsedType::make(T);
}
/// isTagName() - This method is called *for error recovery purposes only*
@@ -233,9 +230,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
- TypeTy *&SuggestedType) {
+ ParsedType &SuggestedType) {
// We don't have anything to suggest (yet).
- SuggestedType = 0;
+ SuggestedType = ParsedType();
// There may have been a typo in the name of the type. Look up typo
// results, in case we have something that we can suggest.
@@ -282,7 +279,8 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
CXXScopeSpec EmptySS;
TemplateTy TemplateResult;
bool MemberOfUnknownSpecialization;
- if (isTemplateName(S, SS ? *SS : EmptySS, Name, 0, true, TemplateResult,
+ if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false,
+ Name, ParsedType(), true, TemplateResult,
MemberOfUnknownSpecialization) == TNK_Type_template) {
TemplateName TplName = TemplateResult.getAsVal<TemplateName>();
Diag(IILoc, diag::err_template_missing_args) << TplName;
@@ -343,8 +341,10 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
return DC;
}
+ // ObjCMethodDecls are parsed (for some reason) outside the context
+ // of the class.
if (isa<ObjCMethodDecl>(DC))
- return Context.getTranslationUnitDecl();
+ return DC->getLexicalParent()->getLexicalParent();
return DC->getLexicalParent();
}
@@ -360,6 +360,7 @@ void Sema::PopDeclContext() {
assert(CurContext && "DeclContext imbalance!");
CurContext = getContainingDC(CurContext);
+ assert(CurContext && "Popped translation unit!");
}
/// EnterDeclaratorContext - Used when we must lookup names in the context
@@ -458,8 +459,8 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
IEnd = IdResolver.end();
for (; I != IEnd; ++I) {
- if (S->isDeclScope(DeclPtrTy::make(*I)) && D->declarationReplaces(*I)) {
- S->RemoveDecl(DeclPtrTy::make(*I));
+ if (S->isDeclScope(*I) && D->declarationReplaces(*I)) {
+ S->RemoveDecl(*I);
IdResolver.RemoveDecl(*I);
// Should only need to replace one decl.
@@ -467,7 +468,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
}
}
- S->AddDecl(DeclPtrTy::make(D));
+ S->AddDecl(D);
IdResolver.AddDecl(D);
}
@@ -475,6 +476,17 @@ bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S) {
return IdResolver.isDeclInScope(D, Ctx, Context, S);
}
+Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) {
+ DeclContext *TargetDC = DC->getPrimaryContext();
+ do {
+ if (DeclContext *ScopeDC = (DeclContext*) S->getEntity())
+ if (ScopeDC->getPrimaryContext() == TargetDC)
+ return S;
+ } while ((S = S->getParent()));
+
+ return 0;
+}
+
static bool isOutOfScopePreviousDeclaration(NamedDecl *,
DeclContext*,
ASTContext&);
@@ -517,6 +529,90 @@ static void RemoveUsingDecls(LookupResult &R) {
F.done();
}
+/// \brief Check for this common pattern:
+/// @code
+/// class S {
+/// S(const S&); // DO NOT IMPLEMENT
+/// void operator=(const S&); // DO NOT IMPLEMENT
+/// };
+/// @endcode
+static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) {
+ // FIXME: Should check for private access too but access is set after we get
+ // the decl here.
+ if (D->isThisDeclarationADefinition())
+ return false;
+
+ if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
+ return CD->isCopyConstructor();
+ return D->isCopyAssignment();
+}
+
+bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
+ assert(D);
+
+ if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>())
+ return false;
+
+ // Ignore class templates.
+ if (D->getDeclContext()->isDependentContext())
+ return false;
+
+ // We warn for unused decls internal to the translation unit.
+ if (D->getLinkage() == ExternalLinkage)
+ return false;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return false;
+
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD))
+ return false;
+ } else {
+ // 'static inline' functions are used in headers; don't warn.
+ if (FD->getStorageClass() == SC_Static &&
+ FD->isInlineSpecified())
+ return false;
+ }
+
+ if (FD->isThisDeclarationADefinition())
+ return !Context.DeclMustBeEmitted(FD);
+ return true;
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->isStaticDataMember() &&
+ VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+ return false;
+
+ if ( VD->isFileVarDecl() &&
+ !VD->getType().isConstant(Context))
+ return !Context.DeclMustBeEmitted(VD);
+ }
+
+ return false;
+ }
+
+ void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) {
+ if (!D)
+ return;
+
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ const FunctionDecl *First = FD->getFirstDeclaration();
+ if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+ return; // First should already be in the vector.
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ const VarDecl *First = VD->getFirstDeclaration();
+ if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First))
+ return; // First should already be in the vector.
+ }
+
+ if (ShouldWarnIfUnusedFileScopedDecl(D))
+ UnusedFileScopedDecls.push_back(D);
+ }
+
static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (D->isInvalidDecl())
return false;
@@ -585,7 +681,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
- Decl *TmpD = (*I).getAs<Decl>();
+ Decl *TmpD = (*I);
assert(TmpD && "This decl didn't get pushed??");
assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?");
@@ -731,8 +827,8 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
FunctionDecl *New = FunctionDecl::Create(Context,
Context.getTranslationUnitDecl(),
Loc, II, R, /*TInfo=*/0,
- FunctionDecl::Extern,
- FunctionDecl::None, false,
+ SC_Extern,
+ SC_None, false,
/*hasPrototype=*/true);
New->setImplicit();
@@ -743,7 +839,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0,
FT->getArgType(i), /*TInfo=*/0,
- VarDecl::None, VarDecl::None, 0));
+ SC_None, SC_None, 0));
New->setParams(Params.data(), Params.size());
}
@@ -909,25 +1005,40 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
/// DeclhasAttr - returns true if decl Declaration already has the target
/// attribute.
static bool
-DeclHasAttr(const Decl *decl, const Attr *target) {
- for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext())
- if (attr->getKind() == target->getKind())
+DeclHasAttr(const Decl *D, const Attr *A) {
+ const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A);
+ for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i)
+ if ((*i)->getKind() == A->getKind()) {
+ // FIXME: Don't hardcode this check
+ if (OA && isa<OwnershipAttr>(*i))
+ return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind();
return true;
+ }
return false;
}
-/// MergeAttributes - append attributes from the Old decl to the New one.
-static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) {
- for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) {
- if (!DeclHasAttr(New, attr) && attr->isMerged()) {
- Attr *NewAttr = attr->clone(C);
+/// MergeDeclAttributes - append attributes from the Old decl to the New one.
+static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
+ if (!Old->hasAttrs())
+ return;
+ // Ensure that any moving of objects within the allocated map is done before
+ // we process them.
+ if (!New->hasAttrs())
+ New->setAttrs(AttrVec());
+ for (Decl::attr_iterator i = Old->attr_begin(), e = Old->attr_end(); i != e;
+ ++i) {
+ // FIXME: Make this more general than just checking for Overloadable.
+ if (!DeclHasAttr(New, *i) && (*i)->getKind() != attr::Overloadable) {
+ Attr *NewAttr = (*i)->clone(C);
NewAttr->setInherited(true);
New->addAttr(NewAttr);
}
}
}
+namespace {
+
/// Used in MergeFunctionDecl to keep track of function parameters in
/// C.
struct GNUCompatibleParamWarning {
@@ -936,6 +1047,7 @@ struct GNUCompatibleParamWarning {
QualType PromotedType;
};
+}
/// getSpecialMember - get the special member enum for a method.
Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) {
@@ -960,7 +1072,7 @@ static bool canRedefineFunction(const FunctionDecl *FD,
const LangOptions& LangOpts) {
return (LangOpts.GNUMode && !LangOpts.C99 && !LangOpts.CPlusPlus &&
FD->isInlineSpecified() &&
- FD->getStorageClass() == FunctionDecl::Extern);
+ FD->getStorageClass() == SC_Extern);
}
/// MergeFunctionDecl - We just parsed a function 'New' from
@@ -1014,8 +1126,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
// Don't complain about this if we're in GNU89 mode and the old function
// is an extern inline function.
if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) &&
- New->getStorageClass() == FunctionDecl::Static &&
- Old->getStorageClass() != FunctionDecl::Static &&
+ New->getStorageClass() == SC_Static &&
+ Old->getStorageClass() != SC_Static &&
!canRedefineFunction(Old, getLangOptions())) {
Diag(New->getLocation(), diag::err_static_non_static)
<< New;
@@ -1196,7 +1308,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, New,
SourceLocation(), 0,
*ParamType, /*TInfo=*/0,
- VarDecl::None, VarDecl::None,
+ SC_None, SC_None,
0);
Param->setImplicit();
Params.push_back(Param);
@@ -1242,7 +1354,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
NewProto->getArgType(Idx))) {
ArgTypes.push_back(NewParm->getType());
} else if (Context.typesAreCompatible(OldParm->getType(),
- NewParm->getType())) {
+ NewParm->getType(),
+ /*CompareUnqualified=*/true)) {
GNUCompatibleParamWarning Warn
= { OldParm, NewParm, NewProto->getArgType(Idx) };
Warnings.push_back(Warn);
@@ -1257,8 +1370,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
diag::ext_param_promoted_not_compatible_with_prototype)
<< Warnings[Warn].PromotedType
<< Warnings[Warn].OldParm->getType();
- Diag(Warnings[Warn].OldParm->getLocation(),
- diag::note_previous_declaration);
+ if (Warnings[Warn].OldParm->getLocation().isValid())
+ Diag(Warnings[Warn].OldParm->getLocation(),
+ diag::note_previous_declaration);
}
New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],
@@ -1309,11 +1423,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
/// \returns false
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
// Merge the attributes
- MergeAttributes(New, Old, Context);
+ MergeDeclAttributes(New, Old, Context);
// Merge the storage class.
- if (Old->getStorageClass() != FunctionDecl::Extern &&
- Old->getStorageClass() != FunctionDecl::None)
+ if (Old->getStorageClass() != SC_Extern &&
+ Old->getStorageClass() != SC_None)
New->setStorageClass(Old->getStorageClass());
// Merge "pure" flag.
@@ -1354,7 +1468,18 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
return New->setInvalidDecl();
}
- MergeAttributes(New, Old, Context);
+ // C++ [class.mem]p1:
+ // A member shall not be declared twice in the member-specification [...]
+ //
+ // Here, we need only consider static data members.
+ if (Old->isStaticDataMember() && !New->isOutOfLine()) {
+ Diag(New->getLocation(), diag::err_duplicate_member)
+ << New->getIdentifier();
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ New->setInvalidDecl();
+ }
+
+ MergeDeclAttributes(New, Old, Context);
// Merge the types
QualType MergedT;
@@ -1398,8 +1523,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
New->setType(MergedT);
// C99 6.2.2p4: Check if we have a static decl followed by a non-static.
- if (New->getStorageClass() == VarDecl::Static &&
- (Old->getStorageClass() == VarDecl::None || Old->hasExternalStorage())) {
+ if (New->getStorageClass() == SC_Static &&
+ (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) {
Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -1415,8 +1540,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// identifier has external linkage.
if (New->hasExternalStorage() && Old->hasLinkage())
/* Okay */;
- else if (New->getStorageClass() != VarDecl::Static &&
- Old->getStorageClass() == VarDecl::Static) {
+ else if (New->getStorageClass() != SC_Static &&
+ Old->getStorageClass() == SC_Static) {
Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
return New->setInvalidDecl();
@@ -1475,8 +1600,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
-Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
- DeclSpec &DS) {
+Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+ DeclSpec &DS) {
// FIXME: Error on auto/register at file scope
// FIXME: Error on inline/virtual/explicit
// FIXME: Warn on useless __thread
@@ -1489,10 +1614,10 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
DS.getTypeSpecType() == DeclSpec::TST_struct ||
DS.getTypeSpecType() == DeclSpec::TST_union ||
DS.getTypeSpecType() == DeclSpec::TST_enum) {
- TagD = static_cast<Decl *>(DS.getTypeRep());
+ TagD = DS.getRepAsDecl();
if (!TagD) // We probably had an error
- return DeclPtrTy();
+ return 0;
// Note that the above type specs guarantee that the
// type rep is a Decl, whereas in many of the others
@@ -1513,14 +1638,12 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// If we're dealing with a class template decl, assume that the
// template routines are handling it.
if (TagD && isa<ClassTemplateDecl>(TagD))
- return DeclPtrTy();
+ return 0;
return ActOnFriendTypeDecl(S, DS, MultiTemplateParamsArg(*this, 0, 0));
}
if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) {
- // If there are attributes in the DeclSpec, apply them to the record.
- if (const AttributeList *AL = DS.getAttributes())
- ProcessDeclAttributeList(S, Record, AL);
+ ProcessDeclAttributeList(S, Record, DS.getAttributes());
if (!Record->getDeclName() && Record->isDefinition() &&
DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
@@ -1536,7 +1659,7 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
// about them.
// FIXME: Should we support Microsoft's extensions in this area?
if (Record->getDeclName() && getLangOptions().Microsoft)
- return DeclPtrTy::make(Tag);
+ return Tag;
}
if (getLangOptions().CPlusPlus &&
@@ -1550,19 +1673,19 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
if (!DS.isMissingDeclaratorOk() &&
DS.getTypeSpecType() != DeclSpec::TST_error) {
// Warn about typedefs of enums without names, since this is an
- // extension in both Microsoft an GNU.
+ // extension in both Microsoft and GNU.
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef &&
Tag && isa<EnumDecl>(Tag)) {
Diag(DS.getSourceRange().getBegin(), diag::ext_typedef_without_a_name)
<< DS.getSourceRange();
- return DeclPtrTy::make(Tag);
+ return Tag;
}
Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
<< DS.getSourceRange();
}
- return DeclPtrTy::make(Tag);
+ return TagD;
}
/// We are trying to inject an anonymous member into the given scope;
@@ -1639,7 +1762,7 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
// considered to have been defined in the scope in which the
// anonymous union is declared.
Owner->makeDeclVisibleInContext(*F);
- S->AddDecl(Sema::DeclPtrTy::make(*F));
+ S->AddDecl(*F);
SemaRef.IdResolver.AddDecl(*F);
// That includes picking up the appropriate access specifier.
@@ -1660,58 +1783,38 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
/// a VarDecl::StorageClass. Any error reporting is up to the caller:
-/// illegal input values are mapped to VarDecl::None.
-/// If the input declaration context is a linkage specification
-/// with no braces, then Extern is mapped to None.
-static VarDecl::StorageClass
-StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec,
- DeclContext *DC) {
+/// illegal input values are mapped to SC_None.
+static StorageClass
+StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
switch (StorageClassSpec) {
- case DeclSpec::SCS_unspecified: return VarDecl::None;
- case DeclSpec::SCS_extern:
- // If the current context is a C++ linkage specification
- // having no braces, then the keyword "extern" is properly part
- // of the linkage specification itself, rather than being
- // the written storage class specifier.
- return (DC && isa<LinkageSpecDecl>(DC) &&
- !cast<LinkageSpecDecl>(DC)->hasBraces())
- ? VarDecl::None : VarDecl::Extern;
- case DeclSpec::SCS_static: return VarDecl::Static;
- case DeclSpec::SCS_auto: return VarDecl::Auto;
- case DeclSpec::SCS_register: return VarDecl::Register;
- case DeclSpec::SCS_private_extern: return VarDecl::PrivateExtern;
+ case DeclSpec::SCS_unspecified: return SC_None;
+ case DeclSpec::SCS_extern: return SC_Extern;
+ case DeclSpec::SCS_static: return SC_Static;
+ case DeclSpec::SCS_auto: return SC_Auto;
+ case DeclSpec::SCS_register: return SC_Register;
+ case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
// Illegal SCSs map to None: error reporting is up to the caller.
case DeclSpec::SCS_mutable: // Fall through.
- case DeclSpec::SCS_typedef: return VarDecl::None;
+ case DeclSpec::SCS_typedef: return SC_None;
}
llvm_unreachable("unknown storage class specifier");
}
/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
-/// a FunctionDecl::StorageClass. Any error reporting is up to the caller:
-/// illegal input values are mapped to FunctionDecl::None.
-/// If the input declaration context is a linkage specification
-/// with no braces, then Extern is mapped to None.
-static FunctionDecl::StorageClass
-StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec,
- DeclContext *DC) {
+/// a StorageClass. Any error reporting is up to the caller:
+/// illegal input values are mapped to SC_None.
+static StorageClass
+StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
switch (StorageClassSpec) {
- case DeclSpec::SCS_unspecified: return FunctionDecl::None;
- case DeclSpec::SCS_extern:
- // If the current context is a C++ linkage specification
- // having no braces, then the keyword "extern" is properly part
- // of the linkage specification itself, rather than being
- // the written storage class specifier.
- return (DC && isa<LinkageSpecDecl>(DC) &&
- !cast<LinkageSpecDecl>(DC)->hasBraces())
- ? FunctionDecl::None : FunctionDecl::Extern;
- case DeclSpec::SCS_static: return FunctionDecl::Static;
- case DeclSpec::SCS_private_extern: return FunctionDecl::PrivateExtern;
+ case DeclSpec::SCS_unspecified: return SC_None;
+ case DeclSpec::SCS_extern: return SC_Extern;
+ case DeclSpec::SCS_static: return SC_Static;
+ case DeclSpec::SCS_private_extern: return SC_PrivateExtern;
// Illegal SCSs map to None: error reporting is up to the caller.
case DeclSpec::SCS_auto: // Fall through.
case DeclSpec::SCS_mutable: // Fall through.
case DeclSpec::SCS_register: // Fall through.
- case DeclSpec::SCS_typedef: return FunctionDecl::None;
+ case DeclSpec::SCS_typedef: return SC_None;
}
llvm_unreachable("unknown storage class specifier");
}
@@ -1720,9 +1823,9 @@ StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec,
/// anonymous structure or union. Anonymous unions are a C++ feature
/// (C++ [class.union]) and a GNU C extension; anonymous structures
/// are a GNU C and GNU C++ extension.
-Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
- AccessSpecifier AS,
- RecordDecl *Record) {
+Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+ AccessSpecifier AS,
+ RecordDecl *Record) {
DeclContext *Owner = Record->getDeclContext();
// Diagnose whether this anonymous struct/union is an extension.
@@ -1782,6 +1885,9 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
<< (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
Invalid = true;
}
+
+ if (CheckNontrivialField(FD))
+ Invalid = true;
} else if ((*Mem)->isImplicit()) {
// Any implicit members are fine.
} else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) {
@@ -1845,17 +1951,17 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
- VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
Diag(Record->getLocation(), diag::err_mutable_nonmember);
Invalid = true;
- SC = VarDecl::None;
+ SC = SC_None;
}
SCSpec = DS.getStorageClassSpecAsWritten();
VarDecl::StorageClass SCAsWritten
- = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
+ = StorageClassSpecToVarDeclStorageClass(SCSpec);
Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
/*IdentifierInfo=*/0,
@@ -1886,85 +1992,115 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
if (Invalid)
Anon->setInvalidDecl();
- return DeclPtrTy::make(Anon);
+ return Anon;
}
/// GetNameForDeclarator - Determine the full declaration name for the
/// given Declarator.
-DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
+DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) {
return GetNameFromUnqualifiedId(D.getName());
}
-/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
-DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
- switch (Name.getKind()) {
- case UnqualifiedId::IK_Identifier:
- return DeclarationName(Name.Identifier);
-
- case UnqualifiedId::IK_OperatorFunctionId:
- return Context.DeclarationNames.getCXXOperatorName(
- Name.OperatorFunctionId.Operator);
-
- case UnqualifiedId::IK_LiteralOperatorId:
- return Context.DeclarationNames.getCXXLiteralOperatorName(
- Name.Identifier);
-
- case UnqualifiedId::IK_ConversionFunctionId: {
- QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
- if (Ty.isNull())
- return DeclarationName();
-
- return Context.DeclarationNames.getCXXConversionFunctionName(
- Context.getCanonicalType(Ty));
- }
-
- case UnqualifiedId::IK_ConstructorName: {
- QualType Ty = GetTypeFromParser(Name.ConstructorName);
- if (Ty.isNull())
- return DeclarationName();
-
- return Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(Ty));
- }
-
- case UnqualifiedId::IK_ConstructorTemplateId: {
- // In well-formed code, we can only have a constructor
- // template-id that refers to the current context, so go there
- // to find the actual type being constructed.
- CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext);
- if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name)
- return DeclarationName();
+/// \brief Retrieves the declaration name from a parsed unqualified-id.
+DeclarationNameInfo
+Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
+ DeclarationNameInfo NameInfo;
+ NameInfo.setLoc(Name.StartLocation);
- // Determine the type of the class being constructed.
- QualType CurClassType = Context.getTypeDeclType(CurClass);
+ switch (Name.getKind()) {
- // FIXME: Check two things: that the template-id names the same type as
- // CurClassType, and that the template-id does not occur when the name
- // was qualified.
+ case UnqualifiedId::IK_Identifier:
+ NameInfo.setName(Name.Identifier);
+ NameInfo.setLoc(Name.StartLocation);
+ return NameInfo;
+
+ case UnqualifiedId::IK_OperatorFunctionId:
+ NameInfo.setName(Context.DeclarationNames.getCXXOperatorName(
+ Name.OperatorFunctionId.Operator));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc
+ = Name.OperatorFunctionId.SymbolLocations[0];
+ NameInfo.getInfo().CXXOperatorName.EndOpNameLoc
+ = Name.EndLocation.getRawEncoding();
+ return NameInfo;
+
+ case UnqualifiedId::IK_LiteralOperatorId:
+ NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName(
+ Name.Identifier));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation);
+ return NameInfo;
+
+ case UnqualifiedId::IK_ConversionFunctionId: {
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo);
+ if (Ty.isNull())
+ return DeclarationNameInfo();
+ NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName(
+ Context.getCanonicalType(Ty)));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setNamedTypeInfo(TInfo);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_ConstructorName: {
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo);
+ if (Ty.isNull())
+ return DeclarationNameInfo();
+ NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(Ty)));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setNamedTypeInfo(TInfo);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_ConstructorTemplateId: {
+ // In well-formed code, we can only have a constructor
+ // template-id that refers to the current context, so go there
+ // to find the actual type being constructed.
+ CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext);
+ if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name)
+ return DeclarationNameInfo();
+
+ // Determine the type of the class being constructed.
+ QualType CurClassType = Context.getTypeDeclType(CurClass);
+
+ // FIXME: Check two things: that the template-id names the same type as
+ // CurClassType, and that the template-id does not occur when the name
+ // was qualified.
+
+ NameInfo.setName(Context.DeclarationNames.getCXXConstructorName(
+ Context.getCanonicalType(CurClassType)));
+ NameInfo.setLoc(Name.StartLocation);
+ // FIXME: should we retrieve TypeSourceInfo?
+ NameInfo.setNamedTypeInfo(0);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_DestructorName: {
+ TypeSourceInfo *TInfo;
+ QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo);
+ if (Ty.isNull())
+ return DeclarationNameInfo();
+ NameInfo.setName(Context.DeclarationNames.getCXXDestructorName(
+ Context.getCanonicalType(Ty)));
+ NameInfo.setLoc(Name.StartLocation);
+ NameInfo.setNamedTypeInfo(TInfo);
+ return NameInfo;
+ }
+
+ case UnqualifiedId::IK_TemplateId: {
+ TemplateName TName = Name.TemplateId->Template.get();
+ SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc;
+ return Context.getNameForTemplate(TName, TNameLoc);
+ }
+
+ } // switch (Name.getKind())
- return Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(CurClassType));
- }
-
- case UnqualifiedId::IK_DestructorName: {
- QualType Ty = GetTypeFromParser(Name.DestructorName);
- if (Ty.isNull())
- return DeclarationName();
-
- return Context.DeclarationNames.getCXXDestructorName(
- Context.getCanonicalType(Ty));
- }
-
- case UnqualifiedId::IK_TemplateId: {
- TemplateName TName
- = TemplateName::getFromVoidPointer(Name.TemplateId->Template);
- return Context.getNameForTemplate(TName);
- }
- }
-
assert(false && "Unknown name kind");
- return DeclarationName();
+ return DeclarationNameInfo();
}
/// isNearlyMatchingFunction - Determine whether the C++ functions
@@ -2007,11 +2143,10 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_typename:
case DeclSpec::TST_typeofType:
- case DeclSpec::TST_typeofExpr:
case DeclSpec::TST_decltype: {
// Grab the type from the parser.
TypeSourceInfo *TSI = 0;
- QualType T = S.GetTypeFromParser(DS.getTypeRep(), &TSI);
+ QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI);
if (T.isNull() || !T->isDependentType()) break;
// Make sure there's a type source info. This isn't really much
@@ -2025,8 +2160,16 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
if (!TSI) return true;
// Store the new type back in the decl spec.
- QualType LocType = S.CreateLocInfoType(TSI->getType(), TSI);
- DS.UpdateTypeRep(LocType.getAsOpaquePtr());
+ ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI);
+ DS.UpdateTypeRep(LocType);
+ break;
+ }
+
+ case DeclSpec::TST_typeofExpr: {
+ Expr *E = DS.getRepAsExpr();
+ ExprResult Result = S.RebuildExprInCurrentInstantiation(E);
+ if (Result.isInvalid()) return true;
+ DS.UpdateExprRep(Result.get());
break;
}
@@ -2054,11 +2197,16 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D,
return false;
}
-Sema::DeclPtrTy
-Sema::HandleDeclarator(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParamLists,
- bool IsFunctionDefinition) {
- DeclarationName Name = GetNameForDeclarator(D);
+Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
+ return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
+}
+
+Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool IsFunctionDefinition) {
+ // TODO: consider using NameInfo for diagnostic.
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
// All of these full declarators require an identifier. If it doesn't have
// one, the ParsedFreeStandingDeclSpec action should be used.
@@ -2067,7 +2215,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
Diag(D.getDeclSpec().getSourceRange().getBegin(),
diag::err_declarator_need_ident)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
- return DeclPtrTy();
+ return 0;
}
// The scope passed in may not be a decl scope. Zip up the scope tree until
@@ -2091,14 +2239,14 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
diag::err_template_qualified_declarator_no_match)
<< (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep()
<< D.getCXXScopeSpec().getRange();
- return DeclPtrTy();
+ return 0;
}
bool IsDependentContext = DC->isDependentContext();
if (!IsDependentContext &&
RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
- return DeclPtrTy();
+ return 0;
if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
Diag(D.getIdentifierLoc(),
@@ -2122,7 +2270,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
- LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForRedeclaration);
// See if this is a redefinition of a variable in the same scope.
@@ -2140,7 +2288,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
IsLinkageLookup = true;
} else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
IsLinkageLookup = true;
- else if (CurContext->getLookupContext()->isTranslationUnit() &&
+ else if (CurContext->getRedeclContext()->isTranslationUnit() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
IsLinkageLookup = true;
@@ -2225,7 +2373,7 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
if (TemplateParamLists.size()) {
Diag(D.getIdentifierLoc(), diag::err_template_typedef);
- return DeclPtrTy();
+ return 0;
}
New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration);
@@ -2240,14 +2388,14 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
}
if (New == 0)
- return DeclPtrTy();
+ return 0;
// If this has an identifier and is not an invalid redeclaration or
// function template specialization, add it to the scope stack.
- if (Name && !(Redeclaration && New->isInvalidDecl()))
+ if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl()))
PushOnScopeChains(New, S);
- return DeclPtrTy::make(New);
+ return New;
}
/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
@@ -2255,20 +2403,26 @@ Sema::HandleDeclarator(Scope *S, Declarator &D,
/// be errors (for GCC compatibility).
static QualType TryToFixInvalidVariablyModifiedType(QualType T,
ASTContext &Context,
- bool &SizeIsNegative) {
+ bool &SizeIsNegative,
+ llvm::APSInt &Oversized) {
// This method tries to turn a variable array into a constant
// array even when the size isn't an ICE. This is necessary
// for compatibility with code that depends on gcc's buggy
// constant expression folding, like struct {char x[(int)(char*)2];}
SizeIsNegative = false;
-
+ Oversized = 0;
+
+ if (T->isDependentType())
+ return QualType();
+
QualifierCollector Qs;
const Type *Ty = Qs.strip(T);
if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) {
QualType Pointee = PTy->getPointeeType();
QualType FixedType =
- TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative);
+ TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative,
+ Oversized);
if (FixedType.isNull()) return FixedType;
FixedType = Context.getPointerType(FixedType);
return Qs.apply(FixedType);
@@ -2287,15 +2441,24 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
!EvalResult.Val.isInt())
return QualType();
+ // Check whether the array size is negative.
llvm::APSInt &Res = EvalResult.Val.getInt();
- if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) {
- // TODO: preserve the size expression in declarator info
- return Context.getConstantArrayType(VLATy->getElementType(),
- Res, ArrayType::Normal, 0);
+ if (Res.isSigned() && Res.isNegative()) {
+ SizeIsNegative = true;
+ return QualType();
}
- SizeIsNegative = true;
- return QualType();
+ // Check whether the array is too large to be addressed.
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(),
+ Res);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+ Oversized = Res;
+ return QualType();
+ }
+
+ return Context.getConstantArrayType(VLATy->getElementType(),
+ Res, ArrayType::Normal, 0);
}
/// \brief Register the given locally-scoped external C declaration so
@@ -2320,11 +2483,11 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) {
// The previous declaration was found on the identifer resolver
// chain, so remove it from its scope.
- while (S && !S->isDeclScope(DeclPtrTy::make(PrevDecl)))
+ while (S && !S->isDeclScope(PrevDecl))
S = S->getParent();
if (S)
- S->RemoveDecl(DeclPtrTy::make(PrevDecl));
+ S->RemoveDecl(PrevDecl);
}
}
@@ -2382,24 +2545,20 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
- // Merge the decl with the existing one if appropriate. If the decl is
- // in an outer scope, it isn't the same thing.
- FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
- if (!Previous.empty()) {
- Redeclaration = true;
- MergeTypeDefDecl(NewTD, Previous);
- }
-
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
+ // Note that variably modified types must be fixed before merging the decl so
+ // that redeclarations will match.
QualType T = NewTD->getUnderlyingType();
if (T->isVariablyModifiedType()) {
- FunctionNeedsScopeChecking() = true;
+ getCurFunction()->setHasBranchProtectedScope();
if (S->getFnParent() == 0) {
bool SizeIsNegative;
+ llvm::APSInt Oversized;
QualType FixedTy =
- TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
+ TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+ Oversized);
if (!FixedTy.isNull()) {
Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size);
NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy));
@@ -2408,6 +2567,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size);
else if (T->isVariableArrayType())
Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope);
+ else if (Oversized.getBoolValue())
+ Diag(D.getIdentifierLoc(), diag::err_array_too_large)
+ << Oversized.toString(10);
else
Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope);
NewTD->setInvalidDecl();
@@ -2415,10 +2577,18 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
+ // Merge the decl with the existing one if appropriate. If the decl is
+ // in an outer scope, it isn't the same thing.
+ FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
+ if (!Previous.empty()) {
+ Redeclaration = true;
+ MergeTypeDefDecl(NewTD, Previous);
+ }
+
// If this is the C FILE type, notify the AST context.
if (IdentifierInfo *II = NewTD->getIdentifier())
if (!NewTD->isInvalidDecl() &&
- NewTD->getDeclContext()->getLookupContext()->isTranslationUnit()) {
+ NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
if (II->isStr("FILE"))
Context.setFILEDecl(NewTD);
else if (II->isStr("jmp_buf"))
@@ -2452,7 +2622,7 @@ static bool
isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
ASTContext &Context) {
if (!PrevDecl)
- return 0;
+ return false;
if (!PrevDecl->hasLinkage())
return false;
@@ -2464,30 +2634,25 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,
// outside the innermost enclosing namespace scope, the block
// scope declaration declares that same entity and receives the
// linkage of the previous declaration.
- DeclContext *OuterContext = DC->getLookupContext();
+ DeclContext *OuterContext = DC->getRedeclContext();
if (!OuterContext->isFunctionOrMethod())
// This rule only applies to block-scope declarations.
return false;
- else {
- DeclContext *PrevOuterContext = PrevDecl->getDeclContext();
- if (PrevOuterContext->isRecord())
- // We found a member function: ignore it.
- return false;
- else {
- // Find the innermost enclosing namespace for the new and
- // previous declarations.
- while (!OuterContext->isFileContext())
- OuterContext = OuterContext->getParent();
- while (!PrevOuterContext->isFileContext())
- PrevOuterContext = PrevOuterContext->getParent();
-
- // The previous declaration is in a different namespace, so it
- // isn't the same function.
- if (OuterContext->getPrimaryContext() !=
- PrevOuterContext->getPrimaryContext())
- return false;
- }
- }
+
+ DeclContext *PrevOuterContext = PrevDecl->getDeclContext();
+ if (PrevOuterContext->isRecord())
+ // We found a member function: ignore it.
+ return false;
+
+ // Find the innermost enclosing namespace for the new and
+ // previous declarations.
+ OuterContext = OuterContext->getEnclosingNamespaceContext();
+ PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext();
+
+ // The previous declaration is in a different namespace, so it
+ // isn't the same function.
+ if (!OuterContext->Equals(PrevOuterContext))
+ return false;
}
return true;
@@ -2506,7 +2671,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
bool &Redeclaration) {
- DeclarationName Name = GetNameForDeclarator(D);
+ DeclarationName Name = GetNameForDeclarator(D).getName();
// Check that there are no default arguments (C++ only).
if (getLangOptions().CPlusPlus)
@@ -2515,17 +2680,17 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
assert(SCSpec != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class VarDecl.");
- VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
+ VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
if (SCSpec == DeclSpec::SCS_mutable) {
// mutable can only appear on non-static class members, so it's always
// an error here
Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
D.setInvalidType();
- SC = VarDecl::None;
+ SC = SC_None;
}
SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
VarDecl::StorageClass SCAsWritten
- = StorageClassSpecToVarDeclStorageClass(SCSpec, DC);
+ = StorageClassSpecToVarDeclStorageClass(SCSpec);
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (!II) {
@@ -2539,11 +2704,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (!DC->isRecord() && S->getFnParent() == 0) {
// C99 6.9p2: The storage-class specifiers auto and register shall not
// appear in the declaration specifiers in an external declaration.
- if (SC == VarDecl::Auto || SC == VarDecl::Register) {
+ if (SC == SC_Auto || SC == SC_Register) {
// If this is a register variable with an asm label specified, then this
// is a GNU extension.
- if (SC == VarDecl::Register && D.getAsmLabel())
+ if (SC == SC_Register && D.getAsmLabel())
Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register);
else
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope);
@@ -2552,14 +2717,14 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
if (DC->isRecord() && !CurContext->isRecord()) {
// This is an out-of-line definition of a static data member.
- if (SC == VarDecl::Static) {
+ if (SC == SC_Static) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
- } else if (SC == VarDecl::None)
- SC = VarDecl::Static;
+ } else if (SC == SC_None)
+ SC = SC_Static;
}
- if (SC == VarDecl::Static) {
+ if (SC == SC_Static) {
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
if (RD->isLocalClass())
Diag(D.getIdentifierLoc(),
@@ -2613,7 +2778,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
SetNestedNameSpecifier(NewVD, D);
- if (NumMatchedTemplateParamLists > 0) {
+ if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
NewVD->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
(TemplateParameterList**)TemplateParamLists.release());
@@ -2639,7 +2804,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
+ NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0),
+ Context, SE->getString()));
}
// Diagnose shadowed variables before filtering for scope.
@@ -2679,6 +2845,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewVD->setInvalidDecl();
// attributes declared post-definition are currently ignored
+ // FIXME: This should be handled in attribute merging, not
+ // here.
if (Previous.isSingleResult()) {
VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
if (Def && (Def = Def->getDefinition()) &&
@@ -2694,6 +2862,13 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
!NewVD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
+ // If there's a #pragma GCC visibility in scope, and this isn't a class
+ // member, set the visibility of this variable.
+ if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
+ AddPushedVisibilityAttribute(NewVD);
+
+ MarkUnusedFileScopedDecl(NewVD);
+
return NewVD;
}
@@ -2807,19 +2982,16 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,
bool isVM = T->isVariablyModifiedType();
if (isVM || NewVD->hasAttr<CleanupAttr>() ||
- NewVD->hasAttr<BlocksAttr>() ||
- // FIXME: We need to diagnose jumps passed initialized variables in C++.
- // However, this turns on the scope checker for everything with a variable
- // which may impact compile time. See if we can find a better solution
- // to this, perhaps only checking functions that contain gotos in C++?
- (LangOpts.CPlusPlus && NewVD->hasLocalStorage()))
- FunctionNeedsScopeChecking() = true;
+ NewVD->hasAttr<BlocksAttr>())
+ getCurFunction()->setHasBranchProtectedScope();
if ((isVM && NewVD->hasLinkage()) ||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
bool SizeIsNegative;
+ llvm::APSInt Oversized;
QualType FixedTy =
- TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative);
+ TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative,
+ Oversized);
if (FixedTy.isNull() && T->isVariableArrayType()) {
const VariableArrayType *VAT = Context.getAsVariableArrayType(T);
@@ -2830,7 +3002,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,
if (NewVD->isFileVarDecl())
Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope)
<< SizeRange;
- else if (NewVD->getStorageClass() == VarDecl::Static)
+ else if (NewVD->getStorageClass() == SC_Static)
Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage)
<< SizeRange;
else
@@ -2970,8 +3142,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
bool IsFunctionDefinition, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
- DeclarationName Name = GetNameForDeclarator(D);
- FunctionDecl::StorageClass SC = FunctionDecl::None;
+ // TODO: consider using NameInfo for diagnostic.
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+ FunctionDecl::StorageClass SC = SC_None;
switch (D.getDeclSpec().getStorageClassSpec()) {
default: assert(0 && "Unknown storage class!");
case DeclSpec::SCS_auto:
@@ -2981,10 +3155,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
diag::err_typecheck_sclass_func);
D.setInvalidType();
break;
- case DeclSpec::SCS_unspecified: SC = FunctionDecl::None; break;
- case DeclSpec::SCS_extern: SC = FunctionDecl::Extern; break;
+ case DeclSpec::SCS_unspecified: SC = SC_None; break;
+ case DeclSpec::SCS_extern: SC = SC_Extern; break;
case DeclSpec::SCS_static: {
- if (CurContext->getLookupContext()->isFunctionOrMethod()) {
+ if (CurContext->getRedeclContext()->isFunctionOrMethod()) {
// C99 6.7.1p5:
// The declaration of an identifier for a function that has
// block scope shall have no explicit storage-class specifier
@@ -2992,12 +3166,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// See also (C++ [dcl.stc]p4).
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_block_func);
- SC = FunctionDecl::None;
+ SC = SC_None;
} else
- SC = FunctionDecl::Static;
+ SC = SC_Static;
break;
}
- case DeclSpec::SCS_private_extern: SC = FunctionDecl::PrivateExtern;break;
+ case DeclSpec::SCS_private_extern: SC = SC_PrivateExtern;break;
}
if (D.getDeclSpec().isThreadSpecified())
@@ -3010,7 +3184,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
FunctionDecl::StorageClass SCAsWritten
- = StorageClassSpecToFunctionDeclStorageClass(SCSpec, DC);
+ = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
// Check that the return type is not an abstract class type.
// For record types, this is done by the AbstractClassUsageDiagnoser once
@@ -3050,7 +3224,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Create the new declaration
NewFD = CXXConstructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R, TInfo,
+ NameInfo, R, TInfo,
isExplicit, isInline,
/*isImplicitlyDeclared=*/false);
} else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
@@ -3060,7 +3234,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R,
+ NameInfo, R,
isInline,
/*isImplicitlyDeclared=*/false);
NewFD->setTypeSourceInfo(TInfo);
@@ -3085,7 +3259,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
CheckConversionDeclarator(D, R, SC);
NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R, TInfo,
+ NameInfo, R, TInfo,
isInline, isExplicit);
isVirtualOkay = true;
@@ -3103,7 +3277,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
return 0;
}
- bool isStatic = SC == FunctionDecl::Static;
+ bool isStatic = SC == SC_Static;
// [class.free]p1:
// Any allocation function for a class T is a static member
@@ -3120,7 +3294,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
- D.getIdentifierLoc(), Name, R, TInfo,
+ NameInfo, R, TInfo,
isStatic, SCAsWritten, isInline);
isVirtualOkay = !isStatic;
@@ -3137,8 +3311,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
(!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType());
NewFD = FunctionDecl::Create(Context, DC,
- D.getIdentifierLoc(),
- Name, R, TInfo, SC, SCAsWritten, isInline,
+ NameInfo, R, TInfo, SC, SCAsWritten, isInline,
HasPrototype);
}
@@ -3212,7 +3385,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
- if (NumMatchedTemplateParamLists > 0) {
+ if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) {
NewFD->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
(TemplateParameterList**)TemplateParamLists.release());
@@ -3244,6 +3417,17 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
}
+ // C++ [dcl.fct.spec]p3:
+ // The inline specifier shall not appear on a block scope function declaration.
+ if (isInline && !NewFD->isInvalidDecl() && getLangOptions().CPlusPlus) {
+ if (CurContext->isFunctionOrMethod()) {
+ // 'inline' is not allowed on block scope function declaration.
+ Diag(D.getDeclSpec().getInlineSpecLoc(),
+ diag::err_inline_declaration_block_scope) << Name
+ << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
+ }
+ }
+
// C++ [dcl.fct.spec]p6:
// The explicit specifier shall be used only in the declaration of a
// constructor or conversion function within its class definition; see 12.3.1
@@ -3282,7 +3466,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
NewFD->setAccess(AS_public);
}
- if (SC == FunctionDecl::Static && isa<CXXMethodDecl>(NewFD) &&
+ if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
!CurContext->isRecord()) {
// C++ [class.static]p1:
// A data or function member of a class may be declared static
@@ -3300,7 +3484,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (Expr *E = (Expr*) D.getAsmLabel()) {
// The parser guarantees this is a string.
StringLiteral *SE = cast<StringLiteral>(E);
- NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
+ NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context,
+ SE->getString()));
}
// Copy the parameter declarations from the declarator D to the function
@@ -3316,9 +3501,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// already checks for that case.
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
FTI.ArgInfo[0].Param &&
- FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType()) {
+ cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
// Empty arg list, don't push any params.
- ParmVarDecl *Param = FTI.ArgInfo[0].Param.getAs<ParmVarDecl>();
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[0].Param);
// In C++, the empty parameter-type-list must be spelled "void"; a
// typedef of void is not permitted.
@@ -3328,7 +3513,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// FIXME: Leaks decl?
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
assert(Param->getDeclContext() != NewFD && "Was set before ?");
Param->setDeclContext(NewFD);
Params.push_back(Param);
@@ -3479,14 +3664,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// definition (C++ [dcl.meaning]p1).
// Note that this is not the case for explicit specializations of
// function templates or member functions of class templates, per
- // C++ [temp.expl.spec]p2.
+ // C++ [temp.expl.spec]p2. We also allow these declarations as an extension
+ // for compatibility with old SWIG code which likes to generate them.
if (!IsFunctionDefinition && !isFriend &&
!isFunctionTemplateSpecialization && !isExplicitSpecialization) {
- Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
+ Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration)
<< D.getCXXScopeSpec().getRange();
- NewFD->setInvalidDecl();
- } else if (!Redeclaration &&
- !(isFriend && CurContext->isDependentContext())) {
+ }
+ if (!Redeclaration && !(isFriend && CurContext->isDependentContext())) {
// The user tried to provide an out-of-line definition for a
// function that is a member of a class or namespace, but there
// was no such member function declared (C++ [class.mfct]p2,
@@ -3526,6 +3711,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
ProcessDeclAttributes(S, NewFD, D);
// attributes declared post-definition are currently ignored
+ // FIXME: This should happen during attribute merging
if (Redeclaration && Previous.isSingleResult()) {
const FunctionDecl *Def;
FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
@@ -3537,7 +3723,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
AddKnownFunctionAttributes(NewFD);
- if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) {
+ if (OverloadableAttrRequired && !NewFD->hasAttr<OverloadableAttr>()) {
// If a function name is overloadable in C, then every function
// with that name must be marked "overloadable".
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
@@ -3545,9 +3731,28 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (!Previous.empty())
Diag(Previous.getRepresentativeDecl()->getLocation(),
diag::note_attribute_overloadable_prev_overload);
- NewFD->addAttr(::new (Context) OverloadableAttr());
+ NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), Context));
+ }
+
+ if (NewFD->hasAttr<OverloadableAttr>() &&
+ !NewFD->getType()->getAs<FunctionProtoType>()) {
+ Diag(NewFD->getLocation(),
+ diag::err_attribute_overloadable_no_prototype)
+ << NewFD;
+
+ // Turn this into a variadic function with no parameters.
+ const FunctionType *FT = NewFD->getType()->getAs<FunctionType>();
+ QualType R = Context.getFunctionType(FT->getResultType(),
+ 0, 0, true, 0, false, false, 0, 0,
+ FT->getExtInfo());
+ NewFD->setType(R);
}
+ // If there's a #pragma GCC visibility in scope, and this isn't a class
+ // member, set the visibility of this function.
+ if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord())
+ AddPushedVisibilityAttribute(NewFD);
+
// If this is a locally-scoped extern C function, update the
// map of such names.
if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
@@ -3563,17 +3768,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
if (FunctionTemplate)
return FunctionTemplate;
-
- // Keep track of static, non-inlined function definitions that
- // have not been used. We will warn later.
- // FIXME: Also include static functions declared but not defined.
- if (!NewFD->isInvalidDecl() && IsFunctionDefinition
- && !NewFD->isInlined() && NewFD->getLinkage() == InternalLinkage
- && !NewFD->isUsed() && !NewFD->hasAttr<UnusedAttr>()
- && !NewFD->hasAttr<ConstructorAttr>()
- && !NewFD->hasAttr<DestructorAttr>())
- UnusedStaticFuncs.push_back(NewFD);
-
+ MarkUnusedFileScopedDecl(NewFD);
+
return NewFD;
}
@@ -3597,8 +3793,14 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
bool &Redeclaration,
bool &OverloadableAttrRequired) {
// If NewFD is already known erroneous, don't do any of this checking.
- if (NewFD->isInvalidDecl())
+ if (NewFD->isInvalidDecl()) {
+ // If this is a class member, mark the class invalid immediately.
+ // This avoids some consistency errors later.
+ if (isa<CXXMethodDecl>(NewFD))
+ cast<CXXMethodDecl>(NewFD)->getParent()->setInvalidDecl();
+
return;
+ }
if (NewFD->getResultType()->isVariablyModifiedType()) {
// Functions returning a variably modified type violate C99 6.7.5.2p2
@@ -3634,27 +3836,9 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
Redeclaration = true;
OldDecl = Previous.getFoundDecl();
} else {
- if (!getLangOptions().CPlusPlus) {
+ if (!getLangOptions().CPlusPlus)
OverloadableAttrRequired = true;
- // Functions marked "overloadable" must have a prototype (that
- // we can't get through declaration merging).
- if (!NewFD->getType()->getAs<FunctionProtoType>()) {
- Diag(NewFD->getLocation(),
- diag::err_attribute_overloadable_no_prototype)
- << NewFD;
- Redeclaration = true;
-
- // Turn this into a variadic function with no parameters.
- QualType R = Context.getFunctionType(
- NewFD->getType()->getAs<FunctionType>()->getResultType(),
- 0, 0, true, 0, false, false, 0, 0,
- FunctionType::ExtInfo());
- NewFD->setType(R);
- return NewFD->setInvalidDecl();
- }
- }
-
switch (CheckOverload(S, NewFD, Previous, OldDecl,
/*NewIsUsingDecl*/ false)) {
case Ovl_Match:
@@ -3723,6 +3907,8 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(
Context.getCanonicalType(ClassType));
+// NewFD->getDeclName().dump();
+// Name.dump();
if (NewFD->getDeclName() != Name) {
Diag(NewFD->getLocation(), diag::err_destructor_name);
return NewFD->setInvalidDecl();
@@ -3750,12 +3936,6 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
AddOverriddenMethods(Method->getParent(), Method);
}
- // Additional checks for the destructor; make sure we do this after we
- // figure out whether the destructor is virtual.
- if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
- if (!Destructor->getParent()->isDependentType())
- CheckDestructor(Destructor);
-
// Extra checking for C++ overloaded operators (C++ [over.oper]).
if (NewFD->isOverloadedOperator() &&
CheckOverloadedOperatorDeclaration(NewFD))
@@ -3781,7 +3961,7 @@ void Sema::CheckMain(FunctionDecl* FD) {
// shall not appear in a declaration of main.
// static main is not an error under C99, but we should warn about it.
bool isInline = FD->isInlineSpecified();
- bool isStatic = FD->getStorageClass() == FunctionDecl::Static;
+ bool isStatic = FD->getStorageClass() == SC_Static;
if (isInline || isStatic) {
unsigned diagID = diag::warn_unusual_main_decl;
if (isInline || getLangOptions().CPlusPlus)
@@ -3874,22 +4054,21 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
// "may accept other forms of constant expressions" exception.
// (We never end up here for C++, so the constant expression
// rules there don't matter.)
- if (Init->isConstantInitializer(Context))
+ if (Init->isConstantInitializer(Context, false))
return false;
Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
<< Init->getSourceRange();
return true;
}
-void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init) {
- AddInitializerToDecl(dcl, move(init), /*DirectInit=*/false);
+void Sema::AddInitializerToDecl(Decl *dcl, Expr *init) {
+ AddInitializerToDecl(dcl, init, /*DirectInit=*/false);
}
/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
-void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
- Decl *RealDecl = dcl.getAs<Decl>();
+void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
if (RealDecl == 0)
@@ -3900,7 +4079,6 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// distinguish between a normal initializer and a pure-specifier.
// Thus this grotesque test.
IntegerLiteral *IL;
- Expr *Init = static_cast<Expr *>(init.get());
if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
Context.getCanonicalType(IL->getType()) == Context.IntTy)
CheckPureMethod(Method, Init->getSourceRange());
@@ -3925,6 +4103,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
return;
}
+
+
// 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.
@@ -3951,11 +4131,28 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
VDecl->setInvalidDecl();
return;
}
+
+ // C++ [class.static.data]p4
+ // If a static data member is of const integral or const
+ // enumeration type, its declaration in the class definition can
+ // specify a constant-initializer which shall be an integral
+ // constant expression (5.19). In that case, the member can appear
+ // in integral constant expressions. The member shall still be
+ // defined in a namespace scope if it is used in the program and the
+ // namespace scope definition shall not contain an initializer.
+ //
+ // We already performed a redefinition check above, but for static
+ // data members we also need to check whether there was an in-class
+ // declaration with an initializer.
+ const VarDecl* PrevInit = 0;
+ if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+ Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName();
+ Diag(PrevInit->getLocation(), diag::note_previous_definition);
+ return;
+ }
- // Take ownership of the expression, now that we're sure we have somewhere
- // to put it.
- Expr *Init = init.takeAs<Expr>();
- assert(Init && "missing initializer");
+ if (getLangOptions().CPlusPlus && VDecl->hasLocalStorage())
+ getCurFunction()->setHasBranchProtectedScope();
// Capture the variable that is being initialized and the style of
// initialization.
@@ -3978,8 +4175,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
VDecl->setInvalidDecl();
} else if (!VDecl->isInvalidDecl()) {
InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&Init, 1),
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Init, 1),
&DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
@@ -3991,7 +4188,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
// Don't check invalid declarations to avoid emitting useless diagnostics.
if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) {
- if (VDecl->getStorageClass() == VarDecl::Static) // C99 6.7.8p4.
+ if (VDecl->getStorageClass() == SC_Static) // C99 6.7.8p4.
CheckForConstantInitializer(Init, DclT);
}
}
@@ -4039,18 +4236,18 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
<< Init->getSourceRange();
VDecl->setInvalidDecl();
} else if (!VDecl->getType()->isDependentType())
- ImpCastExprToType(Init, VDecl->getType(), CastExpr::CK_IntegralCast);
+ ImpCastExprToType(Init, VDecl->getType(), CK_IntegralCast);
}
}
} else if (VDecl->isFileVarDecl()) {
- if (VDecl->getStorageClass() == VarDecl::Extern &&
+ if (VDecl->getStorageClass() == SC_Extern &&
(!getLangOptions().CPlusPlus ||
!Context.getBaseElementType(VDecl->getType()).isConstQualified()))
Diag(VDecl->getLocation(), diag::warn_extern_init);
if (!VDecl->isInvalidDecl()) {
InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&Init, 1),
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Init, 1),
&DclT);
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
@@ -4081,6 +4278,14 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
VDecl->setInit(Init);
if (getLangOptions().CPlusPlus) {
+ if (!VDecl->isInvalidDecl() &&
+ !VDecl->getDeclContext()->isDependentContext() &&
+ VDecl->hasGlobalStorage() && !VDecl->isStaticLocal() &&
+ !Init->isConstantInitializer(Context,
+ VDecl->getType()->isReferenceType()))
+ Diag(VDecl->getLocation(), diag::warn_global_constructor)
+ << Init->getSourceRange();
+
// Make sure we mark the destructor as used if necessary.
QualType InitType = VDecl->getType();
while (const ArrayType *Array = Context.getAsArrayType(InitType))
@@ -4095,10 +4300,9 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
/// ActOnInitializerError - Given that there was an error parsing an
/// initializer for the given declaration, try to return to some form
/// of sanity.
-void Sema::ActOnInitializerError(DeclPtrTy dcl) {
+void Sema::ActOnInitializerError(Decl *D) {
// Our main concern here is re-establishing invariants like "a
// variable's type is either dependent or complete".
- Decl *D = dcl.getAs<Decl>();
if (!D || D->isInvalidDecl()) return;
VarDecl *VD = dyn_cast<VarDecl>(D);
@@ -4127,10 +4331,8 @@ void Sema::ActOnInitializerError(DeclPtrTy dcl) {
// though.
}
-void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
+void Sema::ActOnUninitializedDecl(Decl *RealDecl,
bool TypeContainsUndeducedAuto) {
- Decl *RealDecl = dcl.getAs<Decl>();
-
// If there is no declaration, there was an error parsing it. Just ignore it.
if (RealDecl == 0)
return;
@@ -4190,7 +4392,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
ArrayT->getElementType(),
diag::err_illegal_decl_array_incomplete_type))
Var->setInvalidDecl();
- } else if (Var->getStorageClass() == VarDecl::Static) {
+ } else if (Var->getStorageClass() == SC_Static) {
// C99 6.9.2p3: If the declaration of an identifier for an object is
// a tentative definition and has internal linkage (C99 6.2.2p3), the
// declared type shall not be an incomplete type.
@@ -4221,15 +4423,15 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
return;
}
- // Provide a specific diagnostic for uninitialized variable
- // definitions with reference type.
- if (Type->isReferenceType()) {
- Diag(Var->getLocation(), diag::err_reference_var_requires_init)
- << Var->getDeclName()
- << SourceRange(Var->getLocation(), Var->getLocation());
- Var->setInvalidDecl();
- return;
- }
+ // Provide a specific diagnostic for uninitialized variable
+ // definitions with reference type.
+ if (Type->isReferenceType()) {
+ Diag(Var->getLocation(), diag::err_reference_var_requires_init)
+ << Var->getDeclName()
+ << SourceRange(Var->getLocation(), Var->getLocation());
+ Var->setInvalidDecl();
+ return;
+ }
// Do not attempt to type-check the default initializer for a
// variable with dependent type.
@@ -4271,17 +4473,30 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
// program is ill-formed.
// FIXME: DPG thinks it is very fishy that C++0x disables this.
} else {
+ // Check for jumps past the implicit initializer. C++0x
+ // clarifies that this applies to a "variable with automatic
+ // storage duration", not a "local variable".
+ if (getLangOptions().CPlusPlus && Var->hasLocalStorage())
+ getCurFunction()->setHasBranchProtectedScope();
+
InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
InitializationKind Kind
= InitializationKind::CreateDefault(Var->getLocation());
InitializationSequence InitSeq(*this, Entity, Kind, 0, 0);
- OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, 0, 0));
+ ExprResult Init = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, 0, 0));
if (Init.isInvalid())
Var->setInvalidDecl();
- else if (Init.get())
+ else if (Init.get()) {
Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>()));
+
+ if (getLangOptions().CPlusPlus && !Var->isInvalidDecl() &&
+ Var->hasGlobalStorage() && !Var->isStaticLocal() &&
+ !Var->getDeclContext()->isDependentContext() &&
+ !Var->getInit()->isConstantInitializer(Context, false))
+ Diag(Var->getLocation(), diag::warn_global_constructor);
+ }
}
if (!Var->isInvalidDecl() && getLangOptions().CPlusPlus && Record)
@@ -4289,16 +4504,16 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
}
}
-Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
- DeclPtrTy *Group,
- unsigned NumDecls) {
+Sema::DeclGroupPtrTy
+Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ Decl **Group, unsigned NumDecls) {
llvm::SmallVector<Decl*, 8> Decls;
if (DS.isTypeSpecOwned())
- Decls.push_back((Decl*)DS.getTypeRep());
+ Decls.push_back(DS.getRepAsDecl());
for (unsigned i = 0; i != NumDecls; ++i)
- if (Decl *D = Group[i].getAs<Decl>())
+ if (Decl *D = Group[i])
Decls.push_back(D);
return DeclGroupPtrTy::make(DeclGroupRef::Create(Context,
@@ -4308,16 +4523,15 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator()
/// to introduce parameters into function prototype scope.
-Sema::DeclPtrTy
-Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
+Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
// Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
- VarDecl::StorageClass StorageClass = VarDecl::None;
- VarDecl::StorageClass StorageClassAsWritten = VarDecl::None;
+ VarDecl::StorageClass StorageClass = SC_None;
+ VarDecl::StorageClass StorageClassAsWritten = SC_None;
if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
- StorageClass = VarDecl::Register;
- StorageClassAsWritten = VarDecl::Register;
+ StorageClass = SC_Register;
+ StorageClassAsWritten = SC_Register;
} else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) {
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
@@ -4358,7 +4572,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
PrevDecl = 0;
- } else if (S->isDeclScope(DeclPtrTy::make(PrevDecl))) {
+ } else if (S->isDeclScope(PrevDecl)) {
Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II;
Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
@@ -4389,7 +4603,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
}
// Add the parameter declaration into this scope.
- S->AddDecl(DeclPtrTy::make(New));
+ S->AddDecl(New);
if (II)
IdResolver.AddDecl(New);
@@ -4398,7 +4612,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
if (New->hasAttr<BlocksAttr>()) {
Diag(New->getLocation(), diag::err_block_on_nonlocal);
}
- return DeclPtrTy::make(New);
+ return New;
}
/// \brief Synthesizes a variable for a parameter arising from a
@@ -4408,11 +4622,31 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
QualType T) {
ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0,
T, Context.getTrivialTypeSourceInfo(T, Loc),
- VarDecl::None, VarDecl::None, 0);
+ SC_None, SC_None, 0);
Param->setImplicit();
return Param;
}
+void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param,
+ ParmVarDecl * const *ParamEnd) {
+ if (Diags.getDiagnosticLevel(diag::warn_unused_parameter) ==
+ Diagnostic::Ignored)
+ return;
+
+ // Don't diagnose unused-parameter errors in template instantiations; we
+ // will already have done so in the template itself.
+ if (!ActiveTemplateInstantiations.empty())
+ return;
+
+ for (; Param != ParamEnd; ++Param) {
+ if (!(*Param)->isUsed() && (*Param)->getDeclName() &&
+ !(*Param)->hasAttr<UnusedAttr>()) {
+ Diag((*Param)->getLocation(), diag::warn_unused_parameter)
+ << (*Param)->getDeclName();
+ }
+ }
+}
+
ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
@@ -4487,8 +4721,8 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
}
}
-Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
- Declarator &D) {
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
+ Declarator &D) {
assert(getCurFunctionDecl() == 0 && "Function parsing confused");
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"Not a function declarator!");
@@ -4500,9 +4734,9 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
Scope *ParentScope = FnBodyScope->getParent();
- DeclPtrTy DP = HandleDeclarator(ParentScope, D,
- MultiTemplateParamsArg(*this),
- /*IsFunctionDefinition=*/true);
+ Decl *DP = HandleDeclarator(ParentScope, D,
+ MultiTemplateParamsArg(*this),
+ /*IsFunctionDefinition=*/true);
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
@@ -4550,7 +4784,7 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) {
return MissingPrototype;
}
-Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Clear the last template instantiation error context.
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
@@ -4558,11 +4792,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
return D;
FunctionDecl *FD = 0;
- if (FunctionTemplateDecl *FunTmpl
- = dyn_cast<FunctionTemplateDecl>(D.getAs<Decl>()))
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
FD = FunTmpl->getTemplatedDecl();
else
- FD = cast<FunctionDecl>(D.getAs<Decl>());
+ FD = cast<FunctionDecl>(D);
// Enter a new function scope
PushFunctionScope();
@@ -4627,15 +4860,15 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// Checking attributes of current function definition
// dllimport attribute.
- if (FD->getAttr<DLLImportAttr>() &&
- (!FD->getAttr<DLLExportAttr>())) {
- // dllimport attribute cannot be applied to definition.
- if (!(FD->getAttr<DLLImportAttr>())->isInherited()) {
+ DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
+ if (DA && (!FD->getAttr<DLLExportAttr>())) {
+ // dllimport attribute cannot be directly applied to definition.
+ if (!DA->isInherited()) {
Diag(FD->getLocation(),
diag::err_attribute_can_be_applied_only_to_symbol_declaration)
<< "dllimport";
FD->setInvalidDecl();
- return DeclPtrTy::make(FD);
+ return FD;
}
// Visual C++ appears to not think this is an issue, so only issue
@@ -4646,10 +4879,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
// emitted.
Diag(FD->getLocation(),
diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
- << FD->getNameAsCString() << "dllimport";
+ << FD->getName() << "dllimport";
}
}
- return DeclPtrTy::make(FD);
+ return FD;
}
/// \brief Given the set of return statements within a function body,
@@ -4668,9 +4901,11 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
/// FIXME: Employ a smarter algorithm that accounts for multiple return
/// statements and the lifetimes of the NRVO candidates. We should be able to
/// find a maximal set of NRVO variables.
-static void ComputeNRVO(Stmt *Body, ReturnStmt **Returns, unsigned NumReturns) {
+static void ComputeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
+ ReturnStmt **Returns = Scope->Returns.data();
+
const VarDecl *NRVOCandidate = 0;
- for (unsigned I = 0; I != NumReturns; ++I) {
+ for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
if (!Returns[I]->getNRVOCandidate())
return;
@@ -4684,15 +4919,12 @@ static void ComputeNRVO(Stmt *Body, ReturnStmt **Returns, unsigned NumReturns) {
const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true);
}
-Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) {
+Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
return ActOnFinishFunctionBody(D, move(BodyArg), false);
}
-Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
- bool IsInstantiation) {
- Decl *dcl = D.getAs<Decl>();
- Stmt *Body = BodyArg.takeAs<Stmt>();
-
+Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
+ bool IsInstantiation) {
FunctionDecl *FD = 0;
FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
if (FunTmpl)
@@ -4718,8 +4950,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
MarkVTableUsed(FD->getLocation(), Constructor->getParent());
- ComputeNRVO(Body, FunctionScopes.back()->Returns.data(),
- FunctionScopes.back()->Returns.size());
+ ComputeNRVO(Body, getCurFunction());
}
assert(FD == getCurFunctionDecl() && "Function parsing confused");
@@ -4730,15 +4961,15 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
if (!MD->isInvalidDecl())
DiagnoseUnusedParameters(MD->param_begin(), MD->param_end());
} else {
- Body->Destroy(Context);
- return DeclPtrTy();
+ return 0;
}
// Verify and clean out per-function state.
// Check goto/label use.
+ FunctionScopeInfo *CurFn = getCurFunction();
for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
- I = getLabelMap().begin(), E = getLabelMap().end(); I != E; ++I) {
+ I = CurFn->LabelMap.begin(), E = CurFn->LabelMap.end(); I != E; ++I) {
LabelStmt *L = I->second;
// Verify that we have no forward references left. If so, there was a goto
@@ -4754,8 +4985,7 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
// the function body so that they aren't leaked and that the AST is well
// formed.
if (Body == 0) {
- // The whole function wasn't parsed correctly, just delete this.
- L->Destroy(Context);
+ // The whole function wasn't parsed correctly.
continue;
}
@@ -4785,14 +5015,18 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
// Verify that that gotos and switch cases don't jump into scopes illegally.
// Verify that that gotos and switch cases don't jump into scopes illegally.
- if (FunctionNeedsScopeChecking() &&
+ if (getCurFunction()->NeedsScopeChecking() &&
!dcl->isInvalidDecl() &&
!hasAnyErrorsInThisFunction())
DiagnoseInvalidJumps(Body);
- if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl))
+ if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) {
+ if (!Destructor->getParent()->isDependentType())
+ CheckDestructor(Destructor);
+
MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
Destructor->getParent());
+ }
// 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
@@ -4804,13 +5038,11 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
// enabled.
QualType ResultType;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(dcl)) {
- ResultType = FD->getResultType();
- }
- else {
+ AnalysisWarnings.IssueWarnings(WP, FD);
+ } else {
ObjCMethodDecl *MD = cast<ObjCMethodDecl>(dcl);
- ResultType = MD->getResultType();
+ AnalysisWarnings.IssueWarnings(WP, MD);
}
- AnalysisWarnings.IssueWarnings(WP, dcl);
}
assert(ExprTemporaries.empty() && "Leftover temporaries in function");
@@ -4826,8 +5058,8 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
// deletion in some later function.
if (getDiagnostics().hasErrorOccurred())
ExprTemporaries.clear();
-
- return D;
+
+ return dcl;
}
/// ImplicitlyDefineFunction - An undeclared identifier was used in a function
@@ -4873,8 +5105,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
DeclContext *PrevDC = CurContext;
CurContext = Context.getTranslationUnitDecl();
- FunctionDecl *FD =
- dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D));
FD->setImplicit();
CurContext = PrevDC;
@@ -4902,9 +5133,17 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
bool HasVAListArg;
if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) {
if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1,
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "printf", FormatIdx+1,
HasVAListArg ? 0 : FormatIdx+2));
}
+ if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx,
+ HasVAListArg)) {
+ if (!FD->getAttr<FormatAttr>())
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "scanf", FormatIdx+1,
+ HasVAListArg ? 0 : FormatIdx+2));
+ }
// Mark const if we don't care about errno and that is the only
// thing preventing the function from being const. This allows
@@ -4912,15 +5151,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
if (!getLangOptions().MathErrno &&
Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) {
if (!FD->getAttr<ConstAttr>())
- FD->addAttr(::new (Context) ConstAttr());
+ FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
}
if (Context.BuiltinInfo.isNoReturn(BuiltinID))
FD->setType(Context.getNoReturnType(FD->getType()));
if (Context.BuiltinInfo.isNoThrow(BuiltinID))
- FD->addAttr(::new (Context) NoThrowAttr());
+ FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
if (Context.BuiltinInfo.isConst(BuiltinID))
- FD->addAttr(::new (Context) ConstAttr());
+ FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
}
IdentifierInfo *Name = FD->getIdentifier();
@@ -4942,13 +5181,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
// FIXME: We known better than our headers.
const_cast<FormatAttr *>(Format)->setType(Context, "printf");
} else
- FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1,
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "printf", 1,
Name->isStr("NSLogv") ? 0 : 2));
} else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) {
// FIXME: asprintf and vasprintf aren't C99 functions. Should they be
// target-specific builtins, perhaps?
if (!FD->getAttr<FormatAttr>())
- FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2,
+ FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context,
+ "printf", 2,
Name->isStr("vasprintf") ? 0 : 3));
}
}
@@ -5031,7 +5272,7 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous,
/// former case, Name will be non-null. In the later case, Name will be null.
/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a
/// reference/declaration/definition of a tag.
-Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr, AccessSpecifier AS,
@@ -5063,7 +5304,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// This is a declaration or definition of a class template (which may
// be a member of another template).
if (Invalid)
- return DeclPtrTy();
+ return 0;
OwnedDecl = false;
DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
@@ -5106,26 +5347,26 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
DC = computeDeclContext(SS, false);
if (!DC) {
IsDependent = true;
- return DeclPtrTy();
+ return 0;
}
} else {
DC = computeDeclContext(SS, true);
if (!DC) {
Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
<< SS.getRange();
- return DeclPtrTy();
+ return 0;
}
}
if (RequireCompleteDeclContext(SS, DC))
- return DeclPtrTy::make((Decl *)0);
+ return 0;
SearchDC = DC;
// Look-up name inside 'foo::'.
LookupQualifiedName(Previous, DC);
if (Previous.isAmbiguous())
- return DeclPtrTy();
+ return 0;
if (Previous.empty()) {
// Name lookup did not find anything. However, if the
@@ -5135,7 +5376,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// this as a dependent elaborated-type-specifier.
if (Previous.wasNotFoundInCurrentInstantiation()) {
IsDependent = true;
- return DeclPtrTy();
+ return 0;
}
// A tag 'foo::bar' must already exist.
@@ -5155,7 +5396,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Note: there used to be some attempt at recovery here.
if (Previous.isAmbiguous())
- return DeclPtrTy();
+ return 0;
if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
@@ -5176,7 +5417,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
- DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) {
+ DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) {
// This is a declaration of or a reference to "std::bad_alloc".
isStdBadAlloc = true;
@@ -5184,7 +5425,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// std::bad_alloc has been implicitly declared (but made invisible to
// name lookup). Fill in this implicit declaration as the previous
// declaration, so that the declarations get chained appropriately.
- Previous.addDecl(StdBadAlloc);
+ Previous.addDecl(getStdBadAlloc());
}
}
@@ -5271,11 +5512,12 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
TagDecl *Tag = TT->getDecl();
if (Tag->getDeclName() == Name &&
- Tag->getDeclContext()->getLookupContext()
- ->Equals(TD->getDeclContext()->getLookupContext())) {
+ Tag->getDeclContext()->getRedeclContext()
+ ->Equals(TD->getDeclContext()->getRedeclContext())) {
PrevDecl = Tag;
Previous.clear();
Previous.addDecl(Tag);
+ Previous.resolveKind();
}
}
}
@@ -5321,7 +5563,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
// need to be changed with DeclGroups.
if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) ||
TUK == TUK_Friend)
- return DeclPtrTy::make(PrevTagDecl);
+ return PrevTagDecl;
// Diagnose attempts to redefine a tag.
if (TUK == TUK_Definition) {
@@ -5475,7 +5717,7 @@ CreateNewDecl:
New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
cast_or_null<CXXRecordDecl>(PrevDecl));
- if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit()))
+ if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit()))
StdBadAlloc = cast<CXXRecordDecl>(New);
} else
New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc,
@@ -5549,7 +5791,7 @@ CreateNewDecl:
if (PrevDecl)
New->setAccess(PrevDecl->getAccess());
- DeclContext *DC = New->getDeclContext()->getLookupContext();
+ DeclContext *DC = New->getDeclContext()->getRedeclContext();
DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
if (Name) // can be null along some error paths
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
@@ -5564,26 +5806,26 @@ CreateNewDecl:
// If this is the C FILE type, notify the AST context.
if (IdentifierInfo *II = New->getIdentifier())
if (!New->isInvalidDecl() &&
- New->getDeclContext()->getLookupContext()->isTranslationUnit() &&
+ New->getDeclContext()->getRedeclContext()->isTranslationUnit() &&
II->isStr("FILE"))
Context.setFILEDecl(New);
OwnedDecl = true;
- return DeclPtrTy::make(New);
+ return New;
}
-void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) {
+void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
AdjustDeclIfTemplate(TagD);
- TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+ TagDecl *Tag = cast<TagDecl>(TagD);
// Enter the tag context.
PushDeclContext(S, Tag);
}
-void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD,
+void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
SourceLocation LBraceLoc) {
AdjustDeclIfTemplate(TagD);
- CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD.getAs<Decl>());
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD);
FieldCollector->StartClass();
@@ -5610,10 +5852,10 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD,
"Broken injected-class-name");
}
-void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
+void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD,
SourceLocation RBraceLoc) {
AdjustDeclIfTemplate(TagD);
- TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+ TagDecl *Tag = cast<TagDecl>(TagD);
Tag->setRBraceLoc(RBraceLoc);
if (isa<CXXRecordDecl>(Tag))
@@ -5626,9 +5868,9 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
Consumer.HandleTagDeclDefinition(Tag);
}
-void Sema::ActOnTagDefinitionError(Scope *S, DeclPtrTy TagD) {
+void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
AdjustDeclIfTemplate(TagD);
- TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+ TagDecl *Tag = cast<TagDecl>(TagD);
Tag->setInvalidDecl();
// We're undoing ActOnTagStartDefinition here, not
@@ -5711,13 +5953,13 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
/// ActOnField - Each field of a struct/union/class is passed into this in order
/// to create a FieldDecl object for it.
-Sema::DeclPtrTy Sema::ActOnField(Scope *S, DeclPtrTy TagD,
+Decl *Sema::ActOnField(Scope *S, Decl *TagD,
SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth) {
- FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD.getAs<Decl>()),
+ FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD),
DeclStart, D, static_cast<Expr*>(BitfieldWidth),
AS_public);
- return DeclPtrTy::make(Res);
+ return Res;
}
/// HandleField - Analyze a field of a C struct or a C++ data member.
@@ -5739,9 +5981,17 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
+
+ // Check to see if this name was declared as a member previously
+ LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
+ LookupName(Previous, S);
+ assert((Previous.empty() || Previous.isOverloadedResult() ||
+ Previous.isSingleResult())
+ && "Lookup of member name should be either overloaded, single or null");
- NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName,
- ForRedeclaration);
+ // If the name is overloaded then get any declaration else get the single result
+ NamedDecl *PrevDecl = Previous.isOverloadedResult() ?
+ Previous.getRepresentativeDecl() : Previous.getAsSingle<NamedDecl>();
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
@@ -5804,21 +6054,29 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
QualType EltTy = Context.getBaseElementType(T);
if (!EltTy->isDependentType() &&
- RequireCompleteType(Loc, EltTy, diag::err_field_incomplete))
+ RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) {
+ // Fields of incomplete type force their record to be invalid.
+ Record->setInvalidDecl();
InvalidDecl = true;
+ }
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (!InvalidDecl && T->isVariablyModifiedType()) {
bool SizeIsNegative;
+ llvm::APSInt Oversized;
QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
- SizeIsNegative);
+ SizeIsNegative,
+ Oversized);
if (!FixedTy.isNull()) {
Diag(Loc, diag::warn_illegal_constant_array_size);
T = FixedTy;
} else {
if (SizeIsNegative)
Diag(Loc, diag::err_typecheck_negative_array_size);
+ else if (Oversized.getBoolValue())
+ Diag(Loc, diag::err_array_too_large)
+ << Oversized.toString(10);
else
Diag(Loc, diag::err_typecheck_field_variable_size);
InvalidDecl = true;
@@ -5836,7 +6094,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
if (!InvalidDecl && BitWidth &&
VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
InvalidDecl = true;
- DeleteExpr(BitWidth);
BitWidth = 0;
ZeroWidth = false;
}
@@ -5877,6 +6134,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
CXXRecord->setPOD(false);
if (!ZeroWidth)
CXXRecord->setEmpty(false);
+ if (T->isReferenceType())
+ CXXRecord->setHasTrivialConstructor(false);
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
@@ -5896,27 +6155,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// cannot be a member of a union, nor can an array of such
// objects.
// TODO: C++0x alters this restriction significantly.
- if (Record->isUnion()) {
- // We check for copy constructors before constructors
- // because otherwise we'll never get complaints about
- // copy constructors.
-
- CXXSpecialMember member = CXXInvalid;
- if (!RDecl->hasTrivialCopyConstructor())
- member = CXXCopyConstructor;
- else if (!RDecl->hasTrivialConstructor())
- member = CXXConstructor;
- else if (!RDecl->hasTrivialCopyAssignment())
- member = CXXCopyAssignment;
- else if (!RDecl->hasTrivialDestructor())
- member = CXXDestructor;
-
- if (member != CXXInvalid) {
- Diag(Loc, diag::err_illegal_union_member) << Name << member;
- DiagnoseNontrivial(RT, member);
- NewFD->setInvalidDecl();
- }
- }
+ if (Record->isUnion() && CheckNontrivialField(NewFD))
+ NewFD->setInvalidDecl();
}
}
}
@@ -5946,6 +6186,43 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
return NewFD;
}
+bool Sema::CheckNontrivialField(FieldDecl *FD) {
+ assert(FD);
+ assert(getLangOptions().CPlusPlus && "valid check only for C++");
+
+ if (FD->isInvalidDecl())
+ return true;
+
+ QualType EltTy = Context.getBaseElementType(FD->getType());
+ if (const RecordType *RT = EltTy->getAs<RecordType>()) {
+ CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (RDecl->getDefinition()) {
+ // We check for copy constructors before constructors
+ // because otherwise we'll never get complaints about
+ // copy constructors.
+
+ CXXSpecialMember member = CXXInvalid;
+ if (!RDecl->hasTrivialCopyConstructor())
+ member = CXXCopyConstructor;
+ else if (!RDecl->hasTrivialConstructor())
+ member = CXXConstructor;
+ else if (!RDecl->hasTrivialCopyAssignment())
+ member = CXXCopyAssignment;
+ else if (!RDecl->hasTrivialDestructor())
+ member = CXXDestructor;
+
+ if (member != CXXInvalid) {
+ Diag(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member)
+ << (int)FD->getParent()->isUnion() << FD->getDeclName() << member;
+ DiagnoseNontrivial(RT, member);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
/// DiagnoseNontrivial - Given that a class has a non-trivial
/// special member, figure out why.
void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
@@ -6091,9 +6368,9 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
/// ActOnIvar - Each ivar field of an objective-c class is passed into this
/// in order to create an IvarDecl object for it.
-Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
+Decl *Sema::ActOnIvar(Scope *S,
SourceLocation DeclStart,
- DeclPtrTy IntfDecl,
+ Decl *IntfDecl,
Declarator &D, ExprTy *BitfieldWidth,
tok::ObjCKeywordKind Visibility) {
@@ -6112,7 +6389,6 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
// 6.7.2.1p3, 6.7.2.1p4
if (VerifyBitField(Loc, II, T, BitWidth)) {
D.setInvalidType();
- DeleteExpr(BitWidth);
BitWidth = 0;
}
} else {
@@ -6137,19 +6413,23 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility)
: ObjCIvarDecl::None;
// Must set ivar's DeclContext to its enclosing interface.
- ObjCContainerDecl *EnclosingDecl = IntfDecl.getAs<ObjCContainerDecl>();
+ ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(IntfDecl);
ObjCContainerDecl *EnclosingContext;
if (ObjCImplementationDecl *IMPDecl =
dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
+ if (!LangOpts.ObjCNonFragileABI2) {
// Case of ivar declared in an implementation. Context is that of its class.
- EnclosingContext = IMPDecl->getClassInterface();
- assert(EnclosingContext && "Implementation has no class interface!");
+ EnclosingContext = IMPDecl->getClassInterface();
+ assert(EnclosingContext && "Implementation has no class interface!");
+ }
+ else
+ EnclosingContext = EnclosingDecl;
} else {
if (ObjCCategoryDecl *CDecl =
dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) {
Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
- return DeclPtrTy();
+ return 0;
}
}
EnclosingContext = EnclosingDecl;
@@ -6180,19 +6460,59 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S,
if (II) {
// FIXME: When interfaces are DeclContexts, we'll need to add
// these to the interface.
- S->AddDecl(DeclPtrTy::make(NewID));
+ S->AddDecl(NewID);
IdResolver.AddDecl(NewID);
}
- return DeclPtrTy::make(NewID);
+ return NewID;
+}
+
+/// ActOnLastBitfield - This routine handles synthesized bitfields rules for
+/// class and class extensions. For every class @interface and class
+/// extension @interface, if the last ivar is a bitfield of any type,
+/// then add an implicit `char :0` ivar to the end of that interface.
+void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl,
+ llvm::SmallVectorImpl<Decl *> &AllIvarDecls) {
+ if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty())
+ return;
+
+ Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1];
+ ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl);
+
+ if (!Ivar->isBitField())
+ return;
+ uint64_t BitFieldSize =
+ Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue();
+ if (BitFieldSize == 0)
+ return;
+ ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl);
+ if (!ID) {
+ if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
+ if (!CD->IsClassExtension())
+ return;
+ }
+ // No need to add this to end of @implementation.
+ else
+ return;
+ }
+ // All conditions are met. Add a new bitfield to the tail end of ivars.
+ llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0);
+ Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc);
+
+ Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl),
+ DeclLoc, 0,
+ Context.CharTy,
+ Context.CreateTypeSourceInfo(Context.CharTy),
+ ObjCIvarDecl::Private, BW,
+ true);
+ AllIvarDecls.push_back(Ivar);
}
void Sema::ActOnFields(Scope* S,
- SourceLocation RecLoc, DeclPtrTy RecDecl,
- DeclPtrTy *Fields, unsigned NumFields,
+ SourceLocation RecLoc, Decl *EnclosingDecl,
+ Decl **Fields, unsigned NumFields,
SourceLocation LBrac, SourceLocation RBrac,
AttributeList *Attr) {
- Decl *EnclosingDecl = RecDecl.getAs<Decl>();
assert(EnclosingDecl && "missing record or interface decl");
// If the decl this is being inserted into is invalid, then it may be a
@@ -6209,7 +6529,7 @@ void Sema::ActOnFields(Scope* S,
RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
for (unsigned i = 0; i != NumFields; ++i) {
- FieldDecl *FD = cast<FieldDecl>(Fields[i].getAs<Decl>());
+ FieldDecl *FD = cast<FieldDecl>(Fields[i]);
// Get the type for the field.
Type *FDTy = FD->getType().getTypePtr();
@@ -6244,7 +6564,7 @@ void Sema::ActOnFields(Scope* S,
EnclosingDecl->setInvalidDecl();
continue;
} else if (FDTy->isIncompleteArrayType() && i == NumFields - 1 &&
- Record && Record->isStruct()) {
+ Record && !Record->isUnion()) {
// Flexible array member.
if (NumNamedMembers < 1) {
Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
@@ -6360,6 +6680,11 @@ void Sema::ActOnFields(Scope* S,
if (Attr)
ProcessDeclAttributeList(S, Record, Attr);
+
+ // If there's a #pragma GCC visibility in scope, and this isn't a subclass,
+ // set the visibility of this record.
+ if (Record && !Record->getDeclContext()->isRecord())
+ AddPushedVisibilityAttribute(Record);
}
/// \brief Determine whether the given integral value is representable within
@@ -6405,9 +6730,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EnumConstantDecl *LastEnumConst,
SourceLocation IdLoc,
IdentifierInfo *Id,
- ExprArg val) {
- Expr *Val = (Expr *)val.get();
-
+ Expr *Val) {
unsigned IntWidth = Context.Target.getIntWidth();
llvm::APSInt EnumVal(IntWidth);
QualType EltTy;
@@ -6434,12 +6757,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
<< (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
- ImpCastExprToType(Val, Context.IntTy, CastExpr::CK_IntegralCast);
-
- if (Val != val.get()) {
- val.release();
- val = Val;
- }
+ ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast);
}
}
@@ -6527,20 +6845,19 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
EnumVal.setIsSigned(EltTy->isSignedIntegerType());
}
- val.release();
return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy,
Val, EnumVal);
}
-Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
- DeclPtrTy lastEnumConst,
+Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl,
+ Decl *lastEnumConst,
SourceLocation IdLoc,
IdentifierInfo *Id,
SourceLocation EqualLoc, ExprTy *val) {
- EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl.getAs<Decl>());
+ EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
EnumConstantDecl *LastEnumConst =
- cast_or_null<EnumConstantDecl>(lastEnumConst.getAs<Decl>());
+ cast_or_null<EnumConstantDecl>(lastEnumConst);
Expr *Val = static_cast<Expr*>(val);
// The scope passed in may not be a decl scope. Zip up the scope tree until
@@ -6569,13 +6886,12 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
else
Diag(IdLoc, diag::err_redefinition) << Id;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- if (Val) Val->Destroy(Context);
- return DeclPtrTy();
+ return 0;
}
}
EnumConstantDecl *New = CheckEnumConstant(TheEnumDecl, LastEnumConst,
- IdLoc, Id, Owned(Val));
+ IdLoc, Id, Val);
// Register this decl in the current scope stack.
if (New) {
@@ -6583,14 +6899,14 @@ Sema::DeclPtrTy Sema::ActOnEnumConstant(Scope *S, DeclPtrTy theEnumDecl,
PushOnScopeChains(New, S);
}
- return DeclPtrTy::make(New);
+ return New;
}
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
- SourceLocation RBraceLoc, DeclPtrTy EnumDeclX,
- DeclPtrTy *Elements, unsigned NumElements,
+ SourceLocation RBraceLoc, Decl *EnumDeclX,
+ Decl **Elements, unsigned NumElements,
Scope *S, AttributeList *Attr) {
- EnumDecl *Enum = cast<EnumDecl>(EnumDeclX.getAs<Decl>());
+ EnumDecl *Enum = cast<EnumDecl>(EnumDeclX);
QualType EnumType = Context.getTypeDeclType(Enum);
if (Attr)
@@ -6599,7 +6915,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
if (Enum->isDependentType()) {
for (unsigned i = 0; i != NumElements; ++i) {
EnumConstantDecl *ECD =
- cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+ cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue;
ECD->setType(EnumType);
@@ -6626,7 +6942,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
for (unsigned i = 0; i != NumElements; ++i) {
EnumConstantDecl *ECD =
- cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+ cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue; // Already issued a diagnostic.
const llvm::APSInt &InitVal = ECD->getInitVal();
@@ -6728,8 +7044,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// Loop over all of the enumerator constants, changing their types to match
// the type of the enum if needed.
for (unsigned i = 0; i != NumElements; ++i) {
- EnumConstantDecl *ECD =
- cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>());
+ EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]);
if (!ECD) continue; // Already issued a diagnostic.
// Standard C says the enumerators have int type, but we allow, as an
@@ -6772,11 +7087,11 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
// Adjust the Expr initializer and type.
if (ECD->getInitExpr())
- ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy,
- CastExpr::CK_IntegralCast,
- ECD->getInitExpr(),
- CXXBaseSpecifierArray(),
- /*isLvalue=*/false));
+ ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy,
+ CK_IntegralCast,
+ ECD->getInitExpr(),
+ /*base paths*/ 0,
+ VK_RValue));
if (getLangOptions().CPlusPlus)
// C++ [dcl.enum]p4: Following the closing brace of an
// enum-specifier, each enumerator has the type of its
@@ -6790,14 +7105,13 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
NumPositiveBits, NumNegativeBits);
}
-Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
- ExprArg expr) {
- StringLiteral *AsmString = cast<StringLiteral>(expr.takeAs<Expr>());
+Decl *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr) {
+ StringLiteral *AsmString = cast<StringLiteral>(expr);
FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext,
Loc, AsmString);
CurContext->addDecl(New);
- return DeclPtrTy::make(New);
+ return New;
}
void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
@@ -6806,7 +7120,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName);
if (PrevDecl) {
- PrevDecl->addAttr(::new (Context) WeakAttr());
+ PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context));
} else {
(void)WeakUndeclaredIdentifiers.insert(
std::pair<IdentifierInfo*,WeakInfo>
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 3b82f58be43e..25af73ae13d3 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -11,15 +11,18 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/DelayedDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
+using namespace sema;
//===----------------------------------------------------------------------===//
// Helper functions
@@ -193,7 +196,7 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
// Instantiate/Install the vector type, and let Sema build the type for us.
// This will run the reguired checks.
- QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
+ QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc());
if (!T.isNull()) {
// FIXME: preserve the old source info.
tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
@@ -211,7 +214,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
if (TagDecl *TD = dyn_cast<TagDecl>(d))
- TD->addAttr(::new (S.Context) PackedAttr);
+ TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
// If the alignment is less than or equal to 8 bits, the packed attribute
// has no effect.
@@ -220,7 +223,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
<< Attr.getName() << FD->getType();
else
- FD->addAttr(::new (S.Context) PackedAttr);
+ FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context));
} else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
}
@@ -235,7 +238,7 @@ static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) {
// The IBAction attributes only apply to instance methods.
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
if (MD->isInstanceMethod()) {
- d->addAttr(::new (S.Context) IBActionAttr());
+ d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context));
return;
}
@@ -252,7 +255,7 @@ static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) {
// The IBOutlet attributes only apply to instance variables of
// Objective-C classes.
if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) {
- d->addAttr(::new (S.Context) IBOutletAttr());
+ d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context));
return;
}
@@ -263,7 +266,7 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
Sema &S) {
// The iboutletcollection attribute can have zero or one arguments.
- if (Attr.getNumArgs() > 1) {
+ if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
@@ -274,9 +277,41 @@ static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr,
S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet) << Attr.getName();
return;
}
-
- // FIXME: Eventually accept the type argument.
- d->addAttr(::new (S.Context) IBOutletCollectionAttr());
+ if (const ValueDecl *VD = dyn_cast<ValueDecl>(d))
+ if (!VD->getType()->getAs<ObjCObjectPointerType>()) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
+ << VD->getType() << 0;
+ return;
+ }
+ if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d))
+ if (!PD->getType()->getAs<ObjCObjectPointerType>()) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type)
+ << PD->getType() << 1;
+ return;
+ }
+
+ IdentifierInfo *II = Attr.getParameterName();
+ if (!II)
+ II = &S.Context.Idents.get("id");
+
+ ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),
+ S.getScopeForContext(d->getDeclContext()->getParent()));
+ if (!TypeRep) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+ return;
+ }
+ QualType QT = TypeRep.get();
+ // Diagnose use of non-object type in iboutletcollection attribute.
+ // FIXME. Gnu attribute extension ignores use of builtin types in
+ // attributes. So, __attribute__((iboutletcollection(char))) will be
+ // treated as __attribute__((iboutletcollection())).
+ if (!QT->isObjCIdType() && !QT->isObjCClassType() &&
+ !QT->isObjCObjectType()) {
+ S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II;
+ return;
+ }
+ d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context,
+ QT));
}
static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -321,7 +356,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
QualType T = getFunctionOrMethodArgType(d, x);
if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
// FIXME: Should also highlight argument in decl.
- S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only)
+ S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only)
<< "nonnull" << Ex->getSourceRange();
continue;
}
@@ -346,15 +381,162 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
unsigned* start = &NonNullArgs[0];
unsigned size = NonNullArgs.size();
- std::sort(start, start + size);
- d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size));
+ llvm::array_pod_sort(start, start + size);
+ d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start,
+ size));
+}
+
+static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) {
+ // This attribute must be applied to a function declaration.
+ // The first argument to the attribute must be a string,
+ // the name of the resource, for example "malloc".
+ // The following arguments must be argument indexes, the arguments must be
+ // of integer type for Returns, otherwise of pointer type.
+ // The difference between Holds and Takes is that a pointer may still be used
+ // after being held. free() should be __attribute((ownership_takes)), whereas
+ // a list append function may well be __attribute((ownership_holds)).
+
+ if (!AL.getParameterName()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string)
+ << AL.getName()->getName() << 1;
+ return;
+ }
+ // Figure out our Kind, and check arguments while we're at it.
+ OwnershipAttr::OwnershipKind K;
+ switch (AL.getKind()) {
+ case AttributeList::AT_ownership_takes:
+ K = OwnershipAttr::Takes;
+ if (AL.getNumArgs() < 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ return;
+ }
+ break;
+ case AttributeList::AT_ownership_holds:
+ K = OwnershipAttr::Holds;
+ if (AL.getNumArgs() < 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ return;
+ }
+ break;
+ case AttributeList::AT_ownership_returns:
+ K = OwnershipAttr::Returns;
+ if (AL.getNumArgs() > 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
+ << AL.getNumArgs() + 1;
+ return;
+ }
+ break;
+ default:
+ // This should never happen given how we are called.
+ llvm_unreachable("Unknown ownership attribute");
+ }
+
+ if (!isFunction(d) || !hasFunctionProto(d)) {
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL.getName()
+ << 0 /*function*/;
+ return;
+ }
+
+ unsigned NumArgs = getFunctionOrMethodNumArgs(d);
+
+ llvm::StringRef Module = AL.getParameterName()->getName();
+
+ // Normalize the argument, __foo__ becomes foo.
+ if (Module.startswith("__") && Module.endswith("__"))
+ Module = Module.substr(2, Module.size() - 4);
+
+ llvm::SmallVector<unsigned, 10> OwnershipArgs;
+
+ for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E;
+ ++I) {
+
+ Expr *IdxExpr = static_cast<Expr *>(*I);
+ llvm::APSInt ArgNum(32);
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
+ || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int)
+ << AL.getName()->getName() << IdxExpr->getSourceRange();
+ continue;
+ }
+
+ unsigned x = (unsigned) ArgNum.getZExtValue();
+
+ if (x > NumArgs || x < 1) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << AL.getName()->getName() << x << IdxExpr->getSourceRange();
+ continue;
+ }
+ --x;
+ switch (K) {
+ case OwnershipAttr::Takes:
+ case OwnershipAttr::Holds: {
+ // Is the function argument a pointer type?
+ QualType T = getFunctionOrMethodArgType(d, x);
+ if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
+ // FIXME: Should also highlight argument in decl.
+ S.Diag(AL.getLoc(), diag::err_ownership_type)
+ << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds")
+ << "pointer"
+ << IdxExpr->getSourceRange();
+ continue;
+ }
+ break;
+ }
+ case OwnershipAttr::Returns: {
+ if (AL.getNumArgs() > 1) {
+ // Is the function argument an integer type?
+ Expr *IdxExpr = static_cast<Expr *>(AL.getArg(0));
+ llvm::APSInt ArgNum(32);
+ if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
+ || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(AL.getLoc(), diag::err_ownership_type)
+ << "ownership_returns" << "integer"
+ << IdxExpr->getSourceRange();
+ return;
+ }
+ }
+ break;
+ }
+ default:
+ llvm_unreachable("Unknown ownership attribute");
+ } // switch
+
+ // Check we don't have a conflict with another ownership attribute.
+ for (specific_attr_iterator<OwnershipAttr>
+ i = d->specific_attr_begin<OwnershipAttr>(),
+ e = d->specific_attr_end<OwnershipAttr>();
+ i != e; ++i) {
+ if ((*i)->getOwnKind() != K) {
+ for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end();
+ I!=E; ++I) {
+ if (x == *I) {
+ S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)
+ << AL.getName()->getName() << "ownership_*";
+ }
+ }
+ }
+ }
+ OwnershipArgs.push_back(x);
+ }
+
+ unsigned* start = OwnershipArgs.data();
+ unsigned size = OwnershipArgs.size();
+ llvm::array_pod_sort(start, start + size);
+
+ if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) {
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module,
+ start, size));
}
static bool isStaticVarOrStaticFunciton(Decl *D) {
if (VarDecl *VD = dyn_cast<VarDecl>(D))
- return VD->getStorageClass() == VarDecl::Static;
+ return VD->getStorageClass() == SC_Static;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->getStorageClass() == FunctionDecl::Static;
+ return FD->getStorageClass() == SC_Static;
return false;
}
@@ -375,13 +557,11 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// static int a __attribute__((weakref ("v2")));
// }
// we reject them
- if (const DeclContext *Ctx = d->getDeclContext()) {
- Ctx = Ctx->getLookupContext();
- if (!isa<TranslationUnitDecl>(Ctx) && !isa<NamespaceDecl>(Ctx) ) {
- S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
- dyn_cast<NamedDecl>(d)->getNameAsString();
- return;
- }
+ const DeclContext *Ctx = d->getDeclContext()->getRedeclContext();
+ if (!Ctx->isFileContext()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
+ dyn_cast<NamedDecl>(d)->getNameAsString();
+ return;
}
// The GCC manual says
@@ -424,10 +604,10 @@ static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
// GCC will accept anything as the argument of weakref. Should we
// check for an existing decl?
- d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString()));
+ d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
}
- d->addAttr(::new (S.Context) WeakRefAttr());
+ d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context));
}
static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -449,7 +629,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// FIXME: check if target symbol exists in current file
- d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString()));
+ d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, Str->getString()));
}
static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
@@ -466,7 +646,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
return;
}
- d->addAttr(::new (S.Context) AlwaysInlineAttr());
+ d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context));
}
static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -479,7 +659,7 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
QualType RetTy = FD->getResultType();
if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
- d->addAttr(::new (S.Context) MallocAttr());
+ d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context));
return;
}
}
@@ -487,39 +667,75 @@ static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
}
-static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
- Sema &S) {
- // check the attribute arguments.
+static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+ /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
+ assert(Attr.isInvalid() == false);
+ d->addAttr(::new (S.Context) NoReturnAttr(Attr.getLoc(), S.Context));
+}
+
+static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+
+ // The checking path for 'noreturn' and 'analyzer_noreturn' are different
+ // because 'analyzer_noreturn' does not impact the type.
+
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
- return false;
+ return;
}
-
+
if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
ValueDecl *VD = dyn_cast<ValueDecl>(d);
if (VD == 0 || (!VD->getType()->isBlockPointerType()
&& !VD->getType()->isFunctionPointerType())) {
S.Diag(Attr.getLoc(),
Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
- : diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 0 /*function*/;
- return false;
+ : diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 0 /*function*/;
+ return;
}
}
-
- return true;
-}
-
-static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- /* Diagnostics (if any) was emitted by Sema::ProcessFnAttr(). */
- assert(Attr.isInvalid() == false);
- d->addAttr(::new (S.Context) NoReturnAttr());
+
+ d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context));
}
-static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
+// PS3 PPU-specific.
+static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
- if (HandleCommonNoReturnAttr(d, Attr, S))
- d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
+/*
+ Returning a Vector Class in Registers
+
+ According to the PPU ABI specifications, a class with a single member of vector type is returned in
+ memory when used as the return value of a function. This results in inefficient code when implementing
+ vector classes. To return the value in a single vector register, add the vecreturn attribute to the class
+ definition. This attribute is also applicable to struct types.
+
+ Example:
+
+ struct Vector
+ {
+ __vector float xyzw;
+ } __attribute__((vecreturn));
+
+ Vector Add(Vector lhs, Vector rhs)
+ {
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will be returned in a register
+ }
+*/
+ if (!isa<CXXRecordDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+ << Attr.getName() << 9 /*class*/;
+ return;
+ }
+
+ if (d->getAttr<VecReturnAttr>()) {
+ S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+ return;
+ }
+
+ d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
}
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -545,7 +761,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UnusedAttr());
+ d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context));
}
static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -566,7 +782,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UsedAttr());
+ d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
}
static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -596,7 +812,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) ConstructorAttr(priority));
+ d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, priority));
}
static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -626,7 +842,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) DestructorAttr(priority));
+ d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, priority));
}
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -636,7 +852,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) DeprecatedAttr());
+ d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context));
}
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -646,7 +862,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) UnavailableAttr());
+ d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context));
}
static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -667,22 +883,22 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
}
llvm::StringRef TypeStr = Str->getString();
- VisibilityAttr::VisibilityTypes type;
+ VisibilityAttr::VisibilityType type;
if (TypeStr == "default")
- type = VisibilityAttr::DefaultVisibility;
+ type = VisibilityAttr::Default;
else if (TypeStr == "hidden")
- type = VisibilityAttr::HiddenVisibility;
+ type = VisibilityAttr::Hidden;
else if (TypeStr == "internal")
- type = VisibilityAttr::HiddenVisibility; // FIXME
+ type = VisibilityAttr::Hidden; // FIXME
else if (TypeStr == "protected")
- type = VisibilityAttr::ProtectedVisibility;
+ type = VisibilityAttr::Protected;
else {
S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
return;
}
- d->addAttr(::new (S.Context) VisibilityAttr(type));
+ d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type));
}
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
@@ -698,7 +914,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
return;
}
- D->addAttr(::new (S.Context) ObjCExceptionAttr());
+ D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context));
}
static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -714,7 +930,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
}
- D->addAttr(::new (S.Context) ObjCNSObjectAttr());
+ D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context));
}
static void
@@ -729,7 +945,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) OverloadableAttr());
+ D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context));
}
static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -744,7 +960,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- BlocksAttr::BlocksAttrTypes type;
+ BlocksAttr::BlockType type;
if (Attr.getParameterName()->isStr("byref"))
type = BlocksAttr::ByRef;
else {
@@ -753,7 +969,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) BlocksAttr(type));
+ d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type));
}
static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -846,7 +1062,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
<< Attr.getName() << 6 /*function, method or block */;
return;
}
- d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
+ d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, nullPos));
}
static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -874,7 +1090,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S)
return;
}
- D->addAttr(::new (S.Context) WarnUnusedResultAttr());
+ D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context));
}
static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -898,7 +1114,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) WeakAttr());
+ D->addAttr(::new (S.Context) WeakAttr(Attr.getLoc(), S.Context));
}
static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -934,7 +1150,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) WeakImportAttr());
+ D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context));
}
static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
@@ -957,7 +1173,8 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
}
WGSize[i] = (unsigned) ArgNum.getZExtValue();
}
- D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1],
+ D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context,
+ WGSize[0], WGSize[1],
WGSize[2]));
}
@@ -991,7 +1208,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) SectionAttr(S.Context, SE->getString()));
+ D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context, SE->getString()));
}
@@ -1002,7 +1219,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoThrowAttr());
+ d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context));
}
static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1012,7 +1229,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) ConstAttr());
+ d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context));
}
static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1022,7 +1239,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) PureAttr());
+ d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context));
}
static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1080,7 +1297,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) CleanupAttr(FD));
+ d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD));
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
@@ -1143,7 +1360,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
+ d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, Idx.getZExtValue()));
}
enum FormatAttrKind {
@@ -1225,7 +1442,7 @@ static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr,
Attr.setInvalid();
return;
}
- d->addAttr(::new (S.Context) InitPriorityAttr(prioritynum));
+ d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, prioritynum));
}
/// Handle __attribute__((format(type,idx,firstarg))) attributes based on
@@ -1369,7 +1586,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FormatAttr(S.Context, Format, Idx.getZExtValue(),
+ d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format,
+ Idx.getZExtValue(),
FirstArg.getZExtValue()));
}
@@ -1438,7 +1656,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
}
}
- RD->addAttr(::new (S.Context) TransparentUnionAttr());
+ RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context));
}
static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1456,7 +1674,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
return;
}
- d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString()));
+ d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, SE->getString()));
}
static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -1471,9 +1689,7 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// weaker alignment, rather than being silently ignored.
if (Attr.getNumArgs() == 0) {
- // FIXME: This should be the target specific maximum alignment.
- // (For now we just use 128 bits which is the maximum on X86).
- D->addAttr(::new (S.Context) AlignedAttr(128));
+ D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0));
return;
}
@@ -1483,10 +1699,11 @@ static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) {
void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
if (E->isTypeDependent() || E->isValueDependent()) {
// Save dependent expressions in the AST to be instantiated.
- D->addAttr(::new (Context) AlignedAttr(E));
+ D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
return;
}
+ // FIXME: Cache the number on the Attr object?
llvm::APSInt Alignment(32);
if (!E->isIntegerConstantExpr(Alignment, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_not_int)
@@ -1499,7 +1716,14 @@ void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) {
return;
}
- D->addAttr(::new (Context) AlignedAttr(Alignment.getZExtValue() * 8));
+ D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E));
+}
+
+void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) {
+ // FIXME: Cache the number on the Attr object if non-dependent?
+ // FIXME: Perform checking of type validity
+ D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS));
+ return;
}
/// HandleModeAttr - This attribute modifies the width of a decl with primitive
@@ -1686,7 +1910,7 @@ static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoDebugAttr());
+ d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context));
}
static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1702,7 +1926,7 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) NoInlineAttr());
+ d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context));
}
static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
@@ -1719,7 +1943,7 @@ static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr,
return;
}
- d->addAttr(::new (S.Context) NoInstrumentFunctionAttr());
+ d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), S.Context));
}
static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1741,7 +1965,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) GNUInlineAttr());
+ d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context));
}
static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1751,15 +1975,19 @@ static void HandleCallConvAttr(Decl *d, const AttributeList &Attr, Sema &S) {
switch (Attr.getKind()) {
case AttributeList::AT_fastcall:
- d->addAttr(::new (S.Context) FastCallAttr());
+ d->addAttr(::new (S.Context) FastCallAttr(Attr.getLoc(), S.Context));
return;
case AttributeList::AT_stdcall:
- d->addAttr(::new (S.Context) StdCallAttr());
+ d->addAttr(::new (S.Context) StdCallAttr(Attr.getLoc(), S.Context));
return;
case AttributeList::AT_thiscall:
- d->addAttr(::new (S.Context) ThisCallAttr());
+ d->addAttr(::new (S.Context) ThisCallAttr(Attr.getLoc(), S.Context));
+ return;
case AttributeList::AT_cdecl:
- d->addAttr(::new (S.Context) CDeclAttr());
+ d->addAttr(::new (S.Context) CDeclAttr(Attr.getLoc(), S.Context));
+ return;
+ case AttributeList::AT_pascal:
+ d->addAttr(::new (S.Context) PascalAttr(Attr.getLoc(), S.Context));
return;
default:
llvm_unreachable("unexpected attribute kind");
@@ -1801,7 +2029,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
+ d->addAttr(::new (S.Context) RegparmAttr(Attr.getLoc(), S.Context,
+ NumParams.getZExtValue()));
}
static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1827,7 +2056,7 @@ static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) FinalAttr());
+ d->addAttr(::new (S.Context) FinalAttr(Attr.getLoc(), S.Context));
}
//===----------------------------------------------------------------------===//
@@ -1853,7 +2082,7 @@ static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) BaseCheckAttr());
+ d->addAttr(::new (S.Context) BaseCheckAttr(Attr.getLoc(), S.Context));
}
static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1878,7 +2107,7 @@ static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) HidingAttr());
+ d->addAttr(::new (S.Context) HidingAttr(Attr.getLoc(), S.Context));
}
static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
@@ -1903,7 +2132,7 @@ static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
return;
}
- d->addAttr(::new (S.Context) OverrideAttr());
+ d->addAttr(::new (S.Context) OverrideAttr(Attr.getLoc(), S.Context));
}
//===----------------------------------------------------------------------===//
@@ -1939,16 +2168,16 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
assert(0 && "invalid ownership attribute");
return;
case AttributeList::AT_cf_returns_not_retained:
- d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr());
+ d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
return;
case AttributeList::AT_ns_returns_not_retained:
- d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr());
+ d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getLoc(), S.Context));
return;
case AttributeList::AT_cf_returns_retained:
- d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
+ d->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getLoc(), S.Context));
return;
case AttributeList::AT_ns_returns_retained:
- d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
+ d->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getLoc(), S.Context));
return;
};
}
@@ -2009,9 +2238,14 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break;
case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break;
case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break;
+ case AttributeList::AT_ownership_returns:
+ case AttributeList::AT_ownership_takes:
+ case AttributeList::AT_ownership_holds:
+ HandleOwnershipAttr (D, Attr, S); break;
case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break;
case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
case AttributeList::AT_override: HandleOverrideAttr (D, Attr, S); break;
+ case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break;
// Checker-specific.
case AttributeList::AT_ns_returns_not_retained:
@@ -2063,6 +2297,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D,
case AttributeList::AT_cdecl:
case AttributeList::AT_fastcall:
case AttributeList::AT_thiscall:
+ case AttributeList::AT_pascal:
HandleCallConvAttr(D, Attr, S);
break;
default:
@@ -2087,7 +2322,7 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *Attr
// but that looks really pointless. We reject it.
if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
- dyn_cast<NamedDecl>(D)->getNameAsString();
+ dyn_cast<NamedDecl>(D)->getNameAsString();
return;
}
}
@@ -2127,8 +2362,9 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
IdentifierInfo *NDId = ND->getIdentifier();
NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
- NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName()));
- NewD->addAttr(::new (Context) WeakAttr());
+ NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context,
+ NDId->getName()));
+ NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
WeakTopLevelDecl.push_back(NewD);
// FIXME: "hideous" code from Sema::LazilyCreateBuiltin
// to insert Decl at TU scope, sorry.
@@ -2137,7 +2373,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
PushOnScopeChains(NewD, S);
CurContext = SavedContext;
} else { // just add weak to existing
- ND->addAttr(::new (Context) WeakAttr());
+ ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context));
}
}
@@ -2179,12 +2415,12 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
///
/// The state token we use is the start index of this scope
/// on the warning stack.
-Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
+Sema::ParsingDeclStackState Sema::PushParsingDeclaration() {
ParsingDeclDepth++;
return (ParsingDeclStackState) DelayedDiagnostics.size();
}
-void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
+void Sema::PopParsingDeclaration(ParsingDeclStackState S, Decl *D) {
assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
ParsingDeclDepth--;
@@ -2199,7 +2435,6 @@ void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
// We only want to actually emit delayed diagnostics when we
// successfully parsed a decl.
- Decl *D = Ctx ? Ctx.getAs<Decl>() : 0;
if (D) {
// We really do want to start with 0 here. We get one push for a
// decl spec and another for each declarator; in a decl group like:
@@ -2238,7 +2473,7 @@ static bool isDeclDeprecated(Decl *D) {
return false;
}
-void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD,
+void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
Decl *Ctx) {
if (isDeclDeprecated(Ctx))
return;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index bd97df2ce9d1..63acdb5f1cc6 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -11,9 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/CXXFieldCollector.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
@@ -23,10 +25,11 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include <map>
#include <set>
@@ -108,7 +111,7 @@ namespace {
}
bool
-Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
+Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
SourceLocation EqualLoc) {
if (RequireCompleteType(Param->getLocation(), Param->getType(),
diag::err_typecheck_decl_incomplete_type)) {
@@ -116,8 +119,6 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
return true;
}
- Expr *Arg = (Expr *)DefaultArg.get();
-
// C++ [dcl.fct.default]p5
// A default argument expression is implicitly converted (clause
// 4) to the parameter type. The default argument expression has
@@ -128,8 +129,8 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
EqualLoc);
InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1);
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&Arg, 1));
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Arg, 1));
if (Result.isInvalid())
return true;
Arg = Result.takeAs<Expr>();
@@ -139,8 +140,6 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
// Okay: add the default argument to the parameter
Param->setDefaultArg(Arg);
- DefaultArg.release();
-
return false;
}
@@ -148,16 +147,14 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, ExprArg DefaultArg,
/// provided for a function parameter is well-formed. If so, attach it
/// to the parameter declaration.
void
-Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
- ExprArg defarg) {
- if (!param || !defarg.get())
+Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
+ Expr *DefaultArg) {
+ if (!param || !DefaultArg)
return;
- ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
+ ParmVarDecl *Param = cast<ParmVarDecl>(param);
UnparsedDefaultArgLocs.erase(Param);
- ExprOwningPtr<Expr> DefaultArg(this, defarg.takeAs<Expr>());
-
// Default arguments are only permitted in C++
if (!getLangOptions().CPlusPlus) {
Diag(EqualLoc, diag::err_param_default_argument)
@@ -167,26 +164,26 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
}
// Check that the default argument is well-formed
- CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg.get(), this);
- if (DefaultArgChecker.Visit(DefaultArg.get())) {
+ CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
+ if (DefaultArgChecker.Visit(DefaultArg)) {
Param->setInvalidDecl();
return;
}
- SetParamDefaultArgument(Param, move(DefaultArg), EqualLoc);
+ SetParamDefaultArgument(Param, DefaultArg, EqualLoc);
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
/// argument for a function parameter, but we can't parse it yet
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
-void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
+void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
SourceLocation EqualLoc,
SourceLocation ArgLoc) {
if (!param)
return;
- ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
+ ParmVarDecl *Param = cast<ParmVarDecl>(param);
if (Param)
Param->setUnparsedDefaultArg();
@@ -195,11 +192,11 @@ void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
-void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
+void Sema::ActOnParamDefaultArgumentError(Decl *param) {
if (!param)
return;
- ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
+ ParmVarDecl *Param = cast<ParmVarDecl>(param);
Param->setInvalidDecl();
@@ -224,7 +221,7 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
if (chunk.Kind == DeclaratorChunk::Function) {
for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) {
ParmVarDecl *Param =
- cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param.getAs<Decl>());
+ cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens;
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
@@ -412,8 +409,6 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->hasDefaultArg()) {
- if (!Param->hasUnparsedDefaultArg())
- Param->getDefaultArg()->Destroy(Context);
Param->setDefaultArg(0);
}
}
@@ -449,8 +444,9 @@ CXXBaseSpecifier *
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- QualType BaseType,
- SourceLocation BaseLoc) {
+ TypeSourceInfo *TInfo) {
+ QualType BaseType = TInfo->getType();
+
// C++ [class.union]p1:
// A union shall not have base classes.
if (Class->isUnion()) {
@@ -461,8 +457,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
if (BaseType->isDependentType())
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
- Class->getTagKind() == TTK_Class,
- Access, BaseType);
+ Class->getTagKind() == TTK_Class,
+ Access, TInfo);
+
+ SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();
// Base specifiers must be record types.
if (!BaseType->isRecordType()) {
@@ -482,8 +480,10 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
// defined class.
if (RequireCompleteType(BaseLoc, BaseType,
PDiag(diag::err_incomplete_base_class)
- << SpecifierRange))
+ << SpecifierRange)) {
+ Class->setInvalidDecl();
return 0;
+ }
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
@@ -502,11 +502,14 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
}
SetClassDeclAttributesFromBase(Class, CXXBaseDecl, Virtual);
+
+ if (BaseDecl->isInvalidDecl())
+ Class->setInvalidDecl();
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
- Class->getTagKind() == TTK_Class,
- Access, BaseType);
+ Class->getTagKind() == TTK_Class,
+ Access, TInfo);
}
void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
@@ -581,22 +584,22 @@ void Sema::SetClassDeclAttributesFromBase(CXXRecordDecl *Class,
/// example:
/// class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
-Sema::BaseResult
-Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
+BaseResult
+Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- TypeTy *basetype, SourceLocation BaseLoc) {
+ ParsedType basetype, SourceLocation BaseLoc) {
if (!classdecl)
return true;
AdjustDeclIfTemplate(classdecl);
- CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl.getAs<Decl>());
+ CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl);
if (!Class)
return true;
- QualType BaseType = GetTypeFromParser(basetype);
+ TypeSourceInfo *TInfo = 0;
+ GetTypeFromParser(basetype, &TInfo);
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
- Virtual, Access,
- BaseType, BaseLoc))
+ Virtual, Access, TInfo))
return BaseSpec;
return true;
@@ -664,13 +667,13 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases,
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
-void Sema::ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases,
+void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases,
unsigned NumBases) {
if (!ClassDecl || !Bases || !NumBases)
return;
AdjustDeclIfTemplate(ClassDecl);
- AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl.getAs<Decl>()),
+ AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl),
(CXXBaseSpecifier**)(Bases), NumBases);
}
@@ -719,7 +722,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) {
}
void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
- CXXBaseSpecifierArray &BasePathArray) {
+ CXXCastPath &BasePathArray) {
assert(BasePathArray.empty() && "Base path array must be empty!");
assert(Paths.isRecordingPaths() && "Must record paths!");
@@ -738,14 +741,14 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
// Now add all bases.
for (unsigned I = Start, E = Path.size(); I != E; ++I)
- BasePathArray.push_back(Path[I].Base);
+ BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
}
/// \brief Determine whether the given base path includes a virtual
/// base class.
-bool Sema::BasePathInvolvesVirtualBase(const CXXBaseSpecifierArray &BasePath) {
- for (CXXBaseSpecifierArray::iterator B = BasePath.begin(),
- BEnd = BasePath.end();
+bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) {
+ for (CXXCastPath::const_iterator B = BasePath.begin(),
+ BEnd = BasePath.end();
B != BEnd; ++B)
if ((*B)->isVirtual())
return true;
@@ -767,7 +770,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name,
- CXXBaseSpecifierArray *BasePath) {
+ CXXCastPath *BasePath) {
// First, determine whether the path from Derived to Base is
// ambiguous. This is slightly more expensive than checking whether
// the Derived to Base conversion exists, because here we need to
@@ -825,7 +828,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
- CXXBaseSpecifierArray *BasePath,
+ CXXCastPath *BasePath,
bool IgnoreAccess) {
return CheckDerivedToBaseConversion(Derived, Base,
IgnoreAccess ? 0
@@ -872,30 +875,31 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
//===----------------------------------------------------------------------===//
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
-Sema::DeclPtrTy
-Sema::ActOnAccessSpecifier(AccessSpecifier Access,
- SourceLocation ASLoc, SourceLocation ColonLoc) {
+Decl *Sema::ActOnAccessSpecifier(AccessSpecifier Access,
+ SourceLocation ASLoc,
+ SourceLocation ColonLoc) {
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
- AccessSpecDecl* ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
+ AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
ASLoc, ColonLoc);
CurContext->addHiddenDecl(ASDecl);
- return DeclPtrTy::make(ASDecl);
+ return ASDecl;
}
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
/// bitfield width if there is one and 'InitExpr' specifies the initializer if
/// any.
-Sema::DeclPtrTy
+Decl *
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
ExprTy *BW, ExprTy *InitExpr, bool IsDefinition,
bool Deleted) {
const DeclSpec &DS = D.getDeclSpec();
- DeclarationName Name = GetNameForDeclarator(D);
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
+ SourceLocation Loc = NameInfo.getLoc();
Expr *BitWidth = static_cast<Expr*>(BW);
Expr *Init = static_cast<Expr*>(InitExpr);
- SourceLocation Loc = D.getIdentifierLoc();
assert(isa<CXXRecordDecl>(CurContext));
assert(!DS.isFriendSpecified());
@@ -905,7 +909,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
isFunc = true;
else if (D.getNumTypeObjects() == 0 &&
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename) {
- QualType TDType = GetTypeFromParser(DS.getTypeRep());
+ QualType TDType = GetTypeFromParser(DS.getRepAsType());
isFunc = TDType->isFunctionType();
}
@@ -952,11 +956,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
AS);
assert(Member && "HandleField never returns null");
} else {
- Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition)
- .getAs<Decl>();
+ Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition);
if (!Member) {
- if (BitWidth) DeleteExpr(BitWidth);
- return DeclPtrTy();
+ return 0;
}
// Non-instance-fields can't have a bitfield.
@@ -980,7 +982,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
<< BitWidth->getSourceRange();
}
- DeleteExpr(BitWidth);
BitWidth = 0;
Member->setInvalidDecl();
}
@@ -996,15 +997,15 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
assert((Name || isInstField) && "No identifier for non-field ?");
if (Init)
- AddInitializerToDecl(DeclPtrTy::make(Member), ExprArg(*this, Init), false);
+ AddInitializerToDecl(Member, Init, false);
if (Deleted) // FIXME: Source location is not very good.
- SetDeclDeleted(DeclPtrTy::make(Member), D.getSourceRange().getBegin());
+ SetDeclDeleted(Member, D.getSourceRange().getBegin());
if (isInstField) {
FieldCollector->Add(cast<FieldDecl>(Member));
- return DeclPtrTy();
+ return 0;
}
- return DeclPtrTy::make(Member);
+ return Member;
}
/// \brief Find the direct and/or virtual base specifiers that
@@ -1053,12 +1054,12 @@ static bool FindBaseInitializer(Sema &SemaRef,
}
/// ActOnMemInitializer - Handle a C++ member initializer.
-Sema::MemInitResult
-Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
+MemInitResult
+Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
- TypeTy *TemplateTypeTy,
+ ParsedType TemplateTypeTy,
SourceLocation IdLoc,
SourceLocation LParenLoc,
ExprTy **Args, unsigned NumArgs,
@@ -1070,7 +1071,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
AdjustDeclIfTemplate(ConstructorD);
CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
+ = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor) {
// The user wrote a constructor initializer on a function that is
// not a C++ constructor. Ignore the error for now, because we may
@@ -1148,7 +1149,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) &&
R.isSingleResult()) {
if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
- if (Member->getDeclContext()->getLookupContext()->Equals(ClassDecl)) {
+ if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
// member.
@@ -1259,7 +1260,7 @@ static bool InitExprContainsUninitializedFields(const Stmt *S,
return false;
}
-Sema::MemInitResult
+MemInitResult
Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation LParenLoc,
@@ -1285,15 +1286,12 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent();
- QualType FieldType = Member->getType();
- if (const ArrayType *Array = Context.getAsArrayType(FieldType))
- FieldType = Array->getElementType();
- if (FieldType->isDependentType() || HasDependentArg) {
+ if (Member->getType()->isDependentType() || HasDependentArg) {
// Can't check initialization for a member of dependent type or when
// any of the arguments are type-dependent expressions.
- OwningExprResult Init
- = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
- RParenLoc));
+ Expr *Init
+ = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc);
// Erase any temporaries within this evaluation context; we're not
// going to track them in the AST, since we'll be rebuilding the
@@ -1304,7 +1302,7 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
LParenLoc,
- Init.takeAs<Expr>(),
+ Init,
RParenLoc);
}
@@ -1320,16 +1318,16 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
- OwningExprResult MemberInit =
+ ExprResult MemberInit =
InitSeq.Perform(*this, MemberEntity, Kind,
- MultiExprArg(*this, (void**)Args, NumArgs), 0);
+ MultiExprArg(*this, Args, NumArgs), 0);
if (MemberInit.isInvalid())
return true;
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ MemberInit = MaybeCreateCXXExprWithTemporaries(MemberInit.get());
if (MemberInit.isInvalid())
return true;
@@ -1345,22 +1343,21 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
for (unsigned I = 0; I != NumArgs; ++I)
Args[I]->Retain();
- OwningExprResult Init
- = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
- RParenLoc));
+ Expr *Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc);
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
LParenLoc,
- Init.takeAs<Expr>(),
+ Init,
RParenLoc);
}
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
LParenLoc,
- MemberInit.takeAs<Expr>(),
+ MemberInit.get(),
RParenLoc);
}
-Sema::MemInitResult
+MemInitResult
Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
Expr **Args, unsigned NumArgs,
SourceLocation LParenLoc, SourceLocation RParenLoc,
@@ -1413,7 +1410,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
if (Dependent) {
// Can't check initialization for a base of dependent type or when
// any of the arguments are type-dependent expressions.
- OwningExprResult BaseInit
+ ExprResult BaseInit
= Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
RParenLoc));
@@ -1452,16 +1449,16 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
- OwningExprResult BaseInit =
+ ExprResult BaseInit =
InitSeq.Perform(*this, BaseEntity, Kind,
- MultiExprArg(*this, (void**)Args, NumArgs), 0);
+ MultiExprArg(*this, Args, NumArgs), 0);
if (BaseInit.isInvalid())
return true;
// C++0x [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
- BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(BaseInit.get());
if (BaseInit.isInvalid())
return true;
@@ -1477,7 +1474,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
for (unsigned I = 0; I != NumArgs; ++I)
Args[I]->Retain();
- OwningExprResult Init
+ ExprResult Init
= Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
RParenLoc));
return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
@@ -1512,7 +1509,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
IsInheritedVirtualBase);
- Sema::OwningExprResult BaseInit(SemaRef);
+ ExprResult BaseInit;
switch (ImplicitInitKind) {
case IIK_Default: {
@@ -1520,7 +1517,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= InitializationKind::CreateDefault(Constructor->getLocation());
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind,
- Sema::MultiExprArg(SemaRef, 0, 0));
+ MultiExprArg(SemaRef, 0, 0));
break;
}
@@ -1536,10 +1533,12 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
QualType ArgTy =
SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
ParamType.getQualifiers());
- SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
- CastExpr::CK_UncheckedDerivedToBase,
- /*isLvalue=*/true,
- CXXBaseSpecifierArray(BaseSpec));
+
+ CXXCastPath BasePath;
+ BasePath.push_back(BaseSpec);
+ SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
InitializationKind InitKind
= InitializationKind::CreateDirect(Constructor->getLocation(),
@@ -1547,16 +1546,18 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind,
&CopyCtorArg, 1);
BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind,
- Sema::MultiExprArg(SemaRef,
- (void**)&CopyCtorArg, 1));
+ MultiExprArg(&CopyCtorArg, 1));
break;
}
case IIK_Move:
assert(false && "Unhandled initializer kind!");
}
+
+ if (BaseInit.isInvalid())
+ return true;
- BaseInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ BaseInit = SemaRef.MaybeCreateCXXExprWithTemporaries(BaseInit.get());
if (BaseInit.isInvalid())
return true;
@@ -1596,8 +1597,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
Sema::LookupMemberName);
MemberLookup.addDecl(Field, AS_public);
MemberLookup.resolveKind();
- Sema::OwningExprResult CopyCtorArg
- = SemaRef.BuildMemberReferenceExpr(SemaRef.Owned(MemberExprBase),
+ ExprResult CopyCtorArg
+ = SemaRef.BuildMemberReferenceExpr(MemberExprBase,
ParamType, Loc,
/*IsArrow=*/false,
SS,
@@ -1628,19 +1629,19 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
= VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc,
IterationVarName, SizeType,
SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- VarDecl::None, VarDecl::None);
+ SC_None, SC_None);
IndexVariables.push_back(IterationVar);
// Create a reference to the iteration variable.
- Sema::OwningExprResult IterationVarRef
+ ExprResult IterationVarRef
= SemaRef.BuildDeclRefExpr(IterationVar, SizeType, Loc);
assert(!IterationVarRef.isInvalid() &&
"Reference to invented variable cannot fail!");
// Subscript the array with this iteration variable.
- CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(move(CopyCtorArg),
+ CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CopyCtorArg.take(),
Loc,
- move(IterationVarRef),
+ IterationVarRef.take(),
Loc);
if (CopyCtorArg.isInvalid())
return true;
@@ -1667,10 +1668,10 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
&CopyCtorArgE, 1);
- Sema::OwningExprResult MemberInit
+ ExprResult MemberInit
= InitSeq.Perform(SemaRef, Entities.back(), InitKind,
- Sema::MultiExprArg(SemaRef, (void**)&CopyCtorArgE, 1));
- MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ MultiExprArg(&CopyCtorArgE, 1));
+ MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(MemberInit.get());
if (MemberInit.isInvalid())
return true;
@@ -1693,17 +1694,19 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
InitializationKind::CreateDefault(Loc);
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0);
- Sema::OwningExprResult MemberInit =
- InitSeq.Perform(SemaRef, InitEntity, InitKind,
- Sema::MultiExprArg(SemaRef, 0, 0));
- MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ ExprResult MemberInit =
+ InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg());
+ if (MemberInit.isInvalid())
+ return true;
+
+ MemberInit = SemaRef.MaybeCreateCXXExprWithTemporaries(MemberInit.get());
if (MemberInit.isInvalid())
return true;
CXXMemberInit =
new (SemaRef.Context) CXXBaseOrMemberInitializer(SemaRef.Context,
Field, Loc, Loc,
- MemberInit.takeAs<Expr>(),
+ MemberInit.get(),
Loc);
return false;
}
@@ -1797,6 +1800,9 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info,
// Once we've initialized a field of an anonymous union, the union
// field in the class is also initialized, so exit immediately.
return false;
+ } else if ((*FA)->isAnonymousStructOrUnion()) {
+ if (CollectFieldInitializer(Info, Top, *FA))
+ return true;
}
}
@@ -2147,7 +2153,7 @@ bool CheckRedundantUnionInit(Sema &S,
}
/// ActOnMemInitializers - Handle the member initializers for a constructor.
-void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
+void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **meminits, unsigned NumMemInits,
bool AnyErrors) {
@@ -2157,7 +2163,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
AdjustDeclIfTemplate(ConstructorDecl);
CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
+ = dyn_cast<CXXConstructorDecl>(ConstructorDecl);
if (!Constructor) {
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
@@ -2292,35 +2298,30 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
}
}
-void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {
+void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
if (!CDtorDecl)
return;
if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
+ = dyn_cast<CXXConstructorDecl>(CDtorDecl))
SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false);
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- unsigned DiagID, AbstractDiagSelID SelID,
- const CXXRecordDecl *CurrentRD) {
+ unsigned DiagID, AbstractDiagSelID SelID) {
if (SelID == -1)
- return RequireNonAbstractType(Loc, T,
- PDiag(DiagID), CurrentRD);
+ return RequireNonAbstractType(Loc, T, PDiag(DiagID));
else
- return RequireNonAbstractType(Loc, T,
- PDiag(DiagID) << SelID, CurrentRD);
+ return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID);
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- const PartialDiagnostic &PD,
- const CXXRecordDecl *CurrentRD) {
+ const PartialDiagnostic &PD) {
if (!getLangOptions().CPlusPlus)
return false;
if (const ArrayType *AT = Context.getAsArrayType(T))
- return RequireNonAbstractType(Loc, AT->getElementType(), PD,
- CurrentRD);
+ return RequireNonAbstractType(Loc, AT->getElementType(), PD);
if (const PointerType *PT = T->getAs<PointerType>()) {
// Find the innermost pointer type.
@@ -2328,7 +2329,7 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
PT = T;
if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
- return RequireNonAbstractType(Loc, AT->getElementType(), PD, CurrentRD);
+ return RequireNonAbstractType(Loc, AT->getElementType(), PD);
}
const RecordType *RT = T->getAs<RecordType>();
@@ -2337,22 +2338,27 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (CurrentRD && CurrentRD != RD)
- return false;
-
- // FIXME: is this reasonable? It matches current behavior, but....
- if (!RD->getDefinition())
+ // We can't answer whether something is abstract until it has a
+ // definition. If it's currently being defined, we'll walk back
+ // over all the declarations when we have a full definition.
+ const CXXRecordDecl *Def = RD->getDefinition();
+ if (!Def || Def->isBeingDefined())
return false;
if (!RD->isAbstract())
return false;
Diag(Loc, PD) << RD->getDeclName();
+ DiagnoseAbstractType(RD);
- // Check if we've already emitted the list of pure virtual functions for this
- // class.
+ return true;
+}
+
+void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
+ // Check if we've already emitted the list of pure virtual functions
+ // for this class.
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
- return true;
+ return;
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
@@ -2392,69 +2398,168 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
if (!PureVirtualClassDiagSet)
PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
PureVirtualClassDiagSet->insert(RD);
-
- return true;
}
namespace {
- class AbstractClassUsageDiagnoser
- : public DeclVisitor<AbstractClassUsageDiagnoser, bool> {
- Sema &SemaRef;
- CXXRecordDecl *AbstractClass;
+struct AbstractUsageInfo {
+ Sema &S;
+ CXXRecordDecl *Record;
+ CanQualType AbstractType;
+ bool Invalid;
+
+ AbstractUsageInfo(Sema &S, CXXRecordDecl *Record)
+ : S(S), Record(Record),
+ AbstractType(S.Context.getCanonicalType(
+ S.Context.getTypeDeclType(Record))),
+ Invalid(false) {}
+
+ void DiagnoseAbstractType() {
+ if (Invalid) return;
+ S.DiagnoseAbstractType(Record);
+ Invalid = true;
+ }
- bool VisitDeclContext(const DeclContext *DC) {
- bool Invalid = false;
+ void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel);
+};
- for (CXXRecordDecl::decl_iterator I = DC->decls_begin(),
- E = DC->decls_end(); I != E; ++I)
- Invalid |= Visit(*I);
+struct CheckAbstractUsage {
+ AbstractUsageInfo &Info;
+ const NamedDecl *Ctx;
- return Invalid;
+ CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx)
+ : Info(Info), Ctx(Ctx) {}
+
+ void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break;
+#include "clang/AST/TypeLocNodes.def"
}
+ }
- public:
- AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
- : SemaRef(SemaRef), AbstractClass(ac) {
- Visit(SemaRef.Context.getTranslationUnitDecl());
+ void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ Visit(TL.getResultLoc(), Sema::AbstractReturnType);
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo();
+ if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
}
+ }
- bool VisitFunctionDecl(const FunctionDecl *FD) {
- if (FD->isThisDeclarationADefinition()) {
- // No need to do the check if we're in a definition, because it requires
- // that the return/param types are complete.
- // because that requires
- return VisitDeclContext(FD);
- }
+ void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ Visit(TL.getElementLoc(), Sema::AbstractArrayType);
+ }
- // Check the return type.
- QualType RTy = FD->getType()->getAs<FunctionType>()->getResultType();
- bool Invalid =
- SemaRef.RequireNonAbstractType(FD->getLocation(), RTy,
- diag::err_abstract_type_in_decl,
- Sema::AbstractReturnType,
- AbstractClass);
-
- for (FunctionDecl::param_const_iterator I = FD->param_begin(),
- E = FD->param_end(); I != E; ++I) {
- const ParmVarDecl *VD = *I;
- Invalid |=
- SemaRef.RequireNonAbstractType(VD->getLocation(),
- VD->getOriginalType(),
- diag::err_abstract_type_in_decl,
- Sema::AbstractParamType,
- AbstractClass);
- }
+ void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ // Visit the type parameters from a permissive context.
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TemplateArgumentLoc TAL = TL.getArgLoc(I);
+ if (TAL.getArgument().getKind() == TemplateArgument::Type)
+ if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo())
+ Visit(TSI->getTypeLoc(), Sema::AbstractNone);
+ // TODO: other template argument types?
+ }
+ }
- return Invalid;
+ // Visit pointee types from a permissive context.
+#define CheckPolymorphic(Type) \
+ void Check(Type TL, Sema::AbstractDiagSelID Sel) { \
+ Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \
+ }
+ CheckPolymorphic(PointerTypeLoc)
+ CheckPolymorphic(ReferenceTypeLoc)
+ CheckPolymorphic(MemberPointerTypeLoc)
+ CheckPolymorphic(BlockPointerTypeLoc)
+
+ /// Handle all the types we haven't given a more specific
+ /// implementation for above.
+ void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
+ // Every other kind of type that we haven't called out already
+ // that has an inner type is either (1) sugar or (2) contains that
+ // inner type in some way as a subobject.
+ if (TypeLoc Next = TL.getNextTypeLoc())
+ return Visit(Next, Sel);
+
+ // If there's no inner type and we're in a permissive context,
+ // don't diagnose.
+ if (Sel == Sema::AbstractNone) return;
+
+ // Check whether the type matches the abstract type.
+ QualType T = TL.getType();
+ if (T->isArrayType()) {
+ Sel = Sema::AbstractArrayType;
+ T = Info.S.Context.getBaseElementType(T);
}
+ CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType();
+ if (CT != Info.AbstractType) return;
- bool VisitDecl(const Decl* D) {
- if (const DeclContext *DC = dyn_cast<DeclContext>(D))
- return VisitDeclContext(DC);
+ // It matched; do some magic.
+ if (Sel == Sema::AbstractArrayType) {
+ Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type)
+ << T << TL.getSourceRange();
+ } else {
+ Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl)
+ << Sel << T << TL.getSourceRange();
+ }
+ Info.DiagnoseAbstractType();
+ }
+};
- return false;
+void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL,
+ Sema::AbstractDiagSelID Sel) {
+ CheckAbstractUsage(*this, D).Visit(TL, Sel);
+}
+
+}
+
+/// Check for invalid uses of an abstract type in a method declaration.
+static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
+ CXXMethodDecl *MD) {
+ // No need to do the check on definitions, which require that
+ // the return/param types be complete.
+ if (MD->isThisDeclarationADefinition())
+ return;
+
+ // For safety's sake, just ignore it if we don't have type source
+ // information. This should never happen for non-implicit methods,
+ // but...
+ if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
+ Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone);
+}
+
+/// Check for invalid uses of an abstract type within a class definition.
+static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
+ CXXRecordDecl *RD) {
+ for (CXXRecordDecl::decl_iterator
+ I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) {
+ Decl *D = *I;
+ if (D->isImplicit()) continue;
+
+ // Methods and method templates.
+ if (isa<CXXMethodDecl>(D)) {
+ CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D));
+ } else if (isa<FunctionTemplateDecl>(D)) {
+ FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
+ CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD));
+
+ // Fields and static variables.
+ } else if (isa<FieldDecl>(D)) {
+ FieldDecl *FD = cast<FieldDecl>(D);
+ if (TypeSourceInfo *TSI = FD->getTypeSourceInfo())
+ Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType);
+ } else if (isa<VarDecl>(D)) {
+ VarDecl *VD = cast<VarDecl>(D);
+ if (TypeSourceInfo *TSI = VD->getTypeSourceInfo())
+ Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType);
+
+ // Nested classes and class templates.
+ } else if (isa<CXXRecordDecl>(D)) {
+ CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D));
+ } else if (isa<ClassTemplateDecl>(D)) {
+ CheckAbstractClassUsage(Info,
+ cast<ClassTemplateDecl>(D)->getTemplatedDecl());
}
- };
+ }
}
/// \brief Perform semantic checks on a class definition that has been
@@ -2539,8 +2644,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
}
- if (Record->isAbstract() && !Record->isInvalidDecl())
- (void)AbstractClassUsageDiagnoser(*this, Record);
+ if (Record->isAbstract() && !Record->isInvalidDecl()) {
+ AbstractUsageInfo Info(*this, Record);
+ CheckAbstractClassUsage(Info, Record);
+ }
// If this is not an aggregate type and has no user-declared constructor,
// complain about any non-static data members of reference or const scalar
@@ -2571,7 +2678,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
}
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
- DeclPtrTy TagDecl,
+ Decl *TagDecl,
SourceLocation LBrac,
SourceLocation RBrac,
AttributeList *AttrList) {
@@ -2581,11 +2688,12 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
AdjustDeclIfTemplate(TagDecl);
ActOnFields(S, RLoc, TagDecl,
- (DeclPtrTy*)FieldCollector->getCurFields(),
+ // strict aliasing violation!
+ reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList);
CheckCompletedCXXClass(
- dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>()));
+ dyn_cast_or_null<CXXRecordDecl>(TagDecl));
}
namespace {
@@ -2682,8 +2790,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
}
}
-void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
- Decl *D = TemplateD.getAs<Decl>();
+void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
return;
@@ -2701,20 +2808,20 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
Param != ParamEnd; ++Param) {
NamedDecl *Named = cast<NamedDecl>(*Param);
if (Named->getDeclName()) {
- S->AddDecl(DeclPtrTy::make(Named));
+ S->AddDecl(Named);
IdResolver.AddDecl(Named);
}
}
}
-void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
if (!RecordD) return;
AdjustDeclIfTemplate(RecordD);
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD.getAs<Decl>());
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD);
PushDeclContext(S, Record);
}
-void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
if (!RecordD) return;
PopDeclContext();
}
@@ -2727,7 +2834,7 @@ void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
/// Method declaration as if we had just parsed the qualified method
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
-void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
}
/// ActOnDelayedCXXMethodParameter - We've already started a delayed
@@ -2735,18 +2842,18 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
/// function parameter into scope for use in parsing later parts of
/// the method declaration. For example, we could see an
/// ActOnParamDefaultArgument event for this parameter.
-void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
+void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) {
if (!ParamD)
return;
- ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>());
+ ParmVarDecl *Param = cast<ParmVarDecl>(ParamD);
// If this parameter has an unparsed default argument, clear it out
// to make way for the parsed default argument.
if (Param->hasUnparsedDefaultArg())
Param->setDefaultArg(0);
- S->AddDecl(DeclPtrTy::make(Param));
+ S->AddDecl(Param);
if (Param->getDeclName())
IdResolver.AddDecl(Param);
}
@@ -2757,13 +2864,13 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
/// ActOnStartOfFunctionDef action later (not necessarily
/// immediately!) for this method, if it was also defined inside the
/// class body.
-void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
if (!MethodD)
return;
AdjustDeclIfTemplate(MethodD);
- FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
+ FunctionDecl *Method = cast<FunctionDecl>(MethodD);
// Now that we have our default arguments, check the constructor
// again. It could produce additional diagnostics or affect whether
@@ -2784,7 +2891,7 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
/// will be updated to reflect a well-formed type for the constructor and
/// returned.
QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
- FunctionDecl::StorageClass &SC) {
+ StorageClass &SC) {
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
// C++ [class.ctor]p3:
@@ -2799,13 +2906,13 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
}
- if (SC == FunctionDecl::Static) {
+ if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
- SC = FunctionDecl::None;
+ SC = SC_None;
}
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
@@ -2879,8 +2986,9 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
ClassDecl->addedConstructor(Context, Constructor);
}
-/// CheckDestructor - Checks a fully-formed destructor for well-formedness,
-/// issuing any diagnostics required. Returns true on error.
+/// CheckDestructor - Checks a fully-formed destructor definition for
+/// well-formedness, issuing any diagnostics required. Returns true
+/// on error.
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
CXXRecordDecl *RD = Destructor->getParent();
@@ -2911,7 +3019,7 @@ static inline bool
FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
FTI.ArgInfo[0].Param &&
- FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType());
+ cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType());
}
/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
@@ -2921,7 +3029,7 @@ FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) {
/// will be updated to reflect a well-formed type for the destructor and
/// returned.
QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
- FunctionDecl::StorageClass& SC) {
+ StorageClass& SC) {
// C++ [class.dtor]p1:
// [...] A typedef-name that names a class is a class-name
// (7.1.3); however, a typedef-name that names a class shall not
@@ -2940,14 +3048,14 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
// destructor can be invoked for a const, volatile or const
// volatile object. A destructor shall not be declared const,
// volatile or const volatile (9.3.2).
- if (SC == FunctionDecl::Static) {
+ if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< SourceRange(D.getIdentifierLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
- SC = FunctionDecl::None;
+ SC = SC_None;
}
if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) {
// Destructors don't have return types, but the parser will
@@ -3015,18 +3123,18 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
/// false. Either way, the type @p R will be updated to reflect a
/// well-formed type for the conversion operator.
void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
- FunctionDecl::StorageClass& SC) {
+ StorageClass& SC) {
// C++ [class.conv.fct]p1:
// Neither parameter types nor return type can be specified. The
// type of a conversion function (8.3.5) is "function taking no
// parameter returning conversion-type-id."
- if (SC == FunctionDecl::Static) {
+ if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
- SC = FunctionDecl::None;
+ SC = SC_None;
}
QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
@@ -3106,7 +3214,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
/// the declaration of the given C++ conversion function. This routine
/// is responsible for recording the conversion function in the C++
/// class, if possible.
-Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
+Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
assert(Conversion && "Expected to receive a conversion function declaration");
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
@@ -3147,10 +3255,10 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
if (ClassDecl->replaceConversion(
ConversionTemplate->getPreviousDeclaration(),
ConversionTemplate))
- return DeclPtrTy::make(ConversionTemplate);
+ return ConversionTemplate;
} else if (ClassDecl->replaceConversion(Conversion->getPreviousDeclaration(),
Conversion))
- return DeclPtrTy::make(Conversion);
+ return Conversion;
assert(Conversion->isInvalidDecl() && "Conversion should not get here.");
} else if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
@@ -3158,28 +3266,36 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
else
ClassDecl->addConversionFunction(Conversion);
- return DeclPtrTy::make(Conversion);
+ return Conversion;
}
//===----------------------------------------------------------------------===//
// Namespace Handling
//===----------------------------------------------------------------------===//
+
+
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
-Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
- SourceLocation IdentLoc,
- IdentifierInfo *II,
- SourceLocation LBrace,
- AttributeList *AttrList) {
- NamespaceDecl *Namespc =
- NamespaceDecl::Create(Context, CurContext, IdentLoc, II);
+Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+ SourceLocation InlineLoc,
+ SourceLocation IdentLoc,
+ IdentifierInfo *II,
+ SourceLocation LBrace,
+ AttributeList *AttrList) {
+ // anonymous namespace starts at its left brace
+ NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext,
+ (II ? IdentLoc : LBrace) , II);
Namespc->setLBracLoc(LBrace);
+ Namespc->setInline(InlineLoc.isValid());
Scope *DeclRegionScope = NamespcScope->getParent();
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
+ if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
+ PushVisibilityAttr(attr);
+
if (II) {
// C++ [namespace.def]p2:
// The identifier in an original-namespace-definition shall not have been
@@ -3194,15 +3310,25 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
// This is an extended namespace definition.
+ if (Namespc->isInline() != OrigNS->isInline()) {
+ // inline-ness must match
+ Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
+ << Namespc->isInline();
+ Diag(OrigNS->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Recover by ignoring the new namespace's inline status.
+ Namespc->setInline(OrigNS->isInline());
+ }
+
// Attach this namespace decl to the chain of extended namespace
// definitions.
OrigNS->setNextNamespace(Namespc);
Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace());
// Remove the previous declaration from the scope.
- if (DeclRegionScope->isDeclScope(DeclPtrTy::make(OrigNS))) {
+ if (DeclRegionScope->isDeclScope(OrigNS)) {
IdResolver.RemoveDecl(OrigNS);
- DeclRegionScope->RemoveDecl(DeclPtrTy::make(OrigNS));
+ DeclRegionScope->RemoveDecl(OrigNS);
}
} else if (PrevDecl) {
// This is an invalid name redefinition.
@@ -3212,15 +3338,15 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
Namespc->setInvalidDecl();
// Continue on to push Namespc as current DeclContext and return it.
} else if (II->isStr("std") &&
- CurContext->getLookupContext()->isTranslationUnit()) {
+ CurContext->getRedeclContext()->isTranslationUnit()) {
// This is the first "real" definition of the namespace "std", so update
// our cache of the "std" namespace to point at this definition.
- if (StdNamespace) {
+ if (NamespaceDecl *StdNS = getStdNamespace()) {
// We had already defined a dummy namespace "std". Link this new
// namespace definition to the dummy namespace "std".
- StdNamespace->setNextNamespace(Namespc);
- StdNamespace->setLocation(IdentLoc);
- Namespc->setOriginalNamespace(StdNamespace->getOriginalNamespace());
+ StdNS->setNextNamespace(Namespc);
+ StdNS->setLocation(IdentLoc);
+ Namespc->setOriginalNamespace(StdNS->getOriginalNamespace());
}
// Make our StdNamespace cache point at the first real definition of the
@@ -3235,7 +3361,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// Link the anonymous namespace into its parent.
NamespaceDecl *PrevDecl;
- DeclContext *Parent = CurContext->getLookupContext();
+ DeclContext *Parent = CurContext->getRedeclContext();
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
PrevDecl = TU->getAnonymousNamespace();
TU->setAnonymousNamespace(Namespc);
@@ -3251,6 +3377,16 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
assert(!PrevDecl->getNextNamespace());
Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace());
PrevDecl->setNextNamespace(Namespc);
+
+ if (Namespc->isInline() != PrevDecl->isInline()) {
+ // inline-ness must match
+ Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch)
+ << Namespc->isInline();
+ Diag(PrevDecl->getLocation(), diag::note_previous_definition);
+ Namespc->setInvalidDecl();
+ // Recover by ignoring the new namespace's inline status.
+ Namespc->setInline(PrevDecl->isInline());
+ }
}
CurContext->addDecl(Namespc);
@@ -3292,7 +3428,7 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// for the namespace has the declarations that showed up in that particular
// namespace definition.
PushDeclContext(NamespcScope, Namespc);
- return DeclPtrTy::make(Namespc);
+ return Namespc;
}
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
@@ -3305,30 +3441,41 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
/// ActOnFinishNamespaceDef - This callback is called after a namespace is
/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
-void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) {
- Decl *Dcl = D.getAs<Decl>();
+void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
Namespc->setRBracLoc(RBrace);
PopDeclContext();
+ if (Namespc->hasAttr<VisibilityAttr>())
+ PopPragmaVisibility();
+}
+
+CXXRecordDecl *Sema::getStdBadAlloc() const {
+ return cast_or_null<CXXRecordDecl>(
+ StdBadAlloc.get(Context.getExternalSource()));
+}
+
+NamespaceDecl *Sema::getStdNamespace() const {
+ return cast_or_null<NamespaceDecl>(
+ StdNamespace.get(Context.getExternalSource()));
}
/// \brief Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
-NamespaceDecl *Sema::getStdNamespace() {
+NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
// The "std" namespace has not yet been defined, so build one implicitly.
StdNamespace = NamespaceDecl::Create(Context,
Context.getTranslationUnitDecl(),
SourceLocation(),
&PP.getIdentifierTable().get("std"));
- StdNamespace->setImplicit(true);
+ getStdNamespace()->setImplicit(true);
}
- return StdNamespace;
+ return getStdNamespace();
}
-Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
+Decl *Sema::ActOnUsingDirective(Scope *S,
SourceLocation UsingLoc,
SourceLocation NamespcLoc,
CXXScopeSpec &SS,
@@ -3349,7 +3496,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
if (R.isAmbiguous())
- return DeclPtrTy();
+ return 0;
if (R.empty()) {
// Allow "using namespace std;" or "using namespace ::std;" even if
@@ -3357,7 +3504,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
NamespcName->isStr("std")) {
Diag(IdentLoc, diag::ext_using_undefined_std);
- R.addDecl(getStdNamespace());
+ R.addDecl(getOrCreateStdNamespace());
R.resolveKind();
}
// Otherwise, attempt typo correction.
@@ -3416,7 +3563,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S,
// FIXME: We ignore attributes for now.
delete AttrList;
- return DeclPtrTy::make(UDir);
+ return UDir;
}
void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
@@ -3428,11 +3575,11 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
else
// Otherwise it is block-sope. using-directives will affect lookup
// only to the end of scope.
- S->PushUsingDirective(DeclPtrTy::make(UDir));
+ S->PushUsingDirective(UDir);
}
-Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
+Decl *Sema::ActOnUsingDeclaration(Scope *S,
AccessSpecifier AS,
bool HasUsingKeyword,
SourceLocation UsingLoc,
@@ -3457,22 +3604,23 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor)
<< SS.getRange();
- return DeclPtrTy();
+ return 0;
case UnqualifiedId::IK_DestructorName:
Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor)
<< SS.getRange();
- return DeclPtrTy();
+ return 0;
case UnqualifiedId::IK_TemplateId:
Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
- return DeclPtrTy();
+ return 0;
}
-
- DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
+
+ DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
+ DeclarationName TargetName = TargetNameInfo.getName();
if (!TargetName)
- return DeclPtrTy();
+ return 0;
// Warn about using declarations.
// TODO: store that the declaration was written without 'using' and
@@ -3486,14 +3634,13 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
}
NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
- Name.getSourceRange().getBegin(),
- TargetName, AttrList,
+ TargetNameInfo, AttrList,
/* IsInstantiation */ false,
IsTypeName, TypenameLoc);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
- return DeclPtrTy::make(UD);
+ return UD;
}
/// \brief Determine whether a using declaration considers the given
@@ -3717,7 +3864,7 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
// ...and the scope, if applicable...
if (S) {
- S->RemoveDecl(DeclPtrTy::make(static_cast<Decl*>(Shadow)));
+ S->RemoveDecl(Shadow);
IdResolver.RemoveDecl(Shadow);
}
@@ -3736,13 +3883,13 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- DeclarationName Name,
+ const DeclarationNameInfo &NameInfo,
AttributeList *AttrList,
bool IsInstantiation,
bool IsTypeName,
SourceLocation TypenameLoc) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
+ SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
// FIXME: We ignore attributes for now.
@@ -3754,7 +3901,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
}
// Do the redeclaration lookup in the current scope.
- LookupResult Previous(*this, Name, IdentLoc, LookupUsingDeclName,
+ LookupResult Previous(*this, NameInfo, LookupUsingDeclName,
ForRedeclaration);
Previous.setHideTags(false);
if (S) {
@@ -3793,15 +3940,15 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
SS.getRange(), NNS,
- IdentLoc, Name);
+ IdentLoc, NameInfo.getName());
} else {
D = UnresolvedUsingValueDecl::Create(Context, CurContext,
- UsingLoc, SS.getRange(), NNS,
- IdentLoc, Name);
+ UsingLoc, SS.getRange(),
+ NNS, NameInfo);
}
} else {
- D = UsingDecl::Create(Context, CurContext, IdentLoc,
- SS.getRange(), UsingLoc, NNS, Name,
+ D = UsingDecl::Create(Context, CurContext,
+ SS.getRange(), UsingLoc, NNS, NameInfo,
IsTypeName);
}
D->setAccess(AS);
@@ -3817,7 +3964,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
// Look up the target name.
- LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName);
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
// Unlike most lookups, we don't always want to hide tag
// declarations: tag names are visible through the using declaration
@@ -3830,7 +3977,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
if (R.empty()) {
Diag(IdentLoc, diag::err_no_member)
- << Name << LookupContext << SS.getRange();
+ << NameInfo.getName() << LookupContext << SS.getRange();
UD->setInvalidDecl();
return UD;
}
@@ -3894,7 +4041,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
// allowed.
//
// That's in non-member contexts.
- if (!CurContext->getLookupContext()->isRecord())
+ if (!CurContext->getRedeclContext()->isRecord())
return false;
NestedNameSpecifier *Qual
@@ -4069,7 +4216,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
return true;
}
-Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
+Decl *Sema::ActOnNamespaceAliasDef(Scope *S,
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
@@ -4096,18 +4243,18 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
// declaration to maintain better source information.
if (!R.isAmbiguous() && !R.empty() &&
AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl())))
- return DeclPtrTy();
+ return 0;
}
unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition :
diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
- return DeclPtrTy();
+ return 0;
}
if (R.isAmbiguous())
- return DeclPtrTy();
+ return 0;
if (R.empty()) {
if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false,
@@ -4135,7 +4282,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
if (R.empty()) {
Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();
- return DeclPtrTy();
+ return 0;
}
}
@@ -4146,7 +4293,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
IdentLoc, R.getFoundDecl());
PushOnScopeChains(AliasDecl, S);
- return DeclPtrTy::make(AliasDecl);
+ return AliasDecl;
}
namespace {
@@ -4242,9 +4389,9 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(ClassType);
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
CXXConstructorDecl *DefaultCon
- = CXXConstructorDecl::Create(Context, ClassDecl,
- ClassDecl->getLocation(), Name,
+ = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo,
Context.getFunctionType(Context.VoidTy,
0, 0, false, 0,
ExceptSpec.hasExceptionSpecification(),
@@ -4348,9 +4495,9 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
CXXDestructorDecl *Destructor
- = CXXDestructorDecl::Create(Context, ClassDecl,
- ClassDecl->getLocation(), Name, Ty,
+ = CXXDestructorDecl::Create(Context, ClassDecl, NameInfo, Ty,
/*isInline=*/true,
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
@@ -4426,13 +4573,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
/// \param Depth Internal parameter recording the depth of the recursion.
///
/// \returns A statement or a loop that copies the expressions.
-static Sema::OwningStmtResult
+static StmtResult
BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
- Sema::OwningExprResult To, Sema::OwningExprResult From,
+ Expr *To, Expr *From,
bool CopyingBaseSubobject, unsigned Depth = 0) {
- typedef Sema::OwningStmtResult OwningStmtResult;
- typedef Sema::OwningExprResult OwningExprResult;
-
// C++0x [class.copy]p30:
// Each subobject is assigned in the manner appropriate to its type:
//
@@ -4489,21 +4633,21 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
T.getTypePtr()));
// Create the reference to operator=.
- OwningExprResult OpEqualRef
- = S.BuildMemberReferenceExpr(move(To), T, Loc, /*isArrow=*/false, SS,
+ ExprResult OpEqualRef
+ = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS,
/*FirstQualifierInScope=*/0, OpLookup,
/*TemplateArgs=*/0,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
- return S.StmtError();
+ return StmtError();
// Build the call to the assignment operator.
- Expr *FromE = From.takeAs<Expr>();
- OwningExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
+
+ ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0,
OpEqualRef.takeAs<Expr>(),
- Loc, &FromE, 1, 0, Loc);
+ Loc, &From, 1, 0, Loc);
if (Call.isInvalid())
- return S.StmtError();
+ return StmtError();
return S.Owned(Call.takeAs<Stmt>());
}
@@ -4512,12 +4656,9 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// operator is used.
const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
if (!ArrayTy) {
- OwningExprResult Assignment = S.CreateBuiltinBinOp(Loc,
- BinaryOperator::Assign,
- To.takeAs<Expr>(),
- From.takeAs<Expr>());
+ ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From);
if (Assignment.isInvalid())
- return S.StmtError();
+ return StmtError();
return S.Owned(Assignment.takeAs<Stmt>());
}
@@ -4543,11 +4684,11 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
- VarDecl::None, VarDecl::None);
+ SC_None, SC_None);
// Initialize the iteration variable to zero.
llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
- IterationVar->setInit(new (S.Context) IntegerLiteral(Zero, SizeType, Loc));
+ IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
// Create a reference to the iteration variable; we'll use this several
// times throughout.
@@ -4561,43 +4702,37 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// Create the comparison against the array bound.
llvm::APInt Upper = ArrayTy->getSize();
Upper.zextOrTrunc(S.Context.getTypeSize(SizeType));
- OwningExprResult Comparison
- = S.Owned(new (S.Context) BinaryOperator(IterationVarRef->Retain(),
- new (S.Context) IntegerLiteral(Upper, SizeType, Loc),
- BinaryOperator::NE, S.Context.BoolTy, Loc));
+ Expr *Comparison
+ = new (S.Context) BinaryOperator(IterationVarRef->Retain(),
+ IntegerLiteral::Create(S.Context,
+ Upper, SizeType, Loc),
+ BO_NE, S.Context.BoolTy, Loc);
// Create the pre-increment of the iteration variable.
- OwningExprResult Increment
- = S.Owned(new (S.Context) UnaryOperator(IterationVarRef->Retain(),
- UnaryOperator::PreInc,
- SizeType, Loc));
+ Expr *Increment
+ = new (S.Context) UnaryOperator(IterationVarRef->Retain(),
+ UO_PreInc,
+ SizeType, Loc);
// Subscript the "from" and "to" expressions with the iteration variable.
- From = S.CreateBuiltinArraySubscriptExpr(move(From), Loc,
- S.Owned(IterationVarRef->Retain()),
- Loc);
- To = S.CreateBuiltinArraySubscriptExpr(move(To), Loc,
- S.Owned(IterationVarRef->Retain()),
- Loc);
- assert(!From.isInvalid() && "Builtin subscripting can't fail!");
- assert(!To.isInvalid() && "Builtin subscripting can't fail!");
+ From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
+ IterationVarRef, Loc));
+ To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc,
+ IterationVarRef, Loc));
// Build the copy for an individual element of the array.
- OwningStmtResult Copy = BuildSingleCopyAssign(S, Loc,
+ StmtResult Copy = BuildSingleCopyAssign(S, Loc,
ArrayTy->getElementType(),
- move(To), move(From),
+ To, From,
CopyingBaseSubobject, Depth+1);
- if (Copy.isInvalid()) {
- InitStmt->Destroy(S.Context);
- return S.StmtError();
- }
+ if (Copy.isInvalid())
+ return StmtError();
// Construct the loop that copies all elements of this array.
- return S.ActOnForStmt(Loc, Loc, S.Owned(InitStmt),
+ return S.ActOnForStmt(Loc, Loc, InitStmt,
S.MakeFullExpr(Comparison),
- Sema::DeclPtrTy(),
- S.MakeFullExpr(Increment),
- Loc, move(Copy));
+ 0, S.MakeFullExpr(Increment),
+ Loc, Copy.take());
}
/// \brief Determine whether the given class has a copy assignment operator
@@ -4747,8 +4882,9 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// An implicitly-declared copy assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
CXXMethodDecl *CopyAssignment
- = CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
+ = CXXMethodDecl::Create(Context, ClassDecl, NameInfo,
Context.getFunctionType(RetType, &ArgType, 1,
false, 0,
ExceptSpec.hasExceptionSpecification(),
@@ -4757,7 +4893,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
ExceptSpec.data(),
FunctionType::ExtInfo()),
/*TInfo=*/0, /*isStatic=*/false,
- /*StorageClassAsWritten=*/FunctionDecl::None,
+ /*StorageClassAsWritten=*/SC_None,
/*isInline=*/true);
CopyAssignment->setAccess(AS_public);
CopyAssignment->setImplicit();
@@ -4769,8 +4905,8 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
ClassDecl->getLocation(),
/*Id=*/0,
ArgType, /*TInfo=*/0,
- VarDecl::None,
- VarDecl::None, 0);
+ SC_None,
+ SC_None, 0);
CopyAssignment->setParams(&FromParam, 1);
// Note that we have added this copy-assignment operator.
@@ -4814,7 +4950,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// which they were declared in the class definition.
// The statements that form the synthesized function body.
- ASTOwningVector<&ActionBase::DeleteStmt> Statements(*this);
+ ASTOwningVector<Stmt*> Statements(*this);
// The parameter for the "other" object, which we are copying from.
ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0);
@@ -4854,30 +4990,32 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
continue;
}
+ CXXCastPath BasePath;
+ BasePath.push_back(Base);
+
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
Expr *From = OtherRef->Retain();
ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals),
- CastExpr::CK_UncheckedDerivedToBase, /*isLvalue=*/true,
- CXXBaseSpecifierArray(Base));
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
// Dereference "this".
- OwningExprResult To = CreateBuiltinUnaryOp(Loc, UnaryOperator::Deref,
- Owned(This->Retain()));
+ ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
// Implicitly cast "this" to the appropriately-qualified base type.
Expr *ToE = To.takeAs<Expr>();
ImpCastExprToType(ToE,
Context.getCVRQualifiedType(BaseType,
CopyAssignOperator->getTypeQualifiers()),
- CastExpr::CK_UncheckedDerivedToBase,
- /*isLvalue=*/true, CXXBaseSpecifierArray(Base));
+ CK_UncheckedDerivedToBase,
+ VK_LValue, &BasePath);
To = Owned(ToE);
// Build the copy.
- OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
- move(To), Owned(From),
- /*CopyingBaseSubobject=*/true);
+ StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType,
+ To.get(), From,
+ /*CopyingBaseSubobject=*/true);
if (Copy.isInvalid()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
@@ -4934,12 +5072,10 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
LookupMemberName);
MemberLookup.addDecl(*Field);
MemberLookup.resolveKind();
- OwningExprResult From = BuildMemberReferenceExpr(Owned(OtherRef->Retain()),
- OtherRefType,
+ ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
Loc, /*IsArrow=*/false,
SS, 0, MemberLookup, 0);
- OwningExprResult To = BuildMemberReferenceExpr(Owned(This->Retain()),
- This->getType(),
+ ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
Loc, /*IsArrow=*/true,
SS, 0, MemberLookup, 0);
assert(!From.isInvalid() && "Implicit field reference cannot fail");
@@ -4967,8 +5103,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Take the address of the field references for "from" and "to".
- From = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(From));
- To = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(To));
+ From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get());
+ To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get());
bool NeedsCollectableMemCpy =
(BaseType->isRecordType() &&
@@ -5016,22 +5152,22 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
}
- ASTOwningVector<&ActionBase::DeleteExpr> CallArgs(*this);
+ ASTOwningVector<Expr*> CallArgs(*this);
CallArgs.push_back(To.takeAs<Expr>());
CallArgs.push_back(From.takeAs<Expr>());
- CallArgs.push_back(new (Context) IntegerLiteral(Size, SizeType, Loc));
+ CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc));
llvm::SmallVector<SourceLocation, 4> Commas; // FIXME: Silly
Commas.push_back(Loc);
Commas.push_back(Loc);
- OwningExprResult Call = ExprError();
+ ExprResult Call = ExprError();
if (NeedsCollectableMemCpy)
Call = ActOnCallExpr(/*Scope=*/0,
- Owned(CollectableMemCpyRef->Retain()),
+ CollectableMemCpyRef,
Loc, move_arg(CallArgs),
Commas.data(), Loc);
else
Call = ActOnCallExpr(/*Scope=*/0,
- Owned(BuiltinMemCpyRef->Retain()),
+ BuiltinMemCpyRef,
Loc, move_arg(CallArgs),
Commas.data(), Loc);
@@ -5041,8 +5177,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
}
// Build the copy of this field.
- OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType,
- move(To), move(From),
+ StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType,
+ To.get(), From.get(),
/*CopyingBaseSubobject=*/false);
if (Copy.isInvalid()) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
@@ -5057,10 +5193,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
if (!Invalid) {
// Add a "return *this;"
- OwningExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UnaryOperator::Deref,
- Owned(This->Retain()));
+ ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This);
- OwningStmtResult Return = ActOnReturnStmt(Loc, move(ThisObj));
+ StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else {
@@ -5079,7 +5214,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
return;
}
- OwningStmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements),
+ StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements),
/*isStmtExpr=*/false);
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
CopyAssignOperator->setBody(Body.takeAs<Stmt>());
@@ -5220,9 +5355,9 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
+ DeclarationNameInfo NameInfo(Name, ClassDecl->getLocation());
CXXConstructorDecl *CopyConstructor
- = CXXConstructorDecl::Create(Context, ClassDecl,
- ClassDecl->getLocation(), Name,
+ = CXXConstructorDecl::Create(Context, ClassDecl, NameInfo,
Context.getFunctionType(Context.VoidTy,
&ArgType, 1,
false, 0,
@@ -5248,8 +5383,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
ClassDecl->getLocation(),
/*IdentifierInfo=*/0,
ArgType, /*TInfo=*/0,
- VarDecl::None,
- VarDecl::None, 0);
+ SC_None,
+ SC_None, 0);
CopyConstructor->setParams(&FromParam, 1);
if (Scope *S = getScopeForContext(ClassDecl))
PushOnScopeChains(CopyConstructor, S, false);
@@ -5288,12 +5423,12 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CopyConstructor->setUsed();
}
-Sema::OwningExprResult
+ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor,
MultiExprArg ExprArgs,
bool RequiresZeroInit,
- CXXConstructExpr::ConstructionKind ConstructKind) {
+ unsigned ConstructKind) {
bool Elidable = false;
// C++0x [class.copy]p34:
@@ -5309,6 +5444,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
if (Constructor->isCopyConstructor() && ExprArgs.size() >= 1) {
Expr *SubExpr = ((Expr **)ExprArgs.get())[0];
Elidable = SubExpr->isTemporaryObject() &&
+ ConstructKind == CXXConstructExpr::CK_Complete &&
Context.hasSameUnqualifiedType(SubExpr->getType(),
Context.getTypeDeclType(Constructor->getParent()));
}
@@ -5320,27 +5456,28 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
/// including handling of its default argument expressions.
-Sema::OwningExprResult
+ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
MultiExprArg ExprArgs,
bool RequiresZeroInit,
- CXXConstructExpr::ConstructionKind ConstructKind) {
+ unsigned ConstructKind) {
unsigned NumExprs = ExprArgs.size();
Expr **Exprs = (Expr **)ExprArgs.release();
MarkDeclarationReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
- RequiresZeroInit, ConstructKind));
+ RequiresZeroInit,
+ static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind)));
}
bool Sema::InitializeVarWithConstructor(VarDecl *VD,
CXXConstructorDecl *Constructor,
MultiExprArg Exprs) {
- OwningExprResult TempResult =
+ ExprResult TempResult =
BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor,
- move(Exprs));
+ move(Exprs), false, CXXConstructExpr::CK_Complete);
if (TempResult.isInvalid())
return true;
@@ -5362,19 +5499,21 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
PDiag(diag::err_access_dtor_var)
<< VD->getDeclName()
<< VD->getType());
+
+ if (!VD->isInvalidDecl() && VD->hasGlobalStorage())
+ Diag(VD->getLocation(), diag::warn_global_destructor);
}
}
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
/// e.g: "int x(1);"
-void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
+void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
SourceLocation LParenLoc,
MultiExprArg Exprs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
assert(Exprs.size() != 0 && Exprs.get() && "missing expressions");
- Decl *RealDecl = Dcl.getAs<Decl>();
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
@@ -5402,9 +5541,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
// The form of initialization (using parentheses or '=') is generally
// insignificant, but does matter when the entity being initialized has a
// class type.
- QualType DeclInitType = VDecl->getType();
- if (const ArrayType *Array = Context.getAsArrayType(DeclInitType))
- DeclInitType = Context.getBaseElementType(Array);
if (!VDecl->getType()->isDependentType() &&
RequireCompleteType(VDecl->getLocation(), VDecl->getType(),
@@ -5428,6 +5564,25 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
return;
}
+ // C++ [class.static.data]p4
+ // If a static data member is of const integral or const
+ // enumeration type, its declaration in the class definition can
+ // specify a constant-initializer which shall be an integral
+ // constant expression (5.19). In that case, the member can appear
+ // in integral constant expressions. The member shall still be
+ // defined in a namespace scope if it is used in the program and the
+ // namespace scope definition shall not contain an initializer.
+ //
+ // We already performed a redefinition check above, but for static
+ // data members we also need to check whether there was an in-class
+ // declaration with an initializer.
+ const VarDecl* PrevInit = 0;
+ if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) {
+ Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName();
+ Diag(PrevInit->getLocation(), diag::note_previous_definition);
+ return;
+ }
+
// If either the declaration has a dependent type or if any of the
// expressions is type-dependent, we represent the initialization
// via a ParenListExpr for later use during template instantiation.
@@ -5454,17 +5609,25 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
LParenLoc, RParenLoc);
InitializationSequence InitSeq(*this, Entity, Kind,
- (Expr**)Exprs.get(), Exprs.size());
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs));
+ Exprs.get(), Exprs.size());
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs));
if (Result.isInvalid()) {
VDecl->setInvalidDecl();
return;
}
- Result = MaybeCreateCXXExprWithTemporaries(move(Result));
+ Result = MaybeCreateCXXExprWithTemporaries(Result.get());
VDecl->setInit(Result.takeAs<Expr>());
VDecl->setCXXDirectInitializer(true);
+ if (!VDecl->isInvalidDecl() &&
+ !VDecl->getDeclContext()->isDependentContext() &&
+ VDecl->hasGlobalStorage() &&
+ !VDecl->getInit()->isConstantInitializer(Context,
+ VDecl->getType()->isReferenceType()))
+ Diag(VDecl->getLocation(), diag::warn_global_constructor)
+ << VDecl->getInit()->getSourceRange();
+
if (const RecordType *Record = VDecl->getType()->getAs<RecordType>())
FinalizeVarWithDestructor(VDecl, Record);
}
@@ -5478,7 +5641,7 @@ bool
Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
SourceLocation Loc,
- ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) {
+ ASTOwningVector<Expr*> &ConvertedArgs) {
// FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
unsigned NumArgs = ArgsPtr.size();
Expr **Args = (Expr **)ArgsPtr.get();
@@ -5508,7 +5671,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
static inline bool
CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
const FunctionDecl *FnDecl) {
- const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext();
+ const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
if (isa<NamespaceDecl>(DC)) {
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_in_namespace)
@@ -5516,7 +5679,7 @@ CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
}
if (isa<TranslationUnitDecl>(DC) &&
- FnDecl->getStorageClass() == FunctionDecl::Static) {
+ FnDecl->getStorageClass() == SC_Static) {
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_static)
<< FnDecl->getDeclName();
@@ -5622,18 +5785,6 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
diag::err_operator_delete_param_type))
return true;
- QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
- if (FirstParamType->isDependentType())
- return SemaRef.Diag(FnDecl->getLocation(),
- diag::err_operator_delete_dependent_param_type)
- << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy;
-
- if (SemaRef.Context.getCanonicalType(FirstParamType) !=
- SemaRef.Context.VoidPtrTy)
- return SemaRef.Diag(FnDecl->getLocation(),
- diag::err_operator_delete_param_type)
- << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy;
-
return false;
}
@@ -5891,7 +6042,7 @@ FinishedParams:
/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
/// the '{' brace. Otherwise, this linkage specification does not
/// have any braces.
-Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
+Decl *Sema::ActOnStartLinkageSpecification(Scope *S,
SourceLocation ExternLoc,
SourceLocation LangLoc,
llvm::StringRef Lang,
@@ -5903,7 +6054,7 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
Language = LinkageSpecDecl::lang_cxx;
else {
Diag(LangLoc, diag::err_bad_language);
- return DeclPtrTy();
+ return 0;
}
// FIXME: Add all the various semantics of linkage specifications
@@ -5913,15 +6064,15 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S,
LBraceLoc.isValid());
CurContext->addDecl(D);
PushDeclContext(S, D);
- return DeclPtrTy::make(D);
+ return D;
}
-/// ActOnFinishLinkageSpecification - Completely the definition of
+/// ActOnFinishLinkageSpecification - Complete the definition of
/// the C++ linkage specification LinkageSpec. If RBraceLoc is
/// valid, it's the position of the closing '}' brace in a linkage
/// specification that uses braces.
-Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S,
- DeclPtrTy LinkageSpec,
+Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
SourceLocation RBraceLoc) {
if (LinkageSpec)
PopDeclContext();
@@ -5983,9 +6134,30 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
AbstractVariableType))
Invalid = true;
+ // Only the non-fragile NeXT runtime currently supports C++ catches
+ // of ObjC types, and no runtime supports catching ObjC types by value.
+ if (!Invalid && getLangOptions().ObjC1) {
+ QualType T = ExDeclType;
+ if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType();
+
+ if (T->isObjCObjectType()) {
+ Diag(Loc, diag::err_objc_object_catch);
+ Invalid = true;
+ } else if (T->isObjCObjectPointerType()) {
+ if (!getLangOptions().NeXTRuntime) {
+ Diag(Loc, diag::err_objc_pointer_cxx_catch_gnu);
+ Invalid = true;
+ } else if (!getLangOptions().ObjCNonFragileABI) {
+ Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile);
+ Invalid = true;
+ }
+ }
+ }
+
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
- Name, ExDeclType, TInfo, VarDecl::None,
- VarDecl::None);
+ Name, ExDeclType, TInfo, SC_None,
+ SC_None);
ExDecl->setExceptionVariable(true);
if (!Invalid) {
@@ -6005,8 +6177,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
InitializationKind Kind = InitializationKind::CreateCopy(Loc,
SourceLocation());
InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1);
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&ExDeclRef, 1));
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &ExDeclRef, 1));
if (Result.isInvalid())
Invalid = true;
else
@@ -6022,7 +6194,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
/// handler.
-Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
+Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType ExDeclType = TInfo->getType();
@@ -6033,7 +6205,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
ForRedeclaration)) {
// The scope should be freshly made just for us. There is just no way
// it contains any previous declaration.
- assert(!S->isDeclScope(DeclPtrTy::make(PrevDecl)));
+ assert(!S->isDeclScope(PrevDecl));
if (PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
@@ -6061,22 +6233,20 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
CurContext->addDecl(ExDecl);
ProcessDeclAttributes(S, ExDecl, D);
- return DeclPtrTy::make(ExDecl);
+ return ExDecl;
}
-Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
- ExprArg assertexpr,
- ExprArg assertmessageexpr) {
- Expr *AssertExpr = (Expr *)assertexpr.get();
- StringLiteral *AssertMessage =
- cast<StringLiteral>((Expr *)assertmessageexpr.get());
+Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr_) {
+ StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_);
if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) {
llvm::APSInt Value(32);
if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
AssertExpr->getSourceRange();
- return DeclPtrTy();
+ return 0;
}
if (Value == 0) {
@@ -6085,13 +6255,11 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
}
}
- assertexpr.release();
- assertmessageexpr.release();
Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc,
AssertExpr, AssertMessage);
CurContext->addDecl(Decl);
- return DeclPtrTy::make(Decl);
+ return Decl;
}
/// \brief Perform semantic analysis of the given friend type declaration.
@@ -6167,7 +6335,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc,
/// We permit this as a special case; if there are any template
/// parameters present at all, require proper matching, i.e.
/// template <> template <class T> friend class A<int>::B;
-Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TempParams) {
SourceLocation Loc = DS.getSourceRange().getBegin();
@@ -6181,7 +6349,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
- return DeclPtrTy();
+ return 0;
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
@@ -6200,7 +6368,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
Diag(Loc, diag::err_tagless_friend_type_template)
<< DS.getSourceRange();
- return DeclPtrTy();
+ return 0;
}
// C++98 [class.friend]p1: A friend of a class is a function
@@ -6225,18 +6393,17 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI);
if (!D)
- return DeclPtrTy();
+ return 0;
D->setAccess(AS_public);
CurContext->addDecl(D);
- return DeclPtrTy::make(D);
+ return D;
}
-Sema::DeclPtrTy
-Sema::ActOnFriendFunctionDecl(Scope *S,
- Declarator &D,
- bool IsDefinition,
+Decl *Sema::ActOnFriendFunctionDecl(Scope *S,
+ Declarator &D,
+ bool IsDefinition,
MultiTemplateParamsArg TemplateParams) {
const DeclSpec &DS = D.getDeclSpec();
@@ -6262,7 +6429,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// It might be worthwhile to try to recover by creating an
// appropriate declaration.
- return DeclPtrTy();
+ return 0;
}
// C++ [namespace.memdef]p3
@@ -6281,7 +6448,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// namespace scope are not considered.
CXXScopeSpec &ScopeQual = D.getCXXScopeSpec();
- DeclarationName Name = GetNameForDeclarator(D);
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
assert(Name);
// The context we found the declaration in, or in which we should
@@ -6291,14 +6459,14 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// FIXME: handle local classes
// Recover from invalid scope qualifiers as if they just weren't there.
- LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForRedeclaration);
if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
DC = computeDeclContext(ScopeQual);
// FIXME: handle dependent contexts
- if (!DC) return DeclPtrTy();
- if (RequireCompleteDeclContext(ScopeQual, DC)) return DeclPtrTy();
+ if (!DC) return 0;
+ if (RequireCompleteDeclContext(ScopeQual, DC)) return 0;
LookupQualifiedName(Previous, DC);
@@ -6308,7 +6476,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
- if (!D->getDeclContext()->getLookupContext()->Equals(DC))
+ if (!DC->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext()))
F.erase();
}
F.done();
@@ -6316,7 +6485,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
if (Previous.empty()) {
D.setInvalidType();
Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
- return DeclPtrTy();
+ return 0;
}
// C++ [class.friend]p1: A friend of a class is a function or
@@ -6368,7 +6537,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
Diag(Loc, diag::err_introducing_special_friend) <<
(D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
- return DeclPtrTy();
+ return 0;
}
}
@@ -6377,7 +6546,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
move(TemplateParams),
IsDefinition,
Redeclaration);
- if (!ND) return DeclPtrTy();
+ if (!ND) return 0;
assert(ND->getDeclContext() == DC);
assert(ND->getLexicalDeclContext() == CurContext);
@@ -6389,7 +6558,7 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
// Also update the scope-based lookup if the target context's
// lookup context is in lexical scope.
if (!CurContext->isDependentContext()) {
- DC = DC->getLookupContext();
+ DC = DC->getRedeclContext();
DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
@@ -6401,13 +6570,12 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
FrD->setAccess(AS_public);
CurContext->addDecl(FrD);
- return DeclPtrTy::make(ND);
+ return ND;
}
-void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
- AdjustDeclIfTemplate(dcl);
+void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
+ AdjustDeclIfTemplate(Dcl);
- Decl *Dcl = dcl.getAs<Decl>();
FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl);
if (!Fn) {
Diag(DelLoc, diag::err_deleted_non_function);
@@ -6575,9 +6743,8 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
/// class X.
-void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- Decl *D = Dcl.getAs<Decl>();
if (D == 0) return;
// We should only get called for declarations with scope specifiers, like:
@@ -6587,10 +6754,9 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
}
/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
-/// initializer for the out-of-line declaration 'Dcl'.
-void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
+/// initializer for the out-of-line declaration 'D'.
+void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
- Decl *D = Dcl.getAs<Decl>();
if (D == 0) return;
assert(D->isOutOfLine());
@@ -6600,8 +6766,7 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
/// C++ if/switch/while/for statement.
/// e.g: "if (int x = f()) {...}"
-Action::DeclResult
-Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
// C++ 6.4p2:
// The declarator shall not specify a function or an array.
// The type-specifier-seq shall not contain typedef and shall not declare a
@@ -6624,12 +6789,10 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition);
}
- DeclPtrTy Dcl = ActOnDeclarator(S, D);
+ Decl *Dcl = ActOnDeclarator(S, D);
if (!Dcl)
return DeclResult();
- VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>());
- VD->setDeclaredInCondition(true);
return Dcl;
}
@@ -6775,8 +6938,6 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- if (i->isVirtual())
- continue;
if (Base->getNumVBases() == 0)
continue;
MarkVirtualMembersReferenced(Loc, Base);
@@ -6788,7 +6949,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
if (!getLangOptions().CPlusPlus)
return;
- if (const ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
+ if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
llvm::SmallVector<ObjCIvarDecl*, 8> ivars;
CollectIvarsToConstructOrDestruct(OID, ivars);
if (ivars.empty())
@@ -6805,10 +6966,9 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
InitializationKind::CreateDefault(ObjCImplementation->getLocation());
InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
- Sema::OwningExprResult MemberInit =
- InitSeq.Perform(*this, InitEntity, InitKind,
- Sema::MultiExprArg(*this, 0, 0));
- MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ ExprResult MemberInit =
+ InitSeq.Perform(*this, InitEntity, InitKind, MultiExprArg());
+ MemberInit = MaybeCreateCXXExprWithTemporaries(MemberInit.get());
// Note, MemberInit could actually come back empty if no initialization
// is required (e.g., because it would call a trivial default constructor)
if (!MemberInit.get() || MemberInit.isInvalid())
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 21aeb59a0886..a6902a3e391c 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -11,20 +11,24 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/DenseSet.h"
+
using namespace clang;
/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
-void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
+void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
assert(getCurMethodDecl() == 0 && "Method parsing confused");
- ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D.getAs<Decl>());
+ ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);
// If we don't have a valid method decl, simply return.
if (!MDecl)
@@ -32,10 +36,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
// Allow the rest of sema to find private method decl implementations.
if (MDecl->isInstanceMethod())
- AddInstanceMethodToGlobalPool(MDecl);
+ AddInstanceMethodToGlobalPool(MDecl, true);
else
- AddFactoryMethodToGlobalPool(MDecl);
-
+ AddFactoryMethodToGlobalPool(MDecl, true);
+
// Allow all of Sema to see that we are entering a method definition.
PushDeclContext(FnBodyScope, MDecl);
PushFunctionScope();
@@ -56,11 +60,11 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) {
PushOnScopeChains(*PI, FnBodyScope);
}
-Sema::DeclPtrTy Sema::
+Decl *Sema::
ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperName, SourceLocation SuperLoc,
- const DeclPtrTy *ProtoRefs, unsigned NumProtoRefs,
+ Decl * const *ProtoRefs, unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc, AttributeList *AttrList) {
assert(ClassName && "Missing class identifier");
@@ -84,11 +88,14 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
// Return the previous class interface.
// FIXME: don't leak the objects passed in!
- return DeclPtrTy::make(IDecl);
+ return IDecl;
} else {
IDecl->setLocation(AtInterfaceLoc);
IDecl->setForwardDecl(false);
IDecl->setClassLoc(ClassLoc);
+ // If the forward decl was in a PCH, we need to write it again in a
+ // dependent AST file.
+ IDecl->setChangedSinceDeserialization(true);
// Since this ObjCInterfaceDecl was created by a forward declaration,
// we now add it to the DeclContext since it wasn't added before
@@ -176,7 +183,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl->setLocEnd(ClassLoc);
}
- /// Check then save referenced protocols.
+ // Check then save referenced protocols.
if (NumProtoRefs) {
IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
ProtoLocs, Context);
@@ -184,16 +191,16 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
}
CheckObjCDeclScope(IDecl);
- return DeclPtrTy::make(IDecl);
+ return IDecl;
}
/// ActOnCompatiblityAlias - this action is called after complete parsing of
/// @compatibility_alias declaration. It sets up the alias relationships.
-Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
- IdentifierInfo *AliasName,
- SourceLocation AliasLocation,
- IdentifierInfo *ClassName,
- SourceLocation ClassLocation) {
+Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
+ IdentifierInfo *AliasName,
+ SourceLocation AliasLocation,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLocation) {
// Look for previous declaration of alias name
NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation,
LookupOrdinaryName, ForRedeclaration);
@@ -203,7 +210,7 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
else
Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
Diag(ADecl->getLocation(), diag::note_previous_declaration);
- return DeclPtrTy();
+ return 0;
}
// Check for class declaration
NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
@@ -223,7 +230,7 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
if (CDeclU)
Diag(CDeclU->getLocation(), diag::note_previous_declaration);
- return DeclPtrTy();
+ return 0;
}
// Everything checked out, instantiate a new alias declaration AST.
@@ -233,7 +240,7 @@ Sema::DeclPtrTy Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
if (!CheckObjCDeclScope(AliasDecl))
PushOnScopeChains(AliasDecl, TUScope);
- return DeclPtrTy::make(AliasDecl);
+ return AliasDecl;
}
void Sema::CheckForwardProtocolDeclarationForCircularDependency(
@@ -255,11 +262,11 @@ void Sema::CheckForwardProtocolDeclarationForCircularDependency(
}
}
-Sema::DeclPtrTy
+Decl *
Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
IdentifierInfo *ProtocolName,
SourceLocation ProtocolLoc,
- const DeclPtrTy *ProtoRefs,
+ Decl * const *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc,
@@ -274,17 +281,19 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
Diag(PDecl->getLocation(), diag::note_previous_definition);
// Just return the protocol we already had.
// FIXME: don't leak the objects passed in!
- return DeclPtrTy::make(PDecl);
+ return PDecl;
}
ObjCList<ObjCProtocolDecl> PList;
PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
CheckForwardProtocolDeclarationForCircularDependency(
ProtocolName, ProtocolLoc, PDecl->getLocation(), PList);
- PList.Destroy(Context);
// Make sure the cached decl gets a valid start location.
PDecl->setLocation(AtProtoInterfaceLoc);
PDecl->setForwardDecl(false);
+ CurContext->addDecl(PDecl);
+ // Repeat in dependent AST files.
+ PDecl->setChangedSinceDeserialization(true);
} else {
PDecl = ObjCProtocolDecl::Create(Context, CurContext,
AtProtoInterfaceLoc,ProtocolName);
@@ -301,7 +310,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
}
CheckObjCDeclScope(PDecl);
- return DeclPtrTy::make(PDecl);
+ return PDecl;
}
/// FindProtocolDeclaration - This routine looks up protocols and
@@ -311,7 +320,7 @@ void
Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
const IdentifierLocPair *ProtocolId,
unsigned NumProtocols,
- llvm::SmallVectorImpl<DeclPtrTy> &Protocols) {
+ llvm::SmallVectorImpl<Decl *> &Protocols) {
for (unsigned i = 0; i != NumProtocols; ++i) {
ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,
ProtocolId[i].second);
@@ -340,7 +349,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations,
if (WarnOnDeclarations && PDecl->isForwardDecl())
Diag(ProtocolId[i].second, diag::warn_undef_protocolref)
<< ProtocolId[i].first;
- Protocols.push_back(DeclPtrTy::make(PDecl));
+ Protocols.push_back(PDecl);
}
}
@@ -374,7 +383,7 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
}
/// ActOnForwardProtocolDeclaration - Handle @protocol foo;
-Action::DeclPtrTy
+Decl *
Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
const IdentifierLocPair *IdentList,
unsigned NumElts,
@@ -385,13 +394,18 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
for (unsigned i = 0; i != NumElts; ++i) {
IdentifierInfo *Ident = IdentList[i].first;
ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second);
+ bool isNew = false;
if (PDecl == 0) { // Not already seen?
PDecl = ObjCProtocolDecl::Create(Context, CurContext,
IdentList[i].second, Ident);
- PushOnScopeChains(PDecl, TUScope);
+ PushOnScopeChains(PDecl, TUScope, false);
+ isNew = true;
}
- if (attrList)
+ if (attrList) {
ProcessDeclAttributeList(TUScope, PDecl, attrList);
+ if (!isNew)
+ PDecl->setChangedSinceDeserialization(true);
+ }
Protocols.push_back(PDecl);
ProtoLocs.push_back(IdentList[i].second);
}
@@ -402,15 +416,15 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
ProtoLocs.data());
CurContext->addDecl(PDecl);
CheckObjCDeclScope(PDecl);
- return DeclPtrTy::make(PDecl);
+ return PDecl;
}
-Sema::DeclPtrTy Sema::
+Decl *Sema::
ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *CategoryName,
SourceLocation CategoryLoc,
- const DeclPtrTy *ProtoRefs,
+ Decl * const *ProtoRefs,
unsigned NumProtoRefs,
const SourceLocation *ProtoLocs,
SourceLocation EndProtoLoc) {
@@ -426,7 +440,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
ClassLoc, CategoryLoc, CategoryName);
CDecl->setInvalidDecl();
Diag(ClassLoc, diag::err_undef_interface) << ClassName;
- return DeclPtrTy::make(CDecl);
+ return CDecl;
}
if (!CategoryName && IDecl->getImplementation()) {
@@ -471,18 +485,17 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
// Protocols in the class extension belong to the class.
if (CDecl->IsClassExtension())
IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs,
- NumProtoRefs, ProtoLocs,
- Context);
+ NumProtoRefs, Context);
}
CheckObjCDeclScope(CDecl);
- return DeclPtrTy::make(CDecl);
+ return CDecl;
}
/// ActOnStartCategoryImplementation - Perform semantic checks on the
/// category implementation declaration and build an ObjCCategoryImplDecl
/// object.
-Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
+Decl *Sema::ActOnStartCategoryImplementation(
SourceLocation AtCatImplLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *CatName, SourceLocation CatLoc) {
@@ -523,10 +536,10 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation(
}
CheckObjCDeclScope(CDecl);
- return DeclPtrTy::make(CDecl);
+ return CDecl;
}
-Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
+Decl *Sema::ActOnStartClassImplementation(
SourceLocation AtClassImplLoc,
IdentifierInfo *ClassName, SourceLocation ClassLoc,
IdentifierInfo *SuperClassname,
@@ -617,7 +630,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
IDecl, SDecl);
if (CheckObjCDeclScope(IMPDecl))
- return DeclPtrTy::make(IMPDecl);
+ return IMPDecl;
// Check that there is no duplicate implementation of this class.
if (IDecl->getImplementation()) {
@@ -629,7 +642,7 @@ Sema::DeclPtrTy Sema::ActOnStartClassImplementation(
IDecl->setImplementation(IMPDecl);
PushOnScopeChains(IMPDecl, TUScope);
}
- return DeclPtrTy::make(IMPDecl);
+ return IMPDecl;
}
void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
@@ -910,8 +923,9 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
}
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
// Check for any implementation of a methods declared in protocol.
- for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
- E = I->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = I->all_referenced_protocol_begin(),
+ E = I->all_referenced_protocol_end(); PI != E; ++PI)
MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
IMPDecl,
(*PI), IncompleteImpl, false);
@@ -957,8 +971,9 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
// implemented in the implementation class.
if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
- E = I->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = I->all_referenced_protocol_begin(),
+ E = I->all_referenced_protocol_end(); PI != E; ++PI)
CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
InsMap, ClsMap, I);
// Check class extensions (unnamed categories)
@@ -992,7 +1007,7 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
}
/// ActOnForwardClassDeclaration -
-Action::DeclPtrTy
+Decl *
Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
SourceLocation *IdentLocs,
@@ -1053,7 +1068,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
Interfaces.size());
CurContext->addDecl(CDecl);
CheckObjCDeclScope(CDecl);
- return DeclPtrTy::make(CDecl);
+ return CDecl;
}
@@ -1062,13 +1077,14 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
const ObjCMethodDecl *PrevMethod,
- bool matchBasedOnSizeAndAlignment) {
+ bool matchBasedOnSizeAndAlignment,
+ bool matchBasedOnStrictEqulity) {
QualType T1 = Context.getCanonicalType(Method->getResultType());
QualType T2 = Context.getCanonicalType(PrevMethod->getResultType());
if (T1 != T2) {
// The result types are different.
- if (!matchBasedOnSizeAndAlignment)
+ if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity)
return false;
// Incomplete types don't have a size and alignment.
if (T1->isIncompleteType() || T2->isIncompleteType())
@@ -1088,7 +1104,7 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
T2 = Context.getCanonicalType((*PrevI)->getType());
if (T1 != T2) {
// The result types are different.
- if (!matchBasedOnSizeAndAlignment)
+ if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity)
return false;
// Incomplete types don't have a size and alignment.
if (T1->isIncompleteType() || T2->isIncompleteType())
@@ -1101,47 +1117,34 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
return true;
}
-/// \brief Read the contents of the instance and factory method pools
-/// for a given selector from external storage.
+/// \brief Read the contents of the method pool for a given selector from
+/// external storage.
///
-/// This routine should only be called once, when neither the instance
-/// nor the factory method pool has an entry for this selector.
-Sema::MethodPool::iterator Sema::ReadMethodPool(Selector Sel,
- bool isInstance) {
+/// This routine should only be called once, when the method pool has no entry
+/// for this selector.
+Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) {
assert(ExternalSource && "We need an external AST source");
- assert(InstanceMethodPool.find(Sel) == InstanceMethodPool.end() &&
- "Selector data already loaded into the instance method pool");
- assert(FactoryMethodPool.find(Sel) == FactoryMethodPool.end() &&
- "Selector data already loaded into the factory method pool");
+ assert(MethodPool.find(Sel) == MethodPool.end() &&
+ "Selector data already loaded into the method pool");
// Read the method list from the external source.
- std::pair<ObjCMethodList, ObjCMethodList> Methods
- = ExternalSource->ReadMethodPool(Sel);
+ GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel);
- if (isInstance) {
- if (Methods.second.Method)
- FactoryMethodPool[Sel] = Methods.second;
- return InstanceMethodPool.insert(std::make_pair(Sel, Methods.first)).first;
- }
-
- if (Methods.first.Method)
- InstanceMethodPool[Sel] = Methods.first;
-
- return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first;
+ return MethodPool.insert(std::make_pair(Sel, Methods)).first;
}
-void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
- llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
- = InstanceMethodPool.find(Method->getSelector());
- if (Pos == InstanceMethodPool.end()) {
- if (ExternalSource && !FactoryMethodPool.count(Method->getSelector()))
- Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/true);
+void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
+ bool instance) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector());
+ if (Pos == MethodPool.end()) {
+ if (ExternalSource)
+ Pos = ReadMethodPool(Method->getSelector());
else
- Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(),
- ObjCMethodList())).first;
+ Pos = MethodPool.insert(std::make_pair(Method->getSelector(),
+ GlobalMethods())).first;
}
-
- ObjCMethodList &Entry = Pos->second;
+ Method->setDefined(impl);
+ ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;
if (Entry.Method == 0) {
// Haven't seen a method with this selector name yet - add it.
Entry.Method = Method;
@@ -1152,8 +1155,10 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
// We've seen a method with this name, see if we have already seen this type
// signature.
for (ObjCMethodList *List = &Entry; List; List = List->Next)
- if (MatchTwoMethodDeclarations(Method, List->Method))
+ if (MatchTwoMethodDeclarations(Method, List->Method)) {
+ List->Method->setDefined(impl);
return;
+ }
// We have a new signature for an existing method - add it.
// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
@@ -1161,102 +1166,65 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next);
}
-// FIXME: Finish implementing -Wno-strict-selector-match.
-ObjCMethodDecl *Sema::LookupInstanceMethodInGlobalPool(Selector Sel,
- SourceRange R,
- bool warn) {
- llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
- = InstanceMethodPool.find(Sel);
- if (Pos == InstanceMethodPool.end()) {
- if (ExternalSource && !FactoryMethodPool.count(Sel))
- Pos = ReadMethodPool(Sel, /*isInstance=*/true);
+ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass,
+ bool warn, bool instance) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+ if (Pos == MethodPool.end()) {
+ if (ExternalSource)
+ Pos = ReadMethodPool(Sel);
else
return 0;
}
- ObjCMethodList &MethList = Pos->second;
- bool issueWarning = false;
+ ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
- if (MethList.Method && MethList.Next) {
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
- // This checks if the methods differ by size & alignment.
- if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
- issueWarning = warn;
- }
- if (issueWarning && (MethList.Method && MethList.Next)) {
- Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
- Diag(MethList.Method->getLocStart(), diag::note_using)
- << MethList.Method->getSourceRange();
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
- Diag(Next->Method->getLocStart(), diag::note_also_found)
- << Next->Method->getSourceRange();
- }
- return MethList.Method;
-}
+ bool strictSelectorMatch = receiverIdOrClass && warn &&
+ (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl) !=
+ Diagnostic::Ignored);
+ if (warn && MethList.Method && MethList.Next) {
+ bool issueWarning = false;
+ if (strictSelectorMatch)
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
+ // This checks if the methods differ in type mismatch.
+ if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, false, true))
+ issueWarning = true;
+ }
-void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
- llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
- = FactoryMethodPool.find(Method->getSelector());
- if (Pos == FactoryMethodPool.end()) {
- if (ExternalSource && !InstanceMethodPool.count(Method->getSelector()))
- Pos = ReadMethodPool(Method->getSelector(), /*isInstance=*/false);
- else
- Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(),
- ObjCMethodList())).first;
- }
+ if (!issueWarning)
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) {
+ // This checks if the methods differ by size & alignment.
+ if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
+ issueWarning = true;
+ }
- ObjCMethodList &FirstMethod = Pos->second;
- if (!FirstMethod.Method) {
- // Haven't seen a method with this selector name yet - add it.
- FirstMethod.Method = Method;
- FirstMethod.Next = 0;
- } else {
- // We've seen a method with this name, now check the type signature(s).
- bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
-
- for (ObjCMethodList *Next = FirstMethod.Next; !match && Next;
- Next = Next->Next)
- match = MatchTwoMethodDeclarations(Method, Next->Method);
-
- if (!match) {
- // We have a new signature for an existing method - add it.
- // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
- ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
- ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next);
- FirstMethod.Next = OMI;
+ if (issueWarning) {
+ if (strictSelectorMatch)
+ Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
+ else
+ Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
+ Diag(MethList.Method->getLocStart(), diag::note_using)
+ << MethList.Method->getSourceRange();
+ for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
+ Diag(Next->Method->getLocStart(), diag::note_also_found)
+ << Next->Method->getSourceRange();
}
}
+ return MethList.Method;
}
-ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
- SourceRange R) {
- llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
- = FactoryMethodPool.find(Sel);
- if (Pos == FactoryMethodPool.end()) {
- if (ExternalSource && !InstanceMethodPool.count(Sel))
- Pos = ReadMethodPool(Sel, /*isInstance=*/false);
- else
- return 0;
- }
+ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
+ GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
+ if (Pos == MethodPool.end())
+ return 0;
- ObjCMethodList &MethList = Pos->second;
- bool issueWarning = false;
+ GlobalMethods &Methods = Pos->second;
- if (MethList.Method && MethList.Next) {
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
- // This checks if the methods differ by size & alignment.
- if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
- issueWarning = true;
- }
- if (issueWarning && (MethList.Method && MethList.Next)) {
- Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
- Diag(MethList.Method->getLocStart(), diag::note_using)
- << MethList.Method->getSourceRange();
- for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
- Diag(Next->Method->getLocStart(), diag::note_also_found)
- << Next->Method->getSourceRange();
- }
- return MethList.Method;
+ if (Methods.first.Method && Methods.first.Method->isDefined())
+ return Methods.first.Method;
+ if (Methods.second.Method && Methods.second.Method->isDefined())
+ return Methods.second.Method;
+ return 0;
}
/// CompareMethodParamsInBaseAndSuper - This routine compares methods with
@@ -1322,12 +1290,10 @@ void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
// Note: For class/category implemenations, allMethods/allProperties is
// always null.
void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
- DeclPtrTy classDecl,
- DeclPtrTy *allMethods, unsigned allNum,
- DeclPtrTy *allProperties, unsigned pNum,
+ Decl *ClassDecl,
+ Decl **allMethods, unsigned allNum,
+ Decl **allProperties, unsigned pNum,
DeclGroupPtrTy *allTUVars, unsigned tuvNum) {
- Decl *ClassDecl = classDecl.getAs<Decl>();
-
// FIXME: If we don't have a ClassDecl, we have an error. We should consider
// always passing in a decl. If the decl has an error, isInvalidDecl()
// should be true.
@@ -1356,7 +1322,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
for (unsigned i = 0; i < allNum; i++ ) {
ObjCMethodDecl *Method =
- cast_or_null<ObjCMethodDecl>(allMethods[i].getAs<Decl>());
+ cast_or_null<ObjCMethodDecl>(allMethods[i]);
if (!Method) continue; // Already issued a diagnostic.
if (Method->isInstanceMethod()) {
@@ -1403,14 +1369,14 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
// Compares properties declared in this class to those of its
// super class.
ComparePropertiesInBaseAndSuper(I);
- CompareProperties(I, DeclPtrTy::make(I));
+ CompareProperties(I, I);
} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
// Categories are used to extend the class by declaring new methods.
// By the same token, they are also used to add new properties. No
// need to compare the added property to those in the class.
// Compare protocol properties with those in category
- CompareProperties(C, DeclPtrTy::make(C));
+ CompareProperties(C, C);
if (C->IsClassExtension())
DiagnoseClassExtensionDupMethods(C, C->getClassInterface());
}
@@ -1432,6 +1398,7 @@ void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd,
DefaultSynthesizeProperties(S, IC, IDecl);
ImplMethodsVsClassMethods(S, IC, IDecl);
AtomicPropertySetterGetterRules(IC, IDecl);
+
if (LangOpts.ObjCNonFragileABI2)
while (IDecl->getSuperClass()) {
DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
@@ -1491,19 +1458,20 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
}
static inline
-bool containsInvalidMethodImplAttribute(const AttributeList *A) {
+bool containsInvalidMethodImplAttribute(const AttrVec &A) {
// The 'ibaction' attribute is allowed on method definitions because of
// how the IBAction macro is used on both method declarations and definitions.
// If the method definitions contains any other attributes, return true.
- while (A && A->getKind() == AttributeList::AT_IBAction)
- A = A->getNext();
- return A != NULL;
+ for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i)
+ if ((*i)->getKind() != attr::IBAction)
+ return true;
+ return false;
}
-Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
+Decl *Sema::ActOnMethodDeclaration(
SourceLocation MethodLoc, SourceLocation EndLoc,
- tok::TokenKind MethodType, DeclPtrTy classDecl,
- ObjCDeclSpec &ReturnQT, TypeTy *ReturnType,
+ tok::TokenKind MethodType, Decl *ClassDecl,
+ ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
Selector Sel,
// optional arguments. The number of types/arguments is obtained
// from the Sel.getNumArgs().
@@ -1511,13 +1479,11 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args
AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind,
bool isVariadic) {
- Decl *ClassDecl = classDecl.getAs<Decl>();
-
// Make sure we can establish a context for the method.
if (!ClassDecl) {
Diag(MethodLoc, diag::error_missing_method_context);
- getLabelMap().clear();
- return DeclPtrTy();
+ getCurFunction()->LabelMap.clear();
+ return 0;
}
QualType resultDeclType;
@@ -1530,7 +1496,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
if (resultDeclType->isObjCObjectType()) {
Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value)
<< 0 << resultDeclType;
- return DeclPtrTy();
+ return 0;
}
} else // get the type for "id".
resultDeclType = Context.getObjCIdType();
@@ -1540,7 +1506,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
ResultTInfo,
cast<DeclContext>(ClassDecl),
MethodType == tok::minus, isVariadic,
- false,
+ false, false,
MethodDeclKind == tok::objc_optional ?
ObjCMethodDecl::Optional :
ObjCMethodDecl::Required);
@@ -1563,7 +1529,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
ParmVarDecl* Param
= ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc,
ArgInfo[i].Name, ArgType, DI,
- VarDecl::None, VarDecl::None, 0);
+ SC_None, SC_None, 0);
if (ArgType->isObjCObjectType()) {
Diag(ArgInfo[i].NameLoc,
@@ -1582,7 +1548,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
}
for (unsigned i = 0, e = CNumArgs; i != e; ++i) {
- ParmVarDecl *Param = CParamInfo[i].Param.getAs<ParmVarDecl>();
+ ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);
QualType ArgType = Param->getType();
if (ArgType.isNull())
ArgType = Context.getObjCIdType();
@@ -1596,7 +1562,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
Param->setInvalidDecl();
}
Param->setDeclContext(ObjCMethod);
- IdResolver.RemoveDecl(Param);
+ if (Param->getDeclName())
+ IdResolver.RemoveDecl(Param);
Params.push_back(Param);
}
@@ -1626,7 +1593,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
}
InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel,
MethodType == tok::minus);
- if (containsInvalidMethodImplAttribute(AttrList))
+ if (ObjCMethod->hasAttrs() &&
+ containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
Diag(EndLoc, diag::warn_attribute_method_def);
} else if (ObjCCategoryImplDecl *CatImpDecl =
dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
@@ -1637,7 +1605,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
PrevMethod = CatImpDecl->getClassMethod(Sel);
CatImpDecl->addClassMethod(ObjCMethod);
}
- if (containsInvalidMethodImplAttribute(AttrList))
+ if (ObjCMethod->hasAttrs() &&
+ containsInvalidMethodImplAttribute(ObjCMethod->getAttrs()))
Diag(EndLoc, diag::warn_attribute_method_def);
}
if (PrevMethod) {
@@ -1649,14 +1618,16 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration(
// If the interface declared this method, and it was deprecated there,
// mark it deprecated here.
- if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>())
- ObjCMethod->addAttr(::new (Context) DeprecatedAttr());
+ if (InterfaceMD)
+ if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>())
+ ObjCMethod->addAttr(::new (Context) DeprecatedAttr(DA->getLocation(),
+ Context));
- return DeclPtrTy::make(ObjCMethod);
+ return ObjCMethod;
}
bool Sema::CheckObjCDeclScope(Decl *D) {
- if (isa<TranslationUnitDecl>(CurContext->getLookupContext()))
+ if (isa<TranslationUnitDecl>(CurContext->getRedeclContext()))
return false;
Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
@@ -1667,9 +1638,9 @@ bool Sema::CheckObjCDeclScope(Decl *D) {
/// Called whenever @defs(ClassName) is encountered in the source. Inserts the
/// instance variables of ClassName into Decls.
-void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
+void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
- llvm::SmallVectorImpl<DeclPtrTy> &Decls) {
+ llvm::SmallVectorImpl<Decl*> &Decls) {
// Check that ClassName is a valid class
ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart);
if (!Class) {
@@ -1682,25 +1653,25 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart,
}
// Collect the instance variables
- llvm::SmallVector<FieldDecl*, 32> RecFields;
- Context.CollectObjCIvars(Class, RecFields);
+ llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
+ Context.DeepCollectObjCIvars(Class, true, Ivars);
// For each ivar, create a fresh ObjCAtDefsFieldDecl.
- for (unsigned i = 0; i < RecFields.size(); i++) {
- FieldDecl* ID = RecFields[i];
- RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>());
+ for (unsigned i = 0; i < Ivars.size(); i++) {
+ FieldDecl* ID = cast<FieldDecl>(Ivars[i]);
+ RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(),
ID->getIdentifier(), ID->getType(),
ID->getBitWidth());
- Decls.push_back(Sema::DeclPtrTy::make(FD));
+ Decls.push_back(FD);
}
// Introduce all of these fields into the appropriate scope.
- for (llvm::SmallVectorImpl<DeclPtrTy>::iterator D = Decls.begin();
+ for (llvm::SmallVectorImpl<Decl*>::iterator D = Decls.begin();
D != Decls.end(); ++D) {
- FieldDecl *FD = cast<FieldDecl>(D->getAs<Decl>());
+ FieldDecl *FD = cast<FieldDecl>(*D);
if (getLangOptions().CPlusPlus)
PushOnScopeChains(cast<FieldDecl>(FD), S);
- else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>()))
+ else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))
Record->addDecl(FD);
}
}
@@ -1735,7 +1706,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
}
VarDecl *New = VarDecl::Create(Context, CurContext, NameLoc, Name, T, TInfo,
- VarDecl::None, VarDecl::None);
+ SC_None, SC_None);
New->setExceptionVariable(true);
if (Invalid)
@@ -1743,7 +1714,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo,
return New;
}
-Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
+Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
// We allow the "register" storage class on exception variables because
@@ -1788,7 +1759,7 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
}
// Add the parameter declaration into this scope.
- S->AddDecl(DeclPtrTy::make(New));
+ S->AddDecl(New);
if (D.getIdentifier())
IdResolver.AddDecl(New);
@@ -1796,43 +1767,18 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
if (New->hasAttr<BlocksAttr>())
Diag(New->getLocation(), diag::err_block_on_nonlocal);
- return DeclPtrTy::make(New);
+ return New;
}
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
/// initialization.
-void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI,
+void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) {
- for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
- E = OI->ivar_end(); I != E; ++I) {
- ObjCIvarDecl *Iv = (*I);
+ for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;
+ Iv= Iv->getNextIvar()) {
QualType QT = Context.getBaseElementType(Iv->getType());
if (QT->isRecordType())
- Ivars.push_back(*I);
- }
-
- // Find ivars to construct/destruct in class extension.
- for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl;
- CDecl = CDecl->getNextClassExtension()) {
- for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
- E = CDecl->ivar_end(); I != E; ++I) {
- ObjCIvarDecl *Iv = (*I);
- QualType QT = Context.getBaseElementType(Iv->getType());
- if (QT->isRecordType())
- Ivars.push_back(*I);
- }
- }
-
- // Also add any ivar defined in this class's implementation. This
- // includes synthesized ivars.
- if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) {
- for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
- E = ImplDecl->ivar_end(); I != E; ++I) {
- ObjCIvarDecl *Iv = (*I);
- QualType QT = Context.getBaseElementType(Iv->getType());
- if (QT->isRecordType())
- Ivars.push_back(*I);
- }
+ Ivars.push_back(Iv);
}
}
@@ -1849,3 +1795,15 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
}
}
+void Sema::DiagnoseUseOfUnimplementedSelectors() {
+ if (ReferencedSelectors.empty())
+ return;
+ for (llvm::DenseMap<Selector, SourceLocation>::iterator S =
+ ReferencedSelectors.begin(),
+ E = ReferencedSelectors.end(); S != E; ++S) {
+ Selector Sel = (*S).first;
+ if (!LookupImplementedMethodInGlobalPool(Sel))
+ Diag((*S).second, diag::warn_unimplemented_selector) << Sel;
+ }
+ return;
+}
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 34a479ae2a08..c902e7787096 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
@@ -261,6 +261,14 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec();
bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec();
+ if (getLangOptions().Microsoft) {
+ // Treat throw(whatever) as throw(...) to be compatible with MS headers.
+ if (New->hasExceptionSpec() && New->getNumExceptions() > 0)
+ NewAny = true;
+ if (Old->hasExceptionSpec() && Old->getNumExceptions() > 0)
+ OldAny = true;
+ }
+
if (OldAny && NewAny)
return false;
if (OldAny || NewAny) {
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5f46a977b12c..80b465230e14 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
-#include "Lookup.h"
-#include "AnalysisBasedWarnings.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -29,11 +29,14 @@
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Designator.h"
-#include "clang/Parse/Scope.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/Template.h"
using namespace clang;
+using namespace sema;
/// \brief Determine whether the use of this declaration is valid, and
@@ -59,7 +62,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is unavailable
if (D->getAttr<UnavailableAttr>()) {
- Diag(Loc, diag::warn_unavailable) << D->getDeclName();
+ Diag(Loc, diag::err_unavailable) << D->getDeclName();
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
}
@@ -192,7 +195,7 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
if (Ty->isFunctionType())
ImpCastExprToType(E, Context.getPointerType(Ty),
- CastExpr::CK_FunctionToPointerDecay);
+ CK_FunctionToPointerDecay);
else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
@@ -208,7 +211,7 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) {
if (getLangOptions().C99 || getLangOptions().CPlusPlus ||
E->isLvalue(Context) == Expr::LV_Valid)
ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
- CastExpr::CK_ArrayToPointerDecay);
+ CK_ArrayToPointerDecay);
}
}
@@ -229,7 +232,7 @@ void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) {
// If the lvalue has qualified type, the value has the unqualified
// version of the type of the lvalue; otherwise, the value has the
// type of the lvalue.
- ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp);
+ ImpCastExprToType(E, Ty.getUnqualifiedType(), CK_NoOp);
}
}
@@ -258,12 +261,12 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) {
// other types are unchanged by the integer promotions.
QualType PTy = Context.isPromotableBitField(Expr);
if (!PTy.isNull()) {
- ImpCastExprToType(Expr, PTy, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(Expr, PTy, CK_IntegralCast);
return Expr;
}
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
- ImpCastExprToType(Expr, PT, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(Expr, PT, CK_IntegralCast);
return Expr;
}
@@ -281,7 +284,7 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) {
// If this is a 'float' (CVR qualified or typedef) promote to double.
if (Ty->isSpecificBuiltinType(BuiltinType::Float))
return ImpCastExprToType(Expr, Context.DoubleTy,
- CastExpr::CK_FloatingCast);
+ CK_FloatingCast);
UsualUnaryConversions(Expr);
}
@@ -355,8 +358,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs);
if (!isCompAssign)
- ImpCastExprToType(lhsExpr, destType, CastExpr::CK_Unknown);
- ImpCastExprToType(rhsExpr, destType, CastExpr::CK_Unknown);
+ ImpCastExprToType(lhsExpr, destType, CK_Unknown);
+ ImpCastExprToType(rhsExpr, destType, CK_Unknown);
return destType;
}
@@ -371,7 +374,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,
/// multiple tokens. However, the common case is that StringToks points to one
/// string.
///
-Action::OwningExprResult
+ExprResult
Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
assert(NumStringToks && "Must have at least one string!");
@@ -459,13 +462,20 @@ static bool ShouldSnapshotBlockValueReference(Sema &S, BlockScopeInfo *CurBlock,
}
+ExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
+ const CXXScopeSpec *SS) {
+ DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
+ return BuildDeclRefExpr(D, Ty, NameInfo, SS);
+}
/// BuildDeclRefExpr - Build a DeclRefExpr.
-Sema::OwningExprResult
-Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
+ExprResult
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS) {
if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
- Diag(Loc,
+ Diag(NameInfo.getLoc(),
diag::err_auto_variable_cannot_appear_in_own_initializer)
<< D->getDeclName();
return ExprError();
@@ -479,7 +489,8 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
} else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) {
if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) {
- Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function)
+ Diag(NameInfo.getLoc(),
+ diag::err_reference_to_local_var_in_enclosing_function)
<< D->getIdentifier() << FD->getDeclName();
Diag(D->getLocation(), diag::note_local_variable_declared_here)
<< D->getIdentifier();
@@ -489,12 +500,12 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
}
}
- MarkDeclarationReferenced(Loc, D);
+ MarkDeclarationReferenced(NameInfo.getLoc(), D);
return Owned(DeclRefExpr::Create(Context,
SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
SS? SS->getRange() : SourceRange(),
- D, Loc, Ty));
+ D, NameInfo, Ty));
}
/// \brief Given a field that represents a member of an anonymous
@@ -535,7 +546,7 @@ VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
return BaseObject;
}
-Sema::OwningExprResult
+ExprResult
Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
FieldDecl *Field,
Expr *BaseObjectExpr,
@@ -553,7 +564,6 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
if (BaseObject) {
// BaseObject is an anonymous struct/union variable (and is,
// therefore, not part of another non-anonymous record).
- if (BaseObjectExpr) BaseObjectExpr->Destroy(Context);
MarkDeclarationReferenced(Loc, BaseObject);
BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
SourceLocation());
@@ -640,7 +650,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
return Owned(Result);
}
-/// Decomposes the given name into a DeclarationName, its location, and
+/// Decomposes the given name into a DeclarationNameInfo, its location, and
/// possibly a list of template arguments.
///
/// If this produces template arguments, it is permitted to call
@@ -652,8 +662,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
static void DecomposeUnqualifiedId(Sema &SemaRef,
const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
- DeclarationName &Name,
- SourceLocation &NameLoc,
+ DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *&TemplateArgs) {
if (Id.getKind() == UnqualifiedId::IK_TemplateId) {
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
@@ -665,15 +674,12 @@ static void DecomposeUnqualifiedId(Sema &SemaRef,
SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer);
TemplateArgsPtr.release();
- TemplateName TName =
- Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>();
-
- Name = SemaRef.Context.getNameForTemplate(TName);
- NameLoc = Id.TemplateId->TemplateNameLoc;
+ TemplateName TName = Id.TemplateId->Template.get();
+ SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc;
+ NameInfo = SemaRef.Context.getNameForTemplate(TName, TNameLoc);
TemplateArgs = &Buffer;
} else {
- Name = SemaRef.GetNameFromUnqualifiedId(Id);
- NameLoc = Id.StartLocation;
+ NameInfo = SemaRef.GetNameFromUnqualifiedId(Id);
TemplateArgs = 0;
}
}
@@ -700,23 +706,6 @@ static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
return true;
}
-/// Determines whether we can lookup this id-expression now or whether
-/// we have to wait until template instantiation is complete.
-static bool IsDependentIdExpression(Sema &SemaRef, const CXXScopeSpec &SS) {
- DeclContext *DC = SemaRef.computeDeclContext(SS, false);
-
- // If the qualifier scope isn't computable, it's definitely dependent.
- if (!DC) return true;
-
- // If the qualifier scope doesn't name a record, we can always look into it.
- if (!isa<CXXRecordDecl>(DC)) return false;
-
- // We can't look into record types unless they're fully-formed.
- if (!IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC))) return true;
-
- return false;
-}
-
/// Determines if the given class is provably not derived from all of
/// the prospective base classes.
static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
@@ -905,25 +894,30 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
if (isInstance) {
- Diag(R.getNameLoc(), diagnostic) << Name
- << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
-
UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(
CallsUndergoingInstantiation.back()->getCallee());
- CXXMethodDecl *DepMethod = cast<CXXMethodDecl>(
+ CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>(
CurMethod->getInstantiatedFromMemberFunction());
- QualType DepThisType = DepMethod->getThisType(Context);
- CXXThisExpr *DepThis = new (Context) CXXThisExpr(R.getNameLoc(),
- DepThisType, false);
- TemplateArgumentListInfo TList;
- if (ULE->hasExplicitTemplateArgs())
- ULE->copyTemplateArgumentsInto(TList);
- CXXDependentScopeMemberExpr *DepExpr =
- CXXDependentScopeMemberExpr::Create(
- Context, DepThis, DepThisType, true, SourceLocation(),
- ULE->getQualifier(), ULE->getQualifierRange(), NULL, Name,
- R.getNameLoc(), &TList);
- CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+ if (DepMethod) {
+ Diag(R.getNameLoc(), diagnostic) << Name
+ << FixItHint::CreateInsertion(R.getNameLoc(), "this->");
+ QualType DepThisType = DepMethod->getThisType(Context);
+ CXXThisExpr *DepThis = new (Context) CXXThisExpr(
+ R.getNameLoc(), DepThisType, false);
+ TemplateArgumentListInfo TList;
+ if (ULE->hasExplicitTemplateArgs())
+ ULE->copyTemplateArgumentsInto(TList);
+ CXXDependentScopeMemberExpr *DepExpr =
+ CXXDependentScopeMemberExpr::Create(
+ Context, DepThis, DepThisType, true, SourceLocation(),
+ ULE->getQualifier(), ULE->getQualifierRange(), NULL,
+ R.getLookupNameInfo(), &TList);
+ CallsUndergoingInstantiation.back()->setCallee(DepExpr);
+ } else {
+ // FIXME: we should be able to handle this case too. It is correct
+ // to add this-> here. This is a workaround for PR7947.
+ Diag(R.getNameLoc(), diagnostic) << Name;
+ }
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
}
@@ -935,6 +929,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// Tell the callee to try to recover.
return false;
}
+
+ R.clear();
}
}
@@ -1005,11 +1001,74 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
return true;
}
-Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
- CXXScopeSpec &SS,
- UnqualifiedId &Id,
- bool HasTrailingLParen,
- bool isAddressOfOperand) {
+static ObjCPropertyDecl *OkToSynthesizeProvisionalIvar(Sema &SemaRef,
+ IdentifierInfo *II,
+ SourceLocation NameLoc) {
+ ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl();
+ ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
+ if (!IDecl)
+ return 0;
+ ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
+ if (!ClassImpDecl)
+ return 0;
+ ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II);
+ if (!property)
+ return 0;
+ if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II))
+ if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
+ return 0;
+ return property;
+}
+
+static ObjCIvarDecl *SynthesizeProvisionalIvar(Sema &SemaRef,
+ LookupResult &Lookup,
+ IdentifierInfo *II,
+ SourceLocation NameLoc) {
+ ObjCMethodDecl *CurMeth = SemaRef.getCurMethodDecl();
+ bool LookForIvars;
+ if (Lookup.empty())
+ LookForIvars = true;
+ else if (CurMeth->isClassMethod())
+ LookForIvars = false;
+ else
+ LookForIvars = (Lookup.isSingleResult() &&
+ Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
+ if (!LookForIvars)
+ return 0;
+
+ ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface();
+ if (!IDecl)
+ return 0;
+ ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation();
+ if (!ClassImpDecl)
+ return 0;
+ bool DynamicImplSeen = false;
+ ObjCPropertyDecl *property = SemaRef.LookupPropertyDecl(IDecl, II);
+ if (!property)
+ return 0;
+ if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II))
+ DynamicImplSeen =
+ (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic);
+ if (!DynamicImplSeen) {
+ QualType PropType = SemaRef.Context.getCanonicalType(property->getType());
+ ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(SemaRef.Context, ClassImpDecl,
+ NameLoc,
+ II, PropType, /*Dinfo=*/0,
+ ObjCIvarDecl::Protected,
+ (Expr *)0, true);
+ ClassImpDecl->addDecl(Ivar);
+ IDecl->makeDeclVisibleInContext(Ivar, false);
+ property->setPropertyIvarDecl(Ivar);
+ return Ivar;
+ }
+ return 0;
+}
+
+ExprResult Sema::ActOnIdExpression(Scope *S,
+ CXXScopeSpec &SS,
+ UnqualifiedId &Id,
+ bool HasTrailingLParen,
+ bool isAddressOfOperand) {
assert(!(isAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
@@ -1019,13 +1078,13 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
TemplateArgumentListInfo TemplateArgsBuffer;
// Decompose the UnqualifiedId into the following data.
- DeclarationName Name;
- SourceLocation NameLoc;
+ DeclarationNameInfo NameInfo;
const TemplateArgumentListInfo *TemplateArgs;
- DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
- Name, NameLoc, TemplateArgs);
+ DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, NameInfo, TemplateArgs);
+ DeclarationName Name = NameInfo.getName();
IdentifierInfo *II = Name.getAsIdentifierInfo();
+ SourceLocation NameLoc = NameInfo.getLoc();
// C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
@@ -1038,16 +1097,30 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// names a dependent type.
// Determine whether this is a member of an unknown specialization;
// we need to handle these differently.
- if ((Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
- Name.getCXXNameType()->isDependentType()) ||
- (SS.isSet() && IsDependentIdExpression(*this, SS))) {
- return ActOnDependentIdExpression(SS, Name, NameLoc,
- isAddressOfOperand,
- TemplateArgs);
+ bool DependentID = false;
+ if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
+ Name.getCXXNameType()->isDependentType()) {
+ DependentID = true;
+ } else if (SS.isSet()) {
+ DeclContext *DC = computeDeclContext(SS, false);
+ if (DC) {
+ if (RequireCompleteDeclContext(SS, DC))
+ return ExprError();
+ // FIXME: We should be checking whether DC is the current instantiation.
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
+ DependentID = !IsFullyFormedScope(*this, RD);
+ } else {
+ DependentID = true;
+ }
}
+ if (DependentID) {
+ return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
+ TemplateArgs);
+ }
+ bool IvarLookupFollowUp = false;
// Perform the required lookup.
- LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
if (TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
@@ -1058,18 +1131,26 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
MemberOfUnknownSpecialization);
} else {
- bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
+ IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
// If this reference is in an Objective-C method, then we need to do
// some special Objective-C lookup, too.
if (IvarLookupFollowUp) {
- OwningExprResult E(LookupInObjCMethod(R, S, II, true));
+ ExprResult E(LookupInObjCMethod(R, S, II, true));
if (E.isInvalid())
return ExprError();
Expr *Ex = E.takeAs<Expr>();
if (Ex) return Owned(Ex);
+ // Synthesize ivars lazily
+ if (getLangOptions().ObjCNonFragileABI2) {
+ if (SynthesizeProvisionalIvar(*this, R, II, NameLoc))
+ return ActOnIdExpression(S, SS, Id, HasTrailingLParen,
+ isAddressOfOperand);
+ }
+ // for further use, this must be set to false if in class method.
+ IvarLookupFollowUp = getCurMethodDecl()->isInstanceMethod();
}
}
@@ -1102,7 +1183,7 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// reference the ivar.
if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
R.clear();
- OwningExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
+ ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
assert(E.isInvalid() || E.get());
return move(E);
}
@@ -1113,23 +1194,15 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
assert(!R.empty() || ADL);
if (VarDecl *Var = R.getAsSingle<VarDecl>()) {
- // Warn about constructs like:
- // if (void *X = foo()) { ... } else { X }.
- // In the else block, the pointer is always false.
- if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) {
- Scope *CheckS = S;
- while (CheckS && CheckS->getControlParent()) {
- if ((CheckS->getFlags() & Scope::ElseScope) &&
- CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) {
- ExprError(Diag(NameLoc, diag::warn_value_always_zero)
- << Var->getDeclName()
- << (Var->getType()->isPointerType() ? 2 :
- Var->getType()->isBooleanType() ? 1 : 0));
- break;
- }
-
- // Move to the parent of this scope.
- CheckS = CheckS->getParent();
+ if (getLangOptions().ObjCNonFragileABI && IvarLookupFollowUp &&
+ !getLangOptions().ObjCNonFragileABI2 &&
+ Var->isFileVarDecl()) {
+ ObjCPropertyDecl *Property =
+ OkToSynthesizeProvisionalIvar(*this, II, NameLoc);
+ if (Property) {
+ Diag(NameLoc, diag::warn_ivar_variable_conflict) << Var->getDeclName();
+ Diag(Property->getLocation(), diag::note_property_declare);
+ Diag(Var->getLocation(), diag::note_global_declared_at);
}
}
} else if (FunctionDecl *Func = R.getAsSingle<FunctionDecl>()) {
@@ -1152,15 +1225,43 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
}
// Check whether this might be a C++ implicit instance member access.
- // C++ [expr.prim.general]p6:
- // Within the definition of a non-static member function, an
- // identifier that names a non-static member is transformed to a
- // class member access expression.
- // But note that &SomeClass::foo is grammatically distinct, even
- // though we don't parse it that way.
+ // C++ [class.mfct.non-static]p3:
+ // When an id-expression that is not part of a class member access
+ // syntax and not used to form a pointer to member is used in the
+ // body of a non-static member function of class X, if name lookup
+ // resolves the name in the id-expression to a non-static non-type
+ // member of some class C, the id-expression is transformed into a
+ // class member access expression using (*this) as the
+ // postfix-expression to the left of the . operator.
+ //
+ // But we don't actually need to do this for '&' operands if R
+ // resolved to a function or overloaded function set, because the
+ // expression is ill-formed if it actually works out to be a
+ // non-static member function:
+ //
+ // C++ [expr.ref]p4:
+ // Otherwise, if E1.E2 refers to a non-static member function. . .
+ // [t]he expression can be used only as the left-hand operand of a
+ // member function call.
+ //
+ // There are other safeguards against such uses, but it's important
+ // to get this right here so that we don't end up making a
+ // spuriously dependent expression if we're inside a dependent
+ // instance method.
if (!R.empty() && (*R.begin())->isCXXClassMember()) {
- bool isAbstractMemberPointer = (isAddressOfOperand && !SS.isEmpty());
- if (!isAbstractMemberPointer)
+ bool MightBeImplicitMember;
+ if (!isAddressOfOperand)
+ MightBeImplicitMember = true;
+ else if (!SS.isEmpty())
+ MightBeImplicitMember = false;
+ else if (R.isOverloadedResult())
+ MightBeImplicitMember = false;
+ else if (R.isUnresolvableResult())
+ MightBeImplicitMember = true;
+ else
+ MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl());
+
+ if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs);
}
@@ -1171,7 +1272,7 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
}
/// Builds an expression which might be an implicit member expression.
-Sema::OwningExprResult
+ExprResult
Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
@@ -1210,25 +1311,25 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
/// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along
/// this path.
-Sema::OwningExprResult
+ExprResult
Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc) {
+ const DeclarationNameInfo &NameInfo) {
DeclContext *DC;
if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext())
- return BuildDependentDeclRefExpr(SS, Name, NameLoc, 0);
+ return BuildDependentDeclRefExpr(SS, NameInfo, 0);
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
- LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
LookupQualifiedName(R, DC);
if (R.isAmbiguous())
return ExprError();
if (R.empty()) {
- Diag(NameLoc, diag::err_no_member) << Name << DC << SS.getRange();
+ Diag(NameInfo.getLoc(), diag::err_no_member)
+ << NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
@@ -1243,7 +1344,7 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
/// actually quite a lot of extra work involved.
///
/// Returns a null sentinel to indicate trivial success.
-Sema::OwningExprResult
+ExprResult
Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
@@ -1298,7 +1399,7 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
UnqualifiedId SelfName;
SelfName.setIdentifier(&II, SourceLocation());
CXXScopeSpec SelfScopeSpec;
- OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
+ ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec,
SelfName, false, false);
MarkDeclarationReferenced(Loc, IV);
return Owned(new (Context)
@@ -1403,9 +1504,8 @@ Sema::PerformObjectMemberConversion(Expr *&From,
SourceRange FromRange = From->getSourceRange();
SourceLocation FromLoc = FromRange.getBegin();
- bool isLvalue
- = (From->isLvalue(Context) == Expr::LV_Valid) && !PointerConversions;
-
+ ExprValueKind VK = CastCategory(From);
+
// C++ [class.member.lookup]p8:
// [...] Ambiguities can often be resolved by qualifying a name with its
// class name.
@@ -1435,15 +1535,15 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// type of the object type, in which case we just ignore it.
// Otherwise build the appropriate casts.
if (IsDerivedFrom(FromRecordType, QRecordType)) {
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
FromLoc, FromRange, &BasePath))
return true;
if (PointerConversions)
QType = Context.getPointerType(QType);
- ImpCastExprToType(From, QType, CastExpr::CK_UncheckedDerivedToBase,
- isLvalue, BasePath);
+ ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
FromType = QType;
FromRecordType = QRecordType;
@@ -1471,7 +1571,7 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// conversion is non-trivial.
if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
assert(IsDerivedFrom(FromRecordType, URecordType));
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
FromLoc, FromRange, &BasePath))
return true;
@@ -1479,8 +1579,8 @@ Sema::PerformObjectMemberConversion(Expr *&From,
QualType UType = URecordType;
if (PointerConversions)
UType = Context.getPointerType(UType);
- ImpCastExprToType(From, UType, CastExpr::CK_UncheckedDerivedToBase,
- isLvalue, BasePath);
+ ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
FromType = UType;
FromRecordType = URecordType;
}
@@ -1490,14 +1590,14 @@ Sema::PerformObjectMemberConversion(Expr *&From,
IgnoreAccess = true;
}
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
FromLoc, FromRange, &BasePath,
IgnoreAccess))
return true;
- ImpCastExprToType(From, DestType, CastExpr::CK_UncheckedDerivedToBase,
- isLvalue, BasePath);
+ ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
+ VK, &BasePath);
return false;
}
@@ -1505,7 +1605,8 @@ Sema::PerformObjectMemberConversion(Expr *&From,
static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
const CXXScopeSpec &SS, ValueDecl *Member,
DeclAccessPair FoundDecl,
- SourceLocation Loc, QualType Ty,
+ const DeclarationNameInfo &MemberNameInfo,
+ QualType Ty,
const TemplateArgumentListInfo *TemplateArgs = 0) {
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
@@ -1515,14 +1616,15 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
}
return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
- Member, FoundDecl, Loc, TemplateArgs, Ty);
+ Member, FoundDecl, MemberNameInfo,
+ TemplateArgs, Ty);
}
/// Builds an implicit member access expression. The current context
/// is known to be an instance method, and the given unqualified lookup
/// set is known to contain only instance members, at least one of which
/// is from an appropriate type.
-Sema::OwningExprResult
+ExprResult
Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
@@ -1551,7 +1653,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
This = new (Context) CXXThisExpr(Loc, ThisType, /*isImplicit=*/true);
}
- return BuildMemberReferenceExpr(ExprArg(*this, This), ThisType,
+ return BuildMemberReferenceExpr(This, ThisType,
/*OpLoc*/ SourceLocation(),
/*IsArrow*/ true,
SS,
@@ -1638,14 +1740,15 @@ static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
return false;
}
-Sema::OwningExprResult
+ExprResult
Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
LookupResult &R,
bool NeedsADL) {
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>())
- return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl());
+ return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(),
+ R.getFoundDecl());
// We only need to check the declaration if there's exactly one
// result, because in the overloaded case the results can only be
@@ -1664,8 +1767,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
(NestedNameSpecifier*) SS.getScopeRep(),
- SS.getRange(),
- R.getLookupName(), R.getNameLoc(),
+ SS.getRange(), R.getLookupNameInfo(),
NeedsADL, R.isOverloadedResult(),
R.begin(), R.end());
@@ -1674,13 +1776,15 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
/// \brief Complete semantic analysis for a reference to the given declaration.
-Sema::OwningExprResult
+ExprResult
Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- SourceLocation Loc, NamedDecl *D) {
+ const DeclarationNameInfo &NameInfo,
+ NamedDecl *D) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
+ SourceLocation Loc = NameInfo.getLoc();
if (CheckDeclInExpr(*this, Loc, D))
return ExprError();
@@ -1755,13 +1859,13 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
DeclRefExpr(const_cast<ValueDecl*>(BDRE->getDecl()), T,
SourceLocation());
- OwningExprResult Res = PerformCopyInitialization(
+ ExprResult Res = PerformCopyInitialization(
InitializedEntity::InitializeBlock(VD->getLocation(),
T, false),
SourceLocation(),
Owned(E));
if (!Res.isInvalid()) {
- Res = MaybeCreateCXXExprWithTemporaries(move(Res));
+ Res = MaybeCreateCXXExprWithTemporaries(Res.get());
Expr *Init = Res.takeAs<Expr>();
BDRE->setCopyConstructorExpr(Init);
}
@@ -1772,10 +1876,11 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
- return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc, &SS);
+ return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
+ NameInfo, &SS);
}
-Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
+ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
PredefinedExpr::IdentType IT;
@@ -1790,6 +1895,8 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
// string.
Decl *currentDecl = getCurFunctionOrMethodDecl();
+ if (!currentDecl && getCurBlock())
+ currentDecl = getCurBlock()->TheDecl;
if (!currentDecl) {
Diag(Loc, diag::ext_predef_outside_function);
currentDecl = Context.getTranslationUnitDecl();
@@ -1808,7 +1915,7 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT));
}
-Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
+ExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
llvm::SmallString<16> CharBuffer;
bool Invalid = false;
llvm::StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid);
@@ -1835,13 +1942,13 @@ Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) {
Ty, Tok.getLocation()));
}
-Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) {
+ExprResult Sema::ActOnNumericConstant(const Token &Tok) {
// Fast path for a single digit (which is quite common). A single digit
// cannot have a trigraph, escaped newline, radix prefix, or type suffix.
if (Tok.getLength() == 1) {
const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
unsigned IntSize = Context.Target.getIntWidth();
- return Owned(new (Context) IntegerLiteral(llvm::APInt(IntSize, Val-'0'),
+ return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'),
Context.IntTy, Tok.getLocation()));
}
@@ -1899,7 +2006,7 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) {
}
bool isExact = (result == APFloat::opOK);
- Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation());
+ Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation());
} else if (!Literal.isIntegerLiteral()) {
return ExprError();
@@ -1986,7 +2093,7 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) {
if (ResultVal.getBitWidth() != Width)
ResultVal.trunc(Width);
}
- Res = new (Context) IntegerLiteral(ResultVal, Ty, Tok.getLocation());
+ Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
}
// If this is an imaginary literal, create the ImaginaryLiteral wrapper.
@@ -1997,9 +2104,8 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) {
return Owned(Res);
}
-Action::OwningExprResult Sema::ActOnParenExpr(SourceLocation L,
- SourceLocation R, ExprArg Val) {
- Expr *E = Val.takeAs<Expr>();
+ExprResult Sema::ActOnParenExpr(SourceLocation L,
+ SourceLocation R, Expr *E) {
assert((E != 0) && "ActOnParenExpr() missing expr");
return Owned(new (Context) ParenExpr(L, R, E));
}
@@ -2083,7 +2189,7 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc,
}
/// \brief Build a sizeof or alignof expression given a type operand.
-Action::OwningExprResult
+ExprResult
Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
@@ -2104,7 +2210,7 @@ Sema::CreateSizeOfAlignOfExpr(TypeSourceInfo *TInfo,
/// \brief Build a sizeof or alignof expression given an expression
/// operand.
-Action::OwningExprResult
+ExprResult
Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
// Verify that the operand is valid.
@@ -2132,7 +2238,7 @@ Sema::CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc,
/// ActOnSizeOfAlignOfExpr - Handle @c sizeof(type) and @c sizeof @c expr and
/// the same for @c alignof and @c __alignof
/// Note that the ArgRange is invalid if isType is false.
-Action::OwningExprResult
+ExprResult
Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
// If error parsing type, ignore.
@@ -2140,17 +2246,14 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
if (isType) {
TypeSourceInfo *TInfo;
- (void) GetTypeFromParser(TyOrEx, &TInfo);
+ (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
return CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeof, ArgRange);
}
Expr *ArgEx = (Expr *)TyOrEx;
- Action::OwningExprResult Result
+ ExprResult Result
= CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange());
- if (Result.isInvalid())
- DeleteExpr(ArgEx);
-
return move(Result);
}
@@ -2174,32 +2277,31 @@ QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
-Action::OwningExprResult
+ExprResult
Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind, ExprArg Input) {
- UnaryOperator::Opcode Opc;
+ tok::TokenKind Kind, Expr *Input) {
+ UnaryOperatorKind Opc;
switch (Kind) {
default: assert(0 && "Unknown unary op!");
- case tok::plusplus: Opc = UnaryOperator::PostInc; break;
- case tok::minusminus: Opc = UnaryOperator::PostDec; break;
+ case tok::plusplus: Opc = UO_PostInc; break;
+ case tok::minusminus: Opc = UO_PostDec; break;
}
- return BuildUnaryOp(S, OpLoc, Opc, move(Input));
+ return BuildUnaryOp(S, OpLoc, Opc, Input);
}
-Action::OwningExprResult
-Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
- ExprArg Idx, SourceLocation RLoc) {
+ExprResult
+Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc) {
// Since this might be a postfix expression, get rid of ParenListExprs.
- Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid()) return ExprError();
+ Base = Result.take();
- Expr *LHSExp = static_cast<Expr*>(Base.get()),
- *RHSExp = static_cast<Expr*>(Idx.get());
+ Expr *LHSExp = Base, *RHSExp = Idx;
if (getLangOptions().CPlusPlus &&
(LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
- Base.release();
- Idx.release();
return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
Context.DependentTy, RLoc));
}
@@ -2209,18 +2311,18 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
LHSExp->getType()->isEnumeralType() ||
RHSExp->getType()->isRecordType() ||
RHSExp->getType()->isEnumeralType())) {
- return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx));
+ return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx);
}
- return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc);
+ return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc);
}
-Action::OwningExprResult
-Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
- ExprArg Idx, SourceLocation RLoc) {
- Expr *LHSExp = static_cast<Expr*>(Base.get());
- Expr *RHSExp = static_cast<Expr*>(Idx.get());
+ExprResult
+Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc) {
+ Expr *LHSExp = Base;
+ Expr *RHSExp = Idx;
// Perform default conversions.
if (!LHSExp->getType()->getAs<VectorType>())
@@ -2274,7 +2376,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
LHSExp->getSourceRange();
ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
- CastExpr::CK_ArrayToPointerDecay);
+ CK_ArrayToPointerDecay);
LHSTy = LHSExp->getType();
BaseExpr = LHSExp;
@@ -2285,7 +2387,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<
RHSExp->getSourceRange();
ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
- CastExpr::CK_ArrayToPointerDecay);
+ CK_ArrayToPointerDecay);
RHSTy = RHSExp->getType();
BaseExpr = RHSExp;
@@ -2296,8 +2398,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
<< LHSExp->getSourceRange() << RHSExp->getSourceRange());
}
// C99 6.5.2.1p1
- if (!(IndexExpr->getType()->isIntegerType() &&
- IndexExpr->getType()->isScalarType()) && !IndexExpr->isTypeDependent())
+ if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent())
return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer)
<< IndexExpr->getSourceRange());
@@ -2329,8 +2430,6 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc,
return ExprError();
}
- Base.release();
- Idx.release();
return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
ResultType, RLoc));
}
@@ -2377,7 +2476,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
// We didn't get to the end of the string. This means the component names
// didn't come from the same set *or* we encountered an illegal name.
Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
- << std::string(compStr,compStr+1) << SourceRange(CompLoc);
+ << llvm::StringRef(compStr, 1) << SourceRange(CompLoc);
return QualType();
}
@@ -2470,15 +2569,13 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy,
return GDecl;
}
-Sema::OwningExprResult
-Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType,
+ExprResult
+Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
bool IsArrow, SourceLocation OpLoc,
const CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
- DeclarationName Name, SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
- Expr *BaseExpr = Base.takeAs<Expr>();
-
// Even in dependent contexts, try to diagnose base expressions with
// obviously wrong types, e.g.:
//
@@ -2493,24 +2590,24 @@ Sema::ActOnDependentMemberExpr(ExprArg Base, QualType BaseType,
if (PT && (!getLangOptions().ObjC1 ||
PT->getPointeeType()->isRecordType())) {
assert(BaseExpr && "cannot happen with implicit member accesses");
- Diag(NameLoc, diag::err_typecheck_member_reference_struct_union)
+ Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union)
<< BaseType << BaseExpr->getSourceRange();
return ExprError();
}
}
- assert(BaseType->isDependentType() || Name.isDependentName() ||
+ assert(BaseType->isDependentType() ||
+ NameInfo.getName().isDependentName() ||
isDependentScopeSpecifier(SS));
// Get the type being accessed in BaseType. If this is an arrow, the BaseExpr
// must have pointer type, and the accessed type is the pointee.
return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType,
IsArrow, OpLoc,
- static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
+ SS.getScopeRep(),
SS.getRange(),
FirstQualifierInScope,
- Name, NameLoc,
- TemplateArgs));
+ NameInfo, TemplateArgs));
}
/// We know that the given qualified member reference points only to
@@ -2562,12 +2659,15 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr,
return false;
// Note that we use the DC of the decl, not the underlying decl.
- CXXRecordDecl *RecordD = cast<CXXRecordDecl>((*I)->getDeclContext());
- while (RecordD->isAnonymousStructOrUnion())
- RecordD = cast<CXXRecordDecl>(RecordD->getParent());
+ DeclContext *DC = (*I)->getDeclContext();
+ while (DC->isTransparentContext())
+ DC = DC->getParent();
+ if (!DC->isRecord())
+ continue;
+
llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord;
- MemberRecord.insert(RecordD->getCanonicalDecl());
+ MemberRecord.insert(cast<CXXRecordDecl>(DC)->getCanonicalDecl());
if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord))
return false;
@@ -2646,24 +2746,21 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
return false;
}
-Sema::OwningExprResult
-Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
+ExprResult
+Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
- DeclarationName Name, SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
- Expr *Base = BaseArg.takeAs<Expr>();
-
if (BaseType->isDependentType() ||
(SS.isSet() && isDependentScopeSpecifier(SS)))
- return ActOnDependentMemberExpr(ExprArg(*this, Base), BaseType,
+ return ActOnDependentMemberExpr(Base, BaseType,
IsArrow, OpLoc,
SS, FirstQualifierInScope,
- Name, NameLoc,
- TemplateArgs);
+ NameInfo, TemplateArgs);
- LookupResult R(*this, Name, NameLoc, LookupMemberName);
+ LookupResult R(*this, NameInfo, LookupMemberName);
// Implicit member accesses.
if (!Base) {
@@ -2676,9 +2773,9 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
// Explicit member accesses.
} else {
- OwningExprResult Result =
+ ExprResult Result =
LookupMemberExpr(R, Base, IsArrow, OpLoc,
- SS, /*ObjCImpDecl*/ DeclPtrTy(), TemplateArgs != 0);
+ SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0);
if (Result.isInvalid()) {
Owned(Base);
@@ -2692,20 +2789,19 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType,
BaseType = Base->getType();
}
- return BuildMemberReferenceExpr(ExprArg(*this, Base), BaseType,
+ return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, FirstQualifierInScope,
R, TemplateArgs);
}
-Sema::OwningExprResult
-Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
+ExprResult
+Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
SourceLocation OpLoc, bool IsArrow,
const CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
bool SuppressQualifierCheck) {
- Expr *BaseExpr = Base.takeAs<Expr>();
QualType BaseType = BaseExprType;
if (IsArrow) {
assert(BaseType->isPointerType());
@@ -2713,10 +2809,10 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
}
R.setBaseObjectType(BaseType);
- NestedNameSpecifier *Qualifier =
- static_cast<NestedNameSpecifier*>(SS.getScopeRep());
- DeclarationName MemberName = R.getLookupName();
- SourceLocation MemberLoc = R.getNameLoc();
+ NestedNameSpecifier *Qualifier = SS.getScopeRep();
+ const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();
+ DeclarationName MemberName = MemberNameInfo.getName();
+ SourceLocation MemberLoc = MemberNameInfo.getLoc();
if (R.isAmbiguous())
return ExprError();
@@ -2765,7 +2861,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
BaseExpr, BaseExprType,
IsArrow, OpLoc,
Qualifier, SS.getRange(),
- MemberName, MemberLoc,
+ MemberNameInfo,
TemplateArgs, R.begin(), R.end());
return Owned(MemExpr);
@@ -2787,7 +2883,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
if (!BaseExpr) {
// If this is not an instance member, convert to a non-member access.
if (!MemberDecl->isCXXInstanceMember())
- return BuildDeclarationNameExpr(SS, R.getNameLoc(), MemberDecl);
+ return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl);
SourceLocation Loc = R.getNameLoc();
if (SS.getRange().isValid())
@@ -2838,34 +2934,36 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
if (PerformObjectMemberConversion(BaseExpr, Qualifier, FoundDecl, FD))
return ExprError();
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- FD, FoundDecl, MemberLoc, MemberType));
+ FD, FoundDecl, MemberNameInfo,
+ MemberType));
}
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, Var);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- Var, FoundDecl, MemberLoc,
+ Var, FoundDecl, MemberNameInfo,
Var->getType().getNonReferenceType()));
}
if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- MemberFn, FoundDecl, MemberLoc,
+ MemberFn, FoundDecl, MemberNameInfo,
MemberFn->getType()));
}
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- Enum, FoundDecl, MemberLoc, Enum->getType()));
+ Enum, FoundDecl, MemberNameInfo,
+ Enum->getType()));
}
Owned(BaseExpr);
// We found something that we didn't expect. Complain.
if (isa<TypeDecl>(MemberDecl))
- Diag(MemberLoc,diag::err_typecheck_member_reference_type)
+ Diag(MemberLoc, diag::err_typecheck_member_reference_type)
<< MemberName << BaseType << int(IsArrow);
else
Diag(MemberLoc, diag::err_typecheck_member_reference_unknown)
@@ -2887,11 +2985,11 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
///
/// The ObjCImpDecl bit is a gross hack that will need to be properly
/// fixed for ObjC++.
-Sema::OwningExprResult
+ExprResult
Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
bool &IsArrow, SourceLocation OpLoc,
CXXScopeSpec &SS,
- DeclPtrTy ObjCImpDecl, bool HasTemplateArgs) {
+ Decl *ObjCImpDecl, bool HasTemplateArgs) {
assert(BaseExpr && "no base expression");
// Perform default conversions.
@@ -2921,8 +3019,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
<< QualType(Fun, 0)
<< FixItHint::CreateInsertion(Loc, "()");
- OwningExprResult NewBase
- = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc,
+ ExprResult NewBase
+ = ActOnCallExpr(0, BaseExpr, Loc,
MultiExprArg(*this, 0, 0), 0, Loc);
BaseExpr = 0;
if (NewBase.isInvalid())
@@ -2952,7 +3050,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// is a reference to 'isa'.
if (BaseType != Context.ObjCIdRedefinitionType) {
BaseType = Context.ObjCIdRedefinitionType;
- ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
+ ImpCastExprToType(BaseExpr, BaseType, CK_BitCast);
}
}
@@ -2963,7 +3061,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// is a reference to 'sel_id'.
if (BaseType != Context.ObjCSelRedefinitionType) {
BaseType = Context.ObjCSelRedefinitionType;
- ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
+ ImpCastExprToType(BaseExpr, BaseType, CK_BitCast);
}
}
@@ -3022,7 +3120,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
if (BaseType->isObjCClassType() &&
BaseType != Context.ObjCClassRedefinitionType) {
BaseType = Context.ObjCClassRedefinitionType;
- ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);
+ ImpCastExprToType(BaseExpr, BaseType, CK_BitCast);
}
if (IsArrow) {
@@ -3129,12 +3227,11 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
// down the context as argument to this routine. Ideally, this context
// need be passed down in the AST node and somehow calculated from the
// AST for a function decl.
- Decl *ImplDecl = ObjCImpDecl.getAs<Decl>();
if (ObjCImplementationDecl *IMPD =
- dyn_cast<ObjCImplementationDecl>(ImplDecl))
+ dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))
ClassOfMethodDecl = IMPD->getClassInterface();
else if (ObjCCategoryImplDecl* CatImplClass =
- dyn_cast<ObjCCategoryImplDecl>(ImplDecl))
+ dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl))
ClassOfMethodDecl = CatImplClass->getClassInterface();
}
@@ -3235,12 +3332,12 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
/// \param ObjCImpDecl the current ObjC @implementation decl;
/// this is an ugly hack around the fact that ObjC @implementations
/// aren't properly put in the context chain
-Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
+ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
UnqualifiedId &Id,
- DeclPtrTy ObjCImpDecl,
+ Decl *ObjCImpDecl,
bool HasTrailingLParen) {
if (SS.isSet() && SS.isInvalid())
return ExprError();
@@ -3248,12 +3345,12 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
TemplateArgumentListInfo TemplateArgsBuffer;
// Decompose the name into its component parts.
- DeclarationName Name;
- SourceLocation NameLoc;
+ DeclarationNameInfo NameInfo;
const TemplateArgumentListInfo *TemplateArgs;
DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer,
- Name, NameLoc, TemplateArgs);
+ NameInfo, TemplateArgs);
+ DeclarationName Name = NameInfo.getName();
bool IsArrow = (OpKind == tok::arrow);
NamedDecl *FirstQualifierInScope
@@ -3261,19 +3358,18 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
static_cast<NestedNameSpecifier*>(SS.getScopeRep())));
// This is a postfix expression, so get rid of ParenListExprs.
- BaseArg = MaybeConvertParenListExprToParenExpr(S, move(BaseArg));
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid()) return ExprError();
+ Base = Result.take();
- Expr *Base = BaseArg.takeAs<Expr>();
- OwningExprResult Result(*this);
if (Base->getType()->isDependentType() || Name.isDependentName() ||
isDependentScopeSpecifier(SS)) {
- Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(),
+ Result = ActOnDependentMemberExpr(Base, Base->getType(),
IsArrow, OpLoc,
SS, FirstQualifierInScope,
- Name, NameLoc,
- TemplateArgs);
+ NameInfo, TemplateArgs);
} else {
- LookupResult R(*this, Name, NameLoc, LookupMemberName);
+ LookupResult R(*this, NameInfo, LookupMemberName);
Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
SS, ObjCImpDecl, TemplateArgs != 0);
@@ -3289,12 +3385,12 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
// call now.
if (!HasTrailingLParen &&
Id.getKind() == UnqualifiedId::IK_DestructorName)
- return DiagnoseDtorReference(NameLoc, move(Result));
+ return DiagnoseDtorReference(NameInfo.getLoc(), Result.get());
return move(Result);
}
- Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(),
+ Result = BuildMemberReferenceExpr(Base, Base->getType(),
OpLoc, IsArrow, SS, FirstQualifierInScope,
R, TemplateArgs);
}
@@ -3302,7 +3398,7 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg,
return move(Result);
}
-Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
FunctionDecl *FD,
ParmVarDecl *Param) {
if (Param->hasUnparsedDefaultArg()) {
@@ -3324,7 +3420,7 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first,
Innermost.second);
- OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
+ ExprResult Result = SubstExpr(UninstExpr, ArgList);
if (Result.isInvalid())
return ExprError();
@@ -3338,7 +3434,7 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1);
Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&ResultE, 1));
+ MultiExprArg(*this, &ResultE, 1));
if (Result.isInvalid())
return ExprError();
@@ -3457,7 +3553,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
InitializedEntity Entity =
Param? InitializedEntity::InitializeParameter(Param)
: InitializedEntity::InitializeParameter(ProtoArgType);
- OwningExprResult ArgE = PerformCopyInitialization(Entity,
+ ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(Arg));
if (ArgE.isInvalid())
@@ -3467,7 +3563,7 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
} else {
ParmVarDecl *Param = FDecl->getParamDecl(i);
- OwningExprResult ArgExpr =
+ ExprResult ArgExpr =
BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
if (ArgExpr.isInvalid())
return true;
@@ -3492,18 +3588,18 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc,
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
-Action::OwningExprResult
-Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
+ExprResult
+Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg args,
SourceLocation *CommaLocs, SourceLocation RParenLoc) {
unsigned NumArgs = args.size();
// Since this might be a postfix expression, get rid of ParenListExprs.
- fn = MaybeConvertParenListExprToParenExpr(S, move(fn));
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn);
+ if (Result.isInvalid()) return ExprError();
+ Fn = Result.take();
- Expr *Fn = fn.takeAs<Expr>();
- Expr **Args = reinterpret_cast<Expr**>(args.release());
- assert(Fn && "no function call expression");
+ Expr **Args = args.release();
if (getLangOptions().CPlusPlus) {
// If this is a pseudo-destructor expression, build the call immediately.
@@ -3515,9 +3611,6 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
SourceRange(Args[0]->getLocStart(),
Args[NumArgs-1]->getLocEnd()));
- for (unsigned I = 0; I != NumArgs; ++I)
- Args[I]->Destroy(Context);
-
NumArgs = 0;
}
@@ -3572,27 +3665,27 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
// Determine whether this is a call to a pointer-to-member function.
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
- if (BO->getOpcode() == BinaryOperator::PtrMemD ||
- BO->getOpcode() == BinaryOperator::PtrMemI) {
+ if (BO->getOpcode() == BO_PtrMemD ||
+ BO->getOpcode() == BO_PtrMemI) {
if (const FunctionProtoType *FPT
= BO->getType()->getAs<FunctionProtoType>()) {
QualType ResultTy = FPT->getCallResultType(Context);
- ExprOwningPtr<CXXMemberCallExpr>
- TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args,
- NumArgs, ResultTy,
- RParenLoc));
+ CXXMemberCallExpr *TheCall
+ = new (Context) CXXMemberCallExpr(Context, BO, Args,
+ NumArgs, ResultTy,
+ RParenLoc);
if (CheckCallReturnType(FPT->getResultType(),
BO->getRHS()->getSourceRange().getBegin(),
- TheCall.get(), 0))
+ TheCall, 0))
return ExprError();
- if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs,
+ if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs,
RParenLoc))
return ExprError();
- return Owned(MaybeBindToTemporary(TheCall.release()).release());
+ return MaybeBindToTemporary(TheCall);
}
return ExprError(Diag(Fn->getLocStart(),
diag::err_typecheck_call_not_function)
@@ -3625,7 +3718,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
/// block-pointer type.
///
/// \param NDecl the declaration being called, if available
-Sema::OwningExprResult
+ExprResult
Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -3637,10 +3730,10 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Make the call expr early, before semantic checks. This guarantees cleanup
// of arguments and function on error.
- ExprOwningPtr<CallExpr> TheCall(this, new (Context) CallExpr(Context, Fn,
- Args, NumArgs,
- Context.BoolTy,
- RParenLoc));
+ CallExpr *TheCall = new (Context) CallExpr(Context, Fn,
+ Args, NumArgs,
+ Context.BoolTy,
+ RParenLoc);
const FunctionType *FuncT;
if (!Fn->getType()->isBlockPointerType()) {
@@ -3661,7 +3754,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Check for a valid return type
if (CheckCallReturnType(FuncT->getResultType(),
- Fn->getSourceRange().getBegin(), TheCall.get(),
+ Fn->getSourceRange().getBegin(), TheCall,
FDecl))
return ExprError();
@@ -3669,7 +3762,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
TheCall->setType(FuncT->getCallResultType(Context));
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
- if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs,
+ if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
RParenLoc))
return ExprError();
} else {
@@ -3713,22 +3806,22 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// Do special checking on direct calls to functions.
if (FDecl) {
- if (CheckFunctionCall(FDecl, TheCall.get()))
+ if (CheckFunctionCall(FDecl, TheCall))
return ExprError();
if (unsigned BuiltinID = FDecl->getBuiltinID())
- return CheckBuiltinFunctionCall(BuiltinID, TheCall.take());
+ return CheckBuiltinFunctionCall(BuiltinID, TheCall);
} else if (NDecl) {
- if (CheckBlockCall(NDecl, TheCall.get()))
+ if (CheckBlockCall(NDecl, TheCall))
return ExprError();
}
- return MaybeBindToTemporary(TheCall.take());
+ return MaybeBindToTemporary(TheCall);
}
-Action::OwningExprResult
-Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
- SourceLocation RParenLoc, ExprArg InitExpr) {
+ExprResult
+Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *InitExpr) {
assert((Ty != 0) && "ActOnCompoundLiteral(): missing type");
// FIXME: put back this assert when initializers are worked out.
//assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression");
@@ -3738,14 +3831,13 @@ Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(literalType);
- return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, move(InitExpr));
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr);
}
-Action::OwningExprResult
+ExprResult
Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
- SourceLocation RParenLoc, ExprArg InitExpr) {
+ SourceLocation RParenLoc, Expr *literalExpr) {
QualType literalType = TInfo->getType();
- Expr *literalExpr = static_cast<Expr*>(InitExpr.get());
if (literalType->isArrayType()) {
if (literalType->isVariableArrayType())
@@ -3764,13 +3856,12 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
= InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc),
/*IsCStyleCast=*/true);
InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1);
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&literalExpr, 1),
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &literalExpr, 1),
&literalType);
if (Result.isInvalid())
return ExprError();
- InitExpr.release();
- literalExpr = static_cast<Expr*>(Result.get());
+ literalExpr = Result.get();
bool isFileScope = getCurFunctionOrMethodDecl() == 0;
if (isFileScope) { // 6.5.2.5p3
@@ -3778,17 +3869,15 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
}
- Result.release();
-
return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
literalExpr, isFileScope));
}
-Action::OwningExprResult
+ExprResult
Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
SourceLocation RBraceLoc) {
unsigned NumInit = initlist.size();
- Expr **InitList = reinterpret_cast<Expr**>(initlist.release());
+ Expr **InitList = initlist.release();
// Semantic analysis for initializers is done by ActOnDeclarator() and
// CheckInitializer() - it requires knowledge of the object being intialized.
@@ -3799,45 +3888,45 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
return Owned(E);
}
-static CastExpr::CastKind getScalarCastKind(ASTContext &Context,
+static CastKind getScalarCastKind(ASTContext &Context,
QualType SrcTy, QualType DestTy) {
if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
- return CastExpr::CK_NoOp;
+ return CK_NoOp;
if (SrcTy->hasPointerRepresentation()) {
if (DestTy->hasPointerRepresentation())
return DestTy->isObjCObjectPointerType() ?
- CastExpr::CK_AnyPointerToObjCPointerCast :
- CastExpr::CK_BitCast;
+ CK_AnyPointerToObjCPointerCast :
+ CK_BitCast;
if (DestTy->isIntegerType())
- return CastExpr::CK_PointerToIntegral;
+ return CK_PointerToIntegral;
}
if (SrcTy->isIntegerType()) {
if (DestTy->isIntegerType())
- return CastExpr::CK_IntegralCast;
+ return CK_IntegralCast;
if (DestTy->hasPointerRepresentation())
- return CastExpr::CK_IntegralToPointer;
+ return CK_IntegralToPointer;
if (DestTy->isRealFloatingType())
- return CastExpr::CK_IntegralToFloating;
+ return CK_IntegralToFloating;
}
if (SrcTy->isRealFloatingType()) {
if (DestTy->isRealFloatingType())
- return CastExpr::CK_FloatingCast;
+ return CK_FloatingCast;
if (DestTy->isIntegerType())
- return CastExpr::CK_FloatingToIntegral;
+ return CK_FloatingToIntegral;
}
// FIXME: Assert here.
// assert(false && "Unhandled cast combination!");
- return CastExpr::CK_Unknown;
+ return CK_Unknown;
}
/// CheckCastTypes - Check type constraints for casting between types.
bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
- CastExpr::CastKind& Kind,
- CXXBaseSpecifierArray &BasePath,
+ CastKind& Kind,
+ CXXCastPath &BasePath,
bool FunctionalStyle) {
if (getLangOptions().CPlusPlus)
return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, BasePath,
@@ -3849,10 +3938,14 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
// type needs to be scalar.
if (castType->isVoidType()) {
// Cast to void allows any expr type.
- Kind = CastExpr::CK_ToVoid;
+ Kind = CK_ToVoid;
return false;
}
+ if (RequireCompleteType(TyR.getBegin(), castType,
+ diag::err_typecheck_cast_to_incomplete))
+ return true;
+
if (!castType->isScalarType() && !castType->isVectorType()) {
if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) &&
(castType->isStructureType() || castType->isUnionType())) {
@@ -3860,7 +3953,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
// FIXME: Check that the cast destination type is complete.
Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
<< castType << castExpr->getSourceRange();
- Kind = CastExpr::CK_NoOp;
+ Kind = CK_NoOp;
return false;
}
@@ -3880,7 +3973,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
if (Field == FieldEnd)
return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
<< castExpr->getType() << castExpr->getSourceRange();
- Kind = CastExpr::CK_ToUnion;
+ Kind = CK_ToUnion;
return false;
}
@@ -3922,11 +4015,15 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
}
Kind = getScalarCastKind(Context, castExpr->getType(), castType);
+
+ if (Kind == CK_Unknown || Kind == CK_BitCast)
+ CheckCastAlign(castExpr, castType, TyR);
+
return false;
}
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
- CastExpr::CastKind &Kind) {
+ CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
if (Ty->isVectorType() || Ty->isIntegerType()) {
@@ -3941,12 +4038,12 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
diag::err_invalid_conversion_between_vector_and_scalar)
<< VectorTy << Ty << R;
- Kind = CastExpr::CK_BitCast;
+ Kind = CK_BitCast;
return false;
}
bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
- CastExpr::CastKind &Kind) {
+ CastKind &Kind) {
assert(DestTy->isExtVectorType() && "Not an extended vector type!");
QualType SrcTy = CastExpr->getType();
@@ -3957,7 +4054,7 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
<< DestTy << SrcTy << R;
- Kind = CastExpr::CK_BitCast;
+ Kind = CK_BitCast;
return false;
}
@@ -3973,14 +4070,14 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,
ImpCastExprToType(CastExpr, DestElemTy,
getScalarCastKind(Context, SrcTy, DestElemTy));
- Kind = CastExpr::CK_VectorSplat;
+ Kind = CK_VectorSplat;
return false;
}
-Action::OwningExprResult
-Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty,
- SourceLocation RParenLoc, ExprArg Op) {
- assert((Ty != 0) && (Op.get() != 0) &&
+ExprResult
+Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *castExpr) {
+ assert((Ty != 0) && (castExpr != 0) &&
"ActOnCastExpr(): missing type or expr");
TypeSourceInfo *castTInfo;
@@ -3989,55 +4086,52 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, TypeTy *Ty,
castTInfo = Context.getTrivialTypeSourceInfo(castType);
// If the Expr being casted is a ParenListExpr, handle it specially.
- Expr *castExpr = (Expr *)Op.get();
if (isa<ParenListExpr>(castExpr))
- return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, move(Op),
+ return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, castExpr,
castTInfo);
- return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, move(Op));
+ return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, castExpr);
}
-Action::OwningExprResult
+ExprResult
Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
- SourceLocation RParenLoc, ExprArg Op) {
- Expr *castExpr = static_cast<Expr*>(Op.get());
-
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ SourceLocation RParenLoc, Expr *castExpr) {
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
Kind, BasePath))
return ExprError();
- Op.release();
- return Owned(new (Context) CStyleCastExpr(
+ return Owned(CStyleCastExpr::Create(Context,
Ty->getType().getNonLValueExprType(Context),
- Kind, castExpr, BasePath, Ty,
- LParenLoc, RParenLoc));
+ Kind, castExpr, &BasePath, Ty,
+ LParenLoc, RParenLoc));
}
/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence
/// of comma binary operators.
-Action::OwningExprResult
-Sema::MaybeConvertParenListExprToParenExpr(Scope *S, ExprArg EA) {
- Expr *expr = EA.takeAs<Expr>();
+ExprResult
+Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *expr) {
ParenListExpr *E = dyn_cast<ParenListExpr>(expr);
if (!E)
return Owned(expr);
- OwningExprResult Result(*this, E->getExpr(0));
+ ExprResult Result(E->getExpr(0));
for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i)
- Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, move(Result),
- Owned(E->getExpr(i)));
+ Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(),
+ E->getExpr(i));
- return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), move(Result));
+ if (Result.isInvalid()) return ExprError();
+
+ return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get());
}
-Action::OwningExprResult
+ExprResult
Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
- SourceLocation RParenLoc, ExprArg Op,
+ SourceLocation RParenLoc, Expr *Op,
TypeSourceInfo *TInfo) {
- ParenListExpr *PE = (ParenListExpr *)Op.get();
+ ParenListExpr *PE = cast<ParenListExpr>(Op);
QualType Ty = TInfo->getType();
bool isAltiVecLiteral = false;
@@ -4065,24 +4159,24 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc,
// FIXME: This means that pretty-printing the final AST will produce curly
// braces instead of the original commas.
- Op.release();
InitListExpr *E = new (Context) InitListExpr(Context, LParenLoc,
&initExprs[0],
initExprs.size(), RParenLoc);
E->setType(Ty);
- return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, Owned(E));
+ return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, E);
} else {
// This is not an AltiVec-style cast, so turn the ParenListExpr into a
// sequence of BinOp comma operators.
- Op = MaybeConvertParenListExprToParenExpr(S, move(Op));
- return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, move(Op));
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Op);
+ if (Result.isInvalid()) return ExprError();
+ return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Result.take());
}
}
-Action::OwningExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
+ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val,
- TypeTy *TypeOfCast) {
+ ParsedType TypeOfCast) {
unsigned nexprs = Val.size();
Expr **exprs = reinterpret_cast<Expr**>(Val.release());
assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list");
@@ -4148,8 +4242,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!RHSTy->isVoidType())
Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void)
<< LHS->getSourceRange();
- ImpCastExprToType(LHS, Context.VoidTy, CastExpr::CK_ToVoid);
- ImpCastExprToType(RHS, Context.VoidTy, CastExpr::CK_ToVoid);
+ ImpCastExprToType(LHS, Context.VoidTy, CK_ToVoid);
+ ImpCastExprToType(RHS, Context.VoidTy, CK_ToVoid);
return Context.VoidTy;
}
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
@@ -4157,12 +4251,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
// promote the null to a pointer.
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_Unknown);
+ ImpCastExprToType(RHS, LHSTy, CK_Unknown);
return LHSTy;
}
if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown);
+ ImpCastExprToType(LHS, RHSTy, CK_Unknown);
return RHSTy;
}
@@ -4178,8 +4272,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
QualType destType = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, destType, CK_BitCast);
+ ImpCastExprToType(RHS, destType, CK_BitCast);
return destType;
}
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
@@ -4203,13 +4297,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, incompatTy, CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CK_BitCast);
return incompatTy;
}
// The block pointer types are compatible.
- ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, LHSTy, CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
return LHSTy;
}
@@ -4226,9 +4320,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+ ImpCastExprToType(LHS, destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, destType, CK_BitCast);
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
@@ -4236,9 +4330,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(RHS, destType, CastExpr::CK_NoOp);
+ ImpCastExprToType(RHS, destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, destType, CK_BitCast);
return destType;
}
@@ -4254,8 +4348,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy = Context.getPointerType(Context.VoidTy);
- ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, incompatTy, CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CK_BitCast);
return incompatTy;
}
// The pointer types are compatible.
@@ -4265,8 +4359,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// type.
// FIXME: Need to calculate the composite type.
// FIXME: Need to add qualifiers
- ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, LHSTy, CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
return LHSTy;
}
@@ -4274,13 +4368,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
- ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(LHS, RHSTy, CK_IntegralToPointer);
return RHSTy;
}
if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {
Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)
<< LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange();
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(RHS, LHSTy, CK_IntegralToPointer);
return LHSTy;
}
@@ -4302,34 +4396,34 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
// redefinition type if an attempt is made to access its fields.
if (LHSTy->isObjCClassType() &&
(RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
return LHSTy;
}
if (RHSTy->isObjCClassType() &&
(LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) {
- ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, RHSTy, CK_BitCast);
return RHSTy;
}
// And the same for struct objc_object* / id
if (LHSTy->isObjCIdType() &&
(RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
return LHSTy;
}
if (RHSTy->isObjCIdType() &&
(LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) {
- ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, RHSTy, CK_BitCast);
return RHSTy;
}
// And the same for struct objc_selector* / SEL
if (Context.isObjCSelType(LHSTy) &&
(RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
- ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, LHSTy, CK_BitCast);
return LHSTy;
}
if (Context.isObjCSelType(RHSTy) &&
(LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) {
- ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, RHSTy, CK_BitCast);
return RHSTy;
}
// Check constraints for Objective-C object pointers types.
@@ -4378,13 +4472,13 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
<< LHSTy << RHSTy
<< LHS->getSourceRange() << RHS->getSourceRange();
QualType incompatTy = Context.getObjCIdType();
- ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, incompatTy, CK_BitCast);
+ ImpCastExprToType(RHS, incompatTy, CK_BitCast);
return incompatTy;
}
// The object pointer types are compatible.
- ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast);
- ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, compositeType, CK_BitCast);
+ ImpCastExprToType(RHS, compositeType, CK_BitCast);
return compositeType;
}
// Check Objective-C object pointer types and 'void *'
@@ -4395,9 +4489,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp);
+ ImpCastExprToType(LHS, destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(RHS, destType, CK_BitCast);
return destType;
}
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
@@ -4407,9 +4501,9 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
- ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp);
+ ImpCastExprToType(RHS, destType, CK_NoOp);
// Promote to void*.
- ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);
+ ImpCastExprToType(LHS, destType, CK_BitCast);
return destType;
}
return QualType();
@@ -4417,30 +4511,27 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
-Action::OwningExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
+ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
SourceLocation ColonLoc,
- ExprArg Cond, ExprArg LHS,
- ExprArg RHS) {
- Expr *CondExpr = (Expr *) Cond.get();
- Expr *LHSExpr = (Expr *) LHS.get(), *RHSExpr = (Expr *) RHS.get();
-
+ Expr *CondExpr, Expr *LHSExpr,
+ Expr *RHSExpr) {
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
bool isLHSNull = LHSExpr == 0;
- if (isLHSNull)
- LHSExpr = CondExpr;
+ Expr *SAVEExpr = 0;
+ if (isLHSNull) {
+ LHSExpr = SAVEExpr = CondExpr;
+ }
QualType result = CheckConditionalOperands(CondExpr, LHSExpr,
RHSExpr, QuestionLoc);
if (result.isNull())
return ExprError();
- Cond.release();
- LHS.release();
- RHS.release();
return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
- isLHSNull ? 0 : LHSExpr,
- ColonLoc, RHSExpr, result));
+ LHSExpr, ColonLoc,
+ RHSExpr, SAVEExpr,
+ result));
}
// CheckPointerTypesForAssignment - This is a very tricky routine (despite
@@ -4506,12 +4597,12 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
// "unsigned char" on systems where "char" is unsigned.
if (lhptee->isCharType())
lhptee = Context.UnsignedCharTy;
- else if (lhptee->isSignedIntegerType())
+ else if (lhptee->hasSignedIntegerRepresentation())
lhptee = Context.getCorrespondingUnsignedType(lhptee);
if (rhptee->isCharType())
rhptee = Context.UnsignedCharTy;
- else if (rhptee->isSignedIntegerType())
+ else if (rhptee->hasSignedIntegerRepresentation())
rhptee = Context.getCorrespondingUnsignedType(rhptee);
if (lhptee == rhptee) {
@@ -4668,13 +4759,18 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
}
if (lhsType->isVectorType() || rhsType->isVectorType()) {
- // If we are allowing lax vector conversions, and LHS and RHS are both
- // vectors, the total size only needs to be the same. This is a bitcast;
- // no bits are changed but the result type is different.
- if (getLangOptions().LaxVectorConversions &&
- lhsType->isVectorType() && rhsType->isVectorType()) {
- if (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))
+ if (lhsType->isVectorType() && rhsType->isVectorType()) {
+ // If we are allowing lax vector conversions, and LHS and RHS are both
+ // vectors, the total size only needs to be the same. This is a bitcast;
+ // no bits are changed but the result type is different.
+ if (getLangOptions().LaxVectorConversions &&
+ (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType)))
return IncompatibleVectors;
+
+ // Allow assignments of an AltiVec vector type to an equivalent GCC
+ // vector type and vice versa
+ if (Context.areCompatibleVectorTypes(lhsType, rhsType))
+ return Compatible;
}
return Incompatible;
}
@@ -4832,14 +4928,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {
// 2) null pointer constant
if (FromType->isPointerType())
if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
- ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_BitCast);
+ ImpCastExprToType(rExpr, it->getType(), CK_BitCast);
InitField = *it;
break;
}
if (rExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(rExpr, it->getType(), CK_IntegralToPointer);
InitField = *it;
break;
}
@@ -4883,14 +4979,14 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
lhsType->isBlockPointerType())
&& rExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, lhsType, CastExpr::CK_Unknown);
+ ImpCastExprToType(rExpr, lhsType, CK_Unknown);
return Compatible;
}
// This check seems unnatural, however it is necessary to ensure the proper
// conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ActOnIdExpression), it would mess up the unary
- // expressions that surpress this implicit conversion (&, sizeof).
+ // expressions that suppress this implicit conversion (&, sizeof).
//
// Suppress this for references: C++ 8.5.3p5.
if (!lhsType->isReferenceType())
@@ -4907,7 +5003,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {
// does not have reference type.
if (result != Incompatible && rExpr->getType() != lhsType)
ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context),
- CastExpr::CK_Unknown);
+ CK_Unknown);
return result;
}
@@ -4933,22 +5029,35 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
// Handle the case of a vector & extvector type of the same size and element
// type. It would be nice if we only had one vector type someday.
if (getLangOptions().LaxVectorConversions) {
- // FIXME: Should we warn here?
if (const VectorType *LV = lhsType->getAs<VectorType>()) {
- if (const VectorType *RV = rhsType->getAs<VectorType>())
+ if (const VectorType *RV = rhsType->getAs<VectorType>()) {
if (LV->getElementType() == RV->getElementType() &&
LV->getNumElements() == RV->getNumElements()) {
if (lhsType->isExtVectorType()) {
- ImpCastExprToType(rex, lhsType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lhsType, CK_BitCast);
return lhsType;
}
- ImpCastExprToType(lex, rhsType, CastExpr::CK_BitCast);
+ ImpCastExprToType(lex, rhsType, CK_BitCast);
return rhsType;
+ } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){
+ // If we are allowing lax vector conversions, and LHS and RHS are both
+ // vectors, the total size only needs to be the same. This is a
+ // bitcast; no bits are changed but the result type is different.
+ ImpCastExprToType(rex, lhsType, CK_BitCast);
+ return lhsType;
}
+ }
}
}
+ // Handle the case of equivalent AltiVec and GCC vector types
+ if (lhsType->isVectorType() && rhsType->isVectorType() &&
+ Context.areCompatibleVectorTypes(lhsType, rhsType)) {
+ ImpCastExprToType(lex, rhsType, CK_BitCast);
+ return rhsType;
+ }
+
// Canonicalize the ExtVector to the LHS, remember if we swapped so we can
// swap back (so that we don't reverse the inputs to a subtract, for instance.
bool swapped = false;
@@ -4963,7 +5072,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
QualType EltTy = LV->getElementType();
if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) {
if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) {
- ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(rex, lhsType, CK_IntegralCast);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -4971,7 +5080,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&
rhsType->isRealFloatingType()) {
if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) {
- ImpCastExprToType(rex, lhsType, CastExpr::CK_FloatingCast);
+ ImpCastExprToType(rex, lhsType, CK_FloatingCast);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -5008,7 +5117,8 @@ QualType Sema::CheckMultiplyDivideOperands(
QualType Sema::CheckRemainderOperands(
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
- if (lex->getType()->isIntegerType() && rex->getType()->isIntegerType())
+ if (lex->getType()->hasIntegerRepresentation() &&
+ rex->getType()->hasIntegerRepresentation())
return CheckVectorOperands(Loc, lex, rex);
return InvalidOperands(Loc, lex, rex);
}
@@ -5253,7 +5363,8 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
bool isCompAssign) {
// C99 6.5.7p2: Each of the operands shall have integer type.
- if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
+ if (!lex->getType()->hasIntegerRepresentation() ||
+ !rex->getType()->hasIntegerRepresentation())
return InvalidOperands(Loc, lex, rex);
// Vector shifts promote their scalar inputs to vector type.
@@ -5269,7 +5380,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
LHSTy = Context.getPromotedIntegerType(LHSTy);
}
if (!isCompAssign)
- ImpCastExprToType(lex, LHSTy, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(lex, LHSTy, CK_IntegralCast);
UsualUnaryConversions(rex);
@@ -5305,7 +5416,7 @@ static bool IsWithinTemplateSpecialization(Decl *D) {
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
unsigned OpaqueOpc, bool isRelational) {
- BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)OpaqueOpc;
+ BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc;
// Handle vector comparisons separately.
if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
@@ -5334,19 +5445,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
!IsWithinTemplateSpecialization(DRL->getDecl())) {
DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
<< 0 // self-
- << (Opc == BinaryOperator::EQ
- || Opc == BinaryOperator::LE
- || Opc == BinaryOperator::GE));
+ << (Opc == BO_EQ
+ || Opc == BO_LE
+ || Opc == BO_GE));
} else if (lType->isArrayType() && rType->isArrayType() &&
!DRL->getDecl()->getType()->isReferenceType() &&
!DRR->getDecl()->getType()->isReferenceType()) {
// what is it always going to eval to?
char always_evals_to;
switch(Opc) {
- case BinaryOperator::EQ: // e.g. array1 == array2
+ case BO_EQ: // e.g. array1 == array2
always_evals_to = 0; // false
break;
- case BinaryOperator::NE: // e.g. array1 != array2
+ case BO_NE: // e.g. array1 != array2
always_evals_to = 1; // true
break;
default:
@@ -5386,12 +5497,12 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (literalString) {
std::string resultComparison;
switch (Opc) {
- case BinaryOperator::LT: resultComparison = ") < 0"; break;
- case BinaryOperator::GT: resultComparison = ") > 0"; break;
- case BinaryOperator::LE: resultComparison = ") <= 0"; break;
- case BinaryOperator::GE: resultComparison = ") >= 0"; break;
- case BinaryOperator::EQ: resultComparison = ") == 0"; break;
- case BinaryOperator::NE: resultComparison = ") != 0"; break;
+ case BO_LT: resultComparison = ") < 0"; break;
+ case BO_GT: resultComparison = ") > 0"; break;
+ case BO_LE: resultComparison = ") <= 0"; break;
+ case BO_GE: resultComparison = ") >= 0"; break;
+ case BO_EQ: resultComparison = ") == 0"; break;
+ case BO_NE: resultComparison = ") != 0"; break;
default: assert(false && "Invalid comparison operator");
}
@@ -5461,7 +5572,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (isSFINAEContext())
return QualType();
- ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
}
@@ -5487,8 +5598,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
<< lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
- ImpCastExprToType(rex, T, CastExpr::CK_BitCast);
+ ImpCastExprToType(lex, T, CK_BitCast);
+ ImpCastExprToType(rex, T, CK_BitCast);
return ResultTy;
}
// C99 6.5.9p2 and C99 6.5.8p2
@@ -5513,7 +5624,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
if (LCanPointeeTy != RCanPointeeTy)
- ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
@@ -5523,13 +5634,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
if (RHSIsNull &&
(lType->isPointerType() ||
(!isRelational && lType->isMemberPointerType()))) {
- ImpCastExprToType(rex, lType, CastExpr::CK_NullToMemberPointer);
+ ImpCastExprToType(rex, lType,
+ lType->isMemberPointerType()
+ ? CK_NullToMemberPointer
+ : CK_IntegralToPointer);
return ResultTy;
}
if (LHSIsNull &&
(rType->isPointerType() ||
(!isRelational && rType->isMemberPointerType()))) {
- ImpCastExprToType(lex, rType, CastExpr::CK_NullToMemberPointer);
+ ImpCastExprToType(lex, rType,
+ rType->isMemberPointerType()
+ ? CK_NullToMemberPointer
+ : CK_IntegralToPointer);
return ResultTy;
}
@@ -5560,8 +5677,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
<< lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
- ImpCastExprToType(rex, T, CastExpr::CK_BitCast);
+ ImpCastExprToType(lex, T, CK_BitCast);
+ ImpCastExprToType(rex, T, CK_BitCast);
return ResultTy;
}
@@ -5580,7 +5697,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
// Allow block pointers to be compared with null pointer constants.
@@ -5595,7 +5712,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
@@ -5613,14 +5730,14 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
}
- ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {
if (!Context.areComparableObjCPointerTypes(lType, rType))
Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
- ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);
+ ImpCastExprToType(rex, lType, CK_BitCast);
return ResultTy;
}
}
@@ -5648,21 +5765,21 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
}
if (lType->isIntegerType())
- ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(lex, rType, CK_IntegralToPointer);
else
- ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(rex, lType, CK_IntegralToPointer);
return ResultTy;
}
// Handle block pointers.
if (!isRelational && RHSIsNull
&& lType->isBlockPointerType() && rType->isIntegerType()) {
- ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(rex, lType, CK_IntegralToPointer);
return ResultTy;
}
if (!isRelational && LHSIsNull
&& lType->isIntegerType() && rType->isBlockPointerType()) {
- ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(lex, rType, CK_IntegralToPointer);
return ResultTy;
}
return InvalidOperands(Loc, lex, rex);
@@ -5707,7 +5824,7 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
// Return the type for the comparison, which is the same as vector type for
// integer vectors, or an integer type of identical size and number of
// elements for floating point vectors.
- if (lType->isIntegerType())
+ if (lType->hasIntegerRepresentation())
return lType;
const VectorType *VTy = lType->getAs<VectorType>();
@@ -5724,8 +5841,13 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex,
inline QualType Sema::CheckBitwiseOperands(
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) {
- if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
- return CheckVectorOperands(Loc, lex, rex);
+ if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) {
+ if (lex->getType()->hasIntegerRepresentation() &&
+ rex->getType()->hasIntegerRepresentation())
+ return CheckVectorOperands(Loc, lex, rex);
+
+ return InvalidOperands(Loc, lex, rex);
+ }
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
@@ -5741,18 +5863,21 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
// bitwise one. We do this when the LHS is a non-bool integer and the RHS
// is a constant.
if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() &&
- rex->getType()->isIntegerType() && rex->isEvaluatable(Context) &&
- // Don't warn if the RHS is a (constant folded) boolean expression like
- // "sizeof(int) == 4".
- !rex->isKnownToHaveBooleanValue() &&
+ rex->getType()->isIntegerType() && !rex->isValueDependent() &&
// Don't warn in macros.
- !Loc.isMacroID())
- Diag(Loc, diag::warn_logical_instead_of_bitwise)
- << rex->getSourceRange()
- << (Opc == BinaryOperator::LAnd ? "&&" : "||")
- << (Opc == BinaryOperator::LAnd ? "&" : "|");
-
-
+ !Loc.isMacroID()) {
+ // If the RHS can be constant folded, and if it constant folds to something
+ // that isn't 0 or 1 (which indicate a potential logical operation that
+ // happened to fold to true/false) then warn.
+ Expr::EvalResult Result;
+ if (rex->Evaluate(Result, Context) && !Result.HasSideEffects &&
+ Result.Val.getInt() != 0 && Result.Val.getInt() != 1) {
+ Diag(Loc, diag::warn_logical_instead_of_bitwise)
+ << rex->getSourceRange()
+ << (Opc == BO_LAnd ? "&&" : "||")
+ << (Opc == BO_LAnd ? "&" : "|");
+ }
+ }
if (!Context.getLangOptions().CPlusPlus) {
UsualUnaryConversions(lex);
@@ -5907,8 +6032,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
RHSCheck = ICE->getSubExpr();
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
- if ((UO->getOpcode() == UnaryOperator::Plus ||
- UO->getOpcode() == UnaryOperator::Minus) &&
+ if ((UO->getOpcode() == UO_Plus ||
+ UO->getOpcode() == UO_Minus) &&
Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
// Only if the two operators are exactly adjacent.
Loc.getFileLocWithOffset(1) == UO->getOperatorLoc() &&
@@ -5917,7 +6042,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
Loc.getFileLocWithOffset(2) != UO->getSubExpr()->getLocStart() &&
UO->getSubExpr()->getLocStart().isFileID()) {
Diag(Loc, diag::warn_not_compound_assign)
- << (UO->getOpcode() == UnaryOperator::Plus ? "+" : "-")
+ << (UO->getOpcode() == UO_Plus ? "+" : "-")
<< SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
}
}
@@ -5938,7 +6063,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
// only handles the pattern "*null = whatever", which is a very syntactic
// check.
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts()))
- if (UO->getOpcode() == UnaryOperator::Deref &&
+ if (UO->getOpcode() == UO_Deref &&
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
@@ -6083,9 +6208,9 @@ static NamedDecl *getPrimaryDecl(Expr *E) {
UnaryOperator *UO = cast<UnaryOperator>(E);
switch(UO->getOpcode()) {
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
- case UnaryOperator::Extension:
+ case UO_Real:
+ case UO_Imag:
+ case UO_Extension:
return getPrimaryDecl(UO->getSubExpr());
default:
return 0;
@@ -6109,17 +6234,19 @@ static NamedDecl *getPrimaryDecl(Expr *E) {
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
/// In C++, the operand might be an overloaded function name, in which case
/// we allow the '&' but retain the overloaded-function type.
-QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
- // Make sure to ignore parentheses in subsequent checks
- op = op->IgnoreParens();
-
- if (op->isTypeDependent())
+QualType Sema::CheckAddressOfOperand(Expr *OrigOp, SourceLocation OpLoc) {
+ if (OrigOp->isTypeDependent())
return Context.DependentTy;
+ if (OrigOp->getType() == Context.OverloadTy)
+ return Context.OverloadTy;
+
+ // Make sure to ignore parentheses in subsequent checks
+ Expr *op = OrigOp->IgnoreParens();
if (getLangOptions().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
- if (uOp->getOpcode() == UnaryOperator::Deref)
+ if (uOp->getOpcode() == UO_Deref)
// Per C99 6.5.3.2, the address of a deref always returns a valid result
// (assuming the deref expression is valid).
return uOp->getSubExpr()->getType();
@@ -6130,32 +6257,41 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
NamedDecl *dcl = getPrimaryDecl(op);
Expr::isLvalueResult lval = op->isLvalue(Context);
- MemberExpr *ME = dyn_cast<MemberExpr>(op);
- if (lval == Expr::LV_MemberFunction && ME &&
- isa<CXXMethodDecl>(ME->getMemberDecl())) {
- ValueDecl *dcl = cast<MemberExpr>(op)->getMemberDecl();
- // &f where f is a member of the current object, or &o.f, or &p->f
- // All these are not allowed, and we need to catch them before the dcl
- // branch of the if, below.
- Diag(OpLoc, diag::err_unqualified_pointer_member_function)
- << dcl;
- // FIXME: Improve this diagnostic and provide a fixit.
-
- // Now recover by acting as if the function had been accessed qualified.
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(cast<RecordDecl>(dcl->getDeclContext()))
- .getTypePtr());
- }
-
if (lval == Expr::LV_ClassTemporary) {
Diag(OpLoc, isSFINAEContext()? diag::err_typecheck_addrof_class_temporary
: diag::ext_typecheck_addrof_class_temporary)
<< op->getType() << op->getSourceRange();
if (isSFINAEContext())
return QualType();
- } else if (isa<ObjCSelectorExpr>(op))
+ } else if (isa<ObjCSelectorExpr>(op)) {
return Context.getPointerType(op->getType());
- else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
+ } else if (lval == Expr::LV_MemberFunction) {
+ // If it's an instance method, make a member pointer.
+ // The expression must have exactly the form &A::foo.
+
+ // If the underlying expression isn't a decl ref, give up.
+ if (!isa<DeclRefExpr>(op)) {
+ Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp->getSourceRange();
+ return QualType();
+ }
+ DeclRefExpr *DRE = cast<DeclRefExpr>(op);
+ CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
+
+ // The id-expression was parenthesized.
+ if (OrigOp != DRE) {
+ Diag(OpLoc, diag::err_parens_pointer_member_function)
+ << OrigOp->getSourceRange();
+
+ // The method was named without a qualifier.
+ } else if (!DRE->getQualifier()) {
+ Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ << op->getSourceRange();
+ }
+
+ return Context.getMemberPointerType(op->getType(),
+ Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
if (!op->getType()->isFunctionType()) {
@@ -6183,13 +6319,14 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
// FIXME: Can LHS ever be null here?
if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull())
return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc);
- } else if (isa<UnresolvedLookupExpr>(op)) {
- return Context.OverloadTy;
} else if (dcl) { // C99 6.5.3.2p1
// We have an lvalue with a decl. Make sure the decl is not declared
// with the register storage-class specifier.
if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
- if (vd->getStorageClass() == VarDecl::Register) {
+ // in C++ it is not error to take address of a register
+ // variable (c++03 7.1.1P3)
+ if (vd->getStorageClass() == SC_Register &&
+ !getLangOptions().CPlusPlus) {
Diag(OpLoc, diag::err_typecheck_address_of)
<< "register variable" << op->getSourceRange();
return QualType();
@@ -6214,13 +6351,6 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
}
}
- } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) {
- // Okay: we can take the address of a function.
- // As above.
- if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
- MD->isInstance())
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (!isa<FunctionDecl>(dcl))
assert(0 && "Unknown/unexpected decl type");
}
@@ -6233,6 +6363,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
}
// If the operand has type "type", the result has type "pointer to type".
+ if (op->getType()->isObjCObjectType())
+ return Context.getObjCObjectPointerType(op->getType());
return Context.getPointerType(op->getType());
}
@@ -6264,63 +6396,63 @@ QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) {
return Result;
}
-static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode(
+static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode(
tok::TokenKind Kind) {
- BinaryOperator::Opcode Opc;
+ BinaryOperatorKind Opc;
switch (Kind) {
default: assert(0 && "Unknown binop!");
- case tok::periodstar: Opc = BinaryOperator::PtrMemD; break;
- case tok::arrowstar: Opc = BinaryOperator::PtrMemI; break;
- case tok::star: Opc = BinaryOperator::Mul; break;
- case tok::slash: Opc = BinaryOperator::Div; break;
- case tok::percent: Opc = BinaryOperator::Rem; break;
- case tok::plus: Opc = BinaryOperator::Add; break;
- case tok::minus: Opc = BinaryOperator::Sub; break;
- case tok::lessless: Opc = BinaryOperator::Shl; break;
- case tok::greatergreater: Opc = BinaryOperator::Shr; break;
- case tok::lessequal: Opc = BinaryOperator::LE; break;
- case tok::less: Opc = BinaryOperator::LT; break;
- case tok::greaterequal: Opc = BinaryOperator::GE; break;
- case tok::greater: Opc = BinaryOperator::GT; break;
- case tok::exclaimequal: Opc = BinaryOperator::NE; break;
- case tok::equalequal: Opc = BinaryOperator::EQ; break;
- case tok::amp: Opc = BinaryOperator::And; break;
- case tok::caret: Opc = BinaryOperator::Xor; break;
- case tok::pipe: Opc = BinaryOperator::Or; break;
- case tok::ampamp: Opc = BinaryOperator::LAnd; break;
- case tok::pipepipe: Opc = BinaryOperator::LOr; break;
- case tok::equal: Opc = BinaryOperator::Assign; break;
- case tok::starequal: Opc = BinaryOperator::MulAssign; break;
- case tok::slashequal: Opc = BinaryOperator::DivAssign; break;
- case tok::percentequal: Opc = BinaryOperator::RemAssign; break;
- case tok::plusequal: Opc = BinaryOperator::AddAssign; break;
- case tok::minusequal: Opc = BinaryOperator::SubAssign; break;
- case tok::lesslessequal: Opc = BinaryOperator::ShlAssign; break;
- case tok::greatergreaterequal: Opc = BinaryOperator::ShrAssign; break;
- case tok::ampequal: Opc = BinaryOperator::AndAssign; break;
- case tok::caretequal: Opc = BinaryOperator::XorAssign; break;
- case tok::pipeequal: Opc = BinaryOperator::OrAssign; break;
- case tok::comma: Opc = BinaryOperator::Comma; break;
+ case tok::periodstar: Opc = BO_PtrMemD; break;
+ case tok::arrowstar: Opc = BO_PtrMemI; break;
+ case tok::star: Opc = BO_Mul; break;
+ case tok::slash: Opc = BO_Div; break;
+ case tok::percent: Opc = BO_Rem; break;
+ case tok::plus: Opc = BO_Add; break;
+ case tok::minus: Opc = BO_Sub; break;
+ case tok::lessless: Opc = BO_Shl; break;
+ case tok::greatergreater: Opc = BO_Shr; break;
+ case tok::lessequal: Opc = BO_LE; break;
+ case tok::less: Opc = BO_LT; break;
+ case tok::greaterequal: Opc = BO_GE; break;
+ case tok::greater: Opc = BO_GT; break;
+ case tok::exclaimequal: Opc = BO_NE; break;
+ case tok::equalequal: Opc = BO_EQ; break;
+ case tok::amp: Opc = BO_And; break;
+ case tok::caret: Opc = BO_Xor; break;
+ case tok::pipe: Opc = BO_Or; break;
+ case tok::ampamp: Opc = BO_LAnd; break;
+ case tok::pipepipe: Opc = BO_LOr; break;
+ case tok::equal: Opc = BO_Assign; break;
+ case tok::starequal: Opc = BO_MulAssign; break;
+ case tok::slashequal: Opc = BO_DivAssign; break;
+ case tok::percentequal: Opc = BO_RemAssign; break;
+ case tok::plusequal: Opc = BO_AddAssign; break;
+ case tok::minusequal: Opc = BO_SubAssign; break;
+ case tok::lesslessequal: Opc = BO_ShlAssign; break;
+ case tok::greatergreaterequal: Opc = BO_ShrAssign; break;
+ case tok::ampequal: Opc = BO_AndAssign; break;
+ case tok::caretequal: Opc = BO_XorAssign; break;
+ case tok::pipeequal: Opc = BO_OrAssign; break;
+ case tok::comma: Opc = BO_Comma; break;
}
return Opc;
}
-static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
+static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
tok::TokenKind Kind) {
- UnaryOperator::Opcode Opc;
+ UnaryOperatorKind Opc;
switch (Kind) {
default: assert(0 && "Unknown unary op!");
- case tok::plusplus: Opc = UnaryOperator::PreInc; break;
- case tok::minusminus: Opc = UnaryOperator::PreDec; break;
- case tok::amp: Opc = UnaryOperator::AddrOf; break;
- case tok::star: Opc = UnaryOperator::Deref; break;
- case tok::plus: Opc = UnaryOperator::Plus; break;
- case tok::minus: Opc = UnaryOperator::Minus; break;
- case tok::tilde: Opc = UnaryOperator::Not; break;
- case tok::exclaim: Opc = UnaryOperator::LNot; break;
- case tok::kw___real: Opc = UnaryOperator::Real; break;
- case tok::kw___imag: Opc = UnaryOperator::Imag; break;
- case tok::kw___extension__: Opc = UnaryOperator::Extension; break;
+ case tok::plusplus: Opc = UO_PreInc; break;
+ case tok::minusminus: Opc = UO_PreDec; break;
+ case tok::amp: Opc = UO_AddrOf; break;
+ case tok::star: Opc = UO_Deref; break;
+ case tok::plus: Opc = UO_Plus; break;
+ case tok::minus: Opc = UO_Minus; break;
+ case tok::tilde: Opc = UO_Not; break;
+ case tok::exclaim: Opc = UO_LNot; break;
+ case tok::kw___real: Opc = UO_Real; break;
+ case tok::kw___imag: Opc = UO_Imag; break;
+ case tok::kw___extension__: Opc = UO_Extension; break;
}
return Opc;
}
@@ -6328,106 +6460,111 @@ static inline UnaryOperator::Opcode ConvertTokenKindToUnaryOpcode(
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
/// operator @p Opc at location @c TokLoc. This routine only supports
/// built-in operations; ActOnBinOp handles overloaded operators.
-Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
- unsigned Op,
- Expr *lhs, Expr *rhs) {
+ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
+ unsigned Op,
+ Expr *lhs, Expr *rhs) {
QualType ResultTy; // Result type of the binary operator.
- BinaryOperator::Opcode Opc = (BinaryOperator::Opcode)Op;
+ BinaryOperatorKind Opc = (BinaryOperatorKind) Op;
// The following two variables are used for compound assignment operators
QualType CompLHSTy; // Type of LHS after promotions for computation
QualType CompResultTy; // Type of computation result
switch (Opc) {
- case BinaryOperator::Assign:
+ case BO_Assign:
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
break;
- case BinaryOperator::PtrMemD:
- case BinaryOperator::PtrMemI:
+ case BO_PtrMemD:
+ case BO_PtrMemI:
ResultTy = CheckPointerToMemberOperands(lhs, rhs, OpLoc,
- Opc == BinaryOperator::PtrMemI);
+ Opc == BO_PtrMemI);
break;
- case BinaryOperator::Mul:
- case BinaryOperator::Div:
+ case BO_Mul:
+ case BO_Div:
ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, false,
- Opc == BinaryOperator::Div);
+ Opc == BO_Div);
break;
- case BinaryOperator::Rem:
+ case BO_Rem:
ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc);
break;
- case BinaryOperator::Add:
+ case BO_Add:
ResultTy = CheckAdditionOperands(lhs, rhs, OpLoc);
break;
- case BinaryOperator::Sub:
+ case BO_Sub:
ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc);
break;
- case BinaryOperator::Shl:
- case BinaryOperator::Shr:
+ case BO_Shl:
+ case BO_Shr:
ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
break;
- case BinaryOperator::LE:
- case BinaryOperator::LT:
- case BinaryOperator::GE:
- case BinaryOperator::GT:
+ case BO_LE:
+ case BO_LT:
+ case BO_GE:
+ case BO_GT:
ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, true);
break;
- case BinaryOperator::EQ:
- case BinaryOperator::NE:
+ case BO_EQ:
+ case BO_NE:
ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, false);
break;
- case BinaryOperator::And:
- case BinaryOperator::Xor:
- case BinaryOperator::Or:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
ResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc);
break;
- case BinaryOperator::LAnd:
- case BinaryOperator::LOr:
+ case BO_LAnd:
+ case BO_LOr:
ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc, Opc);
break;
- case BinaryOperator::MulAssign:
- case BinaryOperator::DivAssign:
+ case BO_MulAssign:
+ case BO_DivAssign:
CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true,
- Opc == BinaryOperator::DivAssign);
+ Opc == BO_DivAssign);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
- case BinaryOperator::RemAssign:
+ case BO_RemAssign:
CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
- case BinaryOperator::AddAssign:
+ case BO_AddAssign:
CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy);
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
- case BinaryOperator::SubAssign:
+ case BO_SubAssign:
CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy);
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
- case BinaryOperator::ShlAssign:
- case BinaryOperator::ShrAssign:
+ case BO_ShlAssign:
+ case BO_ShrAssign:
CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
- case BinaryOperator::AndAssign:
- case BinaryOperator::XorAssign:
- case BinaryOperator::OrAssign:
+ case BO_AndAssign:
+ case BO_XorAssign:
+ case BO_OrAssign:
CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull())
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
- case BinaryOperator::Comma:
+ case BO_Comma:
ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
break;
}
if (ResultTy.isNull())
return ExprError();
+ if (ResultTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
+ if (Opc >= BO_Assign && Opc <= BO_OrAssign)
+ Diag(OpLoc, diag::err_assignment_requires_nonfragile_object)
+ << ResultTy;
+ }
if (CompResultTy.isNull())
return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, ResultTy, OpLoc));
else
@@ -6479,7 +6616,7 @@ static void SuggestParentheses(Sema &Self, SourceLocation Loc,
/// operators are mixed in a way that suggests that the programmer forgot that
/// comparison operators have higher precedence. The most typical example of
/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
-static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
SourceLocation OpLoc,Expr *lhs,Expr *rhs){
typedef BinaryOperator BinOp;
BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1),
@@ -6526,19 +6663,17 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc,
/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
/// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3".
/// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does.
-static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc,
+static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
SourceLocation OpLoc, Expr *lhs, Expr *rhs){
if (BinaryOperator::isBitwiseOp(Opc))
DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs);
}
// Binary Operators. 'Tok' is the token for the operator.
-Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
- tok::TokenKind Kind,
- ExprArg LHS, ExprArg RHS) {
- BinaryOperator::Opcode Opc = ConvertTokenKindToBinaryOpcode(Kind);
- Expr *lhs = LHS.takeAs<Expr>(), *rhs = RHS.takeAs<Expr>();
-
+ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
+ tok::TokenKind Kind,
+ Expr *lhs, Expr *rhs) {
+ BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
assert((lhs != 0) && "ActOnBinOp(): missing left expression");
assert((rhs != 0) && "ActOnBinOp(): missing right expression");
@@ -6548,9 +6683,9 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
}
-Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
- BinaryOperator::Opcode Opc,
- Expr *lhs, Expr *rhs) {
+ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+ BinaryOperatorKind Opc,
+ Expr *lhs, Expr *rhs) {
if (getLangOptions().CPlusPlus &&
(lhs->getType()->isOverloadableType() ||
rhs->getType()->isOverloadableType())) {
@@ -6573,38 +6708,32 @@ Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
}
-Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
+ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
unsigned OpcIn,
- ExprArg InputArg) {
- UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
+ Expr *Input) {
+ UnaryOperatorKind Opc = static_cast<UnaryOperatorKind>(OpcIn);
- // FIXME: Input is modified below, but InputArg is not updated appropriately.
- Expr *Input = (Expr *)InputArg.get();
QualType resultType;
switch (Opc) {
- case UnaryOperator::OffsetOf:
- assert(false && "Invalid unary operator");
- break;
-
- case UnaryOperator::PreInc:
- case UnaryOperator::PreDec:
- case UnaryOperator::PostInc:
- case UnaryOperator::PostDec:
+ case UO_PreInc:
+ case UO_PreDec:
+ case UO_PostInc:
+ case UO_PostDec:
resultType = CheckIncrementDecrementOperand(Input, OpLoc,
- Opc == UnaryOperator::PreInc ||
- Opc == UnaryOperator::PostInc,
- Opc == UnaryOperator::PreInc ||
- Opc == UnaryOperator::PreDec);
+ Opc == UO_PreInc ||
+ Opc == UO_PostInc,
+ Opc == UO_PreInc ||
+ Opc == UO_PreDec);
break;
- case UnaryOperator::AddrOf:
+ case UO_AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
break;
- case UnaryOperator::Deref:
+ case UO_Deref:
DefaultFunctionArrayLvalueConversion(Input);
resultType = CheckIndirectionOperand(Input, OpLoc);
break;
- case UnaryOperator::Plus:
- case UnaryOperator::Minus:
+ case UO_Plus:
+ case UO_Minus:
UsualUnaryConversions(Input);
resultType = Input->getType();
if (resultType->isDependentType())
@@ -6616,13 +6745,13 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
resultType->isEnumeralType())
break;
else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6
- Opc == UnaryOperator::Plus &&
+ Opc == UO_Plus &&
resultType->isPointerType())
break;
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input->getSourceRange());
- case UnaryOperator::Not: // bitwise complement
+ case UO_Not: // bitwise complement
UsualUnaryConversions(Input);
resultType = Input->getType();
if (resultType->isDependentType())
@@ -6632,11 +6761,11 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
// C99 does not support '~' for complex conjugation.
Diag(OpLoc, diag::ext_integer_complement_complex)
<< resultType << Input->getSourceRange();
- else if (!resultType->isIntegerType())
+ else if (!resultType->hasIntegerRepresentation())
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input->getSourceRange());
break;
- case UnaryOperator::LNot: // logical negation
+ case UO_LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
DefaultFunctionArrayLvalueConversion(Input);
resultType = Input->getType();
@@ -6649,27 +6778,25 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
// In C++, it's bool. C++ 5.3.1p8
resultType = getLangOptions().CPlusPlus ? Context.BoolTy : Context.IntTy;
break;
- case UnaryOperator::Real:
- case UnaryOperator::Imag:
- resultType = CheckRealImagOperand(Input, OpLoc, Opc == UnaryOperator::Real);
+ case UO_Real:
+ case UO_Imag:
+ resultType = CheckRealImagOperand(Input, OpLoc, Opc == UO_Real);
break;
- case UnaryOperator::Extension:
+ case UO_Extension:
resultType = Input->getType();
break;
}
if (resultType.isNull())
return ExprError();
- InputArg.release();
return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
}
-Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
- UnaryOperator::Opcode Opc,
- ExprArg input) {
- Expr *Input = (Expr*)input.get();
+ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ Expr *Input) {
if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
- Opc != UnaryOperator::Extension) {
+ UnaryOperator::getOverloadedOperator(Opc) != OO_None) {
// 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
@@ -6680,24 +6807,24 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
Functions);
- return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
+ return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input);
}
- return CreateBuiltinUnaryOp(OpLoc, Opc, move(input));
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
// Unary Operators. 'Tok' is the token for the operator.
-Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Op, ExprArg input) {
- return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input));
+ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input) {
+ return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input);
}
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
-Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
+ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
SourceLocation LabLoc,
IdentifierInfo *LabelII) {
// Look up the record for this label identifier.
- LabelStmt *&LabelDecl = getLabelMap()[LabelII];
+ LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII];
// If we haven't seen this label yet, create a forward reference. It
// will be validated and/or cleaned up in ActOnFinishFunctionBody.
@@ -6709,10 +6836,9 @@ Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
Context.getPointerType(Context.VoidTy)));
}
-Sema::OwningExprResult
-Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt,
+ExprResult
+Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
SourceLocation RPLoc) { // "({..})"
- Stmt *SubStmt = static_cast<Stmt*>(substmt.get());
assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
@@ -6742,11 +6868,10 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, StmtArg substmt,
// FIXME: Check that expression type is complete/non-abstract; statement
// expressions are not lvalues.
- substmt.release();
return Owned(new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc));
}
-Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
TypeSourceInfo *TInfo,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
@@ -6865,22 +6990,27 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
return ExprError();
}
-
+
+ RecordDecl *Parent = MemberDecl->getParent();
+ bool AnonStructUnion = Parent->isAnonymousStructOrUnion();
+ if (AnonStructUnion) {
+ do {
+ Parent = cast<RecordDecl>(Parent->getParent());
+ } while (Parent->isAnonymousStructOrUnion());
+ }
+
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
- if (IsDerivedFrom(CurrentType,
- Context.getTypeDeclType(MemberDecl->getParent()),
- Paths)) {
+ if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) {
CXXBasePath &Path = Paths.front();
for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end();
B != BEnd; ++B)
Comps.push_back(OffsetOfNode(B->Base));
}
-
- if (cast<RecordDecl>(MemberDecl->getDeclContext())->
- isAnonymousStructOrUnion()) {
+
+ if (AnonStructUnion) {
llvm::SmallVector<FieldDecl*, 4> Path;
BuildAnonymousStructUnionMemberPath(MemberDecl, Path);
unsigned n = Path.size();
@@ -6897,10 +7027,10 @@ Sema::OwningExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
Exprs.data(), Exprs.size(), RParenLoc));
}
-Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
+ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
- TypeTy *argty,
+ ParsedType argty,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
SourceLocation RPLoc) {
@@ -6910,151 +7040,32 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
if (ArgTy.isNull())
return ExprError();
- if (getLangOptions().CPlusPlus) {
- if (!ArgTInfo)
- ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
-
- return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
- RPLoc);
- }
-
- // FIXME: The code below is marked for death, once we have proper CodeGen
- // support for non-constant OffsetOf expressions.
-
- bool Dependent = ArgTy->isDependentType();
-
- // We must have at least one component that refers to the type, and the first
- // one is known to be a field designator. Verify that the ArgTy represents
- // a struct/union/class.
- if (!Dependent && !ArgTy->isRecordType())
- return ExprError(Diag(TypeLoc, diag::err_offsetof_record_type) << ArgTy);
-
- // FIXME: Type must be complete per C99 7.17p3 because a declaring a variable
- // with an incomplete type would be illegal.
-
- // Otherwise, create a null pointer as the base, and iteratively process
- // the offsetof designators.
- QualType ArgTyPtr = Context.getPointerType(ArgTy);
- Expr* Res = new (Context) ImplicitValueInitExpr(ArgTyPtr);
- Res = new (Context) UnaryOperator(Res, UnaryOperator::Deref,
- ArgTy, SourceLocation());
-
- // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a
- // GCC extension, diagnose them.
- // FIXME: This diagnostic isn't actually visible because the location is in
- // a system header!
- if (NumComponents != 1)
- Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator)
- << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd);
-
- if (!Dependent) {
- bool DidWarnAboutNonPOD = false;
-
- if (RequireCompleteType(TypeLoc, Res->getType(),
- diag::err_offsetof_incomplete_type))
- return ExprError();
-
- // FIXME: Dependent case loses a lot of information here. And probably
- // leaks like a sieve.
- for (unsigned i = 0; i != NumComponents; ++i) {
- const OffsetOfComponent &OC = CompPtr[i];
- if (OC.isBrackets) {
- // Offset of an array sub-field. TODO: Should we allow vector elements?
- const ArrayType *AT = Context.getAsArrayType(Res->getType());
- if (!AT) {
- Res->Destroy(Context);
- return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
- << Res->getType());
- }
-
- // FIXME: C++: Verify that operator[] isn't overloaded.
-
- // Promote the array so it looks more like a normal array subscript
- // expression.
- DefaultFunctionArrayLvalueConversion(Res);
-
- // C99 6.5.2.1p1
- Expr *Idx = static_cast<Expr*>(OC.U.E);
- // FIXME: Leaks Res
- if (!Idx->isTypeDependent() && !Idx->getType()->isIntegerType())
- return ExprError(Diag(Idx->getLocStart(),
- diag::err_typecheck_subscript_not_integer)
- << Idx->getSourceRange());
-
- Res = new (Context) ArraySubscriptExpr(Res, Idx, AT->getElementType(),
- OC.LocEnd);
- continue;
- }
-
- const RecordType *RC = Res->getType()->getAs<RecordType>();
- if (!RC) {
- Res->Destroy(Context);
- return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
- << Res->getType());
- }
-
- // Get the decl corresponding to this.
- RecordDecl *RD = RC->getDecl();
- if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
- if (!CRD->isPOD() && !DidWarnAboutNonPOD &&
- DiagRuntimeBehavior(BuiltinLoc,
- PDiag(diag::warn_offsetof_non_pod_type)
- << SourceRange(CompPtr[0].LocStart, OC.LocEnd)
- << Res->getType()))
- DidWarnAboutNonPOD = true;
- }
-
- LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
- LookupQualifiedName(R, RD);
-
- FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
- // FIXME: Leaks Res
- if (!MemberDecl)
- return ExprError(Diag(BuiltinLoc, diag::err_no_member)
- << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, OC.LocEnd));
-
- // C99 7.17p3:
- // (If the specified member is a bit-field, the behavior is undefined.)
- //
- // We diagnose this as an error.
- if (MemberDecl->getBitWidth()) {
- Diag(OC.LocEnd, diag::err_offsetof_bitfield)
- << MemberDecl->getDeclName()
- << SourceRange(BuiltinLoc, RPLoc);
- Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
- return ExprError();
- }
-
- // FIXME: C++: Verify that MemberDecl isn't a static field.
- // FIXME: Verify that MemberDecl isn't a bitfield.
- if (cast<RecordDecl>(MemberDecl->getDeclContext())->isAnonymousStructOrUnion()) {
- Res = BuildAnonymousStructUnionMemberReference(
- OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
- } else {
- PerformObjectMemberConversion(Res, /*Qualifier=*/0,
- *R.begin(), MemberDecl);
- // MemberDecl->getType() doesn't get the right qualifiers, but it
- // doesn't matter here.
- Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,
- MemberDecl->getType().getNonReferenceType());
- }
- }
- }
-
- return Owned(new (Context) UnaryOperator(Res, UnaryOperator::OffsetOf,
- Context.getSizeType(), BuiltinLoc));
+ if (!ArgTInfo)
+ ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
+
+ return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents,
+ RPLoc);
}
-Sema::OwningExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
- TypeTy *arg1,TypeTy *arg2,
+ExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ ParsedType arg1,ParsedType arg2,
SourceLocation RPLoc) {
- // FIXME: Preserve type source info.
- QualType argT1 = GetTypeFromParser(arg1);
- QualType argT2 = GetTypeFromParser(arg2);
+ TypeSourceInfo *argTInfo1;
+ QualType argT1 = GetTypeFromParser(arg1, &argTInfo1);
+ TypeSourceInfo *argTInfo2;
+ QualType argT2 = GetTypeFromParser(arg2, &argTInfo2);
assert((!argT1.isNull() && !argT2.isNull()) && "Missing type argument(s)");
+ return BuildTypesCompatibleExpr(BuiltinLoc, argTInfo1, argTInfo2, RPLoc);
+}
+
+ExprResult
+Sema::BuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ TypeSourceInfo *argTInfo1,
+ TypeSourceInfo *argTInfo2,
+ SourceLocation RPLoc) {
if (getLangOptions().CPlusPlus) {
Diag(BuiltinLoc, diag::err_types_compatible_p_in_cplusplus)
<< SourceRange(BuiltinLoc, RPLoc);
@@ -7062,17 +7073,14 @@ Sema::OwningExprResult Sema::ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
}
return Owned(new (Context) TypesCompatibleExpr(Context.IntTy, BuiltinLoc,
- argT1, argT2, RPLoc));
+ argTInfo1, argTInfo2, RPLoc));
}
-Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
- ExprArg cond,
- ExprArg expr1, ExprArg expr2,
- SourceLocation RPLoc) {
- Expr *CondExpr = static_cast<Expr*>(cond.get());
- Expr *LHSExpr = static_cast<Expr*>(expr1.get());
- Expr *RHSExpr = static_cast<Expr*>(expr2.get());
+ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *CondExpr,
+ Expr *LHSExpr, Expr *RHSExpr,
+ SourceLocation RPLoc) {
assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
QualType resType;
@@ -7095,7 +7103,6 @@ Sema::OwningExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
: RHSExpr->isValueDependent();
}
- cond.release(); expr1.release(); expr2.release();
return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr,
resType, RPLoc,
resType->isDependentType(),
@@ -7232,8 +7239,8 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
/// ActOnBlockStmtExpr - This is called when the body of a block statement
/// literal was successfully completed. ^(int x){...}
-Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
- StmtArg body, Scope *CurScope) {
+ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
+ Stmt *Body, Scope *CurScope) {
// If blocks are disabled, emit an error.
if (!LangOpts.Blocks)
Diag(CaretLoc, diag::err_blocks_disable);
@@ -7295,10 +7302,10 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
- if (FunctionNeedsScopeChecking() && !hasAnyErrorsInThisFunction())
- DiagnoseInvalidJumps(static_cast<CompoundStmt*>(body.get()));
+ if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction())
+ DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
- BSI->TheDecl->setBody(body.takeAs<CompoundStmt>());
+ BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
bool Good = true;
// Check goto/label use.
@@ -7320,22 +7327,29 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
return ExprError();
}
+ BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy,
+ BSI->hasBlockDeclRefExprs);
+
// Issue any analysis-based warnings.
const sema::AnalysisBasedWarnings::Policy &WP =
AnalysisWarnings.getDefaultPolicy();
- AnalysisWarnings.IssueWarnings(WP, BSI->TheDecl, BlockTy);
+ AnalysisWarnings.IssueWarnings(WP, Result);
- Expr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy,
- BSI->hasBlockDeclRefExprs);
PopFunctionOrBlockScope();
return Owned(Result);
}
-Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
- ExprArg expr, TypeTy *type,
+ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
+ Expr *expr, ParsedType type,
SourceLocation RPLoc) {
- QualType T = GetTypeFromParser(type);
- Expr *E = static_cast<Expr*>(expr.get());
+ TypeSourceInfo *TInfo;
+ QualType T = GetTypeFromParser(type, &TInfo);
+ return BuildVAArgExpr(BuiltinLoc, expr, TInfo, RPLoc);
+}
+
+ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation RPLoc) {
Expr *OrigExpr = E;
InitBuiltinVaListType();
@@ -7367,13 +7381,11 @@ Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
// FIXME: Check that type is complete/non-abstract
// FIXME: Warn if a non-POD type is passed in.
- expr.release();
- return Owned(new (Context) VAArgExpr(BuiltinLoc, E,
- T.getNonLValueExprType(Context),
- RPLoc));
+ QualType T = TInfo->getType().getNonLValueExprType(Context);
+ return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T));
}
-Sema::OwningExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
+ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
// The type of __null will be int or long, depending on the size of
// pointers on the target.
QualType Ty;
@@ -7647,8 +7659,10 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
unsigned TypeQuals;
if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
- if (!Constructor->isUsed(false))
- DefineImplicitDefaultConstructor(Loc, Constructor);
+ if (Constructor->getParent()->hasTrivialConstructor())
+ return;
+ if (!Constructor->isUsed(false))
+ DefineImplicitDefaultConstructor(Loc, Constructor);
} else if (Constructor->isImplicit() &&
Constructor->isCopyConstructor(TypeQuals)) {
if (!Constructor->isUsed(false))
@@ -7696,13 +7710,20 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
Loc));
else
- PendingImplicitInstantiations.push_back(std::make_pair(Function,
- Loc));
+ PendingInstantiations.push_back(std::make_pair(Function, Loc));
+ }
+ } else // Walk redefinitions, as some of them may be instantiable.
+ for (FunctionDecl::redecl_iterator i(Function->redecls_begin()),
+ e(Function->redecls_end()); i != e; ++i) {
+ if (!i->isUsed(false) && i->isImplicitlyInstantiable())
+ MarkDeclarationReferenced(Loc, *i);
}
- }
// FIXME: keep track of references to static functions
- Function->setUsed(true);
+
+ // Recursive functions should be marked when used from another function.
+ if (CurContext != Function)
+ Function->setUsed(true);
return;
}
@@ -7716,7 +7737,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (MSInfo->getPointOfInstantiation().isInvalid() &&
MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
MSInfo->setPointOfInstantiation(Loc);
- PendingImplicitInstantiations.push_back(std::make_pair(Var, Loc));
+ PendingInstantiations.push_back(std::make_pair(Var, Loc));
}
}
@@ -7836,7 +7857,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
if (isa<BinaryOperator>(E)) {
BinaryOperator *Op = cast<BinaryOperator>(E);
- if (Op->getOpcode() != BinaryOperator::Assign)
+ if (Op->getOpcode() != BO_Assign)
return;
// Greylist some idioms by putting them into a warning subcategory.
@@ -7899,16 +7920,13 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) {
return false;
}
-Sema::OwningExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
- ExprArg SubExpr) {
- Expr *Sub = SubExpr.takeAs<Expr>();
+ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc,
+ Expr *Sub) {
if (!Sub)
return ExprError();
- if (CheckBooleanCondition(Sub, Loc)) {
- Sub->Destroy(Context);
+ if (CheckBooleanCondition(Sub, Loc))
return ExprError();
- }
return Owned(Sub);
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 090400fc4e23..5720d931b66b 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -11,28 +11,31 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedTemplate.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Template.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
-
-Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
- IdentifierInfo &II,
- SourceLocation NameLoc,
- Scope *S, CXXScopeSpec &SS,
- TypeTy *ObjectTypePtr,
- bool EnteringContext) {
+using namespace sema;
+
+ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II,
+ SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectTypePtr,
+ bool EnteringContext) {
// Determine where to perform name lookup.
// FIXME: This area of the standard is very messy, and the current
@@ -149,7 +152,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
// FIXME: Should we be suppressing ambiguities here?
if (Found.isAmbiguous())
- return 0;
+ return ParsedType();
if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) {
QualType T = Context.getTypeDeclType(Type);
@@ -158,7 +161,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
Context.hasSameUnqualifiedType(T, SearchType)) {
// We found our type!
- return T.getAsOpaquePtr();
+ return ParsedType::make(T);
}
}
@@ -191,7 +194,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (Spec->getSpecializedTemplate()->getCanonicalDecl() ==
Template->getCanonicalDecl())
- return MemberOfType.getAsOpaquePtr();
+ return ParsedType::make(MemberOfType);
}
continue;
@@ -210,7 +213,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
// specialized.
if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) {
if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl())
- return MemberOfType.getAsOpaquePtr();
+ return ParsedType::make(MemberOfType);
continue;
}
@@ -221,7 +224,7 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
= SpecName.getAsDependentTemplateName()) {
if (DepTemplate->isIdentifier() &&
DepTemplate->getIdentifier() == Template->getIdentifier())
- return MemberOfType.getAsOpaquePtr();
+ return ParsedType::make(MemberOfType);
continue;
}
@@ -242,8 +245,10 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
Range = SourceRange(NameLoc);
}
- return CheckTypenameType(ETK_None, NNS, II, SourceLocation(),
- Range, NameLoc).getAsOpaquePtr();
+ QualType T = CheckTypenameType(ETK_None, NNS, II,
+ SourceLocation(),
+ Range, NameLoc);
+ return ParsedType::make(T);
}
if (ObjectTypePtr)
@@ -252,11 +257,11 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc,
else
Diag(NameLoc, diag::err_destructor_class_name);
- return 0;
+ return ParsedType();
}
/// \brief Build a C++ typeid expression with a type operand.
-Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
+ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
SourceLocation RParenLoc) {
@@ -279,12 +284,11 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
}
/// \brief Build a C++ typeid expression with an expression operand.
-Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
+ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
SourceLocation TypeidLoc,
- ExprArg Operand,
+ Expr *E,
SourceLocation RParenLoc) {
bool isUnevaluatedOperand = true;
- Expr *E = static_cast<Expr *>(Operand.get());
if (E && !E->isTypeDependent()) {
QualType T = E->getType();
if (const RecordType *RecordT = T->getAs<RecordType>()) {
@@ -296,10 +300,10 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
return ExprError();
// C++ [expr.typeid]p3:
- // When typeid is applied to an expression other than an lvalue of a
+ // When typeid is applied to an expression other than an glvalue of a
// polymorphic class type [...] [the] expression is an unevaluated
// operand. [...]
- if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) {
+ if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
isUnevaluatedOperand = false;
// We require a vtable to query the type at run time.
@@ -316,9 +320,7 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals);
if (!Context.hasSameType(T, UnqualT)) {
T = UnqualT;
- ImpCastExprToType(E, UnqualT, CastExpr::CK_NoOp, E->isLvalue(Context));
- Operand.release();
- Operand = Owned(E);
+ ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E));
}
}
@@ -329,12 +331,12 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
ExprEvalContexts.back().Context = Unevaluated;
return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
- Operand.takeAs<Expr>(),
+ E,
SourceRange(TypeidLoc, RParenLoc)));
}
/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression);
-Action::OwningExprResult
+ExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
// Find the std::type_info type.
@@ -343,7 +345,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName);
- LookupQualifiedName(R, StdNamespace);
+ LookupQualifiedName(R, getStdNamespace());
RecordDecl *TypeInfoRecordDecl = R.getAsSingle<RecordDecl>();
if (!TypeInfoRecordDecl)
return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid));
@@ -353,7 +355,8 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
if (isType) {
// The operand is a type; handle it as such.
TypeSourceInfo *TInfo = 0;
- QualType T = GetTypeFromParser(TyOrExpr, &TInfo);
+ QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr),
+ &TInfo);
if (T.isNull())
return ExprError();
@@ -364,11 +367,11 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
}
// The operand is an expression.
- return BuildCXXTypeId(TypeInfoType, OpLoc, Owned((Expr*)TyOrExpr), RParenLoc);
+ return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
}
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
-Action::OwningExprResult
+ExprResult
Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
assert((Kind == tok::kw_true || Kind == tok::kw_false) &&
"Unknown C++ Boolean value!");
@@ -377,15 +380,14 @@ Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
}
/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
-Action::OwningExprResult
+ExprResult
Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
}
/// ActOnCXXThrow - Parse throw expressions.
-Action::OwningExprResult
-Sema::ActOnCXXThrow(SourceLocation OpLoc, ExprArg E) {
- Expr *Ex = E.takeAs<Expr>();
+ExprResult
+Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) {
if (Ex && !Ex->isTypeDependent() && CheckCXXThrowOperand(OpLoc, Ex))
return ExprError();
return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc));
@@ -400,8 +402,8 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
// the type from "array of T" or "function returning T" to "pointer to T"
// or "pointer to function returning T", [...]
if (E->getType().hasQualifiers())
- ImpCastExprToType(E, E->getType().getUnqualifiedType(), CastExpr::CK_NoOp,
- E->isLvalue(Context) == Expr::LV_Valid);
+ ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
+ CastCategory(E));
DefaultFunctionArrayConversion(E);
@@ -432,7 +434,7 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
InitializedEntity Entity =
InitializedEntity::InitializeException(ThrowLoc, E->getType(),
/*NRVO=*/false);
- OwningExprResult Res = PerformCopyInitialization(Entity,
+ ExprResult Res = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(E));
if (Res.isInvalid())
@@ -464,7 +466,7 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
return false;
}
-Action::OwningExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
+ExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
/// C++ 9.3.2: In the body of a non-static member function, the keyword this
/// is a non-lvalue expression whose value is the address of the object for
/// which the function is called.
@@ -483,8 +485,8 @@ Action::OwningExprResult Sema::ActOnCXXThis(SourceLocation ThisLoc) {
/// Can be interpreted either as function-style casting ("int(x)")
/// or class type construction ("ClassType(x,y,z)")
/// or creation of a value-initialized type ("int()").
-Action::OwningExprResult
-Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
+ExprResult
+Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, ParsedType TypeRep,
SourceLocation LParenLoc,
MultiExprArg exprs,
SourceLocation *CommaLocs,
@@ -532,19 +534,19 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
// corresponding cast expression.
//
if (NumExprs == 1) {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, BasePath,
/*FunctionalStyle=*/true))
return ExprError();
exprs.release();
- return Owned(new (Context) CXXFunctionalCastExpr(
+ return Owned(CXXFunctionalCastExpr::Create(Context,
Ty.getNonLValueExprType(Context),
- TInfo, TyBeginLoc, Kind,
- Exprs[0], BasePath,
- RParenLoc));
+ TInfo, TyBeginLoc, Kind,
+ Exprs[0], &BasePath,
+ RParenLoc));
}
if (Ty->isRecordType()) {
@@ -555,7 +557,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
: InitializationKind::CreateValue(TypeRange.getBegin(),
LParenLoc, RParenLoc);
InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
- OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
move(exprs));
// FIXME: Improve AST representation?
@@ -587,7 +589,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
/// or
/// @code ::new Foo(23, "hello") @endcode
/// For the interpretation of this heap of arguments, consult the base version.
-Action::OwningExprResult
+ExprResult
Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
SourceLocation PlacementRParen, SourceRange TypeIdParens,
@@ -643,13 +645,13 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
AllocType,
D.getSourceRange().getBegin(),
R,
- Owned(ArraySize),
+ ArraySize,
ConstructorLParen,
move(ConstructorArgs),
ConstructorRParen);
}
-Sema::OwningExprResult
+ExprResult
Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
SourceLocation PlacementLParen,
MultiExprArg PlacementArgs,
@@ -658,7 +660,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
QualType AllocType,
SourceLocation TypeLoc,
SourceRange TypeRange,
- ExprArg ArraySizeE,
+ Expr *ArraySize,
SourceLocation ConstructorLParen,
MultiExprArg ConstructorArgs,
SourceLocation ConstructorRParen) {
@@ -667,12 +669,12 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
- if (!ArraySizeE.get()) {
+ if (!ArraySize) {
if (const ConstantArrayType *Array
= Context.getAsConstantArrayType(AllocType)) {
- ArraySizeE = Owned(new (Context) IntegerLiteral(Array->getSize(),
- Context.getSizeType(),
- TypeRange.getEnd()));
+ ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
+ Context.getSizeType(),
+ TypeRange.getEnd());
AllocType = Array->getElementType();
}
}
@@ -681,13 +683,12 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
// C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
// or enumeration type with a non-negative value."
- Expr *ArraySize = (Expr *)ArraySizeE.get();
if (ArraySize && !ArraySize->isTypeDependent()) {
QualType SizeType = ArraySize->getType();
- OwningExprResult ConvertedSize
- = ConvertToIntegralOrEnumerationType(StartLoc, move(ArraySizeE),
+ ExprResult ConvertedSize
+ = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize,
PDiag(diag::err_array_size_not_integral),
PDiag(diag::err_array_size_incomplete_type)
<< ArraySize->getSourceRange(),
@@ -700,8 +701,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
if (ConvertedSize.isInvalid())
return ExprError();
- ArraySize = ConvertedSize.takeAs<Expr>();
- ArraySizeE = Owned(ArraySize);
+ ArraySize = ConvertedSize.take();
SizeType = ArraySize->getType();
if (!SizeType->isIntegralOrEnumerationType())
return ExprError();
@@ -716,8 +716,20 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
llvm::APInt::getNullValue(Value.getBitWidth()),
Value.isUnsigned()))
return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
- diag::err_typecheck_negative_array_size)
+ diag::err_typecheck_negative_array_size)
<< ArraySize->getSourceRange());
+
+ if (!AllocType->isDependentType()) {
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
+ Diag(ArraySize->getSourceRange().getBegin(),
+ diag::err_array_too_large)
+ << Value.toString(10)
+ << ArraySize->getSourceRange();
+ return ExprError();
+ }
+ }
} else if (TypeIdParens.isValid()) {
// Can't have dynamic array size when the type-id is in parentheses.
Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst)
@@ -730,7 +742,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
}
ImpCastExprToType(ArraySize, Context.getSizeType(),
- CastExpr::CK_IntegralCast);
+ CK_IntegralCast);
}
FunctionDecl *OperatorNew = 0;
@@ -768,7 +780,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
CXXConstructorDecl *Constructor = 0;
Expr **ConsArgs = (Expr**)ConstructorArgs.get();
unsigned NumConsArgs = ConstructorArgs.size();
- ASTOwningVector<&ActionBase::DeleteExpr> ConvertedConstructorArgs(*this);
+ ASTOwningVector<Expr*> ConvertedConstructorArgs(*this);
// Array 'new' can't have any initializers.
if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) {
@@ -798,7 +810,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
InitializedEntity Entity
= InitializedEntity::InitializeNew(StartLoc, AllocType);
InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs);
- OwningExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
+ ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind,
move(ConstructorArgs));
if (FullInit.isInvalid())
return ExprError();
@@ -839,7 +851,6 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
PlacementArgs.release();
ConstructorArgs.release();
- ArraySizeE.release();
// FIXME: The TypeSourceInfo should also be included in CXXNewExpr.
return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew,
@@ -911,7 +922,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// We don't care about the actual value of this argument.
// FIXME: Should the Sema create the expression and embed it in the syntax
// tree? Or should the consumer just recalculate the value?
- IntegerLiteral Size(llvm::APInt::getNullValue(
+ IntegerLiteral Size(Context, llvm::APInt::getNullValue(
Context.Target.getPointerWidth(0)),
Context.getSizeType(),
SourceLocation());
@@ -929,9 +940,11 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
IsArray ? OO_Array_Delete : OO_Delete);
- if (AllocType->isRecordType() && !UseGlobal) {
+ QualType AllocElemType = Context.getBaseElementType(AllocType);
+
+ if (AllocElemType->isRecordType() && !UseGlobal) {
CXXRecordDecl *Record
- = cast<CXXRecordDecl>(AllocType->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0],
AllocArgs.size(), Record, /*AllowMissing=*/true,
OperatorNew))
@@ -969,9 +982,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// the allocated type is not a class type or array thereof, the
// deallocation function’s name is looked up in the global scope.
LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName);
- if (AllocType->isRecordType() && !UseGlobal) {
+ if (AllocElemType->isRecordType() && !UseGlobal) {
CXXRecordDecl *RD
- = cast<CXXRecordDecl>(AllocType->getAs<RecordType>()->getDecl());
+ = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl());
LookupQualifiedName(FoundDelete, RD);
}
if (FoundDelete.isAmbiguous())
@@ -1115,7 +1128,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// Do the resolution.
OverloadCandidateSet::iterator Best;
- switch(BestViableFunction(Candidates, StartLoc, Best)) {
+ switch (Candidates.BestViableFunction(*this, StartLoc, Best)) {
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
@@ -1125,7 +1138,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
// Watch out for variadic allocator function.
unsigned NumArgsInFnDecl = FnDecl->getNumParams();
for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) {
- OwningExprResult Result
+ ExprResult Result
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
FnDecl->getParamDecl(i)),
SourceLocation(),
@@ -1143,20 +1156,20 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
case OR_No_Viable_Function:
Diag(StartLoc, diag::err_ovl_no_viable_function_in_call)
<< Name << Range;
- PrintOverloadCandidates(Candidates, OCD_AllCandidates, Args, NumArgs);
+ Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return true;
case OR_Ambiguous:
Diag(StartLoc, diag::err_ovl_ambiguous_call)
<< Name << Range;
- PrintOverloadCandidates(Candidates, OCD_ViableCandidates, Args, NumArgs);
+ Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
return true;
case OR_Deleted:
Diag(StartLoc, diag::err_ovl_deleted_call)
<< Best->Function->isDeleted()
<< Name << Range;
- PrintOverloadCandidates(Candidates, OCD_AllCandidates, Args, NumArgs);
+ Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
return true;
}
assert(false && "Unreachable, bad result from BestViableFunction");
@@ -1199,11 +1212,11 @@ void Sema::DeclareGlobalNewDelete() {
// The "std::bad_alloc" class has not yet been declared, so build it
// implicitly.
StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
- getStdNamespace(),
+ getOrCreateStdNamespace(),
SourceLocation(),
&PP.getIdentifierTable().get("bad_alloc"),
SourceLocation(), 0);
- StdBadAlloc->setImplicit(true);
+ getStdBadAlloc()->setImplicit(true);
}
GlobalNewDeleteDeclared = true;
@@ -1245,8 +1258,11 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Context.getCanonicalType(
Func->getParamDecl(0)->getType().getUnqualifiedType());
// FIXME: Do we need to check for default arguments here?
- if (Func->getNumParams() == 1 && InitialParamType == Argument)
+ if (Func->getNumParams() == 1 && InitialParamType == Argument) {
+ if(AddMallocAttr && !Func->hasAttr<MallocAttr>())
+ Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
return;
+ }
}
}
}
@@ -1257,7 +1273,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Name.getCXXOverloadedOperator() == OO_Array_New);
if (HasBadAllocExceptionSpec) {
assert(StdBadAlloc && "Must have std::bad_alloc declared");
- BadAllocType = Context.getTypeDeclType(StdBadAlloc);
+ BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
}
QualType FnType = Context.getFunctionType(Return, &Argument, 1, false, 0,
@@ -1267,23 +1283,23 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
FunctionType::ExtInfo());
FunctionDecl *Alloc =
FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), Name,
- FnType, /*TInfo=*/0, FunctionDecl::None,
- FunctionDecl::None, false, true);
+ FnType, /*TInfo=*/0, SC_None,
+ SC_None, false, true);
Alloc->setImplicit();
if (AddMallocAttr)
- Alloc->addAttr(::new (Context) MallocAttr());
+ Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context));
ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(),
0, Argument, /*TInfo=*/0,
- VarDecl::None,
- VarDecl::None, 0);
+ SC_None,
+ SC_None, 0);
Alloc->setParams(&Param, 1);
// FIXME: Also add this declaration to the IdentifierResolver, but
// make sure it is at the end of the chain to coincide with the
// global scope.
- ((DeclContext *)TUScope->getEntity())->addDecl(Alloc);
+ Context.getTranslationUnitDecl()->addDecl(Alloc);
}
bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
@@ -1298,15 +1314,37 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
Found.suppressDiagnostics();
+ llvm::SmallVector<DeclAccessPair,4> Matches;
for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
F != FEnd; ++F) {
- if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
- if (Delete->isUsualDeallocationFunction()) {
- Operator = Delete;
- CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
- F.getPair());
- return false;
- }
+ NamedDecl *ND = (*F)->getUnderlyingDecl();
+
+ // Ignore template operator delete members from the check for a usual
+ // deallocation function.
+ if (isa<FunctionTemplateDecl>(ND))
+ continue;
+
+ if (cast<CXXMethodDecl>(ND)->isUsualDeallocationFunction())
+ Matches.push_back(F.getPair());
+ }
+
+ // There's exactly one suitable operator; pick it.
+ if (Matches.size() == 1) {
+ Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl());
+ CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(),
+ Matches[0]);
+ return false;
+
+ // We found multiple suitable operators; complain about the ambiguity.
+ } else if (!Matches.empty()) {
+ Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found)
+ << Name << RD;
+
+ for (llvm::SmallVectorImpl<DeclAccessPair>::iterator
+ F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)
+ Diag((*F)->getUnderlyingDecl()->getLocation(),
+ diag::note_member_declared_here) << Name;
+ return true;
}
// We did find operator delete/operator delete[] declarations, but
@@ -1316,10 +1354,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
<< Name << RD;
for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
- F != FEnd; ++F) {
- Diag((*F)->getLocation(), diag::note_member_declared_here)
- << Name;
- }
+ F != FEnd; ++F)
+ Diag((*F)->getUnderlyingDecl()->getLocation(),
+ diag::note_member_declared_here) << Name;
return true;
}
@@ -1344,9 +1381,9 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
/// @code ::delete ptr; @endcode
/// or
/// @code delete [] ptr; @endcode
-Action::OwningExprResult
+ExprResult
Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
- bool ArrayForm, ExprArg Operand) {
+ bool ArrayForm, Expr *Ex) {
// C++ [expr.delete]p1:
// The operand shall have a pointer type, or a class type having a single
// conversion function to a pointer type. The result has type void.
@@ -1355,11 +1392,14 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
FunctionDecl *OperatorDelete = 0;
- Expr *Ex = (Expr *)Operand.get();
if (!Ex->isTypeDependent()) {
QualType Type = Ex->getType();
if (const RecordType *Record = Type->getAs<RecordType>()) {
+ if (RequireCompleteType(StartLoc, Type,
+ PDiag(diag::err_delete_incomplete_class_type)))
+ return ExprError();
+
llvm::SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;
CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
@@ -1378,18 +1418,16 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
QualType ConvType = Conv->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
- if (ConvPtrType->getPointeeType()->isObjectType())
+ if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())
ObjectPtrConversions.push_back(Conv);
}
if (ObjectPtrConversions.size() == 1) {
// We have a single conversion to a pointer-to-object type. Perform
// that conversion.
// TODO: don't redo the conversion calculation.
- Operand.release();
if (!PerformImplicitConversion(Ex,
ObjectPtrConversions.front()->getConversionType(),
AA_Converting)) {
- Operand = Owned(Ex);
Type = Ex->getType();
}
}
@@ -1428,16 +1466,13 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// (5.2.11) of the pointer expression before it is used as the operand
// of the delete-expression. ]
ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy),
- CastExpr::CK_NoOp);
-
- // Update the operand.
- Operand.take();
- Operand = ExprArg(*this, Ex);
+ CK_NoOp);
DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
ArrayForm ? OO_Array_Delete : OO_Delete);
- if (const RecordType *RT = Pointee->getAs<RecordType>()) {
+ QualType PointeeElem = Context.getBaseElementType(Pointee);
+ if (const RecordType *RT = PointeeElem->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (!UseGlobal &&
@@ -1465,14 +1500,13 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// FIXME: Check access and ambiguity of operator delete and destructor.
}
- Operand.release();
return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
OperatorDelete, Ex, StartLoc));
}
/// \brief Check the use of the given variable as a C++ condition in an if,
/// while, do-while, or switch statement.
-Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
+ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
SourceLocation StmtLoc,
bool ConvertToBoolean) {
QualType T = ConditionVar->getType();
@@ -1491,10 +1525,8 @@ Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
ConditionVar->getLocation(),
ConditionVar->getType().getNonReferenceType());
- if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc)) {
- Condition->Destroy(Context);
+ if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc))
return ExprError();
- }
return Owned(Condition);
}
@@ -1543,34 +1575,33 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) {
return false;
}
-static Sema::OwningExprResult BuildCXXCastArgument(Sema &S,
- SourceLocation CastLoc,
- QualType Ty,
- CastExpr::CastKind Kind,
- CXXMethodDecl *Method,
- Sema::ExprArg Arg) {
- Expr *From = Arg.takeAs<Expr>();
-
+static ExprResult BuildCXXCastArgument(Sema &S,
+ SourceLocation CastLoc,
+ QualType Ty,
+ CastKind Kind,
+ CXXMethodDecl *Method,
+ Expr *From) {
switch (Kind) {
default: assert(0 && "Unhandled cast kind!");
- case CastExpr::CK_ConstructorConversion: {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+ case CK_ConstructorConversion: {
+ ASTOwningVector<Expr*> ConstructorArgs(S);
if (S.CompleteConstructorCall(cast<CXXConstructorDecl>(Method),
- Sema::MultiExprArg(S, (void **)&From, 1),
+ MultiExprArg(&From, 1),
CastLoc, ConstructorArgs))
- return S.ExprError();
+ return ExprError();
- Sema::OwningExprResult Result =
+ ExprResult Result =
S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
- move_arg(ConstructorArgs));
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false, CXXConstructExpr::CK_Complete);
if (Result.isInvalid())
- return S.ExprError();
+ return ExprError();
return S.MaybeBindToTemporary(Result.takeAs<Expr>());
}
- case CastExpr::CK_UserDefinedConversion: {
+ case CK_UserDefinedConversion: {
assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
// Create an implicit call expr that calls it.
@@ -1601,10 +1632,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
case ImplicitConversionSequence::UserDefinedConversion: {
FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
- CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
+ CastKind CastKind = CK_Unknown;
QualType BeforeToType;
if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
- CastKind = CastExpr::CK_UserDefinedConversion;
+ CastKind = CK_UserDefinedConversion;
// If the user-defined conversion is specified by a conversion function,
// the initial standard conversion sequence converts the source type to
@@ -1612,7 +1643,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
BeforeToType = Context.getTagDeclType(Conv->getParent());
} else if (const CXXConstructorDecl *Ctor =
dyn_cast<CXXConstructorDecl>(FD)) {
- CastKind = CastExpr::CK_ConstructorConversion;
+ CastKind = CK_ConstructorConversion;
// 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
@@ -1631,12 +1662,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
return true;
}
- OwningExprResult CastArg
+ ExprResult CastArg
= BuildCXXCastArgument(*this,
From->getLocStart(),
ToType.getNonReferenceType(),
CastKind, cast<CXXMethodDecl>(FD),
- Owned(From));
+ From);
if (CastArg.isInvalid())
return true;
@@ -1648,7 +1679,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
}
case ImplicitConversionSequence::AmbiguousConversion:
- DiagnoseAmbiguousConversion(ICS, From->getExprLoc(),
+ ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(),
PDiag(diag::err_typecheck_ambiguous_condition)
<< From->getSourceRange());
return true;
@@ -1685,25 +1716,29 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// FIXME: When can ToType be a reference type?
assert(!ToType->isReferenceType());
if (SCS.Second == ICK_Derived_To_Base) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+ ASTOwningVector<Expr*> ConstructorArgs(*this);
if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor),
- MultiExprArg(*this, (void **)&From, 1),
+ MultiExprArg(*this, &From, 1),
/*FIXME:ConstructLoc*/SourceLocation(),
ConstructorArgs))
return true;
- OwningExprResult FromResult =
+ ExprResult FromResult =
BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
ToType, SCS.CopyConstructor,
- move_arg(ConstructorArgs));
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete);
if (FromResult.isInvalid())
return true;
From = FromResult.takeAs<Expr>();
return false;
}
- OwningExprResult FromResult =
+ ExprResult FromResult =
BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
ToType, SCS.CopyConstructor,
- MultiExprArg(*this, (void**)&From, 1));
+ MultiExprArg(*this, &From, 1),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete);
if (FromResult.isInvalid())
return true;
@@ -1736,12 +1771,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
case ICK_Array_To_Pointer:
FromType = Context.getArrayDecayedType(FromType);
- ImpCastExprToType(From, FromType, CastExpr::CK_ArrayToPointerDecay);
+ ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay);
break;
case ICK_Function_To_Pointer:
FromType = Context.getPointerType(FromType);
- ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay);
+ ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay);
break;
default:
@@ -1766,33 +1801,33 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
return true;
ImpCastExprToType(From, Context.getNoReturnType(From->getType(), false),
- CastExpr::CK_NoOp);
+ CK_NoOp);
break;
case ICK_Integral_Promotion:
case ICK_Integral_Conversion:
- ImpCastExprToType(From, ToType, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(From, ToType, CK_IntegralCast);
break;
case ICK_Floating_Promotion:
case ICK_Floating_Conversion:
- ImpCastExprToType(From, ToType, CastExpr::CK_FloatingCast);
+ ImpCastExprToType(From, ToType, CK_FloatingCast);
break;
case ICK_Complex_Promotion:
case ICK_Complex_Conversion:
- ImpCastExprToType(From, ToType, CastExpr::CK_Unknown);
+ ImpCastExprToType(From, ToType, CK_Unknown);
break;
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
- ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating);
+ ImpCastExprToType(From, ToType, CK_IntegralToFloating);
else
- ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral);
+ ImpCastExprToType(From, ToType, CK_FloatingToIntegral);
break;
case ICK_Compatible_Conversion:
- ImpCastExprToType(From, ToType, CastExpr::CK_NoOp);
+ ImpCastExprToType(From, ToType, CK_NoOp);
break;
case ICK_Pointer_Conversion: {
@@ -1805,36 +1840,36 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
}
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (CheckPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess))
return true;
- ImpCastExprToType(From, ToType, Kind, /*isLvalue=*/false, BasePath);
+ ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath);
break;
}
case ICK_Pointer_Member: {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXBaseSpecifierArray BasePath;
+ CastKind Kind = CK_Unknown;
+ CXXCastPath BasePath;
if (CheckMemberPointerConversion(From, ToType, Kind, BasePath,
IgnoreBaseAccess))
return true;
if (CheckExceptionSpecCompatibility(From, ToType))
return true;
- ImpCastExprToType(From, ToType, Kind, /*isLvalue=*/false, BasePath);
+ ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath);
break;
}
case ICK_Boolean_Conversion: {
- CastExpr::CastKind Kind = CastExpr::CK_Unknown;
+ CastKind Kind = CK_Unknown;
if (FromType->isMemberPointerType())
- Kind = CastExpr::CK_MemberPointerToBoolean;
+ Kind = CK_MemberPointerToBoolean;
ImpCastExprToType(From, Context.BoolTy, Kind);
break;
}
case ICK_Derived_To_Base: {
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(From->getType(),
ToType.getNonReferenceType(),
From->getLocStart(),
@@ -1843,24 +1878,22 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
IgnoreBaseAccess))
return true;
- ImpCastExprToType(From, ToType.getNonReferenceType(),
- CastExpr::CK_DerivedToBase,
- /*isLvalue=*/(From->getType()->isRecordType() &&
- From->isLvalue(Context) == Expr::LV_Valid),
- BasePath);
+ ImpCastExprToType(From, ToType.getNonReferenceType(),
+ CK_DerivedToBase, CastCategory(From),
+ &BasePath);
break;
}
case ICK_Vector_Conversion:
- ImpCastExprToType(From, ToType, CastExpr::CK_BitCast);
+ ImpCastExprToType(From, ToType, CK_BitCast);
break;
case ICK_Vector_Splat:
- ImpCastExprToType(From, ToType, CastExpr::CK_VectorSplat);
+ ImpCastExprToType(From, ToType, CK_VectorSplat);
break;
case ICK_Complex_Real:
- ImpCastExprToType(From, ToType, CastExpr::CK_Unknown);
+ ImpCastExprToType(From, ToType, CK_Unknown);
break;
case ICK_Lvalue_To_Rvalue:
@@ -1877,18 +1910,21 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
// Nothing to do.
break;
- case ICK_Qualification:
- // FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue
- // references.
+ case ICK_Qualification: {
+ // The qualification keeps the category of the inner expression, unless the
+ // target type isn't a reference.
+ ExprValueKind VK = ToType->isReferenceType() ?
+ CastCategory(From) : VK_RValue;
ImpCastExprToType(From, ToType.getNonLValueExprType(Context),
- CastExpr::CK_NoOp, ToType->isLValueReferenceType());
+ CK_NoOp, VK);
if (SCS.DeprecatedStringLiteralToCharPtr)
Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
<< ToType.getNonReferenceType();
break;
-
+ }
+
default:
assert(false && "Improper third standard conversion");
break;
@@ -1897,10 +1933,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
return false;
}
-Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
SourceLocation KWLoc,
SourceLocation LParen,
- TypeTy *Ty,
+ ParsedType Ty,
SourceLocation RParen) {
QualType T = GetTypeFromParser(Ty);
@@ -1974,12 +2010,12 @@ QualType Sema::CheckPointerToMemberOperands(
}
// Cast LHS to type of use.
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
- bool isLValue = !isIndirect && lex->isLvalue(Context) == Expr::LV_Valid;
-
- CXXBaseSpecifierArray BasePath;
+ ExprValueKind VK =
+ isIndirect ? VK_RValue : CastCategory(lex);
+
+ CXXCastPath BasePath;
BuildBasePathArray(Paths, BasePath);
- ImpCastExprToType(lex, UseType, CastExpr::CK_DerivedToBase, isLValue,
- BasePath);
+ ImpCastExprToType(lex, UseType, CK_DerivedToBase, VK, &BasePath);
}
if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) {
@@ -2108,7 +2144,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet);
OverloadCandidateSet::iterator Best;
- switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
+ switch (CandidateSet.BestViableFunction(Self, Loc, Best)) {
case OR_Success:
// We found a match. Perform the conversions on the arguments and move on.
if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
@@ -2146,8 +2182,7 @@ static bool ConvertForConditional(Sema &Self, Expr *&E, QualType T) {
InitializationKind Kind = InitializationKind::CreateCopy(E->getLocStart(),
SourceLocation());
InitializationSequence InitSeq(Self, Entity, Kind, &E, 1);
- Sema::OwningExprResult Result = InitSeq.Perform(Self, Entity, Kind,
- Sema::MultiExprArg(Self, (void **)&E, 1));
+ ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&E, 1));
if (Result.isInvalid())
return true;
@@ -2286,13 +2321,13 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
if (LTy->isRecordType()) {
// The operands have class type. Make a temporary copy.
InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy);
- OwningExprResult LHSCopy = PerformCopyInitialization(Entity,
+ ExprResult LHSCopy = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(LHS));
if (LHSCopy.isInvalid())
return QualType();
- OwningExprResult RHSCopy = PerformCopyInitialization(Entity,
+ ExprResult RHSCopy = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(RHS));
if (RHSCopy.isInvalid())
@@ -2385,16 +2420,16 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
// the type of the other operand.
if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T2->isMemberPointerType())
- ImpCastExprToType(E1, T2, CastExpr::CK_NullToMemberPointer);
+ ImpCastExprToType(E1, T2, CK_NullToMemberPointer);
else
- ImpCastExprToType(E1, T2, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(E1, T2, CK_IntegralToPointer);
return T2;
}
if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T1->isMemberPointerType())
- ImpCastExprToType(E2, T1, CastExpr::CK_NullToMemberPointer);
+ ImpCastExprToType(E2, T1, CK_NullToMemberPointer);
else
- ImpCastExprToType(E2, T1, CastExpr::CK_IntegralToPointer);
+ ImpCastExprToType(E2, T1, CK_IntegralToPointer);
return T1;
}
@@ -2528,15 +2563,15 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
}
// Convert E1 to Composite1
- OwningExprResult E1Result
- = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,(void**)&E1,1));
+ ExprResult E1Result
+ = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1));
if (E1Result.isInvalid())
return QualType();
E1 = E1Result.takeAs<Expr>();
// Convert E2 to Composite1
- OwningExprResult E2Result
- = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,(void**)&E2,1));
+ ExprResult E2Result
+ = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1));
if (E2Result.isInvalid())
return QualType();
E2 = E2Result.takeAs<Expr>();
@@ -2553,15 +2588,15 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
return QualType();
// Convert E1 to Composite2
- OwningExprResult E1Result
- = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, (void**)&E1, 1));
+ ExprResult E1Result
+ = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1));
if (E1Result.isInvalid())
return QualType();
E1 = E1Result.takeAs<Expr>();
// Convert E2 to Composite2
- OwningExprResult E2Result
- = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, (void**)&E2, 1));
+ ExprResult E2Result
+ = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1));
if (E2Result.isInvalid())
return QualType();
E2 = E2Result.takeAs<Expr>();
@@ -2569,7 +2604,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
return Composite2;
}
-Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
+ExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (!Context.getLangOptions().CPlusPlus)
return Owned(E);
@@ -2579,34 +2614,22 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
if (!RT)
return Owned(E);
- // If this is the result of a call expression, our source might
- // actually be a reference, in which case we shouldn't bind.
+ // If this is the result of a call or an Objective-C message send expression,
+ // our source might actually be a reference, in which case we shouldn't bind.
if (CallExpr *CE = dyn_cast<CallExpr>(E)) {
- QualType Ty = CE->getCallee()->getType();
- if (const PointerType *PT = Ty->getAs<PointerType>())
- Ty = PT->getPointeeType();
- else if (const BlockPointerType *BPT = Ty->getAs<BlockPointerType>())
- Ty = BPT->getPointeeType();
-
- const FunctionType *FTy = Ty->getAs<FunctionType>();
- if (FTy->getResultType()->isReferenceType())
+ if (CE->getCallReturnType()->isReferenceType())
return Owned(E);
+ } else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ if (const ObjCMethodDecl *MD = ME->getMethodDecl()) {
+ if (MD->getResultType()->isReferenceType())
+ return Owned(E);
+ }
}
- else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
- QualType Ty = ME->getType();
- if (const PointerType *PT = Ty->getAs<PointerType>())
- Ty = PT->getPointeeType();
- else if (const BlockPointerType *BPT = Ty->getAs<BlockPointerType>())
- Ty = BPT->getPointeeType();
- if (Ty->isReferenceType())
- return Owned(E);
- }
-
// That should be enough to guarantee that this type is complete.
// If it has a trivial destructor, we can avoid the extra copy.
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
- if (RD->hasTrivialDestructor())
+ if (RD->isInvalidDecl() || RD->hasTrivialDestructor())
return Owned(E);
CXXTemporary *Temp = CXXTemporary::Create(Context, LookupDestructor(RD));
@@ -2641,8 +2664,8 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr) {
return E;
}
-Sema::OwningExprResult
-Sema::MaybeCreateCXXExprWithTemporaries(OwningExprResult SubExpr) {
+ExprResult
+Sema::MaybeCreateCXXExprWithTemporaries(ExprResult SubExpr) {
if (SubExpr.isInvalid())
return ExprError();
@@ -2665,17 +2688,16 @@ FullExpr Sema::CreateFullExpr(Expr *SubExpr) {
return E;
}
-Sema::OwningExprResult
-Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, TypeTy *&ObjectType,
+ExprResult
+Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind, ParsedType &ObjectType,
bool &MayBePseudoDestructor) {
// Since this might be a postfix expression, get rid of ParenListExprs.
- Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid()) return ExprError();
+ Base = Result.get();
- Expr *BaseExpr = (Expr*)Base.get();
- assert(BaseExpr && "no record expansion");
-
- QualType BaseType = BaseExpr->getType();
+ QualType BaseType = Base->getType();
MayBePseudoDestructor = false;
if (BaseType->isDependentType()) {
// If we have a pointer to a dependent type and are using the -> operator,
@@ -2685,9 +2707,9 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
if (const PointerType *Ptr = BaseType->getAs<PointerType>())
BaseType = Ptr->getPointeeType();
- ObjectType = BaseType.getAsOpaquePtr();
+ ObjectType = ParsedType::make(BaseType);
MayBePseudoDestructor = true;
- return move(Base);
+ return Owned(Base);
}
// C++ [over.match.oper]p8:
@@ -2700,13 +2722,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
CTypes.insert(Context.getCanonicalType(BaseType));
while (BaseType->isRecordType()) {
- Base = BuildOverloadedArrowExpr(S, move(Base), OpLoc);
- BaseExpr = (Expr*)Base.get();
- if (BaseExpr == NULL)
+ Result = BuildOverloadedArrowExpr(S, Base, OpLoc);
+ if (Result.isInvalid())
return ExprError();
- if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(BaseExpr))
+ Base = Result.get();
+ if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base))
Locations.push_back(OpCall->getDirectCallee()->getLocation());
- BaseType = BaseExpr->getType();
+ BaseType = Base->getType();
CanQualType CBaseType = Context.getCanonicalType(BaseType);
if (!CTypes.insert(CBaseType)) {
Diag(OpLoc, diag::err_operator_arrow_circular);
@@ -2731,9 +2753,9 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
//
// This also indicates that we should be parsing a
// pseudo-destructor-name.
- ObjectType = 0;
+ ObjectType = ParsedType();
MayBePseudoDestructor = true;
- return move(Base);
+ return Owned(Base);
}
// The object type must be complete (or dependent).
@@ -2747,27 +2769,26 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc,
// 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();
+ ObjectType = ParsedType::make(BaseType);
return move(Base);
}
-Sema::OwningExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
- ExprArg MemExpr) {
- Expr *E = (Expr *) MemExpr.get();
+ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc,
+ Expr *MemExpr) {
SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc);
- Diag(E->getLocStart(), diag::err_dtor_expr_without_call)
- << isa<CXXPseudoDestructorExpr>(E)
+ Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call)
+ << isa<CXXPseudoDestructorExpr>(MemExpr)
<< FixItHint::CreateInsertion(ExpectedLParenLoc, "()");
return ActOnCallExpr(/*Scope*/ 0,
- move(MemExpr),
+ MemExpr,
/*LPLoc*/ ExpectedLParenLoc,
- Sema::MultiExprArg(*this, 0, 0),
+ MultiExprArg(),
/*CommaLocs*/ 0,
/*RPLoc*/ ExpectedLParenLoc);
}
-Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
+ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
const CXXScopeSpec &SS,
@@ -2782,12 +2803,11 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
// The left-hand side of the dot operator shall be of scalar type. The
// left-hand side of the arrow operator shall be of pointer to scalar type.
// This scalar type is the object type.
- Expr *BaseE = (Expr *)Base.get();
- QualType ObjectType = BaseE->getType();
+ QualType ObjectType = Base->getType();
if (OpKind == tok::arrow) {
if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
ObjectType = Ptr->getPointeeType();
- } else if (!BaseE->isTypeDependent()) {
+ } else if (!Base->isTypeDependent()) {
// The user wrote "p->" when she probably meant "p."; fix it.
Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
<< ObjectType << true
@@ -2801,7 +2821,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) {
Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
- << ObjectType << BaseE->getSourceRange();
+ << ObjectType << Base->getSourceRange();
return ExprError();
}
@@ -2815,7 +2835,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
- << ObjectType << DestructedType << BaseE->getSourceRange()
+ << ObjectType << DestructedType << Base->getSourceRange()
<< DestructedTypeInfo->getTypeLoc().getLocalSourceRange();
// Recover by setting the destructed type to the object type.
@@ -2840,7 +2860,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(),
diag::err_pseudo_dtor_type_mismatch)
- << ObjectType << ScopeType << BaseE->getSourceRange()
+ << ObjectType << ScopeType << Base->getSourceRange()
<< ScopeTypeInfo->getTypeLoc().getLocalSourceRange();
ScopeType = QualType();
@@ -2848,25 +2868,22 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
}
}
- OwningExprResult Result
- = Owned(new (Context) CXXPseudoDestructorExpr(Context,
- Base.takeAs<Expr>(),
- OpKind == tok::arrow,
- OpLoc,
- (NestedNameSpecifier *) SS.getScopeRep(),
- SS.getRange(),
- ScopeTypeInfo,
- CCLoc,
- TildeLoc,
- Destructed));
+ Expr *Result
+ = new (Context) CXXPseudoDestructorExpr(Context, Base,
+ OpKind == tok::arrow, OpLoc,
+ SS.getScopeRep(), SS.getRange(),
+ ScopeTypeInfo,
+ CCLoc,
+ TildeLoc,
+ Destructed);
if (HasTrailingLParen)
- return move(Result);
+ return Owned(Result);
- return DiagnoseDtorReference(Destructed.getLocation(), move(Result));
+ return DiagnoseDtorReference(Destructed.getLocation(), Result);
}
-Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
+ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
CXXScopeSpec &SS,
@@ -2882,13 +2899,11 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) &&
"Invalid second type name in pseudo-destructor");
- Expr *BaseE = (Expr *)Base.get();
-
// C++ [expr.pseudo]p2:
// The left-hand side of the dot operator shall be of scalar type. The
// left-hand side of the arrow operator shall be of pointer to scalar type.
// This scalar type is the object type.
- QualType ObjectType = BaseE->getType();
+ QualType ObjectType = Base->getType();
if (OpKind == tok::arrow) {
if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
ObjectType = Ptr->getPointeeType();
@@ -2906,12 +2921,12 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
// Compute the object type that we should use for name lookup purposes. Only
// record types and dependent types matter.
- void *ObjectTypePtrForLookup = 0;
+ ParsedType ObjectTypePtrForLookup;
if (!SS.isSet()) {
- ObjectTypePtrForLookup = const_cast<RecordType*>(
- ObjectType->getAs<RecordType>());
- if (!ObjectTypePtrForLookup && ObjectType->isDependentType())
- ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr();
+ if (const Type *T = ObjectType->getAs<RecordType>())
+ ObjectTypePtrForLookup = ParsedType::make(QualType(T, 0));
+ else if (ObjectType->isDependentType())
+ ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy);
}
// Convert the name of the type being destructed (following the ~) into a
@@ -2920,9 +2935,9 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
TypeSourceInfo *DestructedTypeInfo = 0;
PseudoDestructorTypeStorage Destructed;
if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
- TypeTy *T = getTypeName(*SecondTypeName.Identifier,
- SecondTypeName.StartLocation,
- S, &SS, true, ObjectTypePtrForLookup);
+ ParsedType T = getTypeName(*SecondTypeName.Identifier,
+ SecondTypeName.StartLocation,
+ S, &SS, true, ObjectTypePtrForLookup);
if (!T &&
((SS.isSet() && !computeDeclContext(SS, false)) ||
(!SS.isSet() && ObjectType->isDependentType()))) {
@@ -2949,7 +2964,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TypeResult T = ActOnTemplateIdType(TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -2976,9 +2991,9 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
FirstTypeName.Identifier) {
if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
- TypeTy *T = getTypeName(*FirstTypeName.Identifier,
- FirstTypeName.StartLocation,
- S, &SS, false, ObjectTypePtrForLookup);
+ ParsedType T = getTypeName(*FirstTypeName.Identifier,
+ FirstTypeName.StartLocation,
+ S, &SS, false, ObjectTypePtrForLookup);
if (!T) {
Diag(FirstTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
@@ -2997,7 +3012,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
ASTTemplateArgsPtr TemplateArgsPtr(*this,
TemplateId->getTemplateArgs(),
TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TypeResult T = ActOnTemplateIdType(TemplateId->Template,
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
@@ -3015,7 +3030,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
FirstTypeName.StartLocation);
- return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS,
+ return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS,
ScopeTypeInfo, CCLoc, TildeLoc,
Destructed, HasTrailingLParen);
}
@@ -3028,7 +3043,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?");
MemberExpr *ME =
- new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
+ new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
SourceLocation(), Method->getType());
QualType ResultType = Method->getCallResultType();
MarkDeclarationReferenced(Exp->getLocStart(), Method);
@@ -3038,12 +3053,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
return CE;
}
-Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
- Expr *FullExpr = Arg.takeAs<Expr>();
- if (FullExpr)
- FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr);
- else
- return ExprError();
-
- return Owned(FullExpr);
+ExprResult Sema::ActOnFinishFullExpr(Expr *FullExpr) {
+ if (!FullExpr) return ExprError();
+ return MaybeCreateCXXExprWithTemporaries(FullExpr);
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 9f43471e0ade..b56159c453b5 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -11,9 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
-#include "SemaInit.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Initialization.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprObjC.h"
@@ -23,9 +24,9 @@
using namespace clang;
-Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
- ExprTy **strings,
- unsigned NumStrings) {
+ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
+ Expr **strings,
+ unsigned NumStrings) {
StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings);
// Most ObjC strings are formed out of a single piece. However, we *can*
@@ -50,14 +51,11 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
return true;
}
- // Get the string data.
- StrBuf.append(S->getStrData(), S->getStrData()+S->getByteLength());
+ // Append the string.
+ StrBuf += S->getString();
// Get the locations of the string tokens.
StrLocs.append(S->tokloc_begin(), S->tokloc_end());
-
- // Free the temporary string.
- S->Destroy(Context);
}
// Create the aggregate string with the appropriate content and location
@@ -135,11 +133,11 @@ Expr *Sema::BuildObjCEncodeExpression(SourceLocation AtLoc,
return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc);
}
-Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
- SourceLocation EncodeLoc,
- SourceLocation LParenLoc,
- TypeTy *ty,
- SourceLocation RParenLoc) {
+ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType ty,
+ SourceLocation RParenLoc) {
// FIXME: Preserve type source info ?
TypeSourceInfo *TInfo;
QualType EncodedType = GetTypeFromParser(ty, &TInfo);
@@ -150,28 +148,33 @@ Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc,
return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc);
}
-Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
- SourceLocation AtLoc,
- SourceLocation SelLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
+ExprResult Sema::ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LParenLoc, RParenLoc), false);
+ SourceRange(LParenLoc, RParenLoc), false, false);
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
SourceRange(LParenLoc, RParenLoc));
if (!Method)
Diag(SelLoc, diag::warn_undeclared_selector) << Sel;
+ llvm::DenseMap<Selector, SourceLocation>::iterator Pos
+ = ReferencedSelectors.find(Sel);
+ if (Pos == ReferencedSelectors.end())
+ ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+
QualType Ty = Context.getObjCSelType();
return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc);
}
-Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
- SourceLocation AtLoc,
- SourceLocation ProtoLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc) {
+ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoLoc);
if (!PDecl) {
Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId;
@@ -239,7 +242,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
return true;
InitializedEntity Entity = InitializedEntity::InitializeParameter(Param);
- OwningExprResult ArgE = PerformCopyInitialization(Entity,
+ ExprResult ArgE = PerformCopyInitialization(Entity,
SourceLocation(),
Owned(argExpr->Retain()));
if (ArgE.isInvalid())
@@ -329,7 +332,7 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an
/// objective C interface. This is a property reference expression.
-Action::OwningExprResult Sema::
+ExprResult Sema::
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
Expr *BaseExpr, DeclarationName MemberName,
SourceLocation MemberLoc) {
@@ -431,7 +434,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
-Action::OwningExprResult Sema::
+ExprResult Sema::
ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
IdentifierInfo &propertyName,
SourceLocation receiverNameLoc,
@@ -529,8 +532,8 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
SourceLocation NameLoc,
bool IsSuper,
bool HasTrailingDot,
- TypeTy *&ReceiverType) {
- ReceiverType = 0;
+ ParsedType &ReceiverType) {
+ ReceiverType = ParsedType();
// If the identifier is "super" and there is no trailing dot, we're
// messaging super.
@@ -577,7 +580,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
// We have a class message, and T is the type we're
// messaging. Build source-location information for it.
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
- ReceiverType = CreateLocInfoType(T, TSInfo).getAsOpaquePtr();
+ ReceiverType = CreateParsedType(T, TSInfo);
return ObjCClassMessage;
}
}
@@ -604,7 +607,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
QualType T = Context.getObjCInterfaceType(Class);
TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);
- ReceiverType = CreateLocInfoType(T, TSInfo).getAsOpaquePtr();
+ ReceiverType = CreateParsedType(T, TSInfo);
return ObjCClassMessage;
}
} else if (Result.empty() && Corrected.getAsIdentifierInfo() &&
@@ -622,7 +625,7 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
return ObjCInstanceMessage;
}
-Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S,
+ExprResult Sema::ActOnSuperMessage(Scope *S,
SourceLocation SuperLoc,
Selector Sel,
SourceLocation LBracLoc,
@@ -657,7 +660,7 @@ Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S,
// message to the superclass instance.
QualType SuperTy = Context.getObjCInterfaceType(Super);
SuperTy = Context.getObjCObjectPointerType(SuperTy);
- return BuildInstanceMessage(ExprArg(*this), SuperTy, SuperLoc,
+ return BuildInstanceMessage(0, SuperTy, SuperLoc,
Sel, /*Method=*/0, LBracLoc, RBracLoc,
move(Args));
}
@@ -698,7 +701,7 @@ Sema::OwningExprResult Sema::ActOnSuperMessage(Scope *S,
/// \param RBrac The location of the closing square bracket ']'.
///
/// \param Args The message arguments.
-Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
QualType ReceiverType,
SourceLocation SuperLoc,
Selector Sel,
@@ -757,11 +760,8 @@ Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
unsigned NumArgs = ArgsIn.size();
Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, true,
- LBracLoc, RBracLoc, ReturnType)) {
- for (unsigned I = 0; I != NumArgs; ++I)
- Args[I]->Destroy(Context);
+ LBracLoc, RBracLoc, ReturnType))
return ExprError();
- }
// Construct the appropriate ObjCMessageExpr.
Expr *Result;
@@ -780,8 +780,8 @@ Sema::OwningExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
// ActOnClassMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
-Sema::OwningExprResult Sema::ActOnClassMessage(Scope *S,
- TypeTy *Receiver,
+ExprResult Sema::ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
Selector Sel,
SourceLocation LBracLoc,
SourceLocation SelectorLoc,
@@ -829,7 +829,7 @@ Sema::OwningExprResult Sema::ActOnClassMessage(Scope *S,
/// \param RBrac The location of the closing square bracket ']'.
///
/// \param Args The message arguments.
-Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
+ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
QualType ReceiverType,
SourceLocation SuperLoc,
Selector Sel,
@@ -839,7 +839,6 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
MultiExprArg ArgsIn) {
// If we have a receiver expression, perform appropriate promotions
// and determine receiver type.
- Expr *Receiver = ReceiverE.takeAs<Expr>();
if (Receiver) {
if (Receiver->isTypeDependent()) {
// If the receiver is type-dependent, we can't type-check anything
@@ -864,13 +863,16 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
if (!Method) {
// Handle messages to id.
- if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType() ||
+ bool receiverIsId = ReceiverType->isObjCIdType();
+ if (receiverIsId || ReceiverType->isBlockPointerType() ||
(Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
+ SourceRange(LBracLoc, RBracLoc),
+ receiverIsId);
if (!Method)
Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
+ SourceRange(LBracLoc, RBracLoc),
+ receiverIsId);
} else if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
// Handle messages to Class.
@@ -892,12 +894,14 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
// If not messaging 'self', look for any factory method named 'Sel'.
if (!Receiver || !isSelfExpr(Receiver)) {
Method = LookupFactoryMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
+ SourceRange(LBracLoc, RBracLoc),
+ true);
if (!Method) {
// If no class (factory) method was found, check if an _instance_
// method of the same name exists in the root class only.
Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
+ SourceRange(LBracLoc, RBracLoc),
+ true);
if (Method)
if (const ObjCInterfaceDecl *ID =
dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
@@ -931,7 +935,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
ClassDecl = OCIType->getInterfaceDecl();
// FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
// faster than the following method (which can do *many* linear searches).
- // The idea is to add class info to InstanceMethodPool.
+ // The idea is to add class info to MethodPool.
Method = ClassDecl->lookupInstanceMethod(Sel);
if (!Method) {
@@ -952,7 +956,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
// compatibility. FIXME: should we deviate??
if (OCIType->qual_empty()) {
Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
+ SourceRange(LBracLoc, RBracLoc));
if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
Diag(Loc, diag::warn_maynot_respond)
<< OCIType->getInterfaceDecl()->getIdentifier() << Sel;
@@ -962,19 +966,18 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
if (Method && DiagnoseUseOfDecl(Method, Loc))
return ExprError();
} else if (!Context.getObjCIdType().isNull() &&
- (ReceiverType->isPointerType() ||
- (ReceiverType->isIntegerType() &&
- ReceiverType->isScalarType()))) {
+ (ReceiverType->isPointerType() ||
+ ReceiverType->isIntegerType())) {
// Implicitly convert integers and pointers to 'id' but emit a warning.
Diag(Loc, diag::warn_bad_receiver_type)
<< ReceiverType
<< Receiver->getSourceRange();
if (ReceiverType->isPointerType())
ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CastExpr::CK_BitCast);
+ CK_BitCast);
else
ImpCastExprToType(Receiver, Context.getObjCIdType(),
- CastExpr::CK_IntegralToPointer);
+ CK_IntegralToPointer);
ReceiverType = Receiver->getType();
}
else if (getLangOptions().CPlusPlus &&
@@ -983,7 +986,7 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
Receiver = ICE->getSubExpr();
ReceiverType = Receiver->getType();
}
- return BuildInstanceMessage(Owned(Receiver),
+ return BuildInstanceMessage(Receiver,
ReceiverType,
SuperLoc,
Sel,
@@ -1030,18 +1033,17 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
// ActOnInstanceMessage - used for both unary and keyword messages.
// ArgExprs is optional - if it is present, the number of expressions
// is obtained from Sel.getNumArgs().
-Sema::OwningExprResult Sema::ActOnInstanceMessage(Scope *S,
- ExprArg ReceiverE,
- Selector Sel,
- SourceLocation LBracLoc,
- SourceLocation SelectorLoc,
- SourceLocation RBracLoc,
- MultiExprArg Args) {
- Expr *Receiver = static_cast<Expr *>(ReceiverE.get());
+ExprResult Sema::ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ SourceLocation SelectorLoc,
+ SourceLocation RBracLoc,
+ MultiExprArg Args) {
if (!Receiver)
return ExprError();
- return BuildInstanceMessage(move(ReceiverE), Receiver->getType(),
+ return BuildInstanceMessage(Receiver, Receiver->getType(),
/*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0,
LBracLoc, RBracLoc, move(Args));
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 7ad177557ef4..a28fd7fe12bd 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -15,12 +15,13 @@
//
//===----------------------------------------------------------------------===//
-#include "SemaInit.h"
-#include "Lookup.h"
-#include "Sema.h"
+#include "clang/Sema/Designator.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Lex/Preprocessor.h"
-#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
@@ -263,9 +264,8 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field,
return;
}
- Sema::OwningExprResult MemberInit
- = InitSeq.Perform(SemaRef, MemberEntity, Kind,
- Sema::MultiExprArg(SemaRef, 0, 0));
+ ExprResult MemberInit
+ = InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg());
if (MemberInit.isInvalid()) {
hadError = true;
return;
@@ -373,9 +373,8 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity,
return;
}
- Sema::OwningExprResult ElementInit
- = InitSeq.Perform(SemaRef, ElementEntity, Kind,
- Sema::MultiExprArg(SemaRef, 0, 0));
+ ExprResult ElementInit
+ = InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg());
if (ElementInit.isInvalid()) {
hadError = true;
return;
@@ -678,9 +677,8 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1);
if (Seq) {
- Sema::OwningExprResult Result =
- Seq.Perform(SemaRef, Entity, Kind,
- Sema::MultiExprArg(SemaRef, (void **)&expr, 1));
+ ExprResult Result =
+ Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1));
if (Result.isInvalid())
hadError = true;
@@ -740,13 +738,13 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
unsigned &StructuredIndex) {
if (Index < IList->getNumInits()) {
Expr *expr = IList->getInit(Index);
- if (isa<InitListExpr>(expr)) {
- SemaRef.Diag(IList->getLocStart(),
- diag::err_many_braces_around_scalar_init)
- << IList->getSourceRange();
- hadError = true;
- ++Index;
- ++StructuredIndex;
+ if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) {
+ SemaRef.Diag(SubIList->getLocStart(),
+ diag::warn_many_braces_around_scalar_init)
+ << SubIList->getSourceRange();
+
+ CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList,
+ StructuredIndex);
return;
} else if (isa<DesignatedInitExpr>(expr)) {
SemaRef.Diag(expr->getSourceRange().getBegin(),
@@ -758,7 +756,7 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity,
return;
}
- Sema::OwningExprResult Result =
+ ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
SemaRef.Owned(expr));
@@ -805,7 +803,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity,
return;
}
- Sema::OwningExprResult Result =
+ ExprResult Result =
SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(),
SemaRef.Owned(expr));
@@ -1367,7 +1365,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,
Sema::CTC_NoKeywords) &&
(ReplacementField = R.getAsSingle<FieldDecl>()) &&
- ReplacementField->getDeclContext()->getLookupContext()
+ ReplacementField->getDeclContext()->getRedeclContext()
->Equals(RT->getDecl())) {
SemaRef.Diag(D->getFieldLoc(),
diag::err_field_designator_unknown_suggest)
@@ -1813,10 +1811,10 @@ CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) {
return false;
}
-Sema::OwningExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
+ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig,
SourceLocation Loc,
bool GNUSyntax,
- OwningExprResult Init) {
+ ExprResult Init) {
typedef DesignatedInitExpr::Designator ASTDesignator;
bool Invalid = false;
@@ -2021,18 +2019,21 @@ void InitializationSequence::Step::Destroy() {
switch (Kind) {
case SK_ResolveAddressOfOverloadedFunction:
case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue:
case SK_BindReference:
case SK_BindReferenceToTemporary:
case SK_ExtraneousCopyToTemporary:
case SK_UserConversion:
case SK_QualificationConversionRValue:
+ case SK_QualificationConversionXValue:
case SK_QualificationConversionLValue:
case SK_ListInitialization:
case SK_ConstructorInitialization:
case SK_ZeroInitialization:
case SK_CAssignment:
case SK_StringInit:
+ case SK_ObjCObjectConversion:
break;
case SK_ConversionSequence:
@@ -2091,9 +2092,14 @@ void InitializationSequence::AddAddressOverloadResolutionStep(
}
void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
- bool IsLValue) {
+ ExprValueKind VK) {
Step S;
- S.Kind = IsLValue? SK_CastDerivedToBaseLValue : SK_CastDerivedToBaseRValue;
+ switch (VK) {
+ case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break;
+ case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break;
+ case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break;
+ default: llvm_unreachable("No such category");
+ }
S.Type = BaseType;
Steps.push_back(S);
}
@@ -2125,10 +2131,20 @@ void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
}
void InitializationSequence::AddQualificationConversionStep(QualType Ty,
- bool IsLValue) {
+ ExprValueKind VK) {
Step S;
- S.Kind = IsLValue? SK_QualificationConversionLValue
- : SK_QualificationConversionRValue;
+ S.Kind = SK_QualificationConversionRValue; // work around a gcc warning
+ switch (VK) {
+ case VK_RValue:
+ S.Kind = SK_QualificationConversionRValue;
+ break;
+ case VK_XValue:
+ S.Kind = SK_QualificationConversionXValue;
+ break;
+ case VK_LValue:
+ S.Kind = SK_QualificationConversionLValue;
+ break;
+ }
S.Type = Ty;
Steps.push_back(S);
}
@@ -2184,6 +2200,13 @@ void InitializationSequence::AddStringInitStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddObjCObjectConversionStep(QualType T) {
+ Step S;
+ S.Kind = SK_ObjCObjectConversion;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
@@ -2258,10 +2281,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
QualType T2 = cv2T2.getUnqualifiedType();
bool DerivedToBase;
+ bool ObjCConversion;
assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
- T1, T2, DerivedToBase) &&
+ T1, T2, DerivedToBase,
+ ObjCConversion) &&
"Must have incompatible references when binding via conversion");
(void)DerivedToBase;
+ (void)ObjCConversion;
// Build the candidate set directly in the initialization sequence
// structure, so that it will persist if we fail.
@@ -2278,6 +2304,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// The type we're converting to is a class type. Enumerate its constructors
// to see if there is a suitable conversion.
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
Con != ConEnd; ++Con) {
@@ -2305,6 +2332,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
}
}
}
+ if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
const RecordType *T2RecordType = 0;
if ((T2RecordType = T2->getAs<RecordType>()) &&
@@ -2352,13 +2381,15 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
}
}
}
+ if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl())
+ return OR_No_Viable_Function;
SourceLocation DeclLoc = Initializer->getLocStart();
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
- = S.BestViableFunction(CandidateSet, DeclLoc, Best))
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best))
return Result;
FunctionDecl *Function = Best->Function;
@@ -2375,11 +2406,18 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
// Determine whether we need to perform derived-to-base or
// cv-qualification adjustments.
+ ExprValueKind VK = VK_RValue;
+ if (T2->isLValueReferenceType())
+ VK = VK_LValue;
+ else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>())
+ VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue;
+
bool NewDerivedToBase = false;
+ bool NewObjCConversion = false;
Sema::ReferenceCompareResult NewRefRelationship
= S.CompareReferenceRelationship(DeclLoc, T1,
T2.getNonLValueExprType(S.Context),
- NewDerivedToBase);
+ NewDerivedToBase, NewObjCConversion);
if (NewRefRelationship == Sema::Ref_Incompatible) {
// If the type we've converted to is not reference-related to the
// type we're looking for, then there is another conversion step
@@ -2394,10 +2432,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1,
T2.getNonReferenceType().getQualifiers()),
- /*isLValue=*/true);
-
+ VK);
+ else if (NewObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1,
+ T2.getNonReferenceType().getQualifiers()));
+
if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
- Sequence.AddQualificationConversionStep(cv1T1, T2->isReferenceType());
+ Sequence.AddQualificationConversionStep(cv1T1, VK);
Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
return OR_Success;
@@ -2443,9 +2485,11 @@ static void TryReferenceInitialization(Sema &S,
bool isLValueRef = DestType->isLValueReferenceType();
bool isRValueRef = !isLValueRef;
bool DerivedToBase = false;
+ bool ObjCConversion = false;
Expr::Classification InitCategory = Initializer->Classify(S.Context);
Sema::ReferenceCompareResult RefRelationship
- = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase);
+ = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase,
+ ObjCConversion);
// C++0x [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression of type
@@ -2472,9 +2516,13 @@ static void TryReferenceInitialization(Sema &S,
if (DerivedToBase)
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1, T2Quals),
- /*isLValue=*/true);
+ VK_LValue);
+ else if (ObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1, T2Quals));
+
if (T1Quals != T2Quals)
- Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
+ Sequence.AddQualificationConversionStep(cv1T1, VK_LValue);
bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() &&
(Initializer->getBitField() || Initializer->refersToVectorElement());
Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary);
@@ -2531,6 +2579,7 @@ static void TryReferenceInitialization(Sema &S,
// - [If T1 is not a function type], if T2 is a class type and
if (!T1Function && T2->isRecordType()) {
+ bool isXValue = InitCategory.isXValue();
// - the initializer expression is an rvalue and "cv1 T1" is
// reference-compatible with "cv2 T2", or
if (InitCategory.isRValue() &&
@@ -2550,10 +2599,15 @@ static void TryReferenceInitialization(Sema &S,
if (DerivedToBase)
Sequence.AddDerivedToBaseCastStep(
S.Context.getQualifiedType(T1, T2Quals),
- /*isLValue=*/false);
+ isXValue ? VK_XValue : VK_RValue);
+ else if (ObjCConversion)
+ Sequence.AddObjCObjectConversionStep(
+ S.Context.getQualifiedType(T1, T2Quals));
+
if (T1Quals != T2Quals)
- Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
- Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ Sequence.AddQualificationConversionStep(cv1T1,
+ isXValue ? VK_XValue : VK_RValue);
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/!isXValue);
return;
}
@@ -2717,7 +2771,7 @@ static void TryConstructorInitialization(Sema &S,
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
- = S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
Sequence.SetOverloadFailure(
InitializationSequence::FK_ConstructorOverloadFailed,
Result);
@@ -2803,8 +2857,8 @@ static void TryDefaultInitialization(Sema &S,
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) {
- return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
- Sequence);
+ TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence);
+ return;
}
// - otherwise, no initialization is performed.
@@ -2927,7 +2981,7 @@ static void TryUserDefinedConversion(Sema &S,
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
if (OverloadingResult Result
- = S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
Sequence.SetOverloadFailure(
InitializationSequence::FK_UserConversionOverloadFailed,
Result);
@@ -2969,24 +3023,6 @@ static void TryUserDefinedConversion(Sema &S,
}
}
-bool Sema::TryImplicitConversion(InitializationSequence &Sequence,
- const InitializedEntity &Entity,
- Expr *Initializer,
- bool SuppressUserConversions,
- bool AllowExplicitConversions,
- bool InOverloadResolution) {
- ImplicitConversionSequence ICS
- = TryImplicitConversion(Initializer, Entity.getType(),
- SuppressUserConversions,
- AllowExplicitConversions,
- InOverloadResolution);
- if (ICS.isBad()) return true;
-
- // Perform the actual conversion.
- Sequence.AddConversionSequenceStep(ICS, Entity.getType());
- return false;
-}
-
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -3239,10 +3275,10 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) {
/// \returns An expression that copies the initializer expression into
/// a temporary object, or an error expression if a copy could not be
/// created.
-static Sema::OwningExprResult CopyObject(Sema &S,
+static ExprResult CopyObject(Sema &S,
QualType T,
const InitializedEntity &Entity,
- Sema::OwningExprResult CurInit,
+ ExprResult CurInit,
bool IsExtraneousCopy) {
// Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
@@ -3318,7 +3354,7 @@ static Sema::OwningExprResult CopyObject(Sema &S,
}
OverloadCandidateSet::iterator Best;
- switch (S.BestViableFunction(CandidateSet, Loc, Best)) {
+ switch (CandidateSet.BestViableFunction(S, Loc, Best)) {
case OR_Success:
break;
@@ -3328,19 +3364,17 @@ static Sema::OwningExprResult CopyObject(Sema &S,
: diag::err_temp_copy_no_viable)
<< (int)Entity.getKind() << CurInitExpr->getType()
<< CurInitExpr->getSourceRange();
- S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates,
- &CurInitExpr, 1);
+ CandidateSet.NoteCandidates(S, OCD_AllCandidates, &CurInitExpr, 1);
if (!IsExtraneousCopy || S.isSFINAEContext())
- return S.ExprError();
+ return ExprError();
return move(CurInit);
case OR_Ambiguous:
S.Diag(Loc, diag::err_temp_copy_ambiguous)
<< (int)Entity.getKind() << CurInitExpr->getType()
<< CurInitExpr->getSourceRange();
- S.PrintOverloadCandidates(CandidateSet, Sema::OCD_ViableCandidates,
- &CurInitExpr, 1);
- return S.ExprError();
+ CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1);
+ return ExprError();
case OR_Deleted:
S.Diag(Loc, diag::err_temp_copy_deleted)
@@ -3348,11 +3382,11 @@ static Sema::OwningExprResult CopyObject(Sema &S,
<< CurInitExpr->getSourceRange();
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
<< Best->Function->isDeleted();
- return S.ExprError();
+ return ExprError();
}
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+ ASTOwningVector<Expr*> ConstructorArgs(S);
CurInit.release(); // Ownership transferred into MultiExprArg, below.
S.CheckConstructorAccess(Loc, Constructor, Entity,
@@ -3387,16 +3421,15 @@ static Sema::OwningExprResult CopyObject(Sema &S,
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
- if (S.CompleteConstructorCall(Constructor,
- Sema::MultiExprArg(S,
- (void **)&CurInitExpr,
- 1),
+ if (S.CompleteConstructorCall(Constructor, MultiExprArg(&CurInitExpr, 1),
Loc, ConstructorArgs))
- return S.ExprError();
+ return ExprError();
// Actually perform the constructor call.
CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
- move_arg(ConstructorArgs));
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete);
// If we're supposed to bind temporaries, do so.
if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity))
@@ -3418,16 +3451,16 @@ void InitializationSequence::PrintInitLocationNote(Sema &S,
}
}
-Action::OwningExprResult
+ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
- Action::MultiExprArg Args,
+ MultiExprArg Args,
QualType *ResultType) {
if (SequenceKind == FailedSequence) {
unsigned NumArgs = Args.size();
Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
- return S.ExprError();
+ return ExprError();
}
if (SequenceKind == DependentSequence) {
@@ -3471,7 +3504,7 @@ InitializationSequence::Perform(Sema &S,
}
if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast())
- return Sema::OwningExprResult(S, Args.release()[0]);
+ return ExprResult(Args.release()[0]);
if (Args.size() == 0)
return S.Owned((Expr *)0);
@@ -3495,7 +3528,7 @@ InitializationSequence::Perform(Sema &S,
*ResultType = Entity.getDecl() ? Entity.getDecl()->getType() :
Entity.getType();
- Sema::OwningExprResult CurInit = S.Owned((Expr *)0);
+ ExprResult CurInit = S.Owned((Expr *)0);
assert(!Steps.empty() && "Cannot have an empty initialization sequence");
@@ -3505,21 +3538,24 @@ InitializationSequence::Perform(Sema &S,
switch (Steps.front().Kind) {
case SK_ResolveAddressOfOverloadedFunction:
case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue:
case SK_BindReference:
case SK_BindReferenceToTemporary:
case SK_ExtraneousCopyToTemporary:
case SK_UserConversion:
case SK_QualificationConversionLValue:
+ case SK_QualificationConversionXValue:
case SK_QualificationConversionRValue:
case SK_ConversionSequence:
case SK_ListInitialization:
case SK_CAssignment:
case SK_StringInit:
+ case SK_ObjCObjectConversion:
assert(Args.size() == 1);
- CurInit = Sema::OwningExprResult(S, ((Expr **)(Args.get()))[0]->Retain());
+ CurInit = ExprResult(((Expr **)(Args.get()))[0]->Retain());
if (CurInit.isInvalid())
- return S.ExprError();
+ return ExprError();
break;
case SK_ConstructorInitialization:
@@ -3533,7 +3569,7 @@ InitializationSequence::Perform(Sema &S,
for (step_iterator Step = step_begin(), StepEnd = step_end();
Step != StepEnd; ++Step) {
if (CurInit.isInvalid())
- return S.ExprError();
+ return ExprError();
Expr *CurInitExpr = (Expr *)CurInit.get();
QualType SourceType = CurInitExpr? CurInitExpr->getType() : QualType();
@@ -3550,11 +3586,12 @@ InitializationSequence::Perform(Sema &S,
break;
case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseXValue:
case SK_CastDerivedToBaseLValue: {
// We have a derived-to-base cast that produces either an rvalue or an
// lvalue. Perform that cast.
- CXXBaseSpecifierArray BasePath;
+ CXXCastPath BasePath;
// Casts to inaccessible base classes are allowed with C-style casts.
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
@@ -3562,7 +3599,7 @@ InitializationSequence::Perform(Sema &S,
CurInitExpr->getLocStart(),
CurInitExpr->getSourceRange(),
&BasePath, IgnoreBaseAccess))
- return S.ExprError();
+ return ExprError();
if (S.BasePathInvolvesVirtualBase(BasePath)) {
QualType T = SourceType;
@@ -3573,11 +3610,17 @@ InitializationSequence::Perform(Sema &S,
cast<CXXRecordDecl>(RecordTy->getDecl()));
}
- CurInit = S.Owned(new (S.Context) ImplicitCastExpr(Step->Type,
- CastExpr::CK_DerivedToBase,
- (Expr*)CurInit.release(),
- BasePath,
- Step->Kind == SK_CastDerivedToBaseLValue));
+ ExprValueKind VK =
+ Step->Kind == SK_CastDerivedToBaseLValue ?
+ VK_LValue :
+ (Step->Kind == SK_CastDerivedToBaseXValue ?
+ VK_XValue :
+ VK_RValue);
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+ Step->Type,
+ CK_DerivedToBase,
+ CurInit.get(),
+ &BasePath, VK));
break;
}
@@ -3589,7 +3632,7 @@ InitializationSequence::Perform(Sema &S,
<< BitField->getDeclName()
<< CurInitExpr->getSourceRange();
S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
- return S.ExprError();
+ return ExprError();
}
if (CurInitExpr->refersToVectorElement()) {
@@ -3598,14 +3641,14 @@ InitializationSequence::Perform(Sema &S,
<< Entity.getType().isVolatileQualified()
<< CurInitExpr->getSourceRange();
PrintInitLocationNote(S, Entity);
- return S.ExprError();
+ return ExprError();
}
// Reference binding does not have any corresponding ASTs.
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
- return S.ExprError();
+ return ExprError();
break;
@@ -3614,7 +3657,7 @@ InitializationSequence::Perform(Sema &S,
// Check exception specifications
if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType))
- return S.ExprError();
+ return ExprError();
break;
@@ -3626,7 +3669,7 @@ InitializationSequence::Perform(Sema &S,
case SK_UserConversion: {
// We have a user-defined conversion that invokes either a constructor
// or a conversion function.
- CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
+ CastKind CastKind = CK_Unknown;
bool IsCopy = false;
FunctionDecl *Fn = Step->Function.Function;
DeclAccessPair FoundFn = Step->Function.FoundDecl;
@@ -3634,30 +3677,30 @@ InitializationSequence::Perform(Sema &S,
bool IsLvalue = false;
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+ ASTOwningVector<Expr*> ConstructorArgs(S);
SourceLocation Loc = CurInitExpr->getLocStart();
CurInit.release(); // Ownership transferred into MultiExprArg, below.
// Determine the arguments required to actually perform the constructor
// call.
if (S.CompleteConstructorCall(Constructor,
- Sema::MultiExprArg(S,
- (void **)&CurInitExpr,
- 1),
+ MultiExprArg(&CurInitExpr, 1),
Loc, ConstructorArgs))
- return S.ExprError();
+ return ExprError();
// Build the an expression that constructs a temporary.
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
- move_arg(ConstructorArgs));
+ move_arg(ConstructorArgs),
+ /*ZeroInit*/ false,
+ CXXConstructExpr::CK_Complete);
if (CurInit.isInvalid())
- return S.ExprError();
+ return ExprError();
S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity,
FoundFn.getAccess());
S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation());
- CastKind = CastExpr::CK_ConstructorConversion;
+ CastKind = CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
if (S.Context.hasSameUnqualifiedType(SourceType, Class) ||
S.IsDerivedFrom(SourceType, Class))
@@ -3677,7 +3720,7 @@ InitializationSequence::Perform(Sema &S,
// we don't want to turn off access control here for c-style casts.
if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0,
FoundFn, Conversion))
- return S.ExprError();
+ return ExprError();
// Do a little dance to make sure that CurInit has the proper
// pointer.
@@ -3687,9 +3730,9 @@ InitializationSequence::Perform(Sema &S,
CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn,
Conversion));
if (CurInit.isInvalid() || !CurInit.get())
- return S.ExprError();
+ return ExprError();
- CastKind = CastExpr::CK_UserDefinedConversion;
+ CastKind = CK_UserDefinedConversion;
CreatedObject = Conversion->getResultType()->isRecordType();
}
@@ -3711,35 +3754,41 @@ InitializationSequence::Perform(Sema &S,
}
CurInitExpr = CurInit.takeAs<Expr>();
- CurInit = S.Owned(new (S.Context) ImplicitCastExpr(CurInitExpr->getType(),
- CastKind,
- CurInitExpr,
- CXXBaseSpecifierArray(),
- IsLvalue));
+ // FIXME: xvalues
+ CurInit = S.Owned(ImplicitCastExpr::Create(S.Context,
+ CurInitExpr->getType(),
+ CastKind, CurInitExpr, 0,
+ IsLvalue ? VK_LValue : VK_RValue));
if (RequiresCopy)
CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity,
move(CurInit), /*IsExtraneousCopy=*/false);
-
+
break;
}
-
+
case SK_QualificationConversionLValue:
- case SK_QualificationConversionRValue:
+ case SK_QualificationConversionXValue:
+ case SK_QualificationConversionRValue: {
// Perform a qualification conversion; these can never go wrong.
- S.ImpCastExprToType(CurInitExpr, Step->Type,
- CastExpr::CK_NoOp,
- Step->Kind == SK_QualificationConversionLValue);
+ ExprValueKind VK =
+ Step->Kind == SK_QualificationConversionLValue ?
+ VK_LValue :
+ (Step->Kind == SK_QualificationConversionXValue ?
+ VK_XValue :
+ VK_RValue);
+ S.ImpCastExprToType(CurInitExpr, Step->Type, CK_NoOp, VK);
CurInit.release();
CurInit = S.Owned(CurInitExpr);
break;
-
+ }
+
case SK_ConversionSequence: {
bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast();
if (S.PerformImplicitConversion(CurInitExpr, Step->Type, *Step->ICS,
Sema::AA_Converting, IgnoreBaseAccess))
- return S.ExprError();
+ return ExprError();
CurInit.release();
CurInit = S.Owned(CurInitExpr);
@@ -3750,7 +3799,7 @@ InitializationSequence::Perform(Sema &S,
InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
QualType Ty = Step->Type;
if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty))
- return S.ExprError();
+ return ExprError();
CurInit.release();
CurInit = S.Owned(InitList);
@@ -3763,16 +3812,29 @@ InitializationSequence::Perform(Sema &S,
= cast<CXXConstructorDecl>(Step->Function.Function);
// Build a call to the selected constructor.
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
- SourceLocation Loc = Kind.getLocation();
-
+ ASTOwningVector<Expr*> ConstructorArgs(S);
+ SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
+ ? Kind.getEqualLoc()
+ : Kind.getLocation();
+
+ if (Kind.getKind() == InitializationKind::IK_Default) {
+ // Force even a trivial, implicit default constructor to be
+ // semantically checked. We do this explicitly because we don't build
+ // the definition for completely trivial constructors.
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ assert(ClassDecl && "No parent class for constructor.");
+ if (Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
+ ClassDecl->hasTrivialConstructor() && !Constructor->isUsed(false))
+ S.DefineImplicitDefaultConstructor(Loc, Constructor);
+ }
+
// Determine the arguments required to actually perform the constructor
// call.
if (S.CompleteConstructorCall(Constructor, move(Args),
Loc, ConstructorArgs))
- return S.ExprError();
+ return ExprError();
- // Build the expression that constructs a temporary.
+
if (Entity.getKind() == InitializedEntity::EK_Temporary &&
NumArgs != 1 && // FIXME: Hack to work around cast weirdness
(Kind.getKind() == InitializationKind::IK_Direct ||
@@ -3780,11 +3842,11 @@ InitializationSequence::Perform(Sema &S,
// An explicitly-constructed temporary, e.g., X(1, 2).
unsigned NumExprs = ConstructorArgs.size();
Expr **Exprs = (Expr **)ConstructorArgs.take();
- S.MarkDeclarationReferenced(Kind.getLocation(), Constructor);
+ S.MarkDeclarationReferenced(Loc, Constructor);
CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
Constructor,
Entity.getType(),
- Kind.getLocation(),
+ Loc,
Exprs,
NumExprs,
Kind.getParenRange().getEnd(),
@@ -3815,7 +3877,7 @@ InitializationSequence::Perform(Sema &S,
ConstructKind);
}
if (CurInit.isInvalid())
- return S.ExprError();
+ return ExprError();
// Only check access if all of that succeeded.
S.CheckConstructorAccess(Loc, Constructor, Entity,
@@ -3867,7 +3929,7 @@ InitializationSequence::Perform(Sema &S,
getAssignmentAction(Entity),
&Complained)) {
PrintInitLocationNote(S, Entity);
- return S.ExprError();
+ return ExprError();
} else if (Complained)
PrintInitLocationNote(S, Entity);
@@ -3881,6 +3943,14 @@ InitializationSequence::Perform(Sema &S,
CheckStringInit(CurInitExpr, ResultType ? *ResultType : Ty, S);
break;
}
+
+ case SK_ObjCObjectConversion:
+ S.ImpCastExprToType(CurInitExpr, Step->Type,
+ CK_ObjCObjectLValueCast,
+ S.CastCategory(CurInitExpr));
+ CurInit.release();
+ CurInit = S.Owned(CurInitExpr);
+ break;
}
}
@@ -3937,16 +4007,14 @@ bool InitializationSequence::Diagnose(Sema &S,
<< DestType << Args[0]->getType()
<< Args[0]->getSourceRange();
- S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_ViableCandidates,
- Args, NumArgs);
+ FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs);
break;
case OR_No_Viable_Function:
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
<< Args[0]->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
- S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
- Args, NumArgs);
+ FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
break;
case OR_Deleted: {
@@ -3954,9 +4022,8 @@ bool InitializationSequence::Diagnose(Sema &S,
<< Args[0]->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
- OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet,
- Kind.getLocation(),
- Best);
+ OverloadingResult Ovl
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
if (Ovl == OR_Deleted) {
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
<< Best->Function->isDeleted();
@@ -4049,8 +4116,8 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Ambiguous:
S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
<< DestType << ArgsRange;
- S.PrintOverloadCandidates(FailedCandidateSet,
- Sema::OCD_ViableCandidates, Args, NumArgs);
+ FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates,
+ Args, NumArgs);
break;
case OR_No_Viable_Function:
@@ -4095,17 +4162,15 @@ bool InitializationSequence::Diagnose(Sema &S,
S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
<< DestType << ArgsRange;
- S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
- Args, NumArgs);
+ FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs);
break;
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
<< true << DestType << ArgsRange;
OverloadCandidateSet::iterator Best;
- OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet,
- Kind.getLocation(),
- Best);
+ OverloadingResult Ovl
+ = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
if (Ovl == OR_Deleted) {
S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
<< Best->Function->isDeleted();
@@ -4288,6 +4353,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")";
break;
+ case SK_CastDerivedToBaseXValue:
+ OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")";
+ break;
+
case SK_CastDerivedToBaseLValue:
OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")";
break;
@@ -4307,10 +4376,13 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case SK_UserConversion:
OS << "user-defined conversion via " << S->Function.Function;
break;
-
+
case SK_QualificationConversionRValue:
OS << "qualification conversion (rvalue)";
+ case SK_QualificationConversionXValue:
+ OS << "qualification conversion (xvalue)";
+
case SK_QualificationConversionLValue:
OS << "qualification conversion (lvalue)";
break;
@@ -4340,6 +4412,10 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
case SK_StringInit:
OS << "string initialization";
break;
+
+ case SK_ObjCObjectConversion:
+ OS << "Objective-C object conversion";
+ break;
}
}
}
@@ -4351,10 +4427,10 @@ void InitializationSequence::dump() const {
//===----------------------------------------------------------------------===//
// Initialization helper functions
//===----------------------------------------------------------------------===//
-Sema::OwningExprResult
+ExprResult
Sema::PerformCopyInitialization(const InitializedEntity &Entity,
SourceLocation EqualLoc,
- OwningExprResult Init) {
+ ExprResult Init) {
if (Init.isInvalid())
return ExprError();
@@ -4368,6 +4444,5 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
EqualLoc);
InitializationSequence Seq(*this, Entity, Kind, &InitE, 1);
Init.release();
- return Seq.Perform(*this, Entity, Kind,
- MultiExprArg(*this, (void**)&InitE, 1));
+ return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1));
}
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 2e651838df95..306e95a497e8 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -11,8 +11,13 @@
// Objective-C++.
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Decl.h"
@@ -21,9 +26,9 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
@@ -35,6 +40,7 @@
#include <algorithm>
using namespace clang;
+using namespace sema;
namespace {
class UnqualUsingEntry {
@@ -100,7 +106,7 @@ namespace {
End = S->using_directives_end();
for (; I != End; ++I)
- visit(I->getAs<UsingDirectiveDecl>(), InnermostFileDC);
+ visit(*I, InnermostFileDC);
}
}
}
@@ -254,6 +260,12 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
case Sema::LookupObjCProtocolName:
IDNS = Decl::IDNS_ObjCProtocol;
break;
+
+ case Sema::LookupAnyName:
+ IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member
+ | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol
+ | Decl::IDNS_Type;
+ break;
}
return IDNS;
}
@@ -267,7 +279,7 @@ void LookupResult::configure() {
// operators, make sure that the implicitly-declared new and delete
// operators can be found.
if (!isForRedeclaration()) {
- switch (Name.getCXXOverloadedOperator()) {
+ switch (NameInfo.getName().getCXXOverloadedOperator()) {
case OO_New:
case OO_Delete:
case OO_Array_New:
@@ -281,6 +293,22 @@ void LookupResult::configure() {
}
}
+#ifndef NDEBUG
+void LookupResult::sanity() const {
+ assert(ResultKind != NotFound || Decls.size() == 0);
+ assert(ResultKind != Found || Decls.size() == 1);
+ assert(ResultKind != FoundOverloaded || Decls.size() > 1 ||
+ (Decls.size() == 1 &&
+ isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl())));
+ assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved());
+ assert(ResultKind != Ambiguous || Decls.size() > 1 ||
+ (Decls.size() == 1 && Ambiguity == AmbiguousBaseSubobjects));
+ assert((Paths != NULL) == (ResultKind == Ambiguous &&
+ (Ambiguity == AmbiguousBaseSubobjectTypes ||
+ Ambiguity == AmbiguousBaseSubobjects)));
+}
+#endif
+
// Necessary because CXXBasePaths is not complete in Sema.h
void LookupResult::deletePaths(CXXBasePaths *Paths) {
delete Paths;
@@ -311,7 +339,8 @@ void LookupResult::resolveKind() {
if (ResultKind == Ambiguous) return;
llvm::SmallPtrSet<NamedDecl*, 16> Unique;
-
+ llvm::SmallPtrSet<QualType, 16> UniqueTypes;
+
bool Ambiguous = false;
bool HasTag = false, HasFunction = false, HasNonFunction = false;
bool HasFunctionTemplate = false, HasUnresolved = false;
@@ -323,32 +352,49 @@ void LookupResult::resolveKind() {
NamedDecl *D = Decls[I]->getUnderlyingDecl();
D = cast<NamedDecl>(D->getCanonicalDecl());
+ // Redeclarations of types via typedef can occur both within a scope
+ // and, through using declarations and directives, across scopes. There is
+ // no ambiguity if they all refer to the same type, so unique based on the
+ // canonical type.
+ if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
+ if (!TD->getDeclContext()->isRecord()) {
+ QualType T = SemaRef.Context.getTypeDeclType(TD);
+ if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) {
+ // The type is not unique; pull something off the back and continue
+ // at this index.
+ Decls[I] = Decls[--N];
+ continue;
+ }
+ }
+ }
+
if (!Unique.insert(D)) {
// If it's not unique, pull something off the back (and
// continue at this index).
Decls[I] = Decls[--N];
+ continue;
+ }
+
+ // Otherwise, do some decl type analysis and then continue.
+
+ if (isa<UnresolvedUsingValueDecl>(D)) {
+ HasUnresolved = true;
+ } else if (isa<TagDecl>(D)) {
+ if (HasTag)
+ Ambiguous = true;
+ UniqueTagIndex = I;
+ HasTag = true;
+ } else if (isa<FunctionTemplateDecl>(D)) {
+ HasFunction = true;
+ HasFunctionTemplate = true;
+ } else if (isa<FunctionDecl>(D)) {
+ HasFunction = true;
} else {
- // Otherwise, do some decl type analysis and then continue.
-
- if (isa<UnresolvedUsingValueDecl>(D)) {
- HasUnresolved = true;
- } else if (isa<TagDecl>(D)) {
- if (HasTag)
- Ambiguous = true;
- UniqueTagIndex = I;
- HasTag = true;
- } else if (isa<FunctionTemplateDecl>(D)) {
- HasFunction = true;
- HasFunctionTemplate = true;
- } else if (isa<FunctionDecl>(D)) {
- HasFunction = true;
- } else {
- if (HasNonFunction)
- Ambiguous = true;
- HasNonFunction = true;
- }
- I++;
+ if (HasNonFunction)
+ Ambiguous = true;
+ HasNonFunction = true;
}
+ I++;
}
// C++ [basic.scope.hiding]p2:
@@ -451,6 +497,10 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
/// the class at this point.
static bool CanDeclareSpecialMemberFunction(ASTContext &Context,
const CXXRecordDecl *Class) {
+ // Don't do it if the class is invalid.
+ if (Class->isInvalidDecl())
+ return false;
+
// We need to have a definition for the class.
if (!Class->getDefinition() || Class->isDependentContext())
return false;
@@ -608,7 +658,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) {
// result), perform template argument deduction and place the
// specialization into the result set. We do this to avoid forcing all
// callers to perform special deduction for conversion functions.
- Sema::TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
+ TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc());
FunctionDecl *Specialization = 0;
const FunctionProtoType *ConvProto
@@ -783,7 +833,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
- for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
+ for (; I != IEnd && S->isDeclScope(*I); ++I) {
if (R.isAcceptableDecl(*I)) {
Found = true;
R.addDecl(*I);
@@ -881,7 +931,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
for (; S; S = S->getParent()) {
// Check whether the IdResolver has anything in this scope.
bool Found = false;
- for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
+ for (; I != IEnd && S->isDeclScope(*I); ++I) {
if (R.isAcceptableDecl(*I)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
@@ -1017,7 +1067,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
if (NameKind == LookupRedeclarationWithLinkage) {
// Determine whether this (or a previous) declaration is
// out-of-scope.
- if (!LeftStartingScope && !S->isDeclScope(DeclPtrTy::make(*I)))
+ if (!LeftStartingScope && !S->isDeclScope(*I))
LeftStartingScope = true;
// If we found something outside of our starting scope that
@@ -1034,14 +1084,14 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
// Figure out what scope the identifier is in.
while (!(S->getFlags() & Scope::DeclScope) ||
- !S->isDeclScope(DeclPtrTy::make(*I)))
+ !S->isDeclScope(*I))
S = S->getParent();
// Find the last declaration in this scope (with the same
// name, naturally).
IdentifierResolver::iterator LastI = I;
for (++LastI; LastI != IEnd; ++LastI) {
- if (!S->isDeclScope(DeclPtrTy::make(*LastI)))
+ if (!S->isDeclScope(*LastI))
break;
R.addDecl(*LastI);
}
@@ -1177,6 +1227,17 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
return Found;
}
+/// \brief Callback that looks for any member of a class with the given name.
+static bool LookupAnyMember(const CXXBaseSpecifier *Specifier,
+ CXXBasePath &Path,
+ void *Name) {
+ RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl();
+
+ DeclarationName N = DeclarationName::getFromOpaquePtr(Name);
+ Path.Decls = BaseRecord->lookup(N);
+ return Path.Decls.first != Path.Decls.second;
+}
+
/// \brief Perform qualified name lookup into a given context.
///
/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
@@ -1272,6 +1333,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
BaseCallback = &CXXRecordDecl::FindTagMember;
break;
+ case LookupAnyName:
+ BaseCallback = &LookupAnyMember;
+ break;
+
case LookupUsingDeclName:
// This lookup is for redeclarations only.
@@ -1554,7 +1619,11 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces,
// We don't use DeclContext::getEnclosingNamespaceContext() as this may
// be a locally scoped record.
- while (Ctx->isRecord() || Ctx->isTransparentContext())
+ // We skip out of inline namespaces. The innermost non-inline namespace
+ // contains all names of all its nested inline namespaces anyway, so we can
+ // replace the entire inline namespace tree with its root.
+ while (Ctx->isRecord() || Ctx->isTransparentContext() ||
+ Ctx->isInlineNamespace())
Ctx = Ctx->getParent();
if (Ctx->isFileContext())
@@ -1894,7 +1963,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
// parameter types and return type.
Arg = Arg->IgnoreParens();
if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg))
- if (unaryOp->getOpcode() == UnaryOperator::AddrOf)
+ if (unaryOp->getOpcode() == UO_AddrOf)
Arg = unaryOp->getSubExpr();
UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg);
@@ -2201,6 +2270,10 @@ public:
return !VisitedContexts.insert(Ctx);
}
+ bool alreadyVisitedContext(DeclContext *Ctx) {
+ return VisitedContexts.count(Ctx);
+ }
+
/// \brief Determine whether the given declaration is hidden in the
/// current scope.
///
@@ -2354,9 +2427,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
Visited.add(ND);
}
- // Visit transparent contexts inside this context.
+ // Visit transparent contexts and inline namespaces inside this context.
if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) {
- if (InnerCtx->isTransparentContext())
+ if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass,
Consumer, Visited);
}
@@ -2429,8 +2502,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
}
// Traverse protocols.
- for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
- E = IFace->protocol_end(); I != E; ++I) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ I = IFace->all_referenced_protocol_begin(),
+ E = IFace->all_referenced_protocol_end(); I != E; ++I) {
ShadowContextRAII Shadow(Visited);
LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer,
Visited);
@@ -2481,12 +2555,14 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
if (!S)
return;
- if (!S->getEntity() || !S->getParent() ||
+ if (!S->getEntity() ||
+ (!S->getParent() &&
+ !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) ||
((DeclContext *)S->getEntity())->isFunctionOrMethod()) {
// Walk through the declarations in this Scope.
for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
- if (NamedDecl *ND = dyn_cast<NamedDecl>((Decl *)((*D).get())))
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
if (Result.isAcceptableDecl(ND)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
Visited.add(ND);
@@ -2559,7 +2635,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
}
void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
- VisibleDeclConsumer &Consumer) {
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope) {
// Determine the set of using directives available during
// unqualified name lookup.
Scope *Initial = S;
@@ -2576,14 +2653,19 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind,
// Look for visible declarations.
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
VisibleDeclsRecord Visited;
+ if (!IncludeGlobalScope)
+ Visited.visitedContext(Context.getTranslationUnitDecl());
ShadowContextRAII Shadow(Visited);
::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited);
}
void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
- VisibleDeclConsumer &Consumer) {
+ VisibleDeclConsumer &Consumer,
+ bool IncludeGlobalScope) {
LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
VisibleDeclsRecord Visited;
+ if (!IncludeGlobalScope)
+ Visited.visitedContext(Context.getTranslationUnitDecl());
ShadowContextRAII Shadow(Visited);
::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true,
/*InBaseClass=*/false, Consumer, Visited);
@@ -2911,7 +2993,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS,
if (S && S->getContinueParent())
Consumer.addKeywordResult(Context, "continue");
- if (!getSwitchStack().empty()) {
+ if (!getCurFunction()->SwitchStack.empty()) {
Consumer.addKeywordResult(Context, "case");
Consumer.addKeywordResult(Context, "default");
}
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index ff60599b8510..7181d58f7fb0 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -12,9 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprObjC.h"
+#include "llvm/ADT/DenseSet.h"
using namespace clang;
@@ -22,14 +24,14 @@ using namespace clang;
// Grammar actions.
//===----------------------------------------------------------------------===//
-Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
- FieldDeclarator &FD,
- ObjCDeclSpec &ODS,
- Selector GetterSel,
- Selector SetterSel,
- DeclPtrTy ClassCategory,
- bool *isOverridingProperty,
- tok::ObjCKeywordKind MethodImplKind) {
+Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
+ FieldDeclarator &FD,
+ ObjCDeclSpec &ODS,
+ Selector GetterSel,
+ Selector SetterSel,
+ Decl *ClassCategory,
+ bool *isOverridingProperty,
+ tok::ObjCKeywordKind MethodImplKind) {
unsigned Attributes = ODS.getPropertyAttributes();
bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
// default is readwrite!
@@ -45,15 +47,15 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
QualType T = TSI->getType();
if (T->isReferenceType()) {
Diag(AtLoc, diag::error_reference_property);
- return DeclPtrTy();
+ return 0;
}
// Proceed with constructing the ObjCPropertDecls.
ObjCContainerDecl *ClassDecl =
- cast<ObjCContainerDecl>(ClassCategory.getAs<Decl>());
+ cast<ObjCContainerDecl>(ClassCategory);
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
if (CDecl->IsClassExtension()) {
- DeclPtrTy Res = HandlePropertyInClassExtension(S, CDecl, AtLoc,
+ Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc,
FD, GetterSel, SetterSel,
isAssign, isReadWrite,
Attributes,
@@ -64,16 +66,16 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
return Res;
}
- DeclPtrTy Res = DeclPtrTy::make(CreatePropertyDecl(S, ClassDecl, AtLoc, FD,
- GetterSel, SetterSel,
- isAssign, isReadWrite,
- Attributes, TSI, MethodImplKind));
+ Decl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD,
+ GetterSel, SetterSel,
+ isAssign, isReadWrite,
+ Attributes, TSI, MethodImplKind);
// Validate the attributes on the @property.
CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
return Res;
}
-Sema::DeclPtrTy
+Decl *
Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
SourceLocation AtLoc, FieldDeclarator &FD,
Selector GetterSel, Selector SetterSel,
@@ -92,7 +94,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
Diag(AtLoc, diag::err_duplicate_property);
Diag(prevDecl->getLocation(), diag::note_property_declare);
- return DeclPtrTy();
+ return 0;
}
// Create a new ObjCPropertyDecl with the DeclContext being
@@ -113,7 +115,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
if (!CCPrimary) {
Diag(CDecl->getLocation(), diag::err_continuation_class);
*isOverridingProperty = true;
- return DeclPtrTy();
+ return 0;
}
// Find the property in continuation class's primary class only.
@@ -136,7 +138,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
// is not what it was meant for. However, gcc supports it and so should we.
// Make sure setter/getters are declared here.
ProcessPropertyDecl(PDecl, CCPrimary);
- return DeclPtrTy::make(PDecl);
+ return PDecl;
}
@@ -165,13 +167,13 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
PIkind);
- DeclPtrTy ProtocolPtrTy =
+ Decl *ProtocolPtrTy =
ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS,
PIDecl->getGetterName(),
PIDecl->getSetterName(),
- DeclPtrTy::make(CCPrimary), isOverridingProperty,
+ CCPrimary, isOverridingProperty,
MethodImplKind);
- PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy.getAs<Decl>());
+ PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
}
PIDecl->makeitReadWriteAttribute();
if (Attributes & ObjCDeclSpec::DQ_PR_retain)
@@ -187,7 +189,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
*isOverridingProperty = true;
// Make sure setter decl is synthesized, and added to primary class's list.
ProcessPropertyDecl(PIDecl, CCPrimary);
- return DeclPtrTy();
+ return 0;
}
ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
@@ -289,19 +291,19 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
/// builds the AST node for a property implementation declaration; declared
/// as @synthesize or @dynamic.
///
-Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
- SourceLocation AtLoc,
- SourceLocation PropertyLoc,
- bool Synthesize,
- DeclPtrTy ClassCatImpDecl,
- IdentifierInfo *PropertyId,
- IdentifierInfo *PropertyIvar) {
+Decl *Sema::ActOnPropertyImplDecl(Scope *S,
+ SourceLocation AtLoc,
+ SourceLocation PropertyLoc,
+ bool Synthesize,
+ Decl *ClassCatImpDecl,
+ IdentifierInfo *PropertyId,
+ IdentifierInfo *PropertyIvar) {
ObjCContainerDecl *ClassImpDecl =
- cast_or_null<ObjCContainerDecl>(ClassCatImpDecl.getAs<Decl>());
+ cast_or_null<ObjCContainerDecl>(ClassCatImpDecl);
// Make sure we have a context for the property implementation declaration.
if (!ClassImpDecl) {
Diag(AtLoc, diag::error_missing_property_context);
- return DeclPtrTy();
+ return 0;
}
ObjCPropertyDecl *property = 0;
ObjCInterfaceDecl* IDecl = 0;
@@ -320,25 +322,25 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
property = IDecl->FindPropertyDeclaration(PropertyId);
if (!property) {
Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
- return DeclPtrTy();
+ return 0;
}
if (const ObjCCategoryDecl *CD =
dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
if (!CD->IsClassExtension()) {
Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
Diag(property->getLocation(), diag::note_property_declare);
- return DeclPtrTy();
+ return 0;
}
}
} else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
if (Synthesize) {
Diag(AtLoc, diag::error_synthesize_category_decl);
- return DeclPtrTy();
+ return 0;
}
IDecl = CatImplClass->getClassInterface();
if (!IDecl) {
Diag(AtLoc, diag::error_missing_property_interface);
- return DeclPtrTy();
+ return 0;
}
ObjCCategoryDecl *Category =
IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
@@ -346,17 +348,17 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
// If category for this implementation not found, it is an error which
// has already been reported eralier.
if (!Category)
- return DeclPtrTy();
+ return 0;
// Look for this property declaration in @implementation's category
property = Category->FindPropertyDeclaration(PropertyId);
if (!property) {
Diag(PropertyLoc, diag::error_bad_category_property_decl)
<< Category->getDeclName();
- return DeclPtrTy();
+ return 0;
}
} else {
Diag(AtLoc, diag::error_bad_property_context);
- return DeclPtrTy();
+ return 0;
}
ObjCIvarDecl *Ivar = 0;
// Check that we have a valid, previously declared ivar for @synthesize
@@ -372,7 +374,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc,
PropertyIvar, PropType, /*Dinfo=*/0,
ObjCIvarDecl::Protected,
- (Expr *)0);
+ (Expr *)0, true);
ClassImpDecl->addDecl(Ivar);
IDecl->makeDeclVisibleInContext(Ivar, false);
property->setPropertyIvarDecl(Ivar);
@@ -387,7 +389,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
<< property->getDeclName() << Ivar->getDeclName()
<< ClassDeclared->getDeclName();
Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
- << Ivar << Ivar->getNameAsCString();
+ << Ivar << Ivar->getName();
// Note! I deliberately want it to fall thru so more errors are caught.
}
QualType IvarType = Context.getCanonicalType(Ivar->getType());
@@ -464,7 +466,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
Expr *IvarRefExpr =
new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
SelfExpr, true, true);
- OwningExprResult Res =
+ ExprResult Res =
PerformCopyInitialization(InitializedEntity::InitializeResult(
SourceLocation(),
getterMethod->getResultType(),
@@ -494,8 +496,8 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
ParmVarDecl *Param = (*P);
Expr *rhs = new (Context) DeclRefExpr(Param,Param->getType(),
SourceLocation());
- OwningExprResult Res = BuildBinOp(S, SourceLocation(),
- BinaryOperator::Assign, lhs, rhs);
+ ExprResult Res = BuildBinOp(S, SourceLocation(),
+ BO_Assign, lhs, rhs);
PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
}
}
@@ -514,9 +516,29 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
= IC->FindPropertyImplDecl(PropertyId)) {
Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
- return DeclPtrTy();
+ return 0;
}
IC->addPropertyImplementation(PIDecl);
+ if (getLangOptions().ObjCNonFragileABI2) {
+ // Diagnose if an ivar was lazily synthesdized due to a previous
+ // use and if 1) property is @dynamic or 2) property is synthesized
+ // but it requires an ivar of different name.
+ ObjCInterfaceDecl *ClassDeclared;
+ ObjCIvarDecl *Ivar = 0;
+ if (!Synthesize)
+ Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
+ else {
+ if (PropertyIvar && PropertyIvar != PropertyId)
+ Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
+ }
+ // Issue diagnostics only if Ivar belongs to current class.
+ if (Ivar && Ivar->getSynthesize() &&
+ IC->getClassInterface() == ClassDeclared) {
+ Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
+ << PropertyId;
+ Ivar->setInvalidDecl();
+ }
+ }
} else {
if (Synthesize)
if (ObjCPropertyImplDecl *PPIDecl =
@@ -531,12 +553,12 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(Scope *S,
CatImplClass->FindPropertyImplDecl(PropertyId)) {
Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
- return DeclPtrTy();
+ return 0;
}
CatImplClass->addPropertyImplementation(PIDecl);
}
- return DeclPtrTy::make(PIDecl);
+ return PIDecl;
}
//===----------------------------------------------------------------------===//
@@ -680,9 +702,8 @@ Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
/// declared in 'ClassOrProtocol' objects (which can be a class or an
/// inherited protocol with the list of properties for class/category 'CDecl'
///
-void Sema::CompareProperties(Decl *CDecl,
- DeclPtrTy ClassOrProtocol) {
- Decl *ClassDecl = ClassOrProtocol.getAs<Decl>();
+void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) {
+ Decl *ClassDecl = ClassOrProtocol;
ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
if (!IDecl) {
@@ -699,7 +720,7 @@ void Sema::CompareProperties(Decl *CDecl,
// their properties with those in the category.
for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
E = CatDecl->protocol_end(); P != E; ++P)
- CompareProperties(CatDecl, DeclPtrTy::make(*P));
+ CompareProperties(CatDecl, *P);
} else {
ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
@@ -710,16 +731,18 @@ void Sema::CompareProperties(Decl *CDecl,
}
if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
- for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
- E = MDecl->protocol_end(); P != E; ++P)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = MDecl->all_referenced_protocol_begin(),
+ E = MDecl->all_referenced_protocol_end(); P != E; ++P)
// Match properties of class IDecl with those of protocol (*P).
MatchOneProtocolPropertiesInClass(IDecl, *P);
// Go thru the list of protocols for this class and recursively match
// their properties with those declared in the class.
- for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); P != E; ++P)
- CompareProperties(IDecl, DeclPtrTy::make(*P));
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ P = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); P != E; ++P)
+ CompareProperties(IDecl, *P);
} else {
ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
@@ -791,8 +814,9 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
PropMap[Prop->getIdentifier()] = Prop;
}
// scan through class's protocols.
- for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
@@ -803,7 +827,7 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
PropMap[Prop->getIdentifier()] = Prop;
}
// scan through class's protocols.
- for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+ for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
E = CATDecl->protocol_end(); PI != E; ++PI)
CollectImmediateProperties((*PI), PropMap, SuperPropMap);
}
@@ -838,8 +862,9 @@ static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl,
ObjCPropertyDecl *Prop = (*P);
PropMap[Prop->getIdentifier()] = Prop;
}
- for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); PI != E; ++PI)
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
CollectClassPropertyImplementations((*PI), PropMap);
}
else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
@@ -881,8 +906,9 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
return Prop;
}
// scan through class's protocols.
- for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
- E = IDecl->protocol_end(); PI != E; ++PI) {
+ for (ObjCInterfaceDecl::all_protocol_iterator
+ PI = IDecl->all_referenced_protocol_begin(),
+ E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
if (Prop)
return Prop;
@@ -933,9 +959,15 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
// Property may have been synthesized by user.
if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
continue;
+ if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
+ continue;
+ if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
+ continue;
+ }
ActOnPropertyImplDecl(S, IMPDecl->getLocation(), IMPDecl->getLocation(),
- true, DeclPtrTy::make(IMPDecl),
+ true, IMPDecl,
Prop->getIdentifier(), Prop->getIdentifier());
}
}
@@ -1066,7 +1098,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// for this class.
GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
property->getLocation(), property->getGetterName(),
- property->getType(), 0, CD, true, false, true,
+ property->getType(), 0, CD, true, false, true,
+ false,
(property->getPropertyImplementation() ==
ObjCPropertyDecl::Optional) ?
ObjCMethodDecl::Optional :
@@ -1094,6 +1127,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
property->getLocation(),
property->getSetterName(),
Context.VoidTy, 0, CD, true, false, true,
+ false,
(property->getPropertyImplementation() ==
ObjCPropertyDecl::Optional) ?
ObjCMethodDecl::Optional :
@@ -1105,8 +1139,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
property->getIdentifier(),
property->getType(),
/*TInfo=*/0,
- VarDecl::None,
- VarDecl::None,
+ SC_None,
+ SC_None,
0);
SetterMethod->setMethodParams(Context, &Argument, 1, 1);
CD->addDecl(SetterMethod);
@@ -1138,11 +1172,10 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
AddInstanceMethodToGlobalPool(SetterMethod);
}
-void Sema::CheckObjCPropertyAttributes(DeclPtrTy PropertyPtrTy,
+void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
SourceLocation Loc,
unsigned &Attributes) {
// FIXME: Improve the reported location.
- Decl *PDecl = PropertyPtrTy.getAs<Decl>();
if (!PDecl)
return;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index c4ab9061b445..11b4bb3b92c6 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -11,13 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "Lookup.h"
-#include "SemaInit.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeOrdering.h"
@@ -27,6 +30,34 @@
#include <algorithm>
namespace clang {
+using namespace sema;
+
+static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
+ bool InOverloadResolution,
+ StandardConversionSequence &SCS);
+static OverloadingResult
+IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+ UserDefinedConversionSequence& User,
+ OverloadCandidateSet& Conversions,
+ bool AllowExplicit);
+
+
+static ImplicitConversionSequence::CompareKind
+CompareStandardConversionSequences(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+static ImplicitConversionSequence::CompareKind
+CompareQualificationConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+static ImplicitConversionSequence::CompareKind
+CompareDerivedToBaseConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2);
+
+
/// GetConversionCategory - Retrieve the implicit conversion
/// category corresponding to the given implicit conversion kind.
@@ -298,7 +329,7 @@ namespace {
OverloadCandidate::DeductionFailureInfo
static MakeDeductionFailureInfo(ASTContext &Context,
Sema::TemplateDeductionResult TDK,
- Sema::TemplateDeductionInfo &Info) {
+ TemplateDeductionInfo &Info) {
OverloadCandidate::DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.Data = 0;
@@ -315,7 +346,7 @@ static MakeDeductionFailureInfo(ASTContext &Context,
break;
case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals: {
+ case Sema::TDK_Underqualified: {
// FIXME: Should allocate from normal heap so that we can free this later.
DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
Saved->Param = Info.Param;
@@ -348,7 +379,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
break;
case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals:
+ case Sema::TDK_Underqualified:
// FIXME: Destroy the data?
Data = 0;
break;
@@ -380,7 +411,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return TemplateParameter::getFromOpaqueValue(Data);
case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals:
+ case Sema::TDK_Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
// Unhandled
@@ -402,7 +433,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals:
+ case Sema::TDK_Underqualified:
return 0;
case Sema::TDK_SubstitutionFailure:
@@ -429,7 +460,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
return 0;
case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals:
+ case Sema::TDK_Underqualified:
return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
// Unhandled
@@ -454,7 +485,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
return 0;
case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals:
+ case Sema::TDK_Underqualified:
return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
// Unhandled
@@ -573,6 +604,11 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
bool UseUsingDeclRules) {
+ // If both of the functions are extern "C", then they are not
+ // overloads.
+ if (Old->isExternC() && New->isExternC())
+ return false;
+
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
@@ -669,40 +705,34 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
/// not permitted.
/// If @p AllowExplicit, then explicit user-defined conversions are
/// permitted.
-ImplicitConversionSequence
-Sema::TryImplicitConversion(Expr* From, QualType ToType,
- bool SuppressUserConversions,
- bool AllowExplicit,
- bool InOverloadResolution) {
+static ImplicitConversionSequence
+TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ bool AllowExplicit,
+ bool InOverloadResolution) {
ImplicitConversionSequence ICS;
- if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) {
+ if (IsStandardConversion(S, From, ToType, InOverloadResolution,
+ ICS.Standard)) {
ICS.setStandard();
return ICS;
}
- if (!getLangOptions().CPlusPlus) {
+ if (!S.getLangOptions().CPlusPlus) {
ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
return ICS;
}
- if (SuppressUserConversions) {
- // C++ [over.ics.user]p4:
- // A conversion of an expression of class type to the same class
- // type is given Exact Match rank, and a conversion of an
- // expression of class type to a base class of that type is
- // given Conversion rank, in spite of the fact that a copy/move
- // constructor (i.e., a user-defined conversion function) is
- // called for those cases.
- QualType FromType = From->getType();
- if (!ToType->getAs<RecordType>() || !FromType->getAs<RecordType>() ||
- !(Context.hasSameUnqualifiedType(FromType, ToType) ||
- IsDerivedFrom(FromType, ToType))) {
- // We're not in the case above, so there is no conversion that
- // we can perform.
- ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
- return ICS;
- }
-
+ // C++ [over.ics.user]p4:
+ // A conversion of an expression of class type to the same class
+ // type is given Exact Match rank, and a conversion of an
+ // expression of class type to a base class of that type is
+ // given Conversion rank, in spite of the fact that a copy/move
+ // constructor (i.e., a user-defined conversion function) is
+ // called for those cases.
+ QualType FromType = From->getType();
+ if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
+ (S.Context.hasSameUnqualifiedType(FromType, ToType) ||
+ S.IsDerivedFrom(FromType, ToType))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
@@ -713,18 +743,25 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
// exists. When we actually perform initialization, we'll find the
// appropriate constructor to copy the returned object, if needed.
ICS.Standard.CopyConstructor = 0;
-
+
// Determine whether this is considered a derived-to-base conversion.
- if (!Context.hasSameUnqualifiedType(FromType, ToType))
+ if (!S.Context.hasSameUnqualifiedType(FromType, ToType))
ICS.Standard.Second = ICK_Derived_To_Base;
-
+
+ return ICS;
+ }
+
+ if (SuppressUserConversions) {
+ // We're not in the case above, so there is no conversion that
+ // we can perform.
+ ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
return ICS;
}
// Attempt user-defined conversion.
OverloadCandidateSet Conversions(From->getExprLoc());
OverloadingResult UserDefResult
- = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions,
+ = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
AllowExplicit);
if (UserDefResult == OR_Success) {
@@ -739,10 +776,11 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
QualType FromCanon
- = Context.getCanonicalType(From->getType().getUnqualifiedType());
- QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
+ = S.Context.getCanonicalType(From->getType().getUnqualifiedType());
+ QualType ToCanon
+ = S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
- (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) {
+ (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
ICS.setStandard();
@@ -780,6 +818,24 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
return ICS;
}
+bool Sema::TryImplicitConversion(InitializationSequence &Sequence,
+ const InitializedEntity &Entity,
+ Expr *Initializer,
+ bool SuppressUserConversions,
+ bool AllowExplicitConversions,
+ bool InOverloadResolution) {
+ ImplicitConversionSequence ICS
+ = clang::TryImplicitConversion(*this, Initializer, Entity.getType(),
+ SuppressUserConversions,
+ AllowExplicitConversions,
+ InOverloadResolution);
+ if (ICS.isBad()) return true;
+
+ // Perform the actual conversion.
+ Sequence.AddConversionSequenceStep(ICS, Entity.getType());
+ return false;
+}
+
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType. Returns true if there was an
/// error, false otherwise. The expression From is replaced with the
@@ -797,10 +853,10 @@ bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
AssignmentAction Action, bool AllowExplicit,
ImplicitConversionSequence& ICS) {
- ICS = TryImplicitConversion(From, ToType,
- /*SuppressUserConversions=*/false,
- AllowExplicit,
- /*InOverloadResolution=*/false);
+ ICS = clang::TryImplicitConversion(*this, From, ToType,
+ /*SuppressUserConversions=*/false,
+ AllowExplicit,
+ /*InOverloadResolution=*/false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
@@ -850,16 +906,20 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
return true;
}
}
-
- // If lax vector conversions are permitted and the vector types are of the
- // same size, we can perform the conversion.
- if (Context.getLangOptions().LaxVectorConversions &&
- FromType->isVectorType() && ToType->isVectorType() &&
- Context.getTypeSize(FromType) == Context.getTypeSize(ToType)) {
- ICK = ICK_Vector_Conversion;
- return true;
+
+ // We can perform the conversion between vector types in the following cases:
+ // 1)vector types are equivalent AltiVec and GCC vector types
+ // 2)lax vector conversions are permitted and the vector types are of the
+ // same size
+ if (ToType->isVectorType() && FromType->isVectorType()) {
+ if (Context.areCompatibleVectorTypes(FromType, ToType) ||
+ (Context.getLangOptions().LaxVectorConversions &&
+ (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) {
+ ICK = ICK_Vector_Conversion;
+ return true;
+ }
}
-
+
return false;
}
@@ -871,12 +931,11 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType,
/// contain the standard conversion sequence required to perform this
/// conversion and this routine will return true. Otherwise, this
/// routine will return false and the value of SCS is unspecified.
-bool
-Sema::IsStandardConversion(Expr* From, QualType ToType,
- bool InOverloadResolution,
- StandardConversionSequence &SCS) {
+static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
+ bool InOverloadResolution,
+ StandardConversionSequence &SCS) {
QualType FromType = From->getType();
-
+
// Standard conversions (C++ [conv])
SCS.setAsIdentityConversion();
SCS.DeprecatedStringLiteralToCharPtr = false;
@@ -887,7 +946,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// There are no standard conversions for class types in C++, so
// abort early. When overloading in C, however, we do permit
if (FromType->isRecordType() || ToType->isRecordType()) {
- if (getLangOptions().CPlusPlus)
+ if (S.getLangOptions().CPlusPlus)
return false;
// When we're overloading in C, we allow, as standard conversions,
@@ -897,19 +956,19 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// array-to-pointer conversion, or function-to-pointer conversion
// (C++ 4p1).
- if (FromType == Context.OverloadTy) {
+ if (FromType == S.Context.OverloadTy) {
DeclAccessPair AccessPair;
if (FunctionDecl *Fn
- = ResolveAddressOfOverloadedFunction(From, ToType, false,
- AccessPair)) {
+ = S.ResolveAddressOfOverloadedFunction(From, ToType, false,
+ AccessPair)) {
// We were able to resolve the address of the overloaded function,
// so we can convert to the type of that function.
FromType = Fn->getType();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
if (!Method->isStatic()) {
Type *ClassType
- = Context.getTypeDeclType(Method->getParent()).getTypePtr();
- FromType = Context.getMemberPointerType(FromType, ClassType);
+ = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
+ FromType = S.Context.getMemberPointerType(FromType, ClassType);
}
}
@@ -917,12 +976,12 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// function, update the type of the resulting expression accordingly.
if (FromType->getAs<FunctionType>())
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens()))
- if (UnOp->getOpcode() == UnaryOperator::AddrOf)
- FromType = Context.getPointerType(FromType);
+ if (UnOp->getOpcode() == UO_AddrOf)
+ FromType = S.Context.getPointerType(FromType);
// Check that we've computed the proper type after overload resolution.
- assert(Context.hasSameType(FromType,
- FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
+ assert(S.Context.hasSameType(FromType,
+ S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
} else {
return false;
}
@@ -930,10 +989,10 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// Lvalue-to-rvalue conversion (C++ 4.1):
// An lvalue (3.10) of a non-function, non-array type T can be
// converted to an rvalue.
- Expr::isLvalueResult argIsLvalue = From->isLvalue(Context);
+ Expr::isLvalueResult argIsLvalue = From->isLvalue(S.Context);
if (argIsLvalue == Expr::LV_Valid &&
!FromType->isFunctionType() && !FromType->isArrayType() &&
- Context.getCanonicalType(FromType) != Context.OverloadTy) {
+ S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) {
SCS.First = ICK_Lvalue_To_Rvalue;
// If T is a non-class type, the type of the rvalue is the
@@ -948,9 +1007,9 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// An lvalue or rvalue of type "array of N T" or "array of unknown
// bound of T" can be converted to an rvalue of type "pointer to
// T" (C++ 4.2p1).
- FromType = Context.getArrayDecayedType(FromType);
+ FromType = S.Context.getArrayDecayedType(FromType);
- if (IsStringLiteralToNonConstPointerConversion(From, ToType)) {
+ if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
// This conversion is deprecated. (C++ D.4).
SCS.DeprecatedStringLiteralToCharPtr = true;
@@ -970,7 +1029,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// An lvalue of function type T can be converted to an rvalue of
// type "pointer to T." The result is a pointer to the
// function. (C++ 4.3p1).
- FromType = Context.getPointerType(FromType);
+ FromType = S.Context.getPointerType(FromType);
} else {
// We don't require any conversions for the first step.
SCS.First = ICK_Identity;
@@ -985,24 +1044,24 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// conversion.
bool IncompatibleObjC = false;
ImplicitConversionKind SecondICK = ICK_Identity;
- if (Context.hasSameUnqualifiedType(FromType, ToType)) {
+ if (S.Context.hasSameUnqualifiedType(FromType, ToType)) {
// The unqualified versions of the types are the same: there's no
// conversion to do.
SCS.Second = ICK_Identity;
- } else if (IsIntegralPromotion(From, FromType, ToType)) {
+ } else if (S.IsIntegralPromotion(From, FromType, ToType)) {
// Integral promotion (C++ 4.5).
SCS.Second = ICK_Integral_Promotion;
FromType = ToType.getUnqualifiedType();
- } else if (IsFloatingPointPromotion(FromType, ToType)) {
+ } else if (S.IsFloatingPointPromotion(FromType, ToType)) {
// Floating point promotion (C++ 4.6).
SCS.Second = ICK_Floating_Promotion;
FromType = ToType.getUnqualifiedType();
- } else if (IsComplexPromotion(FromType, ToType)) {
+ } else if (S.IsComplexPromotion(FromType, ToType)) {
// Complex promotion (Clang extension)
SCS.Second = ICK_Complex_Promotion;
FromType = ToType.getUnqualifiedType();
} else if (FromType->isIntegralOrEnumerationType() &&
- ToType->isIntegralType(Context)) {
+ ToType->isIntegralType(S.Context)) {
// Integral conversions (C++ 4.7).
SCS.Second = ICK_Integral_Conversion;
FromType = ToType.getUnqualifiedType();
@@ -1020,19 +1079,19 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
} else if ((FromType->isRealFloatingType() &&
- ToType->isIntegralType(Context) && !ToType->isBooleanType()) ||
+ ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) ||
(FromType->isIntegralOrEnumerationType() &&
ToType->isRealFloatingType())) {
// Floating-integral conversions (C++ 4.9).
SCS.Second = ICK_Floating_Integral;
FromType = ToType.getUnqualifiedType();
- } else if (IsPointerConversion(From, FromType, ToType, InOverloadResolution,
- FromType, IncompatibleObjC)) {
+ } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution,
+ FromType, IncompatibleObjC)) {
// Pointer conversions (C++ 4.10).
SCS.Second = ICK_Pointer_Conversion;
SCS.IncompatibleObjC = IncompatibleObjC;
- } else if (IsMemberPointerConversion(From, FromType, ToType,
- InOverloadResolution, FromType)) {
+ } else if (S.IsMemberPointerConversion(From, FromType, ToType,
+ InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
} else if (ToType->isBooleanType() &&
@@ -1044,16 +1103,16 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
FromType->isNullPtrType())) {
// Boolean conversions (C++ 4.12).
SCS.Second = ICK_Boolean_Conversion;
- FromType = Context.BoolTy;
- } else if (IsVectorConversion(Context, FromType, ToType, SecondICK)) {
+ FromType = S.Context.BoolTy;
+ } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
- } else if (!getLangOptions().CPlusPlus &&
- Context.typesAreCompatible(ToType, FromType)) {
+ } else if (!S.getLangOptions().CPlusPlus &&
+ S.Context.typesAreCompatible(ToType, FromType)) {
// Compatible conversions (Clang extension for C function overloading)
SCS.Second = ICK_Compatible_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if (IsNoReturnConversion(Context, FromType, ToType, FromType)) {
+ } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) {
// Treat a conversion that strips "noreturn" as an identity conversion.
SCS.Second = ICK_NoReturn_Adjustment;
} else {
@@ -1065,11 +1124,11 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
QualType CanonFrom;
QualType CanonTo;
// The third conversion can be a qualification conversion (C++ 4p1).
- if (IsQualificationConversion(FromType, ToType)) {
+ if (S.IsQualificationConversion(FromType, ToType)) {
SCS.Third = ICK_Qualification;
FromType = ToType;
- CanonFrom = Context.getCanonicalType(FromType);
- CanonTo = Context.getCanonicalType(ToType);
+ CanonFrom = S.Context.getCanonicalType(FromType);
+ CanonTo = S.Context.getCanonicalType(ToType);
} else {
// No conversion required
SCS.Third = ICK_Identity;
@@ -1078,8 +1137,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// [...] Any difference in top-level cv-qualification is
// subsumed by the initialization itself and does not constitute
// a conversion. [...]
- CanonFrom = Context.getCanonicalType(FromType);
- CanonTo = Context.getCanonicalType(ToType);
+ CanonFrom = S.Context.getCanonicalType(FromType);
+ CanonTo = S.Context.getCanonicalType(ToType);
if (CanonFrom.getLocalUnqualifiedType()
== CanonTo.getLocalUnqualifiedType() &&
(CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers()
@@ -1397,10 +1456,16 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
QualType FromPointeeType = FromTypePtr->getPointeeType();
+ // If the unqualified pointee types are the same, this can't be a
+ // pointer conversion, so don't do all of the work below.
+ if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType))
+ return false;
+
// An rvalue of type "pointer to cv T," where T is an object type,
// can be converted to an rvalue of type "pointer to cv void" (C++
// 4.10p2).
- if (FromPointeeType->isObjectType() && ToPointeeType->isVoidType()) {
+ if (FromPointeeType->isIncompleteOrObjectType() &&
+ ToPointeeType->isVoidType()) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
@@ -1657,8 +1722,8 @@ bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType,
/// 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,
- CXXBaseSpecifierArray& BasePath,
+ CastKind &Kind,
+ CXXCastPath& BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
@@ -1684,7 +1749,7 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
return true;
// The conversion was successful.
- Kind = CastExpr::CK_DerivedToBase;
+ Kind = CK_DerivedToBase;
}
}
if (const ObjCObjectPointerType *FromPtrType =
@@ -1749,8 +1814,8 @@ 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,
- CXXBaseSpecifierArray &BasePath,
+ CastKind &Kind,
+ CXXCastPath &BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
@@ -1759,7 +1824,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
assert(From->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull) &&
"Expr must be null pointer constant!");
- Kind = CastExpr::CK_NullToMemberPointer;
+ Kind = CK_NullToMemberPointer;
return false;
}
@@ -1803,7 +1868,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
// Must be a base to derived member conversion.
BuildBasePathArray(Paths, BasePath);
- Kind = CastExpr::CK_BaseToDerivedMemberPointer;
+ Kind = CK_BaseToDerivedMemberPointer;
return false;
}
@@ -1869,10 +1934,11 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) {
/// \param AllowExplicit true if the conversion should consider C++0x
/// "explicit" conversion functions as well as non-explicit conversion
/// functions (C++0x [class.conv.fct]p2).
-OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
- UserDefinedConversionSequence& User,
- OverloadCandidateSet& CandidateSet,
- bool AllowExplicit) {
+static OverloadingResult
+IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
+ UserDefinedConversionSequence& User,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowExplicit) {
// Whether we will only visit constructors.
bool ConstructorsOnly = false;
@@ -1887,17 +1953,17 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
// 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.
- if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+ if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
(From->getType()->getAs<RecordType>() &&
- IsDerivedFrom(From->getType(), ToType)))
+ S.IsDerivedFrom(From->getType(), ToType)))
ConstructorsOnly = true;
- if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
+ if (S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag())) {
// We're not going to find any constructors.
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = LookupConstructors(ToRecordDecl);
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
@@ -1915,16 +1981,18 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
- AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
- &From, 1, CandidateSet,
- /*SuppressUserConversions=*/!ConstructorsOnly);
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ &From, 1, CandidateSet,
+ /*SuppressUserConversions=*/
+ !ConstructorsOnly);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
- AddOverloadCandidate(Constructor, FoundDecl,
- &From, 1, CandidateSet,
- /*SuppressUserConversions=*/!ConstructorsOnly);
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ &From, 1, CandidateSet,
+ /*SuppressUserConversions=*/
+ !ConstructorsOnly);
}
}
}
@@ -1932,8 +2000,8 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
// Enumerate conversion functions, if we're allowed to.
if (ConstructorsOnly) {
- } else if (RequireCompleteType(From->getLocStart(), From->getType(),
- PDiag(0) << From->getSourceRange())) {
+ } else if (S.RequireCompleteType(From->getLocStart(), From->getType(),
+ S.PDiag(0) << From->getSourceRange())) {
// No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType
= From->getType()->getAs<RecordType>()) {
@@ -1959,80 +2027,79 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
- AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
- ActingContext, From, ToType,
- CandidateSet);
+ S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
+ ActingContext, From, ToType,
+ CandidateSet);
else
- AddConversionCandidate(Conv, FoundDecl, ActingContext,
- From, ToType, CandidateSet);
+ S.AddConversionCandidate(Conv, FoundDecl, ActingContext,
+ From, ToType, CandidateSet);
}
}
}
}
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) {
- case OR_Success:
- // Record the standard conversion we used and the conversion function.
- if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(Best->Function)) {
- // C++ [over.ics.user]p1:
- // If the user-defined conversion is specified by a
- // constructor (12.3.1), the initial standard conversion
- // sequence converts the source type to the type required by
- // the argument of the constructor.
- //
- QualType ThisType = Constructor->getThisType(Context);
- if (Best->Conversions[0].isEllipsis())
- User.EllipsisConversion = true;
- else {
- User.Before = Best->Conversions[0].Standard;
- User.EllipsisConversion = false;
- }
- User.ConversionFunction = Constructor;
- User.After.setAsIdentityConversion();
- User.After.setFromType(
- ThisType->getAs<PointerType>()->getPointeeType());
- User.After.setAllToTypes(ToType);
- return OR_Success;
- } else if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>(Best->Function)) {
- // C++ [over.ics.user]p1:
- //
- // [...] If the user-defined conversion is specified by a
- // conversion function (12.3.2), the initial standard
- // conversion sequence converts the source type to the
- // implicit object parameter of the conversion function.
+ switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best)) {
+ case OR_Success:
+ // Record the standard conversion we used and the conversion function.
+ if (CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(Best->Function)) {
+ // C++ [over.ics.user]p1:
+ // If the user-defined conversion is specified by a
+ // constructor (12.3.1), the initial standard conversion
+ // sequence converts the source type to the type required by
+ // the argument of the constructor.
+ //
+ QualType ThisType = Constructor->getThisType(S.Context);
+ if (Best->Conversions[0].isEllipsis())
+ User.EllipsisConversion = true;
+ else {
User.Before = Best->Conversions[0].Standard;
- User.ConversionFunction = Conversion;
User.EllipsisConversion = false;
-
- // C++ [over.ics.user]p2:
- // The second standard conversion sequence converts the
- // result of the user-defined conversion to the target type
- // for the sequence. Since an implicit conversion sequence
- // is an initialization, the special rules for
- // initialization by user-defined conversion apply when
- // selecting the best user-defined conversion for a
- // user-defined conversion sequence (see 13.3.3 and
- // 13.3.3.1).
- User.After = Best->FinalConversion;
- return OR_Success;
- } else {
- assert(false && "Not a constructor or conversion function?");
- return OR_No_Viable_Function;
}
-
- case OR_No_Viable_Function:
+ User.ConversionFunction = Constructor;
+ User.After.setAsIdentityConversion();
+ User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
+ User.After.setAllToTypes(ToType);
+ return OR_Success;
+ } else if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>(Best->Function)) {
+ // C++ [over.ics.user]p1:
+ //
+ // [...] If the user-defined conversion is specified by a
+ // conversion function (12.3.2), the initial standard
+ // conversion sequence converts the source type to the
+ // 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
+ // result of the user-defined conversion to the target type
+ // for the sequence. Since an implicit conversion sequence
+ // is an initialization, the special rules for
+ // initialization by user-defined conversion apply when
+ // selecting the best user-defined conversion for a
+ // user-defined conversion sequence (see 13.3.3 and
+ // 13.3.3.1).
+ User.After = Best->FinalConversion;
+ return OR_Success;
+ } else {
+ llvm_unreachable("Not a constructor or conversion function?");
return OR_No_Viable_Function;
- case OR_Deleted:
- // No conversion here! We're done.
- return OR_Deleted;
-
- case OR_Ambiguous:
- return OR_Ambiguous;
}
+ case OR_No_Viable_Function:
+ return OR_No_Viable_Function;
+ case OR_Deleted:
+ // No conversion here! We're done.
+ return OR_Deleted;
+
+ case OR_Ambiguous:
+ return OR_Ambiguous;
+ }
+
return OR_No_Viable_Function;
}
@@ -2041,7 +2108,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet(From->getExprLoc());
OverloadingResult OvResult =
- IsUserDefinedConversion(From, ToType, ICS.UserDefined,
+ IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false);
if (OvResult == OR_Ambiguous)
Diag(From->getSourceRange().getBegin(),
@@ -2053,16 +2120,17 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
<< From->getType() << ToType << From->getSourceRange();
else
return false;
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &From, 1);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1);
return true;
}
/// CompareImplicitConversionSequences - Compare two implicit
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2).
-ImplicitConversionSequence::CompareKind
-Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
- const ImplicitConversionSequence& ICS2)
+static ImplicitConversionSequence::CompareKind
+CompareImplicitConversionSequences(Sema &S,
+ const ImplicitConversionSequence& ICS1,
+ const ImplicitConversionSequence& ICS2)
{
// (C++ 13.3.3.2p2): When comparing the basic forms of implicit
// conversion sequences (as defined in 13.3.3.1)
@@ -2092,7 +2160,7 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
// indistinguishable conversion sequences unless one of the
// following rules apply: (C++ 13.3.3.2p3):
if (ICS1.isStandard())
- return CompareStandardConversionSequences(ICS1.Standard, ICS2.Standard);
+ return CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard);
else if (ICS1.isUserDefined()) {
// User-defined conversion sequence U1 is a better conversion
// sequence than another user-defined conversion sequence U2 if
@@ -2102,7 +2170,8 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
// U2 (C++ 13.3.3.2p3).
if (ICS1.UserDefined.ConversionFunction ==
ICS2.UserDefined.ConversionFunction)
- return CompareStandardConversionSequences(ICS1.UserDefined.After,
+ return CompareStandardConversionSequences(S,
+ ICS1.UserDefined.After,
ICS2.UserDefined.After);
}
@@ -2168,9 +2237,10 @@ compareStandardConversionSubsets(ASTContext &Context,
/// CompareStandardConversionSequences - Compare two standard
/// conversion sequences to determine whether one is better than the
/// other or if they are indistinguishable (C++ 13.3.3.2p3).
-ImplicitConversionSequence::CompareKind
-Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
- const StandardConversionSequence& SCS2)
+static ImplicitConversionSequence::CompareKind
+CompareStandardConversionSequences(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2)
{
// Standard conversion sequence S1 is a better conversion sequence
// than standard conversion sequence S2 if (C++ 13.3.3.2p3):
@@ -2181,7 +2251,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// sequence is considered to be a subsequence of any
// non-identity conversion sequence) or, if not that,
if (ImplicitConversionSequence::CompareKind CK
- = compareStandardConversionSubsets(Context, SCS1, SCS2))
+ = compareStandardConversionSubsets(S.Context, SCS1, SCS2))
return CK;
// -- the rank of S1 is better than the rank of S2 (by the rules
@@ -2212,9 +2282,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// void*, and conversion of A* to void* is better than conversion
// of B* to void*.
bool SCS1ConvertsToVoid
- = SCS1.isPointerConversionToVoidPointer(Context);
+ = SCS1.isPointerConversionToVoidPointer(S.Context);
bool SCS2ConvertsToVoid
- = SCS2.isPointerConversionToVoidPointer(Context);
+ = SCS2.isPointerConversionToVoidPointer(S.Context);
if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
// Exactly one of the conversion sequences is a conversion to
// a void pointer; it's the worse conversion.
@@ -2224,7 +2294,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// Neither conversion sequence converts to a void pointer; compare
// their derived-to-base conversions.
if (ImplicitConversionSequence::CompareKind DerivedCK
- = CompareDerivedToBaseConversions(SCS1, SCS2))
+ = CompareDerivedToBaseConversions(S, SCS1, SCS2))
return DerivedCK;
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
// Both conversion sequences are conversions to void
@@ -2236,18 +2306,18 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// Adjust the types we're converting from via the array-to-pointer
// conversion, if we need to.
if (SCS1.First == ICK_Array_To_Pointer)
- FromType1 = Context.getArrayDecayedType(FromType1);
+ FromType1 = S.Context.getArrayDecayedType(FromType1);
if (SCS2.First == ICK_Array_To_Pointer)
- FromType2 = Context.getArrayDecayedType(FromType2);
+ FromType2 = S.Context.getArrayDecayedType(FromType2);
QualType FromPointee1
= FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType FromPointee2
= FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
- if (IsDerivedFrom(FromPointee2, FromPointee1))
+ if (S.IsDerivedFrom(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
- else if (IsDerivedFrom(FromPointee1, FromPointee2))
+ else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
// Objective-C++: If one interface is more specific than the
@@ -2255,9 +2325,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
if (FromIface1 && FromIface1) {
- if (Context.canAssignObjCInterfaces(FromIface2, FromIface1))
+ if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1))
return ImplicitConversionSequence::Better;
- else if (Context.canAssignObjCInterfaces(FromIface1, FromIface2))
+ else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2))
return ImplicitConversionSequence::Worse;
}
}
@@ -2265,7 +2335,7 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// Compare based on qualification conversions (C++ 13.3.3.2p3,
// bullet 3).
if (ImplicitConversionSequence::CompareKind QualCK
- = CompareQualificationConversions(SCS1, SCS2))
+ = CompareQualificationConversions(S, SCS1, SCS2))
return QualCK;
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
@@ -2289,18 +2359,18 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// to which the reference initialized by S1 refers.
QualType T1 = SCS1.getToType(2);
QualType T2 = SCS2.getToType(2);
- T1 = Context.getCanonicalType(T1);
- T2 = Context.getCanonicalType(T2);
+ T1 = S.Context.getCanonicalType(T1);
+ T2 = S.Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
- QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
- QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+ QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
if (UnqualT1 == UnqualT2) {
// If the type is an array type, promote the element qualifiers to the type
// for comparison.
if (isa<ArrayType>(T1) && T1Quals)
- T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+ T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
if (isa<ArrayType>(T2) && T2Quals)
- T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+ T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
if (T2.isMoreQualifiedThan(T1))
return ImplicitConversionSequence::Better;
else if (T1.isMoreQualifiedThan(T2))
@@ -2315,8 +2385,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
/// sequences to determine whether they can be ranked based on their
/// qualification conversions (C++ 13.3.3.2p3 bullet 3).
ImplicitConversionSequence::CompareKind
-Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
- const StandardConversionSequence& SCS2) {
+CompareQualificationConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
// C++ 13.3.3.2p3:
// -- S1 and S2 differ only in their qualification conversion and
// yield similar types T1 and T2 (C++ 4.4), respectively, and the
@@ -2331,11 +2402,11 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
// conversion (!)
QualType T1 = SCS1.getToType(2);
QualType T2 = SCS2.getToType(2);
- T1 = Context.getCanonicalType(T1);
- T2 = Context.getCanonicalType(T2);
+ T1 = S.Context.getCanonicalType(T1);
+ T2 = S.Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
- QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
- QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+ QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
+ QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
// If the types are the same, we won't learn anything by unwrapped
// them.
@@ -2345,13 +2416,13 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
// If the type is an array type, promote the element qualifiers to the type
// for comparison.
if (isa<ArrayType>(T1) && T1Quals)
- T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+ T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
if (isa<ArrayType>(T2) && T2Quals)
- T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+ T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
- while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
+ while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
// Within each iteration of the loop, we check the qualifiers to
// determine if this still looks like a qualification
// conversion. Then, if all is well, we unwrap one more level of
@@ -2386,7 +2457,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
}
// If the types after this point are equivalent, we're done.
- if (Context.hasSameUnqualifiedType(T1, T2))
+ if (S.Context.hasSameUnqualifiedType(T1, T2))
break;
}
@@ -2416,8 +2487,9 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
/// [over.ics.rank]p4b3). As part of these checks, we also look at
/// conversions between Objective-C interface types.
ImplicitConversionSequence::CompareKind
-Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
- const StandardConversionSequence& SCS2) {
+CompareDerivedToBaseConversions(Sema &S,
+ const StandardConversionSequence& SCS1,
+ const StandardConversionSequence& SCS2) {
QualType FromType1 = SCS1.getFromType();
QualType ToType1 = SCS1.getToType(1);
QualType FromType2 = SCS2.getFromType();
@@ -2426,15 +2498,15 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
// Adjust the types we're converting from via the array-to-pointer
// conversion, if we need to.
if (SCS1.First == ICK_Array_To_Pointer)
- FromType1 = Context.getArrayDecayedType(FromType1);
+ FromType1 = S.Context.getArrayDecayedType(FromType1);
if (SCS2.First == ICK_Array_To_Pointer)
- FromType2 = Context.getArrayDecayedType(FromType2);
+ FromType2 = S.Context.getArrayDecayedType(FromType2);
// Canonicalize all of the types.
- FromType1 = Context.getCanonicalType(FromType1);
- ToType1 = Context.getCanonicalType(ToType1);
- FromType2 = Context.getCanonicalType(FromType2);
- ToType2 = Context.getCanonicalType(ToType2);
+ FromType1 = S.Context.getCanonicalType(FromType1);
+ ToType1 = S.Context.getCanonicalType(ToType1);
+ FromType2 = S.Context.getCanonicalType(FromType2);
+ ToType2 = S.Context.getCanonicalType(ToType2);
// C++ [over.ics.rank]p4b3:
//
@@ -2466,30 +2538,30 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
// -- conversion of C* to B* is better than conversion of C* to A*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
- if (IsDerivedFrom(ToPointee1, ToPointee2))
+ if (S.IsDerivedFrom(ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
- else if (IsDerivedFrom(ToPointee2, ToPointee1))
+ else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
if (ToIface1 && ToIface2) {
- if (Context.canAssignObjCInterfaces(ToIface2, ToIface1))
+ if (S.Context.canAssignObjCInterfaces(ToIface2, ToIface1))
return ImplicitConversionSequence::Better;
- else if (Context.canAssignObjCInterfaces(ToIface1, ToIface2))
+ else if (S.Context.canAssignObjCInterfaces(ToIface1, ToIface2))
return ImplicitConversionSequence::Worse;
}
}
// -- conversion of B* to A* is better than conversion of C* to A*,
if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
- if (IsDerivedFrom(FromPointee2, FromPointee1))
+ if (S.IsDerivedFrom(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
- else if (IsDerivedFrom(FromPointee1, FromPointee2))
+ else if (S.IsDerivedFrom(FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
if (FromIface1 && FromIface2) {
- if (Context.canAssignObjCInterfaces(FromIface1, FromIface2))
+ if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2))
return ImplicitConversionSequence::Better;
- else if (Context.canAssignObjCInterfaces(FromIface2, FromIface1))
+ else if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1))
return ImplicitConversionSequence::Worse;
}
}
@@ -2517,16 +2589,16 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
// conversion of A::* to B::* is better than conversion of A::* to C::*,
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
- if (IsDerivedFrom(ToPointee1, ToPointee2))
+ if (S.IsDerivedFrom(ToPointee1, ToPointee2))
return ImplicitConversionSequence::Worse;
- else if (IsDerivedFrom(ToPointee2, ToPointee1))
+ else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
return ImplicitConversionSequence::Better;
}
// conversion of B::* to C::* is better than conversion of A::* to C::*
if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
- if (IsDerivedFrom(FromPointee1, FromPointee2))
+ if (S.IsDerivedFrom(FromPointee1, FromPointee2))
return ImplicitConversionSequence::Better;
- else if (IsDerivedFrom(FromPointee2, FromPointee1))
+ else if (S.IsDerivedFrom(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Worse;
}
}
@@ -2536,11 +2608,11 @@ 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 (Context.hasSameUnqualifiedType(FromType1, FromType2) &&
- !Context.hasSameUnqualifiedType(ToType1, ToType2)) {
- if (IsDerivedFrom(ToType1, ToType2))
+ if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+ if (S.IsDerivedFrom(ToType1, ToType2))
return ImplicitConversionSequence::Better;
- else if (IsDerivedFrom(ToType2, ToType1))
+ else if (S.IsDerivedFrom(ToType2, ToType1))
return ImplicitConversionSequence::Worse;
}
@@ -2548,11 +2620,11 @@ 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 (!Context.hasSameUnqualifiedType(FromType1, FromType2) &&
- Context.hasSameUnqualifiedType(ToType1, ToType2)) {
- if (IsDerivedFrom(FromType2, FromType1))
+ if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
+ S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
+ if (S.IsDerivedFrom(FromType2, FromType1))
return ImplicitConversionSequence::Better;
- else if (IsDerivedFrom(FromType1, FromType2))
+ else if (S.IsDerivedFrom(FromType1, FromType2))
return ImplicitConversionSequence::Worse;
}
}
@@ -2570,7 +2642,8 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
Sema::ReferenceCompareResult
Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
- bool& DerivedToBase) {
+ bool &DerivedToBase,
+ bool &ObjCConversion) {
assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
@@ -2585,11 +2658,17 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
// reference-related to "cv2 T2" if T1 is the same type as T2, or
// T1 is a base class of T2.
- if (UnqualT1 == UnqualT2)
- DerivedToBase = false;
- else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
+ DerivedToBase = false;
+ ObjCConversion = false;
+ if (UnqualT1 == UnqualT2) {
+ // Nothing to do.
+ } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) &&
IsDerivedFrom(UnqualT2, UnqualT1))
DerivedToBase = true;
+ else if (UnqualT1->isObjCObjectOrInterfaceType() &&
+ UnqualT2->isObjCObjectOrInterfaceType() &&
+ Context.canBindObjCObjectType(UnqualT1, UnqualT2))
+ ObjCConversion = true;
else
return Ref_Incompatible;
@@ -2618,16 +2697,21 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
return Ref_Related;
}
-/// \brief Look for a user-defined conversion to an lvalue reference-compatible
+/// \brief Look for a user-defined conversion to an value reference-compatible
/// with DeclType. Return true if something definite is found.
static bool
-FindConversionToLValue(Sema &S, ImplicitConversionSequence &ICS,
- QualType DeclType, SourceLocation DeclLoc,
- Expr *Init, QualType T2, bool AllowExplicit) {
+FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
+ QualType DeclType, SourceLocation DeclLoc,
+ Expr *Init, QualType T2, bool AllowRvalues,
+ bool AllowExplicit) {
assert(T2->isRecordType() && "Can only find conversions of record types.");
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
+ QualType ToType
+ = AllowRvalues? DeclType->getAs<ReferenceType>()->getPointeeType()
+ : DeclType;
+
OverloadCandidateSet CandidateSet(DeclLoc);
const UnresolvedSetImpl *Conversions
= T2RecordDecl->getVisibleConversionFunctions();
@@ -2646,25 +2730,44 @@ FindConversionToLValue(Sema &S, ImplicitConversionSequence &ICS,
else
Conv = cast<CXXConversionDecl>(D);
- // If the conversion function doesn't return a reference type,
- // it can't be considered for this conversion. An rvalue reference
- // is only acceptable if its referencee is a function type.
- const ReferenceType *RefType =
- Conv->getConversionType()->getAs<ReferenceType>();
- if (RefType && (RefType->isLValueReferenceType() ||
- RefType->getPointeeType()->isFunctionType()) &&
- (AllowExplicit || !Conv->isExplicit())) {
- if (ConvTemplate)
- S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
- Init, DeclType, CandidateSet);
- else
- S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
- DeclType, CandidateSet);
+ // If this is an explicit conversion, and we're not allowed to consider
+ // explicit conversions, skip it.
+ if (!AllowExplicit && Conv->isExplicit())
+ continue;
+
+ if (AllowRvalues) {
+ bool DerivedToBase = false;
+ bool ObjCConversion = false;
+ if (!ConvTemplate &&
+ S.CompareReferenceRelationship(DeclLoc,
+ Conv->getConversionType().getNonReferenceType().getUnqualifiedType(),
+ DeclType.getNonReferenceType().getUnqualifiedType(),
+ DerivedToBase, ObjCConversion)
+ == Sema::Ref_Incompatible)
+ continue;
+ } else {
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion. An rvalue reference
+ // is only acceptable if its referencee is a function type.
+
+ const ReferenceType *RefType =
+ Conv->getConversionType()->getAs<ReferenceType>();
+ if (!RefType ||
+ (!RefType->isLValueReferenceType() &&
+ !RefType->getPointeeType()->isFunctionType()))
+ continue;
}
+
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
+ Init, ToType, CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
+ ToType, CandidateSet);
}
OverloadCandidateSet::iterator Best;
- switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+ switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
case OR_Success:
// C++ [over.ics.ref]p1:
//
@@ -2736,9 +2839,11 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// Compute some basic properties of the types and the initializer.
bool isRValRef = DeclType->isRValueReferenceType();
bool DerivedToBase = false;
+ bool ObjCConversion = false;
Expr::Classification InitCategory = Init->Classify(S.Context);
Sema::ReferenceCompareResult RefRelationship
- = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
+ = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase,
+ ObjCConversion);
// C++0x [dcl.init.ref]p5:
@@ -2764,7 +2869,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// derived-to-base Conversion (13.3.3.1).
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+ ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+ : ObjCConversion? ICK_Compatible_Conversion
+ : ICK_Identity;
ICS.Standard.Third = ICK_Identity;
ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
ICS.Standard.setToType(0, T2);
@@ -2792,8 +2899,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
if (!SuppressUserConversions && T2->isRecordType() &&
!S.RequireCompleteType(DeclLoc, T2, 0) &&
RefRelationship == Sema::Ref_Incompatible) {
- if (FindConversionToLValue(S, ICS, DeclType, DeclLoc,
- Init, T2, AllowExplicit))
+ if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+ Init, T2, /*AllowRvalues=*/false,
+ AllowExplicit))
return ICS;
}
}
@@ -2845,26 +2953,37 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// that is the result of the conversion in the second case
// (or, in either case, to the appropriate base class
// subobject of the object).
- //
- // We're only checking the first case here, which is a direct
- // binding in C++0x but not in C++03.
- if (InitCategory.isRValue() && T2->isRecordType() &&
- RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
- ICS.setStandard();
- ICS.Standard.First = ICK_Identity;
- ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
- ICS.Standard.Third = ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
- ICS.Standard.setToType(0, T2);
- ICS.Standard.setToType(1, T1);
- ICS.Standard.setToType(2, T1);
- ICS.Standard.ReferenceBinding = true;
- ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x;
- ICS.Standard.RRefBinding = isRValRef;
- ICS.Standard.CopyConstructor = 0;
- return ICS;
+ if (T2->isRecordType()) {
+ // First case: "cv1 T1" is reference-compatible with "cv2 T2". This is a
+ // direct binding in C++0x but not in C++03.
+ if (InitCategory.isRValue() &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ ICS.setStandard();
+ ICS.Standard.First = ICK_Identity;
+ ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
+ : ObjCConversion? ICK_Compatible_Conversion
+ : ICK_Identity;
+ ICS.Standard.Third = ICK_Identity;
+ ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setToType(0, T2);
+ ICS.Standard.setToType(1, T1);
+ ICS.Standard.setToType(2, T1);
+ ICS.Standard.ReferenceBinding = true;
+ ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x;
+ ICS.Standard.RRefBinding = isRValRef;
+ ICS.Standard.CopyConstructor = 0;
+ return ICS;
+ }
+
+ // Second case: not reference-related.
+ if (RefRelationship == Sema::Ref_Incompatible &&
+ !S.RequireCompleteType(DeclLoc, T2, 0) &&
+ FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
+ Init, T2, /*AllowRvalues=*/true,
+ AllowExplicit))
+ return ICS;
}
-
+
// -- Otherwise, a temporary of type "cv1 T1" is created and
// initialized from the initializer expression using the
// rules for a non-reference copy initialization (8.5). The
@@ -2899,9 +3018,9 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
// the argument expression. Any difference in top-level
// cv-qualification is subsumed by the initialization itself
// and does not constitute a conversion.
- ICS = S.TryImplicitConversion(Init, T1, SuppressUserConversions,
- /*AllowExplicit=*/false,
- /*InOverloadResolution=*/false);
+ ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
+ /*AllowExplicit=*/false,
+ /*InOverloadResolution=*/false);
// Of course, that's still a reference binding.
if (ICS.isStandard()) {
@@ -2930,25 +3049,25 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
SuppressUserConversions,
/*AllowExplicit=*/false);
- return S.TryImplicitConversion(From, ToType,
- SuppressUserConversions,
- /*AllowExplicit=*/false,
- InOverloadResolution);
+ return TryImplicitConversion(S, From, ToType,
+ SuppressUserConversions,
+ /*AllowExplicit=*/false,
+ InOverloadResolution);
}
/// TryObjectArgumentInitialization - Try to initialize the object
/// parameter of the given member function (@c Method) from the
/// expression @p From.
-ImplicitConversionSequence
-Sema::TryObjectArgumentInitialization(QualType OrigFromType,
- CXXMethodDecl *Method,
- CXXRecordDecl *ActingContext) {
- QualType ClassType = Context.getTypeDeclType(ActingContext);
+static ImplicitConversionSequence
+TryObjectArgumentInitialization(Sema &S, QualType OrigFromType,
+ CXXMethodDecl *Method,
+ CXXRecordDecl *ActingContext) {
+ QualType ClassType = S.Context.getTypeDeclType(ActingContext);
// [class.dtor]p2: A destructor can be invoked for a const, volatile or
// const volatile object.
unsigned Quals = isa<CXXDestructorDecl>(Method) ?
Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
- QualType ImplicitParamType = Context.getCVRQualifiedType(ClassType, Quals);
+ QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals);
// Set up the conversion sequence as a "bad" conversion, to allow us
// to exit early.
@@ -2972,7 +3091,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType,
// 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);
+ QualType FromTypeCanon = S.Context.getCanonicalType(FromType);
if (ImplicitParamType.getCVRQualifiers()
!= FromTypeCanon.getLocalCVRQualifiers() &&
!ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
@@ -2983,11 +3102,11 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType,
// Check that we have either the same type or a derived type. It
// affects the conversion rank.
- QualType ClassTypeCanon = Context.getCanonicalType(ClassType);
+ QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
ImplicitConversionKind SecondKind;
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
SecondKind = ICK_Identity;
- } else if (IsDerivedFrom(FromType, ClassType))
+ } else if (S.IsDerivedFrom(FromType, ClassType))
SecondKind = ICK_Derived_To_Base;
else {
ICS.setBad(BadConversionSequence::unrelated_class,
@@ -3030,7 +3149,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,
// Note that we always use the true parent context when performing
// the actual argument initialization.
ImplicitConversionSequence ICS
- = TryObjectArgumentInitialization(From->getType(), Method,
+ = TryObjectArgumentInitialization(*this, From->getType(), Method,
Method->getParent());
if (ICS.isBad())
return Diag(From->getSourceRange().getBegin(),
@@ -3041,16 +3160,17 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,
return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
if (!Context.hasSameType(From->getType(), DestType))
- ImpCastExprToType(From, DestType, CastExpr::CK_NoOp,
- /*isLvalue=*/!From->getType()->isPointerType());
+ ImpCastExprToType(From, DestType, CK_NoOp,
+ From->getType()->isPointerType() ? VK_RValue : VK_LValue);
return false;
}
/// TryContextuallyConvertToBool - Attempt to contextually convert the
/// expression From to bool (C++0x [conv]p3).
-ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) {
+static ImplicitConversionSequence
+TryContextuallyConvertToBool(Sema &S, Expr *From) {
// FIXME: This is pretty broken.
- return TryImplicitConversion(From, Context.BoolTy,
+ return TryImplicitConversion(S, From, S.Context.BoolTy,
// FIXME: Are these flags correct?
/*SuppressUserConversions=*/false,
/*AllowExplicit=*/true,
@@ -3060,7 +3180,7 @@ ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) {
/// PerformContextuallyConvertToBool - Perform a contextual conversion
/// of the expression From to bool (C++0x [conv]p3).
bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
- ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From);
+ ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
@@ -3073,20 +3193,21 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
/// TryContextuallyConvertToObjCId - Attempt to contextually convert the
/// expression From to 'id'.
-ImplicitConversionSequence Sema::TryContextuallyConvertToObjCId(Expr *From) {
- QualType Ty = Context.getObjCIdType();
- return TryImplicitConversion(From, Ty,
- // FIXME: Are these flags correct?
- /*SuppressUserConversions=*/false,
- /*AllowExplicit=*/true,
- /*InOverloadResolution=*/false);
+static ImplicitConversionSequence
+TryContextuallyConvertToObjCId(Sema &S, Expr *From) {
+ QualType Ty = S.Context.getObjCIdType();
+ return TryImplicitConversion(S, From, Ty,
+ // FIXME: Are these flags correct?
+ /*SuppressUserConversions=*/false,
+ /*AllowExplicit=*/true,
+ /*InOverloadResolution=*/false);
}
-
+
/// PerformContextuallyConvertToObjCId - Perform a contextual conversion
/// of the expression From to 'id'.
bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
QualType Ty = Context.getObjCIdType();
- ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(From);
+ ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
return true;
@@ -3128,8 +3249,8 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) {
///
/// \returns The expression, converted to an integral or enumeration type if
/// successful.
-Sema::OwningExprResult
-Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
+ExprResult
+Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
const PartialDiagnostic &NotIntDiag,
const PartialDiagnostic &IncompleteDiag,
const PartialDiagnostic &ExplicitConvDiag,
@@ -3137,16 +3258,14 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
const PartialDiagnostic &AmbigDiag,
const PartialDiagnostic &AmbigNote,
const PartialDiagnostic &ConvDiag) {
- Expr *From = static_cast<Expr *>(FromE.get());
-
// We can't perform any more checking for type-dependent expressions.
if (From->isTypeDependent())
- return move(FromE);
+ return Owned(From);
// If the expression already has integral or enumeration type, we're golden.
QualType T = From->getType();
if (T->isIntegralOrEnumerationType())
- return move(FromE);
+ return Owned(From);
// FIXME: Check for missing '()' if T is a function type?
@@ -3156,12 +3275,12 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
if (!RecordTy || !getLangOptions().CPlusPlus) {
Diag(Loc, NotIntDiag)
<< T << From->getSourceRange();
- return move(FromE);
+ return Owned(From);
}
// We must have a complete class type.
if (RequireCompleteType(Loc, T, IncompleteDiag))
- return move(FromE);
+ return Owned(From);
// Look for a conversion to an integral or enumeration type.
UnresolvedSet<4> ViableConversions;
@@ -3213,8 +3332,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
return ExprError();
CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
- From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found, Conversion);
- FromE = Owned(From);
+ From = BuildCXXMemberCallExpr(From, Found, Conversion);
}
// We'll complain below about a non-integral condition type.
@@ -3237,9 +3355,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
<< T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
}
- From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found,
+ From = BuildCXXMemberCallExpr(From, Found,
cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
- FromE = Owned(From);
break;
}
@@ -3253,14 +3370,14 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
Diag(Conv->getLocation(), AmbigNote)
<< ConvTy->isEnumeralType() << ConvTy;
}
- return move(FromE);
+ return Owned(From);
}
if (!From->getType()->isIntegralOrEnumerationType())
Diag(Loc, NotIntDiag)
<< From->getType() << From->getSourceRange();
- return move(FromE);
+ return Owned(From);
}
/// AddOverloadCandidate - Adds the given function to the set of
@@ -3306,7 +3423,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
return;
// Overload resolution is always an unevaluated context.
- EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){
// C++ [class.copy]p3:
@@ -3469,7 +3586,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
return;
// Overload resolution is always an unevaluated context.
- EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
@@ -3513,7 +3630,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
// Determine the implicit conversion sequence for the object
// parameter.
Candidate.Conversions[0]
- = TryObjectArgumentInitialization(ObjectType, Method, ActingContext);
+ = TryObjectArgumentInitialization(*this, ObjectType, Method,
+ ActingContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -3666,7 +3784,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
return;
// Overload resolution is always an unevaluated context.
- EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
@@ -3678,25 +3796,32 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(ConvType);
Candidate.FinalConversion.setAllToTypes(ToType);
+ Candidate.Viable = true;
+ Candidate.Conversions.resize(1);
+ // C++ [over.match.funcs]p4:
+ // For conversion functions, the function is considered to be a member of
+ // the class of the implicit implied object argument for the purpose of
+ // defining the type of the implicit object parameter.
+ //
// Determine the implicit conversion sequence for the implicit
// object parameter.
- Candidate.Viable = true;
- Candidate.Conversions.resize(1);
+ QualType ImplicitParamType = From->getType();
+ if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
+ ImplicitParamType = FromPtrType->getPointeeType();
+ CXXRecordDecl *ConversionContext
+ = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
+
Candidate.Conversions[0]
- = TryObjectArgumentInitialization(From->getType(), Conversion,
- ActingContext);
- // Conversion functions to a different type in the base class is visible in
- // the derived class. So, a derived to base conversion should not participate
- // in overload resolution.
- if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base)
- Candidate.Conversions[0].Standard.Second = ICK_Identity;
+ = TryObjectArgumentInitialization(*this, From->getType(), Conversion,
+ ConversionContext);
+
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
-
+
// We won't go through a user-define type conversion function to convert a
// derived to base as such conversions are given Conversion Rank. They only
// go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user]
@@ -3719,9 +3844,10 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// well-formed.
DeclRefExpr ConversionRef(Conversion, Conversion->getType(),
From->getLocStart());
- ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()),
- CastExpr::CK_FunctionToPointerDecay,
- &ConversionRef, CXXBaseSpecifierArray(), false);
+ ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
+ Context.getPointerType(Conversion->getType()),
+ CK_FunctionToPointerDecay,
+ &ConversionRef, VK_RValue);
// Note that it is safe to allocate CallExpr on the stack here because
// there are 0 arguments (i.e., nothing is allocated using ASTContext's
@@ -3819,7 +3945,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
return;
// Overload resolution is always an unevaluated context.
- EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
@@ -3834,7 +3960,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// Determine the implicit conversion sequence for the implicit
// object parameter.
ImplicitConversionSequence ObjectInit
- = TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
+ = TryObjectArgumentInitialization(*this, ObjectType, Conversion,
+ ActingContext);
if (ObjectInit.isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
@@ -3925,9 +4052,6 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
// candidates, non-member candidates and built-in candidates, are
// constructed as follows:
QualType T1 = Args[0]->getType();
- QualType T2;
- if (NumArgs > 1)
- T2 = Args[1]->getType();
// -- If T1 is a class type, the set of member candidates is the
// result of the qualified lookup of T1::operator@
@@ -3966,7 +4090,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
bool IsAssignmentOperator,
unsigned NumContextualBoolArguments) {
// Overload resolution is always an unevaluated context.
- EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
@@ -3999,7 +4123,8 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
if (ArgIdx < NumContextualBoolArguments) {
assert(ParamTys[ArgIdx] == Context.BoolTy &&
"Contextual conversion to bool requires bool type");
- Candidate.Conversions[ArgIdx] = TryContextuallyConvertToBool(Args[ArgIdx]);
+ Candidate.Conversions[ArgIdx]
+ = TryContextuallyConvertToBool(*this, Args[ArgIdx]);
} else {
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx],
@@ -4100,11 +4225,21 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
// Insert this type.
if (!PointerTypes.insert(Ty))
return false;
-
+
+ QualType PointeeTy;
const PointerType *PointerTy = Ty->getAs<PointerType>();
- assert(PointerTy && "type was not a pointer type!");
-
- QualType PointeeTy = PointerTy->getPointeeType();
+ bool buildObjCPtr = false;
+ if (!PointerTy) {
+ if (const ObjCObjectPointerType *PTy = Ty->getAs<ObjCObjectPointerType>()) {
+ PointeeTy = PTy->getPointeeType();
+ buildObjCPtr = true;
+ }
+ else
+ assert(false && "type was not a pointer type!");
+ }
+ else
+ PointeeTy = PointerTy->getPointeeType();
+
// Don't add qualified variants of arrays. For one, they're not allowed
// (the qualifier would sink to the element type), and for another, the
// only overload situation where it matters is subscript or pointer +- int,
@@ -4125,7 +4260,10 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue;
if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue;
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
- PointerTypes.insert(Context.getPointerType(QPointeeTy));
+ if (!buildObjCPtr)
+ PointerTypes.insert(Context.getPointerType(QPointeeTy));
+ else
+ PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy));
}
return true;
@@ -4200,10 +4338,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
// If we're dealing with an array type, decay to the pointer.
if (Ty->isArrayType())
Ty = SemaRef.Context.getArrayDecayedType(Ty);
-
- if (const PointerType *PointerTy = Ty->getAs<PointerType>()) {
- QualType PointeeTy = PointerTy->getPointeeType();
-
+ if (Ty->isObjCIdType() || Ty->isObjCClassType())
+ PointerTypes.insert(Ty);
+ else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) {
// Insert our type, and its more-qualified variants, into the set
// of types.
if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
@@ -4479,7 +4616,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
Ptr != CandidateTypes.pointer_end(); ++Ptr) {
// Skip pointer types that aren't pointers to object types.
- if (!(*Ptr)->getAs<PointerType>()->getPointeeType()->isObjectType())
+ if (!(*Ptr)->getPointeeType()->isIncompleteOrObjectType())
continue;
QualType ParamTypes[2] = {
@@ -4519,7 +4656,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
Ptr != CandidateTypes.pointer_end(); ++Ptr) {
QualType ParamTy = *Ptr;
- QualType PointeeTy = ParamTy->getAs<PointerType>()->getPointeeType();
+ QualType PointeeTy = ParamTy->getPointeeType();
AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy),
&ParamTy, Args, 1, CandidateSet);
}
@@ -5000,7 +5137,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
Ptr != CandidateTypes.pointer_end(); ++Ptr) {
QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
- QualType PointeeType = (*Ptr)->getAs<PointerType>()->getPointeeType();
+ QualType PointeeType = (*Ptr)->getPointeeType();
QualType ResultTy = Context.getLValueReferenceType(PointeeType);
// T& operator[](T*, ptrdiff_t)
@@ -5028,18 +5165,16 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
QualType C1Ty = (*Ptr);
QualType C1;
QualifierCollector Q1;
- if (const PointerType *PointerTy = C1Ty->getAs<PointerType>()) {
- C1 = QualType(Q1.strip(PointerTy->getPointeeType()), 0);
- if (!isa<RecordType>(C1))
- continue;
- // heuristic to reduce number of builtin candidates in the set.
- // Add volatile/restrict version only if there are conversions to a
- // volatile/restrict type.
- if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
- continue;
- if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
- continue;
- }
+ C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
+ if (!isa<RecordType>(C1))
+ continue;
+ // heuristic to reduce number of builtin candidates in the set.
+ // Add volatile/restrict version only if there are conversions to a
+ // volatile/restrict type.
+ if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
+ continue;
+ if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
+ continue;
for (BuiltinCandidateTypeSet::iterator
MemPtr = CandidateTypes.member_pointer_begin(),
MemPtrEnd = CandidateTypes.member_pointer_end();
@@ -5148,9 +5283,10 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool
-Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
- const OverloadCandidate& Cand2,
- SourceLocation Loc) {
+isBetterOverloadCandidate(Sema &S,
+ const OverloadCandidate& Cand1,
+ const OverloadCandidate& Cand2,
+ SourceLocation Loc) {
// Define viable functions to be better candidates than non-viable
// functions.
if (!Cand2.Viable)
@@ -5176,7 +5312,8 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
- switch (CompareImplicitConversionSequences(Cand1.Conversions[ArgIdx],
+ switch (CompareImplicitConversionSequences(S,
+ Cand1.Conversions[ArgIdx],
Cand2.Conversions[ArgIdx])) {
case ImplicitConversionSequence::Better:
// Cand1 has a better conversion sequence.
@@ -5211,9 +5348,9 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
Cand2.Function && Cand2.Function->getPrimaryTemplate())
if (FunctionTemplateDecl *BetterTemplate
- = getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
- Cand2.Function->getPrimaryTemplate(),
- Loc,
+ = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
+ Cand2.Function->getPrimaryTemplate(),
+ Loc,
isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
: TPOC_Call))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
@@ -5227,7 +5364,8 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
if (Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
- switch (CompareStandardConversionSequences(Cand1.FinalConversion,
+ switch (CompareStandardConversionSequences(S,
+ Cand1.FinalConversion,
Cand2.FinalConversion)) {
case ImplicitConversionSequence::Better:
// Cand1 has a better conversion sequence.
@@ -5258,32 +5396,28 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1,
/// function, Best points to the candidate function found.
///
/// \returns The result of overload resolution.
-OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
- SourceLocation Loc,
- OverloadCandidateSet::iterator& Best) {
+OverloadingResult
+OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
+ iterator& Best) {
// Find the best viable function.
- Best = CandidateSet.end();
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
- Cand != CandidateSet.end(); ++Cand) {
- if (Cand->Viable) {
- if (Best == CandidateSet.end() ||
- isBetterOverloadCandidate(*Cand, *Best, Loc))
+ Best = end();
+ for (iterator Cand = begin(); Cand != end(); ++Cand) {
+ if (Cand->Viable)
+ if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc))
Best = Cand;
- }
}
// If we didn't find any viable functions, abort.
- if (Best == CandidateSet.end())
+ if (Best == end())
return OR_No_Viable_Function;
// Make sure that this function is better than every other viable
// function. If not, we have an ambiguity.
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
- Cand != CandidateSet.end(); ++Cand) {
+ for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable &&
Cand != Best &&
- !isBetterOverloadCandidate(*Best, *Cand, Loc)) {
- Best = CandidateSet.end();
+ !isBetterOverloadCandidate(S, *Best, *Cand, Loc)) {
+ Best = end();
return OR_Ambiguous;
}
}
@@ -5301,7 +5435,7 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet,
// (clause 13), user-defined conversions (12.3.2), allocation function for
// placement new (5.3.4), as well as non-default initialization (8.5).
if (Best->Function)
- MarkDeclarationReferenced(Loc, Best->Function);
+ S.MarkDeclarationReferenced(Loc, Best->Function);
return OR_Success;
}
@@ -5365,14 +5499,15 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
/// Diagnoses an ambiguous conversion. The partial diagnostic is the
/// "lead" diagnostic; it will be given two arguments, the source and
/// target types of the conversion.
-void Sema::DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
- SourceLocation CaretLoc,
- const PartialDiagnostic &PDiag) {
- Diag(CaretLoc, PDiag)
- << ICS.Ambiguous.getFromType() << ICS.Ambiguous.getToType();
+void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
+ Sema &S,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) const {
+ S.Diag(CaretLoc, PDiag)
+ << Ambiguous.getFromType() << Ambiguous.getToType();
for (AmbiguousConversionSequence::const_iterator
- I = ICS.Ambiguous.begin(), E = ICS.Ambiguous.end(); I != E; ++I) {
- NoteOverloadCandidate(*I);
+ I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) {
+ S.NoteOverloadCandidate(*I);
}
}
@@ -5589,8 +5724,31 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
return;
}
- case Sema::TDK_Inconsistent:
- case Sema::TDK_InconsistentQuals: {
+ case Sema::TDK_Underqualified: {
+ assert(ParamD && "no parameter found for bad qualifiers deduction result");
+ TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
+
+ QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
+
+ // Param will have been canonicalized, but it should just be a
+ // qualified version of ParamD, so move the qualifiers to that.
+ QualifierCollector Qs(S.Context);
+ Qs.strip(Param);
+ QualType NonCanonParam = Qs.apply(TParam->getTypeForDecl());
+ assert(S.Context.hasSameType(Param, NonCanonParam));
+
+ // Arg has also been canonicalized, but there's nothing we can do
+ // about that. It also doesn't matter as much, because it won't
+ // have any template parameters in it (because deduction isn't
+ // done on dependent types).
+ QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
+
+ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
+ << ParamD->getDeclName() << Arg << NonCanonParam;
+ return;
+ }
+
+ case Sema::TDK_Inconsistent: {
assert(ParamD && "no parameter found for inconsistent deduction result");
int which = 0;
if (isa<TemplateTypeParmDecl>(ParamD))
@@ -5779,7 +5937,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
if (ICS.isBad()) break; // all meaningless after first invalid
if (!ICS.isAmbiguous()) continue;
- S.DiagnoseAmbiguousConversion(ICS, OpLoc,
+ ICS.DiagnoseAmbiguousConversion(S, OpLoc,
S.PDiag(diag::note_ambiguous_type_conversion));
}
}
@@ -5808,8 +5966,8 @@ struct CompareOverloadCandidatesForDisplay {
// TODO: introduce a tri-valued comparison for overload
// candidates. Would be more worthwhile if we had a sort
// that could exploit it.
- if (S.isBetterOverloadCandidate(*L, *R, SourceLocation())) return true;
- if (S.isBetterOverloadCandidate(*R, *L, SourceLocation())) return false;
+ if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true;
+ if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false;
} else if (R->Viable)
return false;
@@ -5838,8 +5996,9 @@ struct CompareOverloadCandidatesForDisplay {
int leftBetter = 0;
unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
for (unsigned E = L->Conversions.size(); I != E; ++I) {
- switch (S.CompareImplicitConversionSequences(L->Conversions[I],
- R->Conversions[I])) {
+ switch (CompareImplicitConversionSequences(S,
+ L->Conversions[I],
+ R->Conversions[I])) {
case ImplicitConversionSequence::Better:
leftBetter++;
break;
@@ -5947,23 +6106,20 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
/// PrintOverloadCandidates - When overload resolution fails, prints
/// diagnostic messages containing the candidates in the candidate
/// set.
-void
-Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
- OverloadCandidateDisplayKind OCD,
- Expr **Args, unsigned NumArgs,
- const char *Opc,
- SourceLocation OpLoc) {
+void OverloadCandidateSet::NoteCandidates(Sema &S,
+ OverloadCandidateDisplayKind OCD,
+ Expr **Args, unsigned NumArgs,
+ const char *Opc,
+ SourceLocation OpLoc) {
// Sort the candidates by viability and position. Sorting directly would
// be prohibitive, so we make a set of pointers and sort those.
llvm::SmallVector<OverloadCandidate*, 32> Cands;
- if (OCD == OCD_AllCandidates) Cands.reserve(CandidateSet.size());
- for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
- LastCand = CandidateSet.end();
- Cand != LastCand; ++Cand) {
+ if (OCD == OCD_AllCandidates) Cands.reserve(size());
+ for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (Cand->Viable)
Cands.push_back(Cand);
else if (OCD == OCD_AllCandidates) {
- CompleteNonViableCandidate(*this, Cand, Args, NumArgs);
+ CompleteNonViableCandidate(S, Cand, Args, NumArgs);
if (Cand->Function || Cand->IsSurrogate)
Cands.push_back(Cand);
// Otherwise, this a non-viable builtin candidate. We do not, in general,
@@ -5972,12 +6128,12 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
}
std::sort(Cands.begin(), Cands.end(),
- CompareOverloadCandidatesForDisplay(*this));
+ CompareOverloadCandidatesForDisplay(S));
bool ReportedAmbiguousConversions = false;
llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
- const Diagnostic::OverloadsShown ShowOverloads = Diags.getShowOverloads();
+ const Diagnostic::OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
unsigned CandsShown = 0;
for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
OverloadCandidate *Cand = *I;
@@ -5991,9 +6147,9 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
++CandsShown;
if (Cand->Function)
- NoteFunctionCandidate(*this, Cand, Args, NumArgs);
+ NoteFunctionCandidate(S, Cand, Args, NumArgs);
else if (Cand->IsSurrogate)
- NoteSurrogateCandidate(*this, Cand);
+ NoteSurrogateCandidate(S, Cand);
else {
assert(Cand->Viable &&
"Non-viable built-in candidates are not added to Cands.");
@@ -6004,17 +6160,17 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
// FIXME: It's quite possible for different conversions to see
// different ambiguities, though.
if (!ReportedAmbiguousConversions) {
- NoteAmbiguousUserConversions(*this, OpLoc, Cand);
+ NoteAmbiguousUserConversions(S, OpLoc, Cand);
ReportedAmbiguousConversions = true;
}
// If this is a viable builtin, print it.
- NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
+ NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand);
}
}
if (I != E)
- Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
+ S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
@@ -6061,12 +6217,13 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
- TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
- if (OvlExpr->hasExplicitTemplateArgs()) {
- OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
- ExplicitTemplateArgs = &ETABuffer;
- }
+ // However, remember whether the expression has member-pointer form:
+ // C++ [expr.unary.op]p4:
+ // A pointer to member is only formed when an explicit & is used
+ // and its operand is a qualified-id not enclosed in
+ // parentheses.
+ OverloadExpr::FindResult Ovl = OverloadExpr::find(From);
+ OverloadExpr *OvlExpr = Ovl.Expression;
// We expect a pointer or reference to function, or a function pointer.
FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
@@ -6078,6 +6235,25 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
}
+ // If the overload expression doesn't have the form of a pointer to
+ // member, don't try to convert it to a pointer-to-member type.
+ if (IsMember && !Ovl.HasFormOfMemberPointer) {
+ if (!Complain) return 0;
+
+ // TODO: Should we condition this on whether any functions might
+ // have matched, or is it more appropriate to do that in callers?
+ // TODO: a fixit wouldn't hurt.
+ Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
+ << ToType << OvlExpr->getSourceRange();
+ return 0;
+ }
+
+ TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
+ if (OvlExpr->hasExplicitTemplateArgs()) {
+ OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
+ ExplicitTemplateArgs = &ETABuffer;
+ }
+
assert(From->getType() == Context.OverloadTy);
// Look through all of the overloaded functions, searching for one
@@ -6267,7 +6443,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
if (From->getType() != Context.OverloadTy)
return 0;
- OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
+ OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
// If we didn't actually find any template-ids, we're done.
if (!OvlExpr->hasExplicitTemplateArgs())
@@ -6405,18 +6581,10 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
PartialOverloading);
}
-static Sema::OwningExprResult Destroy(Sema &SemaRef, Expr *Fn,
- Expr **Args, unsigned NumArgs) {
- Fn->Destroy(SemaRef.Context);
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
- Args[Arg]->Destroy(SemaRef.Context);
- return SemaRef.ExprError();
-}
-
/// Attempts to recover from a call where no functions were found.
///
/// Returns true if new candidates were found.
-static Sema::OwningExprResult
+static ExprResult
BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
@@ -6440,13 +6608,13 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression))
- return Destroy(SemaRef, Fn, Args, NumArgs);
+ return ExprError();
assert(!R.empty() && "lookup results empty despite recovery");
// Build an implicit member call if appropriate. Just drop the
// casts and such from the call, we don't really care.
- Sema::OwningExprResult NewFn = SemaRef.ExprError();
+ ExprResult NewFn = ExprError();
if ((*R.begin())->isCXXClassMember())
NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs);
else if (ExplicitTemplateArgs)
@@ -6455,15 +6623,13 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false);
if (NewFn.isInvalid())
- return Destroy(SemaRef, Fn, Args, NumArgs);
-
- Fn->Destroy(SemaRef.Context);
+ return ExprError();
// This shouldn't cause an infinite loop because we're giving it
// an expression with non-empty lookup results, which should never
// end up here.
- return SemaRef.ActOnCallExpr(/*Scope*/ 0, move(NewFn), LParenLoc,
- Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs),
+ return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc,
+ MultiExprArg(Args, NumArgs),
CommaLocs, RParenLoc);
}
@@ -6474,7 +6640,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
/// the function declaration produced by overload
/// resolution. Otherwise, emits diagnostics, deletes all of the
/// arguments and Fn, and returns NULL.
-Sema::OwningExprResult
+ExprResult
Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -6512,7 +6678,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
CommaLocs, RParenLoc);
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
+ switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
@@ -6525,13 +6691,13 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
Diag(Fn->getSourceRange().getBegin(),
diag::err_ovl_no_viable_function_in_call)
<< ULE->getName() << Fn->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
case OR_Ambiguous:
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
break;
case OR_Deleted:
@@ -6539,15 +6705,11 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
<< Best->Function->isDeleted()
<< ULE->getName()
<< Fn->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
}
- // Overload resolution failed. Destroy all of the subexpressions and
- // return NULL.
- Fn->Destroy(Context);
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
- Args[Arg]->Destroy(Context);
+ // Overload resolution failed.
return ExprError();
}
@@ -6572,16 +6734,17 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
/// by CreateOverloadedUnaryOp().
///
/// \param input The input argument.
-Sema::OwningExprResult
+ExprResult
Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
const UnresolvedSetImpl &Fns,
- ExprArg input) {
+ Expr *Input) {
UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
- Expr *Input = (Expr *)input.get();
OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+ // TODO: provide better source location info.
+ DeclarationNameInfo OpNameInfo(OpName, OpLoc);
Expr *Args[2] = { Input, 0 };
unsigned NumArgs = 1;
@@ -6589,16 +6752,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// For post-increment and post-decrement, add the implicit '0' as
// the second argument, so that we know this is a post-increment or
// post-decrement.
- if (Opc == UnaryOperator::PostInc || Opc == UnaryOperator::PostDec) {
+ if (Opc == UO_PostInc || Opc == UO_PostDec) {
llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
- Args[1] = new (Context) IntegerLiteral(Zero, Context.IntTy,
- SourceLocation());
+ Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy,
+ SourceLocation());
NumArgs = 2;
}
if (Input->isTypeDependent()) {
if (Fns.empty())
- return Owned(new (Context) UnaryOperator(input.takeAs<Expr>(),
+ return Owned(new (Context) UnaryOperator(Input,
Opc,
Context.DependentTy,
OpLoc));
@@ -6606,10 +6769,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
- 0, SourceRange(), OpName, OpLoc,
+ 0, SourceRange(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
- input.release();
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
&Args[0], NumArgs,
Context.DependentTy,
@@ -6636,7 +6798,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
+ switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -6654,16 +6816,14 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
return ExprError();
} else {
// Convert the arguments.
- OwningExprResult InputInit
+ ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
FnDecl->getParamDecl(0)),
SourceLocation(),
- move(input));
+ Input);
if (InputInit.isInvalid())
return ExprError();
-
- input = move(InputInit);
- Input = (Expr *)input.get();
+ Input = InputInit.take();
}
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
@@ -6676,17 +6836,16 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
SourceLocation());
UsualUnaryConversions(FnExpr);
- input.release();
Args[0] = Input;
- ExprOwningPtr<CallExpr> TheCall(this,
+ CallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
- Args, NumArgs, ResultTy, OpLoc));
+ Args, NumArgs, ResultTy, OpLoc);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(),
+ if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
FnDecl))
return ExprError();
- return MaybeBindToTemporary(TheCall.release());
+ return MaybeBindToTemporary(TheCall);
} else {
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
@@ -6708,8 +6867,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs,
- UnaryOperator::getOpcodeStr(Opc), OpLoc);
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+ Args, NumArgs,
+ UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
@@ -6717,15 +6877,14 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
<< Best->Function->isDeleted()
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
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();
- return CreateBuiltinUnaryOp(OpLoc, Opc, Owned(Input));
+ return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
/// \brief Create a binary operation that may resolve to an overloaded
@@ -6745,7 +6904,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
///
/// \param LHS Left-hand argument.
/// \param RHS Right-hand argument.
-Sema::OwningExprResult
+ExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
unsigned OpcIn,
const UnresolvedSetImpl &Fns,
@@ -6763,7 +6922,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Fns.empty()) {
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
- if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
+ if (Opc <= BO_Assign || Opc > BO_OrAssign)
return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
Context.DependentTy, OpLoc));
@@ -6776,9 +6935,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// FIXME: save results of ADL from here?
CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ // TODO: provide better source location info in DNLoc component.
+ DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
- 0, SourceRange(), OpName, OpLoc,
+ 0, SourceRange(), OpNameInfo,
/*ADL*/ true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
@@ -6789,7 +6950,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If this is the .* operator, which is not overloadable, just
// create a built-in binary operator.
- if (Opc == BinaryOperator::PtrMemD)
+ if (Opc == BO_PtrMemD)
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// If this is the assignment operator, we only perform overload resolution
@@ -6798,7 +6959,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// various built-in candidates, but as DR507 points out, this can lead to
// problems. So we do it this way, which pretty much follows what GCC does.
// Note that we go the traditional code path for compound assignment forms.
- if (Opc==BinaryOperator::Assign && !Args[0]->getType()->isOverloadableType())
+ if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType())
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// Build an empty overload set.
@@ -6821,7 +6982,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
+ switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -6835,7 +6996,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Best->Access is only meaningful for class members.
CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl);
- OwningExprResult Arg1
+ ExprResult Arg1
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
FnDecl->getParamDecl(0)),
@@ -6851,7 +7012,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Args[1] = RHS = Arg1.takeAs<Expr>();
} else {
// Convert the arguments.
- OwningExprResult Arg0
+ ExprResult Arg0
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
FnDecl->getParamDecl(0)),
@@ -6860,7 +7021,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Arg0.isInvalid())
return ExprError();
- OwningExprResult Arg1
+ ExprResult Arg1
= PerformCopyInitialization(
InitializedEntity::InitializeParameter(
FnDecl->getParamDecl(1)),
@@ -6884,16 +7045,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
OpLoc);
UsualUnaryConversions(FnExpr);
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
- Args, 2, ResultTy,
- OpLoc));
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, Op, FnExpr,
+ Args, 2, ResultTy, OpLoc);
- if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall.get(),
+ if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall,
FnDecl))
return ExprError();
- return MaybeBindToTemporary(TheCall.release());
+ return MaybeBindToTemporary(TheCall);
} else {
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
@@ -6913,15 +7073,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If the operator is the operator , [...] and there are no
// viable functions, then the operator is assumed to be the
// built-in operator and interpreted according to clause 5.
- if (Opc == BinaryOperator::Comma)
+ if (Opc == BO_Comma)
break;
// For class as left operand for assignment or compound assigment operator
// do not fall through to handling in built-in, but report that no overloaded
// assignment operator found
- OwningExprResult Result = ExprError();
+ ExprResult Result = ExprError();
if (Args[0]->getType()->isRecordType() &&
- Opc >= BinaryOperator::Assign && Opc <= BinaryOperator::OrAssign) {
+ Opc >= BO_Assign && Opc <= BO_OrAssign) {
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
@@ -6933,8 +7093,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
assert(Result.isInvalid() &&
"C++ binary operator overloading is missing candidates!");
if (Result.isInvalid())
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2,
- BinaryOperator::getOpcodeStr(Opc), OpLoc);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
return move(Result);
}
@@ -6942,8 +7102,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, 2,
- BinaryOperator::getOpcodeStr(Opc), OpLoc);
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2,
+ BinaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
@@ -6951,7 +7111,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2);
return ExprError();
}
@@ -6959,12 +7119,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
-Action::OwningExprResult
+ExprResult
Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
SourceLocation RLoc,
- ExprArg Base, ExprArg Idx) {
- Expr *Args[2] = { static_cast<Expr*>(Base.get()),
- static_cast<Expr*>(Idx.get()) };
+ Expr *Base, Expr *Idx) {
+ Expr *Args[2] = { Base, Idx };
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
@@ -6973,16 +7132,17 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators
+ // CHECKME: no 'operator' keyword?
+ DeclarationNameInfo OpNameInfo(OpName, LLoc);
+ OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass,
- 0, SourceRange(), OpName, LLoc,
+ 0, SourceRange(), OpNameInfo,
/*ADL*/ true, /*Overloaded*/ false,
UnresolvedSetIterator(),
UnresolvedSetIterator());
// Can't add any actual overloads yet
- Base.release();
- Idx.release();
return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
Args, 2,
Context.DependentTy,
@@ -7002,7 +7162,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, LLoc, Best)) {
+ switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) {
case OR_Success: {
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
@@ -7021,7 +7181,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return ExprError();
// Convert the arguments.
- OwningExprResult InputInit
+ ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
FnDecl->getParamDecl(0)),
SourceLocation(),
@@ -7041,18 +7201,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
LLoc);
UsualUnaryConversions(FnExpr);
- Base.release();
- Idx.release();
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
- FnExpr, Args, 2,
- ResultTy, RLoc));
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
+ FnExpr, Args, 2,
+ ResultTy, RLoc);
- if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(),
+ if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall,
FnDecl))
return ExprError();
- return MaybeBindToTemporary(TheCall.release());
+ return MaybeBindToTemporary(TheCall);
} else {
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
@@ -7076,32 +7234,29 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Diag(LLoc, diag::err_ovl_no_viable_subscript)
<< Args[0]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2,
- "[]", LLoc);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ "[]", LLoc);
return ExprError();
}
case OR_Ambiguous:
Diag(LLoc, diag::err_ovl_ambiguous_oper)
<< "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, 2,
- "[]", LLoc);
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2,
+ "[]", LLoc);
return ExprError();
case OR_Deleted:
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, 2,
- "[]", LLoc);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2,
+ "[]", LLoc);
return ExprError();
}
// We matched a built-in operator; build it.
- Base.release();
- Idx.release();
- return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc,
- Owned(Args[1]), RLoc);
+ return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc);
}
/// BuildCallToMemberFunction - Build a call to a member
@@ -7111,7 +7266,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
/// parameter). The caller needs to validate that the member
/// expression refers to a member function or an overloaded member
/// function.
-Sema::OwningExprResult
+ExprResult
Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
SourceLocation LParenLoc, Expr **Args,
unsigned NumArgs, SourceLocation *CommaLocs,
@@ -7174,7 +7329,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
DeclarationName DeclName = UnresExpr->getMemberName();
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
+ switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
+ Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
FoundDecl = Best->FoundDecl;
@@ -7186,14 +7342,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(UnresExpr->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
return ExprError();
case OR_Ambiguous:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
return ExprError();
@@ -7201,7 +7357,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName << MemExprE->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
// FIXME: Leaking incoming expressions!
return ExprError();
}
@@ -7219,15 +7375,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
assert(Method && "Member call to something that isn't a method?");
- ExprOwningPtr<CXXMemberCallExpr>
- TheCall(this, new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
- NumArgs,
- Method->getCallResultType(),
- RParenLoc));
+ CXXMemberCallExpr *TheCall =
+ new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+ Method->getCallResultType(),
+ RParenLoc);
// Check for a valid return type.
if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(),
- TheCall.get(), Method))
+ TheCall, Method))
return ExprError();
// Convert the object argument (for a non-static member function call).
@@ -7242,21 +7397,21 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Convert the rest of the arguments
const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>();
- if (ConvertArgumentsForCall(&*TheCall, MemExpr, Method, Proto, Args, NumArgs,
+ if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs,
RParenLoc))
return ExprError();
- if (CheckFunctionCall(Method, TheCall.get()))
+ if (CheckFunctionCall(Method, TheCall))
return ExprError();
- return MaybeBindToTemporary(TheCall.release());
+ return MaybeBindToTemporary(TheCall);
}
/// BuildCallToObjectOfClassType - Build a call to an object of class
/// type (C++ [over.call.object]), which can end up invoking an
/// overloaded function call operator (@c operator()) or performing a
/// user-defined conversion on the object argument.
-Sema::ExprResult
+ExprResult
Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
@@ -7338,7 +7493,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) {
+ switch (CandidateSet.BestViableFunction(*this, Object->getLocStart(),
+ Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the appropriate call
// below.
@@ -7353,14 +7509,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
Diag(Object->getSourceRange().getBegin(),
diag::err_ovl_no_viable_object_call)
<< Object->getType() << Object->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
case OR_Ambiguous:
Diag(Object->getSourceRange().getBegin(),
diag::err_ovl_ambiguous_object_call)
<< Object->getType() << Object->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs);
break;
case OR_Deleted:
@@ -7368,18 +7524,12 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
<< Object->getType() << Object->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs);
break;
}
- if (Best == CandidateSet.end()) {
- // We had an error; delete all of the subexpressions and return
- // the error.
- Object->Destroy(Context);
- for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
- Args[ArgIdx]->Destroy(Context);
+ if (Best == CandidateSet.end())
return true;
- }
if (Best->Function == 0) {
// Since there is no function declaration, this is one of the
@@ -7400,9 +7550,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Best->FoundDecl,
Conv);
- return ActOnCallExpr(S, ExprArg(*this, CE), LParenLoc,
- MultiExprArg(*this, (ExprTy**)Args, NumArgs),
- CommaLocs, RParenLoc).result();
+ return ActOnCallExpr(S, CE, LParenLoc, MultiExprArg(Args, NumArgs),
+ CommaLocs, RParenLoc);
}
CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
@@ -7438,13 +7587,13 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Once we've built TheCall, all of the expressions are properly
// owned.
QualType ResultTy = Method->getCallResultType();
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
- MethodArgs, NumArgs + 1,
- ResultTy, RParenLoc));
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn,
+ MethodArgs, NumArgs + 1,
+ ResultTy, RParenLoc);
delete [] MethodArgs;
- if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall.get(),
+ if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall,
Method))
return true;
@@ -7471,15 +7620,15 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
// Pass the argument.
- OwningExprResult InputInit
+ ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
Method->getParamDecl(i)),
- SourceLocation(), Owned(Arg));
+ SourceLocation(), Arg);
IsError |= InputInit.isInvalid();
Arg = InputInit.takeAs<Expr>();
} else {
- OwningExprResult DefArg
+ ExprResult DefArg
= BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
if (DefArg.isInvalid()) {
IsError = true;
@@ -7504,18 +7653,17 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
if (IsError) return true;
- if (CheckFunctionCall(Method, TheCall.get()))
+ if (CheckFunctionCall(Method, TheCall))
return true;
- return MaybeBindToTemporary(TheCall.release()).result();
+ return MaybeBindToTemporary(TheCall);
}
/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
/// (if one exists), where @c Base is an expression of class type and
/// @c Member is the name of the member we're trying to find.
-Sema::OwningExprResult
-Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
- Expr *Base = static_cast<Expr *>(BaseIn.get());
+ExprResult
+Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) {
assert(Base->getType()->isRecordType() && "left-hand side must have class type");
SourceLocation Loc = Base->getExprLoc();
@@ -7547,7 +7695,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
// Perform overload resolution.
OverloadCandidateSet::iterator Best;
- switch (BestViableFunction(CandidateSet, OpLoc, Best)) {
+ switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success:
// Overload resolution succeeded; we'll build the call below.
break;
@@ -7559,20 +7707,20 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
else
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< "operator->" << Base->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &Base, 1);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
return ExprError();
case OR_Ambiguous:
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< "->" << Base->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, &Base, 1);
+ CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1);
return ExprError();
case OR_Deleted:
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< "->" << Base->getSourceRange();
- PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, &Base, 1);
+ CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1);
return ExprError();
}
@@ -7585,23 +7733,20 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
Best->FoundDecl, Method))
return ExprError();
- // No concerns about early exits now.
- BaseIn.release();
-
// Build the operator call.
Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(),
SourceLocation());
UsualUnaryConversions(FnExpr);
QualType ResultTy = Method->getCallResultType();
- ExprOwningPtr<CXXOperatorCallExpr>
- TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
- &Base, 1, ResultTy, OpLoc));
+ CXXOperatorCallExpr *TheCall =
+ new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr,
+ &Base, 1, ResultTy, OpLoc);
- if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall.get(),
+ if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall,
Method))
return ExprError();
- return move(TheCall);
+ return Owned(TheCall);
}
/// FixOverloadedFunctionReference - E is an expression that refers to
@@ -7626,17 +7771,18 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
assert(Context.hasSameType(ICE->getSubExpr()->getType(),
SubExpr->getType()) &&
"Implicit cast type cannot be determined from overload");
+ assert(ICE->path_empty() && "fixing up hierarchy conversion?");
if (SubExpr == ICE->getSubExpr())
return ICE->Retain();
- return new (Context) ImplicitCastExpr(ICE->getType(),
- ICE->getCastKind(),
- SubExpr, CXXBaseSpecifierArray(),
- ICE->isLvalueCast());
+ return ImplicitCastExpr::Create(Context, ICE->getType(),
+ ICE->getCastKind(),
+ SubExpr, 0,
+ ICE->getValueKind());
}
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
- assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&
+ assert(UnOp->getOpcode() == UO_AddrOf &&
"Can only take the address of an overloaded function");
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
if (Method->isStatic()) {
@@ -7664,7 +7810,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
QualType MemPtrType
= Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
- return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
+ return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
MemPtrType, UnOp->getOperatorLoc());
}
}
@@ -7673,7 +7819,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (SubExpr == UnOp->getSubExpr())
return UnOp->Retain();
- return new (Context) UnaryOperator(SubExpr, UnaryOperator::AddrOf,
+ return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
Context.getPointerType(SubExpr->getType()),
UnOp->getOperatorLoc());
}
@@ -7732,7 +7878,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
MemExpr->getQualifierRange(),
Fn,
Found,
- MemExpr->getMemberLoc(),
+ MemExpr->getMemberNameInfo(),
TemplateArgs,
Fn->getType());
}
@@ -7741,9 +7887,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
return E->Retain();
}
-Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E,
- DeclAccessPair Found,
- FunctionDecl *Fn) {
+ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
+ DeclAccessPair Found,
+ FunctionDecl *Fn) {
return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
}
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 9c8f48bfea17..083e4dba85e3 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -11,8 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
-#include "SemaInit.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/Initialization.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -26,19 +28,11 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
+using namespace sema;
-Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) {
- Expr *E = expr->takeAs<Expr>();
+StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
+ Expr *E = expr.get();
assert(E && "ActOnExprStmt(): missing expression");
- if (E->getType()->isObjCObjectType()) {
- if (LangOpts.ObjCNonFragileABI)
- Diag(E->getLocEnd(), diag::err_indirection_requires_nonfragile_object)
- << E->getType();
- else
- Diag(E->getLocEnd(), diag::err_direct_interface_unsupported)
- << E->getType();
- return StmtError();
- }
// C99 6.8.3p2: The expression in an expression statement is evaluated as a
// void expression for its side effects. Conversion to void allows any
// operand, even incomplete types.
@@ -48,11 +42,11 @@ Sema::OwningStmtResult Sema::ActOnExprStmt(FullExprArg expr) {
}
-Sema::OwningStmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) {
+StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc) {
return Owned(new (Context) NullStmt(SemiLoc));
}
-Sema::OwningStmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg,
+StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg,
SourceLocation StartLoc,
SourceLocation EndLoc) {
DeclGroupRef DG = dg.getAsVal<DeclGroupRef>();
@@ -141,10 +135,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
}
- Diag(Loc, DiagID) << R1 << R2;
+ DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2);
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
MultiStmtArg elts, bool isStmtExpr) {
unsigned NumElts = elts.size();
@@ -179,70 +173,60 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R));
}
-Action::OwningStmtResult
-Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprArg lhsval,
- SourceLocation DotDotDotLoc, ExprArg rhsval,
+StmtResult
+Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
+ SourceLocation DotDotDotLoc, Expr *RHSVal,
SourceLocation ColonLoc) {
- assert((lhsval.get() != 0) && "missing expression in case statement");
+ assert((LHSVal != 0) && "missing expression in case statement");
// C99 6.8.4.2p3: The expression shall be an integer constant.
// However, GCC allows any evaluatable integer expression.
- Expr *LHSVal = static_cast<Expr*>(lhsval.get());
if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() &&
VerifyIntegerConstantExpression(LHSVal))
return StmtError();
// GCC extension: The expression shall be an integer constant.
- Expr *RHSVal = static_cast<Expr*>(rhsval.get());
if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() &&
VerifyIntegerConstantExpression(RHSVal)) {
RHSVal = 0; // Recover by just forgetting about it.
- rhsval = 0;
}
- if (getSwitchStack().empty()) {
+ if (getCurFunction()->SwitchStack.empty()) {
Diag(CaseLoc, diag::err_case_not_in_switch);
return StmtError();
}
- // Only now release the smart pointers.
- lhsval.release();
- rhsval.release();
CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
ColonLoc);
- getSwitchStack().back()->addSwitchCase(CS);
+ getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
return Owned(CS);
}
/// ActOnCaseStmtBody - This installs a statement as the body of a case.
-void Sema::ActOnCaseStmtBody(StmtTy *caseStmt, StmtArg subStmt) {
+void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) {
CaseStmt *CS = static_cast<CaseStmt*>(caseStmt);
- Stmt *SubStmt = subStmt.takeAs<Stmt>();
CS->setSubStmt(SubStmt);
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
- StmtArg subStmt, Scope *CurScope) {
- Stmt *SubStmt = subStmt.takeAs<Stmt>();
-
- if (getSwitchStack().empty()) {
+ Stmt *SubStmt, Scope *CurScope) {
+ if (getCurFunction()->SwitchStack.empty()) {
Diag(DefaultLoc, diag::err_default_not_in_switch);
return Owned(SubStmt);
}
DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
- getSwitchStack().back()->addSwitchCase(DS);
+ getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
return Owned(DS);
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
- SourceLocation ColonLoc, StmtArg subStmt) {
- Stmt *SubStmt = subStmt.takeAs<Stmt>();
+ SourceLocation ColonLoc, Stmt *SubStmt) {
// Look up the record for this label identifier.
- LabelStmt *&LabelDecl = getLabelMap()[II];
+ LabelStmt *&LabelDecl = getCurFunction()->LabelMap[II];
// If not forward referenced or defined already, just create a new LabelStmt.
if (LabelDecl == 0)
@@ -265,15 +249,15 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
return Owned(LabelDecl);
}
-Action::OwningStmtResult
-Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar,
- StmtArg ThenVal, SourceLocation ElseLoc,
- StmtArg ElseVal) {
- OwningExprResult CondResult(CondVal.release());
+StmtResult
+Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
+ Stmt *thenStmt, SourceLocation ElseLoc,
+ Stmt *elseStmt) {
+ ExprResult CondResult(CondVal.release());
VarDecl *ConditionVar = 0;
- if (CondVar.get()) {
- ConditionVar = CondVar.getAs<VarDecl>();
+ if (CondVar) {
+ ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, IfLoc, true);
if (CondResult.isInvalid())
return StmtError();
@@ -282,22 +266,19 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar,
if (!ConditionExpr)
return StmtError();
- Stmt *thenStmt = ThenVal.takeAs<Stmt>();
DiagnoseUnusedExprResult(thenStmt);
// Warn if the if block has a null body without an else value.
// this helps prevent bugs due to typos, such as
// if (condition);
// do_stuff();
- if (!ElseVal.get()) {
+ if (!elseStmt) {
if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt))
Diag(stmt->getSemiLoc(), diag::warn_empty_if_body);
}
- Stmt *elseStmt = ElseVal.takeAs<Stmt>();
DiagnoseUnusedExprResult(elseStmt);
- CondResult.release();
return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
thenStmt, ElseLoc, elseStmt));
}
@@ -404,64 +385,63 @@ static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) {
return expr->getType();
}
-Action::OwningStmtResult
-Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond,
- DeclPtrTy CondVar) {
+StmtResult
+Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
+ Decl *CondVar) {
+ ExprResult CondResult;
+
VarDecl *ConditionVar = 0;
- if (CondVar.get()) {
- ConditionVar = CondVar.getAs<VarDecl>();
- OwningExprResult CondE = CheckConditionVariable(ConditionVar, SourceLocation(), false);
- if (CondE.isInvalid())
+ if (CondVar) {
+ ConditionVar = cast<VarDecl>(CondVar);
+ CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false);
+ if (CondResult.isInvalid())
return StmtError();
- Cond = move(CondE);
+ Cond = CondResult.release();
}
- if (!Cond.get())
+ if (!Cond)
return StmtError();
- Expr *CondExpr = static_cast<Expr *>(Cond.get());
- OwningExprResult ConvertedCond
- = ConvertToIntegralOrEnumerationType(SwitchLoc, move(Cond),
+ CondResult
+ = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond,
PDiag(diag::err_typecheck_statement_requires_integer),
PDiag(diag::err_switch_incomplete_class_type)
- << CondExpr->getSourceRange(),
+ << Cond->getSourceRange(),
PDiag(diag::err_switch_explicit_conversion),
PDiag(diag::note_switch_conversion),
PDiag(diag::err_switch_multiple_conversions),
PDiag(diag::note_switch_conversion),
PDiag(0));
- if (ConvertedCond.isInvalid())
- return StmtError();
+ if (CondResult.isInvalid()) return StmtError();
+ Cond = CondResult.take();
- CondExpr = ConvertedCond.takeAs<Expr>();
-
- if (!CondVar.get()) {
- CondExpr = MaybeCreateCXXExprWithTemporaries(CondExpr);
- if (!CondExpr)
+ if (!CondVar) {
+ CondResult = MaybeCreateCXXExprWithTemporaries(Cond);
+ if (CondResult.isInvalid())
return StmtError();
+ Cond = CondResult.take();
}
+
+ getCurFunction()->setHasBranchIntoScope();
- SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, CondExpr);
- getSwitchStack().push_back(SS);
+ SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond);
+ getCurFunction()->SwitchStack.push_back(SS);
return Owned(SS);
}
-Action::OwningStmtResult
-Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
- StmtArg Body) {
- Stmt *BodyStmt = Body.takeAs<Stmt>();
-
- SwitchStmt *SS = getSwitchStack().back();
- assert(SS == (SwitchStmt*)Switch.get() && "switch stack missing push/pop!");
+StmtResult
+Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+ Stmt *BodyStmt) {
+ SwitchStmt *SS = cast<SwitchStmt>(Switch);
+ assert(SS == getCurFunction()->SwitchStack.back() &&
+ "switch stack missing push/pop!");
SS->setBody(BodyStmt, SwitchLoc);
- getSwitchStack().pop_back();
+ getCurFunction()->SwitchStack.pop_back();
- if (SS->getCond() == 0) {
- SS->Destroy(Context);
+ if (SS->getCond() == 0)
return StmtError();
- }
Expr *CondExpr = SS->getCond();
Expr *CondExprBeforePromotion = CondExpr;
@@ -556,7 +536,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Lo, CondType, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(Lo, CondType, CK_IntegralCast);
CS->setLHS(Lo);
// If this is a case range, remember it in CaseRanges, otherwise CaseVals.
@@ -635,7 +615,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
// If the LHS is not the same type as the condition, insert an implicit
// cast.
- ImpCastExprToType(Hi, CondType, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(Hi, CondType, CK_IntegralCast);
CR->setRHS(Hi);
// If the low value is bigger than the high value, the case is empty.
@@ -804,65 +784,55 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
if (CaseListIsErroneous)
return StmtError();
- Switch.release();
return Owned(SS);
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond,
- DeclPtrTy CondVar, StmtArg Body) {
- OwningExprResult CondResult(Cond.release());
+ Decl *CondVar, Stmt *Body) {
+ ExprResult CondResult(Cond.release());
VarDecl *ConditionVar = 0;
- if (CondVar.get()) {
- ConditionVar = CondVar.getAs<VarDecl>();
+ if (CondVar) {
+ ConditionVar = cast<VarDecl>(CondVar);
CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true);
if (CondResult.isInvalid())
return StmtError();
}
- Expr *ConditionExpr = CondResult.takeAs<Expr>();
+ Expr *ConditionExpr = CondResult.take();
if (!ConditionExpr)
return StmtError();
- Stmt *bodyStmt = Body.takeAs<Stmt>();
- DiagnoseUnusedExprResult(bodyStmt);
+ DiagnoseUnusedExprResult(Body);
- CondResult.release();
return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr,
- bodyStmt, WhileLoc));
+ Body, WhileLoc));
}
-Action::OwningStmtResult
-Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
+StmtResult
+Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
SourceLocation WhileLoc, SourceLocation CondLParen,
- ExprArg Cond, SourceLocation CondRParen) {
- Expr *condExpr = Cond.takeAs<Expr>();
- assert(condExpr && "ActOnDoStmt(): missing expression");
+ Expr *Cond, SourceLocation CondRParen) {
+ assert(Cond && "ActOnDoStmt(): missing expression");
- if (CheckBooleanCondition(condExpr, DoLoc)) {
- Cond = condExpr;
+ if (CheckBooleanCondition(Cond, DoLoc))
return StmtError();
- }
- condExpr = MaybeCreateCXXExprWithTemporaries(condExpr);
- if (!condExpr)
+ ExprResult CondResult = MaybeCreateCXXExprWithTemporaries(Cond);
+ if (CondResult.isInvalid())
return StmtError();
+ Cond = CondResult.take();
- Stmt *bodyStmt = Body.takeAs<Stmt>();
- DiagnoseUnusedExprResult(bodyStmt);
+ DiagnoseUnusedExprResult(Body);
- Cond.release();
- return Owned(new (Context) DoStmt(bodyStmt, condExpr, DoLoc,
- WhileLoc, CondRParen));
+ return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen));
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
- StmtArg first, FullExprArg second, DeclPtrTy secondVar,
+ Stmt *First, FullExprArg second, Decl *secondVar,
FullExprArg third,
- SourceLocation RParenLoc, StmtArg body) {
- Stmt *First = static_cast<Stmt*>(first.get());
-
+ SourceLocation RParenLoc, Stmt *Body) {
if (!getLangOptions().CPlusPlus) {
if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
// C99 6.8.5p3: The declaration part of a 'for' statement shall only
@@ -880,38 +850,32 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
}
}
- OwningExprResult SecondResult(second.release());
+ ExprResult SecondResult(second.release());
VarDecl *ConditionVar = 0;
- if (secondVar.get()) {
- ConditionVar = secondVar.getAs<VarDecl>();
+ if (secondVar) {
+ ConditionVar = cast<VarDecl>(secondVar);
SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true);
if (SecondResult.isInvalid())
return StmtError();
}
Expr *Third = third.release().takeAs<Expr>();
- Stmt *Body = static_cast<Stmt*>(body.get());
DiagnoseUnusedExprResult(First);
DiagnoseUnusedExprResult(Third);
DiagnoseUnusedExprResult(Body);
- first.release();
- body.release();
return Owned(new (Context) ForStmt(Context, First,
- SecondResult.takeAs<Expr>(), ConditionVar,
+ SecondResult.take(), ConditionVar,
Third, Body, ForLoc, LParenLoc,
RParenLoc));
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
SourceLocation LParenLoc,
- StmtArg first, ExprArg second,
- SourceLocation RParenLoc, StmtArg body) {
- Stmt *First = static_cast<Stmt*>(first.get());
- Expr *Second = static_cast<Expr*>(second.get());
- Stmt *Body = static_cast<Stmt*>(body.get());
+ Stmt *First, Expr *Second,
+ SourceLocation RParenLoc, Stmt *Body) {
if (First) {
QualType FirstType;
if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) {
@@ -950,19 +914,39 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
if (!SecondType->isObjCObjectPointerType())
Diag(ForLoc, diag::err_collection_expr_type)
<< SecondType << Second->getSourceRange();
+ else if (const ObjCObjectPointerType *OPT =
+ SecondType->getAsObjCInterfacePointerType()) {
+ llvm::SmallVector<IdentifierInfo *, 4> KeyIdents;
+ IdentifierInfo* selIdent =
+ &Context.Idents.get("countByEnumeratingWithState");
+ KeyIdents.push_back(selIdent);
+ selIdent = &Context.Idents.get("objects");
+ KeyIdents.push_back(selIdent);
+ selIdent = &Context.Idents.get("count");
+ KeyIdents.push_back(selIdent);
+ Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]);
+ if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) {
+ if (!IDecl->isForwardDecl() &&
+ !IDecl->lookupInstanceMethod(CSelector)) {
+ // Must further look into private implementation methods.
+ if (!LookupPrivateInstanceMethod(CSelector, IDecl))
+ Diag(ForLoc, diag::warn_collection_expr_type)
+ << SecondType << CSelector << Second->getSourceRange();
+ }
+ }
+ }
}
- first.release();
- second.release();
- body.release();
return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body,
ForLoc, RParenLoc));
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
IdentifierInfo *LabelII) {
// Look up the record for this label identifier.
- LabelStmt *&LabelDecl = getLabelMap()[LabelII];
+ LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII];
+
+ getCurFunction()->setHasBranchIntoScope();
// If we haven't seen this label yet, create a forward reference.
if (LabelDecl == 0)
@@ -971,11 +955,10 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc));
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
- ExprArg DestExp) {
+ Expr *E) {
// Convert operand to void*
- Expr* E = DestExp.takeAs<Expr>();
if (!E->isTypeDependent()) {
QualType ETy = E->getType();
QualType DestTy = Context.getPointerType(Context.VoidTy.withConst());
@@ -984,10 +967,13 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing))
return StmtError();
}
+
+ getCurFunction()->setHasIndirectGoto();
+
return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
Scope *S = CurScope->getContinueParent();
if (!S) {
@@ -998,7 +984,7 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) {
return Owned(new (Context) ContinueStmt(ContinueLoc));
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
Scope *S = CurScope->getBreakParent();
if (!S) {
@@ -1050,7 +1036,7 @@ static const VarDecl *getNRVOCandidate(ASTContext &Ctx, QualType RetType,
/// ActOnBlockReturnStmt - Utility routine to figure out block's return type.
///
-Action::OwningStmtResult
+StmtResult
Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// If this is the first return we've seen in the block, infer the type of
// the block from it.
@@ -1086,7 +1072,6 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (CurBlock->ReturnType->isVoidType()) {
if (RetValExp) {
Diag(ReturnLoc, diag::err_return_block_has_expr);
- RetValExp->Destroy(Context);
RetValExp = 0;
}
Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0);
@@ -1105,7 +1090,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
// In C++ the return statement is handled via a copy initialization.
// the C version of which boils down to CheckSingleAssignmentConstraints.
NRVOCandidate = getNRVOCandidate(Context, FnRetType, RetValExp);
- OwningExprResult Res = PerformCopyInitialization(
+ ExprResult Res = PerformCopyInitialization(
InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
NRVOCandidate != 0),
@@ -1136,9 +1121,8 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
return Owned(Result);
}
-Action::OwningStmtResult
-Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) {
- Expr *RetValExp = rex.takeAs<Expr>();
+StmtResult
+Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (getCurBlock())
return ActOnBlockReturnStmt(ReturnLoc, RetValExp);
@@ -1197,7 +1181,7 @@ 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.
NRVOCandidate = getNRVOCandidate(Context, FnRetType, RetValExp);
- OwningExprResult Res = PerformCopyInitialization(
+ ExprResult Res = PerformCopyInitialization(
InitializedEntity::InitializeResult(ReturnLoc,
FnRetType,
NRVOCandidate != 0),
@@ -1261,7 +1245,7 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
}
-Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
+StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
bool IsSimple,
bool IsVolatile,
unsigned NumOutputs,
@@ -1269,15 +1253,15 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
IdentifierInfo **Names,
MultiExprArg constraints,
MultiExprArg exprs,
- ExprArg asmString,
+ Expr *asmString,
MultiExprArg clobbers,
SourceLocation RParenLoc,
bool MSAsm) {
unsigned NumClobbers = clobbers.size();
StringLiteral **Constraints =
reinterpret_cast<StringLiteral**>(constraints.get());
- Expr **Exprs = reinterpret_cast<Expr **>(exprs.get());
- StringLiteral *AsmString = cast<StringLiteral>((Expr *)asmString.get());
+ Expr **Exprs = exprs.get();
+ StringLiteral *AsmString = cast<StringLiteral>(asmString);
StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get());
llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
@@ -1373,10 +1357,6 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
diag::err_asm_unknown_register_name) << Clobber);
}
- constraints.release();
- exprs.release();
- asmString.release();
- clobbers.release();
AsmStmt *NS =
new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm,
NumOutputs, NumInputs, Names, Constraints, Exprs,
@@ -1388,7 +1368,6 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
<< AsmString->getSourceRange();
- DeleteStmt(NS);
return StmtError();
}
@@ -1479,45 +1458,41 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
diag::err_asm_tying_incompatible_types)
<< InTy << OutTy << OutputExpr->getSourceRange()
<< InputExpr->getSourceRange();
- DeleteStmt(NS);
return StmtError();
}
return Owned(NS);
}
-Action::OwningStmtResult
+StmtResult
Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
- SourceLocation RParen, DeclPtrTy Parm,
- StmtArg Body) {
- VarDecl *Var = cast_or_null<VarDecl>(Parm.getAs<Decl>());
+ SourceLocation RParen, Decl *Parm,
+ Stmt *Body) {
+ VarDecl *Var = cast_or_null<VarDecl>(Parm);
if (Var && Var->isInvalidDecl())
return StmtError();
- return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var,
- Body.takeAs<Stmt>()));
+ return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body));
}
-Action::OwningStmtResult
-Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, StmtArg Body) {
- return Owned(new (Context) ObjCAtFinallyStmt(AtLoc,
- static_cast<Stmt*>(Body.release())));
+StmtResult
+Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
+ return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body));
}
-Action::OwningStmtResult
-Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, StmtArg Try,
- MultiStmtArg CatchStmts, StmtArg Finally) {
- FunctionNeedsScopeChecking() = true;
+StmtResult
+Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg CatchStmts, Stmt *Finally) {
+ getCurFunction()->setHasBranchProtectedScope();
unsigned NumCatchStmts = CatchStmts.size();
- return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try.takeAs<Stmt>(),
- (Stmt **)CatchStmts.release(),
+ return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try,
+ CatchStmts.release(),
NumCatchStmts,
- Finally.takeAs<Stmt>()));
+ Finally));
}
-Sema::OwningStmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg ThrowE) {
- Expr *Throw = static_cast<Expr *>(ThrowE.get());
+StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc,
+ Expr *Throw) {
if (Throw) {
QualType ThrowType = Throw->getType();
// Make sure the expression type is an ObjC pointer or "void *".
@@ -1530,13 +1505,13 @@ Sema::OwningStmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc,
}
}
- return Owned(new (Context) ObjCAtThrowStmt(AtLoc, ThrowE.takeAs<Expr>()));
+ return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw));
}
-Action::OwningStmtResult
-Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg Throw,
+StmtResult
+Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
Scope *CurScope) {
- if (!Throw.get()) {
+ if (!Throw) {
// @throw without an expression designates a rethrow (which much occur
// in the context of an @catch clause).
Scope *AtCatchParent = CurScope;
@@ -1546,16 +1521,15 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg Throw,
return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch));
}
- return BuildObjCAtThrowStmt(AtLoc, move(Throw));
+ return BuildObjCAtThrowStmt(AtLoc, Throw);
}
-Action::OwningStmtResult
-Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprArg SynchExpr,
- StmtArg SynchBody) {
- FunctionNeedsScopeChecking() = true;
+StmtResult
+Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
+ Stmt *SyncBody) {
+ getCurFunction()->setHasBranchProtectedScope();
// Make sure the expression type is an ObjC pointer or "void *".
- Expr *SyncExpr = static_cast<Expr*>(SynchExpr.get());
if (!SyncExpr->getType()->isDependentType() &&
!SyncExpr->getType()->isObjCObjectPointerType()) {
const PointerType *PT = SyncExpr->getType()->getAs<PointerType>();
@@ -1564,22 +1538,22 @@ Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprArg SynchExpr,
<< SyncExpr->getType() << SyncExpr->getSourceRange());
}
- return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc,
- SynchExpr.takeAs<Stmt>(),
- SynchBody.takeAs<Stmt>()));
+ return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody));
}
/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
/// and creates a proper catch handler from them.
-Action::OwningStmtResult
-Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, DeclPtrTy ExDecl,
- StmtArg HandlerBlock) {
+StmtResult
+Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
+ Stmt *HandlerBlock) {
// There's nothing to test that ActOnExceptionDecl didn't already test.
return Owned(new (Context) CXXCatchStmt(CatchLoc,
- cast_or_null<VarDecl>(ExDecl.getAs<Decl>()),
- HandlerBlock.takeAs<Stmt>()));
+ cast_or_null<VarDecl>(ExDecl),
+ HandlerBlock));
}
+namespace {
+
class TypeWithHandler {
QualType t;
CXXCatchStmt *stmt;
@@ -1602,22 +1576,23 @@ public:
return t == other.t;
}
- QualType getQualType() const { return t; }
CXXCatchStmt *getCatchStmt() const { return stmt; }
SourceLocation getTypeSpecStartLoc() const {
return stmt->getExceptionDecl()->getTypeSpecStartLoc();
}
};
+}
+
/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
/// handlers and creates a try statement from them.
-Action::OwningStmtResult
-Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
+StmtResult
+Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
MultiStmtArg RawHandlers) {
unsigned NumHandlers = RawHandlers.size();
assert(NumHandlers > 0 &&
"The parser shouldn't call this if there are no handlers.");
- Stmt **Handlers = reinterpret_cast<Stmt**>(RawHandlers.get());
+ Stmt **Handlers = RawHandlers.get();
llvm::SmallVector<TypeWithHandler, 8> TypesWithHandlers;
@@ -1657,15 +1632,14 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
}
}
+ getCurFunction()->setHasBranchProtectedScope();
+
// FIXME: We should detect handlers that cannot catch anything because an
// earlier handler catches a superclass. Need to find a method that is not
// quadratic for this.
// Neither of these are explicitly forbidden, but every compiler detects them
// and warns.
- FunctionNeedsScopeChecking() = true;
- RawHandlers.release();
- return Owned(CXXTryStmt::Create(Context, TryLoc,
- static_cast<Stmt*>(TryBlock.release()),
+ return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock,
Handlers, NumHandlers));
}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index f121954eed6e..0fc83927b79c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -9,20 +9,24 @@
// This file implements semantic analysis for C++ templates.
//===----------------------------------------------------------------------===/
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "TreeTransform.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Parse/DeclSpec.h"
-#include "clang/Parse/Template.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ParsedTemplate.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
+using namespace sema;
/// \brief Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
@@ -88,8 +92,13 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
filter.erase();
continue;
}
-
- filter.replace(Repl);
+
+ // FIXME: we promote access to public here as a workaround to
+ // the fact that LookupResult doesn't let us remember that we
+ // found this template through a particular injected class name,
+ // which means we end up doing nasty things to the invariants.
+ // Pretending that access is public is *much* safer.
+ filter.replace(Repl, AS_public);
}
}
filter.done();
@@ -97,8 +106,9 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
TemplateNameKind Sema::isTemplateName(Scope *S,
CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
UnqualifiedId &Name,
- TypeTy *ObjectTypePtr,
+ ParsedType ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult,
bool &MemberOfUnknownSpecialization) {
@@ -125,15 +135,21 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
return TNK_Non_template;
}
- QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+ QualType ObjectType = ObjectTypePtr.get();
LookupResult R(*this, TName, Name.getSourceRange().getBegin(),
LookupOrdinaryName);
- R.suppressDiagnostics();
LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
MemberOfUnknownSpecialization);
- if (R.empty() || R.isAmbiguous())
+ if (R.empty()) return TNK_Non_template;
+ if (R.isAmbiguous()) {
+ // Suppress diagnostics; we'll redo this lookup later.
+ R.suppressDiagnostics();
+
+ // FIXME: we might have ambiguous templates, in which case we
+ // should at least parse them properly!
return TNK_Non_template;
+ }
TemplateName Template;
TemplateNameKind TemplateKind;
@@ -144,20 +160,27 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
// template name in other ways.
Template = Context.getOverloadedTemplateName(R.begin(), R.end());
TemplateKind = TNK_Function_template;
+
+ // We'll do this lookup again later.
+ R.suppressDiagnostics();
} else {
TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
if (SS.isSet() && !SS.isInvalid()) {
NestedNameSpecifier *Qualifier
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
- Template = Context.getQualifiedTemplateName(Qualifier, false, TD);
+ Template = Context.getQualifiedTemplateName(Qualifier,
+ hasTemplateKeyword, TD);
} else {
Template = TemplateName(TD);
}
- if (isa<FunctionTemplateDecl>(TD))
+ if (isa<FunctionTemplateDecl>(TD)) {
TemplateKind = TNK_Function_template;
- else {
+
+ // We'll do this lookup again later.
+ R.suppressDiagnostics();
+ } else {
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD));
TemplateKind = TNK_Type_template;
}
@@ -238,13 +261,10 @@ void Sema::LookupTemplateName(LookupResult &Found,
// expression. If the identifier is not found, it is then looked up in
// the context of the entire postfix-expression and shall name a class
// or function template.
- //
- // FIXME: When we're instantiating a template, do we actually have to
- // look in the scope of the template? Seems fishy...
if (S) LookupName(Found, S);
ObjectTypeSearchedInScope = true;
}
- } else if (isDependent) {
+ } else if (isDependent && (!S || ObjectType.isNull())) {
// We cannot look into a dependent object type or nested nme
// specifier.
MemberOfUnknownSpecialization = true;
@@ -282,8 +302,11 @@ void Sema::LookupTemplateName(LookupResult &Found,
}
FilterAcceptableTemplateNames(Context, Found);
- if (Found.empty())
+ if (Found.empty()) {
+ if (isDependent)
+ MemberOfUnknownSpecialization = true;
return;
+ }
if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) {
// C++ [basic.lookup.classref]p1:
@@ -330,10 +353,9 @@ void Sema::LookupTemplateName(LookupResult &Found,
/// ActOnDependentIdExpression - Handle a dependent id-expression that
/// was just parsed. This is only possible with an explicit scope
/// specifier naming a dependent type.
-Sema::OwningExprResult
+ExprResult
Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
bool isAddressOfOperand,
const TemplateArgumentListInfo *TemplateArgs) {
NestedNameSpecifier *Qualifier
@@ -356,22 +378,21 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
/*Op*/ SourceLocation(),
Qualifier, SS.getRange(),
FirstQualifierInScope,
- Name, NameLoc,
+ NameInfo,
TemplateArgs));
}
- return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs);
+ return BuildDependentDeclRefExpr(SS, NameInfo, TemplateArgs);
}
-Sema::OwningExprResult
+ExprResult
Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
return Owned(DependentScopeDeclRefExpr::Create(Context,
static_cast<NestedNameSpecifier*>(SS.getScopeRep()),
SS.getRange(),
- Name, NameLoc,
+ NameInfo,
TemplateArgs));
}
@@ -398,9 +419,9 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset
/// the parameter D to reference the templated declaration and return a pointer
/// to the template declaration. Otherwise, do nothing to D and return null.
-TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) {
- if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D.getAs<Decl>())) {
- D = DeclPtrTy::make(Temp->getTemplatedDecl());
+TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
+ if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) {
+ D = Temp->getTemplatedDecl();
return Temp;
}
return 0;
@@ -424,8 +445,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
}
case ParsedTemplateArgument::Template: {
- TemplateName Template
- = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
+ TemplateName Template = Arg.getAsTemplate().get();
return TemplateArgumentLoc(TemplateArgument(Template),
Arg.getScopeSpec().getRange(),
Arg.getLocation());
@@ -454,14 +474,14 @@ void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
/// ParamName is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
-Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
- SourceLocation EllipsisLoc,
- SourceLocation KeyLoc,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position,
- SourceLocation EqualLoc,
- TypeTy *DefaultArg) {
+Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg) {
assert(S->isTemplateParamScope() &&
"Template type parameter not in template parameter scope!");
bool Invalid = false;
@@ -488,7 +508,7 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
if (ParamName) {
// Add the template parameter into the current scope.
- S->AddDecl(DeclPtrTy::make(Param));
+ S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
@@ -504,19 +524,19 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
// template-parameter that is not a template parameter pack.
if (Ellipsis) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
- return DeclPtrTy::make(Param);
+ return Param;
}
// Check the template argument itself.
if (CheckTemplateArgument(Param, DefaultTInfo)) {
Param->setInvalidDecl();
- return DeclPtrTy::make(Param);;
+ return Param;
}
Param->setDefaultArgument(DefaultTInfo, false);
}
- return DeclPtrTy::make(Param);
+ return Param;
}
/// \brief Check that the type of a non-type template parameter is
@@ -542,9 +562,7 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
// -- integral or enumeration type,
if (T->isIntegralOrEnumerationType() ||
// -- pointer to object or pointer to function,
- (T->isPointerType() &&
- (T->getAs<PointerType>()->getPointeeType()->isObjectType() ||
- T->getAs<PointerType>()->getPointeeType()->isFunctionType())) ||
+ T->isPointerType() ||
// -- reference to object or reference to function,
T->isReferenceType() ||
// -- pointer to member.
@@ -571,11 +589,11 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
return QualType();
}
-Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
- ExprArg DefaultArg) {
+Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
+ Expr *Default) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
@@ -608,35 +626,35 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
if (D.getIdentifier()) {
// Add the template parameter into the current scope.
- S->AddDecl(DeclPtrTy::make(Param));
+ S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
// Check the well-formedness of the default template argument, if provided.
- if (Expr *Default = static_cast<Expr *>(DefaultArg.get())) {
+ if (Default) {
TemplateArgument Converted;
if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) {
Param->setInvalidDecl();
- return DeclPtrTy::make(Param);;
+ return Param;
}
- Param->setDefaultArgument(DefaultArg.takeAs<Expr>(), false);
+ Param->setDefaultArgument(Default, false);
}
- return DeclPtrTy::make(Param);
+ return Param;
}
/// ActOnTemplateTemplateParameter - Called when a C++ template template
/// parameter (e.g. T in template <template <typename> class T> class array)
/// has been parsed. S is the current scope.
-Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
- SourceLocation TmpLoc,
- TemplateParamsTy *Params,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- unsigned Depth,
- unsigned Position,
- SourceLocation EqualLoc,
+Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
+ SourceLocation TmpLoc,
+ TemplateParamsTy *Params,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ unsigned Depth,
+ unsigned Position,
+ SourceLocation EqualLoc,
const ParsedTemplateArgument &Default) {
assert(S->isTemplateParamScope() &&
"Template template parameter not in template parameter scope!");
@@ -644,13 +662,14 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
// Construct the parameter object.
TemplateTemplateParmDecl *Param =
TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
- TmpLoc, Depth, Position, Name,
+ NameLoc.isInvalid()? TmpLoc : NameLoc,
+ Depth, Position, Name,
(TemplateParameterList*)Params);
// If the template template parameter has a name, then link the identifier
// into the scope and lookup mechanisms.
if (Name) {
- S->AddDecl(DeclPtrTy::make(Param));
+ S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
@@ -667,13 +686,13 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S,
if (DefaultArg.getArgument().getAsTemplate().isNull()) {
Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template)
<< DefaultArg.getSourceRange();
- return DeclPtrTy::make(Param);
+ return Param;
}
Param->setDefaultArgument(DefaultArg, false);
}
- return DeclPtrTy::make(Param);
+ return Param;
}
/// ActOnTemplateParameterList - Builds a TemplateParameterList that
@@ -683,7 +702,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- DeclPtrTy *Params, unsigned NumParams,
+ Decl **Params, unsigned NumParams,
SourceLocation RAngleLoc) {
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
@@ -699,7 +718,7 @@ static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) {
SS.getRange());
}
-Sema::DeclResult
+DeclResult
Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -922,7 +941,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
- DeclContext *DC = SemanticContext->getLookupContext();
+ DeclContext *DC = SemanticContext->getRedeclContext();
DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(NewTemplate, EnclosingScope,
@@ -941,7 +960,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
NewTemplate->setInvalidDecl();
NewClass->setInvalidDecl();
}
- return DeclPtrTy::make(NewTemplate);
+ return NewTemplate;
}
/// \brief Diagnose the presence of a default template argument on a
@@ -1102,7 +1121,6 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
DiagnoseDefaultTemplateArgument(*this, TPC,
NewNonTypeParm->getLocation(),
NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
- NewNonTypeParm->getDefaultArgument()->Destroy(Context);
NewNonTypeParm->removeDefaultArgument();
}
@@ -1477,14 +1495,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
- llvm::FoldingSetNodeID ID;
- ClassTemplateSpecializationDecl::Profile(ID,
- Converted.getFlatArguments(),
- Converted.flatSize(),
- Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *Decl
- = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ = ClassTemplate->findSpecialization(Converted.getFlatArguments(),
+ Converted.flatSize(), InsertPos);
if (!Decl) {
// This is the first time we have referenced this class template
// specialization. Create the canonical declaration and add it to
@@ -1495,7 +1509,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getLocation(),
ClassTemplate,
Converted, 0);
- ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
+ ClassTemplate->AddSpecialization(Decl, InsertPos);
Decl->setLexicalDeclContext(CurContext);
}
@@ -1510,7 +1524,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
}
-Action::TypeResult
+TypeResult
Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
@@ -1536,15 +1550,15 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
- return CreateLocInfoType(Result, DI).getAsOpaquePtr();
+ return CreateParsedType(Result, DI);
}
-Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
- TagUseKind TUK,
- DeclSpec::TST TagSpec,
- SourceLocation TagLoc) {
+TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
+ TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc) {
if (TypeResult.isInvalid())
- return Sema::TypeResult();
+ return ::TypeResult();
// FIXME: preserve source info, ideally without copying the DI.
TypeSourceInfo *DI;
@@ -1571,10 +1585,10 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
= TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
QualType ElabType = Context.getElaboratedType(Keyword, /*NNS=*/0, Type);
- return ElabType.getAsOpaquePtr();
+ return ParsedType::make(ElabType);
}
-Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
LookupResult &R,
bool RequiresADL,
const TemplateArgumentListInfo &TemplateArgs) {
@@ -1603,7 +1617,7 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(),
Qualifier, QualifierRange,
- R.getLookupName(), R.getNameLoc(),
+ R.getLookupNameInfo(),
RequiresADL, TemplateArgs,
R.begin(), R.end());
@@ -1611,19 +1625,18 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
}
// We actually only call this from template instantiation.
-Sema::OwningExprResult
+ExprResult
Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
- DeclarationName Name,
- SourceLocation NameLoc,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo &TemplateArgs) {
DeclContext *DC;
if (!(DC = computeDeclContext(SS, false)) ||
DC->isDependentContext() ||
RequireCompleteDeclContext(SS, DC))
- return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs);
+ return BuildDependentDeclRefExpr(SS, NameInfo, &TemplateArgs);
bool MemberOfUnknownSpecialization;
- LookupResult R(*this, Name, NameLoc, LookupOrdinaryName);
+ LookupResult R(*this, NameInfo, LookupOrdinaryName);
LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false,
MemberOfUnknownSpecialization);
@@ -1631,14 +1644,15 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
return ExprError();
if (R.empty()) {
- Diag(NameLoc, diag::err_template_kw_refers_to_non_template)
- << Name << SS.getRange();
+ Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template)
+ << NameInfo.getName() << SS.getRange();
return ExprError();
}
if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
- Diag(NameLoc, diag::err_template_kw_refers_to_class_template)
- << (NestedNameSpecifier*) SS.getScopeRep() << Name << SS.getRange();
+ Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template)
+ << (NestedNameSpecifier*) SS.getScopeRep()
+ << NameInfo.getName() << SS.getRange();
Diag(Temp->getLocation(), diag::note_referenced_class_template);
return ExprError();
}
@@ -1657,7 +1671,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
SourceLocation TemplateKWLoc,
CXXScopeSpec &SS,
UnqualifiedId &Name,
- TypeTy *ObjectType,
+ ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result) {
if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() &&
@@ -1669,7 +1683,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
if (SS.isSet())
LookupCtx = computeDeclContext(SS, EnteringContext);
if (!LookupCtx && ObjectType)
- LookupCtx = computeDeclContext(QualType::getFromOpaquePtr(ObjectType));
+ LookupCtx = computeDeclContext(ObjectType.get());
if (LookupCtx) {
// C++0x [temp.names]p5:
// If a name prefixed by the keyword template is not the name of
@@ -1688,8 +1702,8 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
// "template" keyword is now permitted). We follow the C++0x
// rules, even in C++03 mode with a warning, retroactively applying the DR.
bool MemberOfUnknownSpecialization;
- TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType,
- EnteringContext, Result,
+ TemplateNameKind TNK = isTemplateName(0, SS, TemplateKWLoc.isValid(), Name,
+ ObjectType, EnteringContext, Result,
MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && LookupCtx->isDependentContext() &&
isa<CXXRecordDecl>(LookupCtx) &&
@@ -1698,7 +1712,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
} else if (TNK == TNK_Non_template) {
Diag(Name.getSourceRange().getBegin(),
diag::err_template_kw_refers_to_non_template)
- << GetNameFromUnqualifiedId(Name)
+ << GetNameFromUnqualifiedId(Name).getName()
<< Name.getSourceRange()
<< TemplateKWLoc;
return TNK_Non_template;
@@ -1731,7 +1745,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
Diag(Name.getSourceRange().getBegin(),
diag::err_template_kw_refers_to_non_template)
- << GetNameFromUnqualifiedId(Name)
+ << GetNameFromUnqualifiedId(Name).getName()
<< Name.getSourceRange()
<< TemplateKWLoc;
return TNK_Non_template;
@@ -1856,7 +1870,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
/// parameters that precede \p Param in the template parameter list.
///
/// \returns the substituted template argument, or NULL if an error occurred.
-static Sema::OwningExprResult
+static ExprResult
SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateDecl *Template,
SourceLocation TemplateLoc,
@@ -1952,7 +1966,7 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
if (!NonTypeParm->hasDefaultArgument())
return TemplateArgumentLoc();
- OwningExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
+ ExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
NonTypeParm,
@@ -2052,12 +2066,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// 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.
+ // template name into an expression.
+
+ DeclarationNameInfo NameInfo(DTN->getIdentifier(),
+ Arg.getTemplateNameLoc());
+
Expr *E = DependentScopeDeclRefExpr::Create(Context,
DTN->getQualifier(),
Arg.getTemplateQualifierRange(),
- DTN->getIdentifier(),
- Arg.getTemplateNameLoc());
+ NameInfo);
TemplateArgument Result;
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
@@ -2272,7 +2289,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
}
- Sema::OwningExprResult E = SubstDefaultTemplateArgument(*this, Template,
+ ExprResult E = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
NTTP,
@@ -2330,31 +2347,33 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
assert(ArgInfo && "invalid TypeSourceInfo");
QualType Arg = ArgInfo->getType();
- // C++ [temp.arg.type]p2:
+ // C++03 [temp.arg.type]p2:
// A local type, a type with no linkage, an unnamed type or a type
// compounded from any of these types shall not be used as a
// template-argument for a template type-parameter.
- //
- // FIXME: Perform the unnamed type check.
+ // C++0x allows these, and even in C++03 we allow them as an extension with
+ // a warning.
SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
- const TagType *Tag = 0;
- if (const EnumType *EnumT = Arg->getAs<EnumType>())
- Tag = EnumT;
- else if (const RecordType *RecordT = Arg->getAs<RecordType>())
- Tag = RecordT;
- if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
- SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
- return Diag(SR.getBegin(), diag::err_template_arg_local_type)
- << QualType(Tag, 0) << SR;
- } else if (Tag && !Tag->getDecl()->getDeclName() &&
- !Tag->getDecl()->getTypedefForAnonDecl()) {
- Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
- Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
- return true;
- } else if (Arg->isVariablyModifiedType()) {
- Diag(SR.getBegin(), diag::err_variably_modified_template_arg)
- << Arg;
- return true;
+ if (!LangOpts.CPlusPlus0x) {
+ const TagType *Tag = 0;
+ if (const EnumType *EnumT = Arg->getAs<EnumType>())
+ Tag = EnumT;
+ else if (const RecordType *RecordT = Arg->getAs<RecordType>())
+ Tag = RecordT;
+ if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
+ SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
+ Diag(SR.getBegin(), diag::ext_template_arg_local_type)
+ << QualType(Tag, 0) << SR;
+ } else if (Tag && !Tag->getDecl()->getDeclName() &&
+ !Tag->getDecl()->getTypedefForAnonDecl()) {
+ Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR;
+ Diag(Tag->getDecl()->getLocation(),
+ diag::note_template_unnamed_type_here);
+ }
+ }
+
+ if (Arg->isVariablyModifiedType()) {
+ return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
} else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
}
@@ -2406,7 +2425,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
bool AddressTaken = false;
SourceLocation AddrOpLoc;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
- if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
+ if (UnOp->getOpcode() == UO_AddrOf) {
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
AddressTaken = true;
AddrOpLoc = UnOp->getOperatorLoc();
@@ -2653,7 +2672,7 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg,
// A pointer-to-member constant written &Class::member.
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
- if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
+ if (UnOp->getOpcode() == UO_AddrOf) {
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
if (DRE && !DRE->getQualifier())
DRE = 0;
@@ -2788,7 +2807,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
// This is an integral promotion or conversion.
- ImpCastExprToType(Arg, ParamType, CastExpr::CK_IntegralCast);
+ ImpCastExprToType(Arg, ParamType, CK_IntegralCast);
} else {
// We can't perform this conversion.
Diag(Arg->getSourceRange().getBegin(),
@@ -2909,8 +2928,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
Arg, Converted);
if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType())) {
- ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp,
- Arg->isLvalue(Context) == Expr::LV_Valid);
+ ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg));
} else if (!Context.hasSameUnqualifiedType(ArgType,
ParamType.getNonReferenceType())) {
// We can't perform this conversion.
@@ -2929,7 +2947,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// object, qualification conversions (4.4) and the
// array-to-pointer conversion (4.2) are applied.
// C++0x also allows a value of std::nullptr_t.
- assert(ParamType->getAs<PointerType>()->getPointeeType()->isObjectType() &&
+ assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
"Only object pointers allowed here");
return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
@@ -2944,7 +2962,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// identical) type of the template-argument. The
// template-parameter is bound directly to the
// template-argument, which must be an lvalue.
- assert(ParamRefType->getPointeeType()->isObjectType() &&
+ assert(ParamRefType->getPointeeType()->isIncompleteOrObjectType() &&
"Only object references allowed here");
if (Arg->getType() == Context.OverloadTy) {
@@ -2973,8 +2991,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
// Types match exactly: nothing more to do here.
} else if (IsQualificationConversion(ArgType, ParamType)) {
- ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp,
- Arg->isLvalue(Context) == Expr::LV_Valid);
+ ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg));
} else {
// We can't perform this conversion.
Diag(Arg->getSourceRange().getBegin(),
@@ -3033,7 +3050,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
/// declaration and the type of its corresponding non-type template
/// parameter, produce an expression that properly refers to that
/// declaration.
-Sema::OwningExprResult
+ExprResult
Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ParamType,
SourceLocation Loc) {
@@ -3052,17 +3069,18 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ClassType
= Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
NestedNameSpecifier *Qualifier
- = NestedNameSpecifier::Create(Context, 0, false, ClassType.getTypePtr());
+ = NestedNameSpecifier::Create(Context, 0, false,
+ ClassType.getTypePtr());
CXXScopeSpec SS;
SS.setScopeRep(Qualifier);
- OwningExprResult RefExpr = BuildDeclRefExpr(VD,
+ ExprResult RefExpr = BuildDeclRefExpr(VD,
VD->getType().getNonReferenceType(),
Loc,
&SS);
if (RefExpr.isInvalid())
return ExprError();
- RefExpr = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(RefExpr));
+ RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
// We might need to perform a trailing qualification conversion, since
// the element type on the parameter could be more qualified than the
@@ -3070,8 +3088,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
ParamType.getUnqualifiedType())) {
Expr *RefE = RefExpr.takeAs<Expr>();
- ImpCastExprToType(RefE, ParamType.getUnqualifiedType(),
- CastExpr::CK_NoOp);
+ ImpCastExprToType(RefE, ParamType.getUnqualifiedType(), CK_NoOp);
RefExpr = Owned(RefE);
}
@@ -3086,7 +3103,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
if (ParamType->isPointerType()) {
// When the non-type template parameter is a pointer, take the
// address of the declaration.
- OwningExprResult RefExpr = BuildDeclRefExpr(VD, T, Loc);
+ ExprResult RefExpr = BuildDeclRefExpr(VD, T, Loc);
if (RefExpr.isInvalid())
return ExprError();
@@ -3103,7 +3120,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
}
// Take the address of everything else
- return CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(RefExpr));
+ return CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
}
// If the non-type template parameter has reference type, qualify the
@@ -3122,7 +3139,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
/// This routine takes care of the mapping from an integral template
/// argument (which may have any integral type) to the appropriate
/// literal value.
-Sema::OwningExprResult
+ExprResult
Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc) {
assert(Arg.getKind() == TemplateArgument::Integral &&
@@ -3140,7 +3157,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
T,
Loc));
- return Owned(new (Context) IntegerLiteral(*Arg.getAsIntegral(), T, Loc));
+ return Owned(IntegerLiteral::Create(Context, *Arg.getAsIntegral(), T, Loc));
}
@@ -3401,7 +3418,7 @@ static bool CheckTemplateSpecializationScope(Sema &S,
// the explicit specialization was declared, or in a namespace
// that encloses the one in which the explicit specialization was
// declared.
- if (S.CurContext->getLookupContext()->isFunctionOrMethod()) {
+ if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
<< Specialized;
return true;
@@ -3426,8 +3443,8 @@ static bool CheckTemplateSpecializationScope(Sema &S,
getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){
// There is no prior declaration of this entity, so this
// specialization must be in the same context as the template
- // itself.
- if (!DC->Equals(SpecializedContext)) {
+ // itself, or in the enclosing namespace set.
+ if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) {
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global)
<< EntityKind << Specialized;
@@ -3597,7 +3614,7 @@ static NamedDecl *getPreviousDecl(NamedDecl *ND) {
return 0;
}
-Sema::DeclResult
+DeclResult
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
TagUseKind TUK,
SourceLocation KWLoc,
@@ -3666,7 +3683,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
diag::err_default_arg_in_partial_spec)
<< DefArg->getSourceRange();
NTTP->removeDefaultArgument();
- DefArg->Destroy(Context);
}
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
@@ -3729,7 +3745,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
- llvm::FoldingSetNodeID ID;
if (isPartialSpecialization) {
bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
@@ -3762,30 +3777,22 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
- } else {
- // FIXME: Template parameter list matters, too
- ClassTemplatePartialSpecializationDecl::Profile(ID,
- Converted.getFlatArguments(),
- Converted.flatSize(),
- Context);
}
}
-
- if (!isPartialSpecialization)
- ClassTemplateSpecializationDecl::Profile(ID,
- Converted.getFlatArguments(),
- Converted.flatSize(),
- Context);
+
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl = 0;
if (isPartialSpecialization)
+ // FIXME: Template parameter list matters, too
PrevDecl
- = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
- InsertPos);
+ = ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(),
+ Converted.flatSize(),
+ InsertPos);
else
PrevDecl
- = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ = ClassTemplate->findSpecialization(Converted.getFlatArguments(),
+ Converted.flatSize(), InsertPos);
ClassTemplateSpecializationDecl *Specialization = 0;
@@ -3823,7 +3830,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
ClassTemplatePartialSpecializationDecl *PrevPartial
= cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber()
- : ClassTemplate->getPartialSpecializations().size();
+ : ClassTemplate->getNextPartialSpecSequenceNumber();
ClassTemplatePartialSpecializationDecl *Partial
= ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
@@ -3836,18 +3843,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
PrevPartial,
SequenceNumber);
SetNestedNameSpecifier(Partial, SS);
- if (NumMatchedTemplateParamLists > 0) {
+ if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
(TemplateParameterList**) TemplateParameterLists.release());
}
- if (PrevPartial) {
- ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial);
- ClassTemplate->getPartialSpecializations().GetOrInsertNode(Partial);
- } else {
- ClassTemplate->getPartialSpecializations().InsertNode(Partial, InsertPos);
- }
+ if (!PrevPartial)
+ ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
// If we are providing an explicit specialization of a member class
@@ -3883,7 +3886,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
else
Diag(Param->getLocation(),
diag::note_partial_spec_unused_parameter)
- << std::string("<anonymous>");
+ << "<anonymous>";
}
}
}
@@ -3898,19 +3901,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Converted,
PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
- if (NumMatchedTemplateParamLists > 0) {
+ if (NumMatchedTemplateParamLists > 0 && SS.isSet()) {
Specialization->setTemplateParameterListsInfo(Context,
NumMatchedTemplateParamLists,
(TemplateParameterList**) TemplateParameterLists.release());
}
- if (PrevDecl) {
- ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
- ClassTemplate->getSpecializations().GetOrInsertNode(Specialization);
- } else {
- ClassTemplate->getSpecializations().InsertNode(Specialization,
- InsertPos);
- }
+ if (!PrevDecl)
+ ClassTemplate->AddSpecialization(Specialization, InsertPos);
CanonType = Context.getTypeDeclType(Specialization);
}
@@ -4004,20 +4002,18 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// context. However, specializations are not found by name lookup.
CurContext->addDecl(Specialization);
}
- return DeclPtrTy::make(Specialization);
+ return Specialization;
}
-Sema::DeclPtrTy
-Sema::ActOnTemplateDeclarator(Scope *S,
+Decl *Sema::ActOnTemplateDeclarator(Scope *S,
MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
+ Declarator &D) {
return HandleDeclarator(S, D, move(TemplateParameterLists), false);
}
-Sema::DeclPtrTy
-Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D) {
+ Declarator &D) {
assert(getCurFunctionDecl() == 0 && "Function parsing confused");
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"Not a function declarator!");
@@ -4029,22 +4025,22 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
Scope *ParentScope = FnBodyScope->getParent();
- DeclPtrTy DP = HandleDeclarator(ParentScope, D,
- move(TemplateParameterLists),
- /*IsFunctionDefinition=*/true);
+ Decl *DP = HandleDeclarator(ParentScope, D,
+ move(TemplateParameterLists),
+ /*IsFunctionDefinition=*/true);
if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast_or_null<FunctionTemplateDecl>(DP.getAs<Decl>()))
+ = dyn_cast_or_null<FunctionTemplateDecl>(DP))
return ActOnStartOfFunctionDef(FnBodyScope,
- DeclPtrTy::make(FunctionTemplate->getTemplatedDecl()));
- if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP.getAs<Decl>()))
- return ActOnStartOfFunctionDef(FnBodyScope, DeclPtrTy::make(Function));
- return DeclPtrTy();
+ FunctionTemplate->getTemplatedDecl());
+ if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP))
+ return ActOnStartOfFunctionDef(FnBodyScope, Function);
+ return 0;
}
/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
- D->invalidateAttrs();
+ D->dropAttrs();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
FD->setInlineSpecified(false);
@@ -4241,12 +4237,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
LookupResult &Previous) {
// Remove anything from Previous that isn't a function template in
// the correct context.
- DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
+ DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next()->getUnderlyingDecl();
if (!isa<FunctionTemplateDecl>(D) ||
- !FDLookupContext->Equals(D->getDeclContext()->getLookupContext()))
+ !FDLookupContext->InEnclosingNamespaceSetOf(
+ D->getDeclContext()->getRedeclContext()))
F.erase();
}
F.done();
@@ -4285,14 +4282,15 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// explicit function template specialization.
UnresolvedSet<8> Candidates;
- DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
+ DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *Ovl = (*I)->getUnderlyingDecl();
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
// Only consider templates found within the same semantic lookup scope as
// FD.
- if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext()))
+ if (!FDLookupContext->InEnclosingNamespaceSetOf(
+ Ovl->getDeclContext()->getRedeclContext()))
continue;
// C++ [temp.expl.spec]p11:
@@ -4373,8 +4371,10 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// Mark the prior declaration as an explicit specialization, so that later
// clients know that this is an explicit specialization.
- if (!isFriend)
+ if (!isFriend) {
SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
+ MarkUnusedFileScopedDecl(Specialization);
+ }
// Turn the given function declaration into a function template
// specialization, with the template arguments from the previous
@@ -4527,6 +4527,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction(
cast<CXXMethodDecl>(InstantiatedFrom),
TSK_ExplicitSpecialization);
+ MarkUnusedFileScopedDecl(InstantiationFunction);
} else if (isa<VarDecl>(Member)) {
VarDecl *InstantiationVar = cast<VarDecl>(Instantiation);
if (InstantiationVar->getTemplateSpecializationKind() ==
@@ -4539,6 +4540,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member),
cast<VarDecl>(InstantiatedFrom),
TSK_ExplicitSpecialization);
+ MarkUnusedFileScopedDecl(InstantiationVar);
} else {
assert(isa<CXXRecordDecl>(Member) && "Only member classes remain");
CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation);
@@ -4567,9 +4569,8 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
SourceLocation InstLoc,
bool WasQualifiedName) {
- DeclContext *ExpectedContext
- = D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext();
- DeclContext *CurContext = S.CurContext->getLookupContext();
+ DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext();
+ DeclContext *CurContext = S.CurContext->getRedeclContext();
if (CurContext->isRecord()) {
S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
@@ -4583,8 +4584,8 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
//
// This is DR275, which we do not retroactively apply to C++98/03.
if (S.getLangOptions().CPlusPlus0x &&
- !CurContext->Encloses(ExpectedContext)) {
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ExpectedContext))
+ !CurContext->Encloses(OrigContext)) {
+ if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext))
S.Diag(InstLoc,
S.getLangOptions().CPlusPlus0x?
diag::err_explicit_instantiation_out_of_scope
@@ -4599,7 +4600,7 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
return false;
}
-
+
// C++0x [temp.explicit]p2:
// If the name declared in the explicit instantiation is an unqualified
// name, the explicit instantiation shall appear in the namespace where
@@ -4607,15 +4608,15 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
// namespace from its enclosing namespace set.
if (WasQualifiedName)
return false;
-
- if (CurContext->Equals(ExpectedContext))
+
+ if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
return false;
-
+
S.Diag(InstLoc,
S.getLangOptions().CPlusPlus0x?
diag::err_explicit_instantiation_unqualified_wrong_namespace
: diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
- << D << ExpectedContext;
+ << D << OrigContext;
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
return false;
}
@@ -4642,7 +4643,7 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
}
// Explicit instantiation of a class template specialization
-Sema::DeclResult
+DeclResult
Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
@@ -4703,14 +4704,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Find the class template specialization declaration that
// corresponds to these arguments.
- llvm::FoldingSetNodeID ID;
- ClassTemplateSpecializationDecl::Profile(ID,
- Converted.getFlatArguments(),
- Converted.flatSize(),
- Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ = ClassTemplate->findSpecialization(Converted.getFlatArguments(),
+ Converted.flatSize(), InsertPos);
TemplateSpecializationKind PrevDecl_TSK
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
@@ -4733,7 +4730,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
PrevDecl, PrevDecl_TSK,
PrevDecl->getPointOfInstantiation(),
HasNoEffect))
- return DeclPtrTy::make(PrevDecl);
+ return PrevDecl;
// Even though HasNoEffect == true means that this explicit instantiation
// has no effect on semantics, we go on to put its syntax in the AST.
@@ -4763,15 +4760,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Converted, PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
- if (!HasNoEffect) {
- if (PrevDecl) {
- // Remove the previous declaration from the folding set, since we want
- // to introduce a new declaration.
- ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
- ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
- }
+ if (!HasNoEffect && !PrevDecl) {
// Insert the new specialization.
- ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
+ ClassTemplate->AddSpecialization(Specialization, InsertPos);
}
}
@@ -4803,7 +4794,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (HasNoEffect) {
// Set the template specialization kind.
Specialization->setTemplateSpecializationKind(TSK);
- return DeclPtrTy::make(Specialization);
+ return Specialization;
}
// C++ [temp.explicit]p3:
@@ -4840,11 +4831,11 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Set the template specialization kind.
Specialization->setTemplateSpecializationKind(TSK);
- return DeclPtrTy::make(Specialization);
+ return Specialization;
}
// Explicit instantiation of a member class of a class template.
-Sema::DeclResult
+DeclResult
Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
@@ -4857,16 +4848,16 @@ Sema::ActOnExplicitInstantiation(Scope *S,
bool Owned = false;
bool IsDependent = false;
- DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TUK_Reference,
- KWLoc, SS, Name, NameLoc, Attr, AS_none,
- MultiTemplateParamsArg(*this, 0, 0),
- Owned, IsDependent);
+ Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
+ KWLoc, SS, Name, NameLoc, Attr, AS_none,
+ MultiTemplateParamsArg(*this, 0, 0),
+ Owned, IsDependent);
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
if (!TagD)
return true;
- TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
+ TagDecl *Tag = cast<TagDecl>(TagD);
if (Tag->isEnum()) {
Diag(TemplateLoc, diag::err_explicit_instantiation_enum)
<< Context.getTypeDeclType(Tag);
@@ -4969,12 +4960,14 @@ Sema::ActOnExplicitInstantiation(Scope *S,
return TagD;
}
-Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- Declarator &D) {
+DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ Declarator &D) {
// Explicit instantiations always require a name.
- DeclarationName Name = GetNameForDeclarator(D);
+ // TODO: check if/when DNInfo should replace Name.
+ DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
+ DeclarationName Name = NameInfo.getName();
if (!Name) {
if (!D.isInvalidType())
Diag(D.getDeclSpec().getSourceRange().getBegin(),
@@ -5024,7 +5017,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
: TSK_ExplicitInstantiationDeclaration;
- LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName);
LookupParsedName(Previous, S, &D.getCXXScopeSpec());
if (!R->isFunctionType()) {
@@ -5081,16 +5074,15 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
HasNoEffect))
return true;
if (HasNoEffect)
- return DeclPtrTy();
+ return (Decl*) 0;
// Instantiate static data member.
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false,
- /*DefinitionRequired=*/true);
+ InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev);
// FIXME: Create an ExplicitInstantiation node?
- return DeclPtrTy();
+ return (Decl*) 0;
}
// If the declarator is a template-id, translate the parser's template
@@ -5188,14 +5180,13 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// FIXME: We may still want to build some representation of this
// explicit specialization.
if (HasNoEffect)
- return DeclPtrTy();
+ return (Decl*) 0;
}
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization,
- false, /*DefinitionRequired=*/true);
+ InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
// C++0x [temp.explicit]p2:
// If the explicit instantiation is for a member function, a member class
@@ -5219,10 +5210,10 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
D.getCXXScopeSpec().isSet());
// FIXME: Create some kind of ExplicitInstantiationDecl here.
- return DeclPtrTy();
+ return (Decl*) 0;
}
-Sema::TypeResult
+TypeResult
Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
const CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation TagLoc, SourceLocation NameLoc) {
@@ -5243,10 +5234,10 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
}
ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
- return Context.getDependentNameType(Kwd, NNS, Name).getAsOpaquePtr();
+ return ParsedType::make(Context.getDependentNameType(Kwd, NNS, Name));
}
-Sema::TypeResult
+TypeResult
Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS, const IdentifierInfo &II,
SourceLocation IdLoc) {
@@ -5278,13 +5269,13 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc);
}
- return CreateLocInfoType(T, TSI).getAsOpaquePtr();
+ return CreateParsedType(T, TSI);
}
-Sema::TypeResult
+TypeResult
Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS, SourceLocation TemplateLoc,
- TypeTy *Ty) {
+ ParsedType Ty) {
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() &&
!getLangOptions().CPlusPlus0x)
Diag(TypenameLoc, diag::ext_typename_outside_of_template)
@@ -5292,8 +5283,6 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
TypeSourceInfo *InnerTSI = 0;
QualType T = GetTypeFromParser(Ty, &InnerTSI);
- NestedNameSpecifier *NNS
- = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
assert(isa<TemplateSpecializationType>(T) &&
"Expected a template specialization type");
@@ -5310,13 +5299,14 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
else
Builder.push<TemplateSpecializationTypeLoc>(T).initialize(TemplateLoc);
- T = Context.getElaboratedType(ETK_Typename, NNS, T);
+ /* Note: NNS already embedded in template specialization type T. */
+ T = Context.getElaboratedType(ETK_Typename, /*NNS=*/0, T);
ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
TL.setKeywordLoc(TypenameLoc);
TL.setQualifierRange(SS.getRange());
TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
- return CreateLocInfoType(T, TSI).getAsOpaquePtr();
+ return CreateParsedType(T, TSI);
}
// TODO: it's really silly that we make a template specialization
@@ -5325,7 +5315,10 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
DependentTemplateName *DTN =
TST->getTemplateName().getAsDependentTemplateName();
assert(DTN && "dependent template has non-dependent name?");
- T = Context.getDependentTemplateSpecializationType(ETK_Typename, NNS,
+ assert(DTN->getQualifier()
+ == static_cast<NestedNameSpecifier*>(SS.getScopeRep()));
+ T = Context.getDependentTemplateSpecializationType(ETK_Typename,
+ DTN->getQualifier(),
DTN->getIdentifier(),
TST->getNumArgs(),
TST->getArgs());
@@ -5344,7 +5337,7 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
}
TL.setKeywordLoc(TypenameLoc);
TL.setQualifierRange(SS.getRange());
- return CreateLocInfoType(T, TSI).getAsOpaquePtr();
+ return CreateParsedType(T, TSI);
}
/// \brief Build the type that describes a C++ typename specifier,
@@ -5463,15 +5456,6 @@ namespace {
this->Loc = Loc;
this->Entity = Entity;
}
-
- /// \brief Transforms an expression by returning the expression itself
- /// (an identity function).
- ///
- /// FIXME: This is completely unsafe; we will need to actually clone the
- /// expressions.
- Sema::OwningExprResult TransformExpr(Expr *E) {
- return getSema().Owned(E->Retain());
- }
};
}
@@ -5511,6 +5495,12 @@ TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
return Rebuilder.TransformType(T);
}
+ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
+ CurrentInstantiationRebuilder Rebuilder(*this, E->getExprLoc(),
+ DeclarationName());
+ return Rebuilder.TransformExpr(E);
+}
+
bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
if (SS.isInvalid()) return true;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 403d5543a64f..5c77ed61060b 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -10,16 +10,21 @@
//
//===----------------------------------------------------------------------===/
-#include "Sema.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/Parse/DeclSpec.h"
#include <algorithm>
namespace clang {
+ using namespace sema;
+
/// \brief Various flags that control template argument deduction.
///
/// These flags can be bitwise-OR'd together.
@@ -74,7 +79,7 @@ DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced);
/// \brief If the given expression is of a form that permits the deduction
@@ -97,7 +102,7 @@ DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
llvm::APSInt Value, QualType ValueType,
bool DeducedFromArrayBound,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
@@ -138,7 +143,7 @@ static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
Expr *Value,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
@@ -180,7 +185,7 @@ static Sema::TemplateDeductionResult
DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
Decl *D,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(NTTP->getDepth() == 0 &&
"Cannot deduce non-type template argument with depth > 0");
@@ -214,7 +219,7 @@ DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
TemplateName Param,
TemplateName Arg,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
TemplateDecl *ParamDecl = Param.getAsTemplateDecl();
if (!ParamDecl) {
@@ -278,7 +283,7 @@ DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateSpecializationType *Param,
QualType Arg,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(Arg.isCanonical() && "Argument type must be canonical");
@@ -345,6 +350,29 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_Success;
}
+/// \brief Determines whether the given type is an opaque type that
+/// might be more qualified when instantiated.
+static bool IsPossiblyOpaquelyQualifiedType(QualType T) {
+ switch (T->getTypeClass()) {
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::DependentName:
+ case Type::Decltype:
+ case Type::UnresolvedUsing:
+ return true;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ return IsPossiblyOpaquelyQualifiedType(
+ cast<ArrayType>(T)->getElementType());
+
+ default:
+ return false;
+ }
+}
+
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
@@ -370,7 +398,7 @@ static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF) {
// We only want to look at the canonical types, since typedefs and
@@ -428,9 +456,9 @@ DeduceTemplateArguments(Sema &S,
// type.
if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
- Info.FirstArg = Deduced[Index];
+ Info.FirstArg = TemplateArgument(Param);
Info.SecondArg = TemplateArgument(Arg);
- return Sema::TDK_InconsistentQuals;
+ return Sema::TDK_Underqualified;
}
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
@@ -469,7 +497,7 @@ DeduceTemplateArguments(Sema &S,
if (TDF & TDF_ParamWithReferenceType) {
if (Param.isMoreQualifiedThan(Arg))
return Sema::TDK_NonDeducedMismatch;
- } else {
+ } else if (!IsPossiblyOpaquelyQualifiedType(Param)) {
if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
return Sema::TDK_NonDeducedMismatch;
}
@@ -530,10 +558,11 @@ DeduceTemplateArguments(Sema &S,
if (!IncompleteArrayArg)
return Sema::TDK_NonDeducedMismatch;
+ unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
return DeduceTemplateArguments(S, TemplateParams,
S.Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
- Info, Deduced, 0);
+ Info, Deduced, SubTDF);
}
// T [integer-constant]
@@ -548,10 +577,11 @@ DeduceTemplateArguments(Sema &S,
if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
return Sema::TDK_NonDeducedMismatch;
+ unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
return DeduceTemplateArguments(S, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
- Info, Deduced, 0);
+ Info, Deduced, SubTDF);
}
// type [i]
@@ -560,6 +590,8 @@ DeduceTemplateArguments(Sema &S,
if (!ArrayArg)
return Sema::TDK_NonDeducedMismatch;
+ unsigned SubTDF = TDF & TDF_IgnoreQualifiers;
+
// Check the element type of the arrays
const DependentSizedArrayType *DependentArrayParm
= S.Context.getAsDependentSizedArrayType(Param);
@@ -567,7 +599,7 @@ DeduceTemplateArguments(Sema &S,
= DeduceTemplateArguments(S, TemplateParams,
DependentArrayParm->getElementType(),
ArrayArg->getElementType(),
- Info, Deduced, 0))
+ Info, Deduced, SubTDF))
return Result;
// Determine the array bound is something we can deduce.
@@ -797,7 +829,7 @@ DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
switch (Param.getKind()) {
case TemplateArgument::Null:
@@ -847,7 +879,6 @@ DeduceTemplateArguments(Sema &S,
return Sema::TDK_NonDeducedMismatch;
}
- assert(false && "Type/value mismatch");
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
@@ -868,7 +899,6 @@ DeduceTemplateArguments(Sema &S,
return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
Info, Deduced);
- assert(false && "Type/value mismatch");
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
@@ -890,7 +920,7 @@ DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) {
assert(ParamList.size() == ArgList.size());
for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
@@ -974,7 +1004,7 @@ FinishTemplateArgumentDeduction(Sema &S,
ClassTemplatePartialSpecializationDecl *Partial,
const TemplateArgumentList &TemplateArgs,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- Sema::TemplateDeductionInfo &Info) {
+ TemplateDeductionInfo &Info) {
// Trap errors.
Sema::SFINAETrap Trap(S);
@@ -1010,7 +1040,7 @@ FinishTemplateArgumentDeduction(Sema &S,
// to the class template.
// FIXME: Do we have to correct the types of deduced non-type template
// arguments (in particular, integral non-type template arguments?).
- Sema::LocalInstantiationScope InstScope(S);
+ LocalInstantiationScope InstScope(S);
ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
const TemplateArgumentLoc *PartialTemplateArgs
= Partial->getTemplateArgsAsWritten();
@@ -1245,7 +1275,8 @@ Sema::SubstituteExplicitTemplateArguments(
Proto->isVariadic(),
Proto->getTypeQuals(),
Function->getLocation(),
- Function->getDeclName());
+ Function->getDeclName(),
+ Proto->getExtInfo());
if (FunctionType->isNull() || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
}
@@ -1486,14 +1517,22 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
return TDK_Success;
}
+/// Gets the type of a function for template-argument-deducton
+/// purposes when it's considered as part of an overload set.
static QualType GetTypeOfFunction(ASTContext &Context,
- bool isAddressOfOperand,
+ const OverloadExpr::FindResult &R,
FunctionDecl *Fn) {
- if (!isAddressOfOperand) return Fn->getType();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
- if (Method->isInstance())
+ if (Method->isInstance()) {
+ // An instance method that's referenced in a form that doesn't
+ // look like a member pointer is just invalid.
+ if (!R.HasFormOfMemberPointer) return QualType();
+
return Context.getMemberPointerType(Fn->getType(),
Context.getTypeDeclType(Method->getParent()).getTypePtr());
+ }
+
+ if (!R.IsAddressOfOperand) return Fn->getType();
return Context.getPointerType(Fn->getType());
}
@@ -1503,11 +1542,19 @@ static QualType GetTypeOfFunction(ASTContext &Context,
/// undeduced context
static QualType
ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
- Expr *Arg, QualType ParamType) {
- llvm::PointerIntPair<OverloadExpr*,1> R = OverloadExpr::find(Arg);
+ Expr *Arg, QualType ParamType,
+ bool ParamWasReference) {
+
+ OverloadExpr::FindResult R = OverloadExpr::find(Arg);
- bool isAddressOfOperand = bool(R.getInt());
- OverloadExpr *Ovl = R.getPointer();
+ OverloadExpr *Ovl = R.Expression;
+
+ // C++0x [temp.deduct.call]p4
+ unsigned TDF = 0;
+ if (ParamWasReference)
+ TDF |= TDF_ParamWithReferenceType;
+ if (R.IsAddressOfOperand)
+ TDF |= TDF_IgnoreQualifiers;
// If there were explicit template arguments, we can only find
// something via C++ [temp.arg.explicit]p3, i.e. if the arguments
@@ -1516,7 +1563,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// But we can still look for an explicit specialization.
if (FunctionDecl *ExplicitSpec
= S.ResolveSingleFunctionTemplateSpecialization(Ovl))
- return GetTypeOfFunction(S.Context, isAddressOfOperand, ExplicitSpec);
+ return GetTypeOfFunction(S.Context, R, ExplicitSpec);
return QualType();
}
@@ -1541,8 +1588,14 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
return QualType();
FunctionDecl *Fn = cast<FunctionDecl>(D);
- QualType ArgType = GetTypeOfFunction(S.Context, isAddressOfOperand, Fn);
+ QualType ArgType = GetTypeOfFunction(S.Context, R, Fn);
+ if (ArgType.isNull()) continue;
+ // Function-to-pointer conversion.
+ if (!ParamWasReference && ParamType->isPointerType() &&
+ ArgType->isFunctionType())
+ ArgType = S.Context.getPointerType(ArgType);
+
// - If the argument is an overload set (not containing function
// templates), trial argument deduction is attempted using each
// of the members of the set. If deduction succeeds for only one
@@ -1557,9 +1610,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
// So we do not reject deductions which were made elsewhere.
llvm::SmallVector<DeducedTemplateArgument, 8>
Deduced(TemplateParams->size());
- Sema::TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
- unsigned TDF = 0;
-
+ TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams,
ParamType, ArgType,
@@ -1624,7 +1675,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// The types of the parameters from which we will perform template argument
// deduction.
- Sema::LocalInstantiationScope InstScope(*this);
+ LocalInstantiationScope InstScope(*this);
TemplateParameterList *TemplateParams
= FunctionTemplate->getTemplateParameters();
llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
@@ -1654,20 +1705,40 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType ParamType = ParamTypes[I];
QualType ArgType = Args[I]->getType();
+ // 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 (ParamType.getCVRQualifiers())
+ ParamType = ParamType.getLocalUnqualifiedType();
+ const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+ if (ParamRefType) {
+ // [...] If P is a reference type, the type referred to by P is used
+ // for type deduction.
+ ParamType = ParamRefType->getPointeeType();
+ }
+
// Overload sets usually make this parameter an undeduced
// context, but there are sometimes special circumstances.
if (ArgType == Context.OverloadTy) {
ArgType = ResolveOverloadForDeduction(*this, TemplateParams,
- Args[I], ParamType);
+ Args[I], ParamType,
+ ParamRefType != 0);
if (ArgType.isNull())
continue;
}
- // C++ [temp.deduct.call]p2:
- // If P is not a reference type:
- QualType CanonParamType = Context.getCanonicalType(ParamType);
- bool ParamWasReference = isa<ReferenceType>(CanonParamType);
- if (!ParamWasReference) {
+ if (ParamRefType) {
+ // C++0x [temp.deduct.call]p3:
+ // [...] If P is of the form T&&, where T is a template parameter, and
+ // the argument is an lvalue, the type A& is used in place of A for
+ // type deduction.
+ if (ParamRefType->isRValueReferenceType() &&
+ ParamRefType->getAs<TemplateTypeParmType>() &&
+ Args[I]->isLvalue(Context) == Expr::LV_Valid)
+ ArgType = Context.getLValueReferenceType(ArgType);
+ } else {
+ // C++ [temp.deduct.call]p2:
+ // If P is not a reference type:
// - If A is an array type, the pointer type produced by the
// array-to-pointer standard conversion (4.2) is used in place of
// A for type deduction; otherwise,
@@ -1682,30 +1753,11 @@ 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.getLocalCVRQualifiers())
- ArgType = CanonArgType.getLocalUnqualifiedType();
+ if (ArgType.getCVRQualifiers())
+ ArgType = ArgType.getUnqualifiedType();
}
}
- // 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.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.
- ParamType = ParamRefType->getPointeeType();
-
- // [...] If P is of the form T&&, where T is a template parameter, and
- // the argument is an lvalue, the type A& is used in place of A for
- // type deduction.
- if (isa<RValueReferenceType>(ParamRefType) &&
- ParamRefType->getAs<TemplateTypeParmType>() &&
- Args[I]->isLvalue(Context) == Expr::LV_Valid)
- ArgType = Context.getLValueReferenceType(ArgType);
- }
-
// C++0x [temp.deduct.call]p4:
// In general, the deduction process attempts to find template argument
// values that will make the deduced A identical to A (after the type A
@@ -1715,12 +1767,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// - If the original P is a reference type, the deduced A (i.e., the
// type referred to by the reference) can be more cv-qualified than
// the transformed A.
- if (ParamWasReference)
+ if (ParamRefType)
TDF |= TDF_ParamWithReferenceType;
// - The transformed A can be another pointer or pointer to member
// type that can be converted to the deduced A via a qualification
// conversion (4.4).
- if (ArgType->isPointerType() || ArgType->isMemberPointerType())
+ if (ArgType->isPointerType() || ArgType->isMemberPointerType() ||
+ ArgType->isObjCObjectPointerType())
TDF |= TDF_IgnoreQualifiers;
// - If P is a class and P has the form simple-template-id, then the
// transformed A can be a derived class of the deduced A. Likewise,
@@ -1783,7 +1836,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
QualType FunctionType = Function->getType();
// Substitute any explicit template arguments.
- Sema::LocalInstantiationScope InstScope(*this);
+ LocalInstantiationScope InstScope(*this);
llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
unsigned NumExplicitlySpecified = 0;
llvm::SmallVector<QualType, 4> ParamTypes;
@@ -1915,7 +1968,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
// modulo the various allowed differences.
// Finish template argument deduction.
- Sema::LocalInstantiationScope InstScope(*this);
+ LocalInstantiationScope InstScope(*this);
FunctionDecl *Spec = 0;
TemplateDeductionResult Result
= FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec,
@@ -1979,7 +2032,7 @@ static Sema::TemplateDeductionResult
DeduceTemplateArgumentsDuringPartialOrdering(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
- Sema::TemplateDeductionInfo &Info,
+ TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
CanQualType Param = S.Context.getCanonicalType(ParamIn);
@@ -2061,7 +2114,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
// C++0x [temp.deduct.partial]p3:
// The types used to determine the ordering depend on the context in which
// the partial ordering is done:
- Sema::TemplateDeductionInfo Info(S.Context, Loc);
+ TemplateDeductionInfo Info(S.Context, Loc);
switch (TPOC) {
case TPOC_Call: {
// - In the context of a function call, the function parameter types are
@@ -2386,7 +2439,7 @@ Sema::getMoreSpecializedPartialSpecialization(
// template partial specialization's template arguments, for
// example.
llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
- Sema::TemplateDeductionInfo Info(Context, Loc);
+ TemplateDeductionInfo Info(Context, Loc);
QualType PT1 = PS1->getInjectedSpecializationType();
QualType PT2 = PS2->getInjectedSpecializationType();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 0cdc8a12ab73..4d4c18130b01 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -10,17 +10,20 @@
//
//===----------------------------------------------------------------------===/
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
#include "TreeTransform.h"
-#include "Lookup.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Template.h"
+#include "clang/Sema/TemplateDeduction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclTemplate.h"
-#include "clang/Parse/DeclSpec.h"
#include "clang/Basic/LangOptions.h"
using namespace clang;
+using namespace sema;
//===----------------------------------------------------------------------===/
// Template Instantiation Support
@@ -614,10 +617,10 @@ namespace {
QualType RebuildElaboratedType(ElaboratedTypeKeyword Keyword,
NestedNameSpecifier *NNS, QualType T);
- Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E);
- Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E);
- Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
- Sema::OwningExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+ ExprResult TransformPredefinedExpr(PredefinedExpr *E);
+ ExprResult TransformDeclRefExpr(DeclRefExpr *E);
+ ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+ ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *D);
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
@@ -631,9 +634,9 @@ namespace {
TemplateTypeParmTypeLoc TL,
QualType ObjectType);
- Sema::OwningExprResult TransformCallExpr(CallExpr *CE) {
+ ExprResult TransformCallExpr(CallExpr *CE) {
getSema().CallsUndergoingInstantiation.push_back(CE);
- OwningExprResult Result =
+ ExprResult Result =
TreeTransform<TemplateInstantiator>::TransformCallExpr(CE);
getSema().CallsUndergoingInstantiation.pop_back();
return move(Result);
@@ -768,7 +771,7 @@ TemplateInstantiator::RebuildElaboratedType(ElaboratedTypeKeyword Keyword,
NNS, T);
}
-Sema::OwningExprResult
+ExprResult
TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
if (!E->isTypeDependent())
return SemaRef.Owned(E->Retain());
@@ -790,7 +793,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) {
return getSema().Owned(PE);
}
-Sema::OwningExprResult
+ExprResult
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
NonTypeTemplateParmDecl *NTTP) {
// If the corresponding template argument is NULL or non-existent, it's
@@ -818,7 +821,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
getSema().FindInstantiatedDecl(E->getLocation(),
VD, TemplateArgs));
if (!VD)
- return SemaRef.ExprError();
+ return ExprError();
// Derive the type we want the substituted decl to have. This had
// better be non-dependent, or these checks will have serious problems.
@@ -837,7 +840,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
}
-Sema::OwningExprResult
+ExprResult
TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
NamedDecl *D = E->getDecl();
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
@@ -851,7 +854,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E);
}
-Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
+ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
CXXDefaultArgExpr *E) {
assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())->
getDescribedFunctionTemplate() &&
@@ -865,7 +868,7 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
QualType ObjectType) {
// We need a local instantiation scope for this function prototype.
- Sema::LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
return inherited::TransformFunctionProtoType(TLB, TL, ObjectType);
}
@@ -1067,7 +1070,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm);
- // Set DeclContext if inside a Block.
+ // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext
+ // can be anything, is this right ?
NewParm->setDeclContext(CurContext);
return NewParm;
@@ -1100,11 +1104,11 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
continue;
}
- QualType BaseType = SubstType(Base->getType(),
- TemplateArgs,
- Base->getSourceRange().getBegin(),
- DeclarationName());
- if (BaseType.isNull()) {
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ if (!BaseTypeLoc) {
Invalid = true;
continue;
}
@@ -1114,9 +1118,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
Base->getSourceRange(),
Base->isVirtual(),
Base->getAccessSpecifierAsWritten(),
- BaseType,
- /*FIXME: Not totally accurate */
- Base->getSourceRange().getBegin()))
+ BaseTypeLoc))
InstantiatedBases.push_back(InstantiatedBase);
else
Invalid = true;
@@ -1199,13 +1201,16 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// PushDeclContext because we don't have a scope.
ContextRAII SavedContext(*this, Instantiation);
EnterExpressionEvaluationContext EvalContext(*this,
- Action::PotentiallyEvaluated);
+ Sema::PotentiallyEvaluated);
// If this is an instantiation of a local class, merge this local
// instantiation scope with the enclosing scope. Otherwise, every
// instantiation of a class has its own local instantiation scope.
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
- Sema::LocalInstantiationScope Scope(*this, MergeWithParentScope);
+ LocalInstantiationScope Scope(*this, MergeWithParentScope);
+
+ // Pull attributes from the pattern onto the instantiation.
+ InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
// Start the definition of this instantiation.
Instantiation->startDefinition();
@@ -1216,14 +1221,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs))
Invalid = true;
- llvm::SmallVector<DeclPtrTy, 4> Fields;
+ llvm::SmallVector<Decl*, 4> Fields;
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
MemberEnd = Pattern->decls_end();
Member != MemberEnd; ++Member) {
Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
if (NewMember) {
if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
- Fields.push_back(DeclPtrTy::make(Field));
+ Fields.push_back(Field);
else if (NewMember->isInvalidDecl())
Invalid = true;
} else {
@@ -1234,7 +1239,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
}
// Finish checking fields.
- ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
+ ActOnFields(0, Instantiation->getLocation(), Instantiation,
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
0);
CheckCompletedCXXClass(Instantiation);
@@ -1416,12 +1421,6 @@ Sema::InstantiateClassTemplateSpecialization(
TSK,
Complain);
- for (unsigned I = 0, N = Matched.size(); I != N; ++I) {
- // FIXME: Implement TemplateArgumentList::Destroy!
- // if (Matched[I].first != Pattern)
- // Matched[I].second->Destroy(Context);
- }
-
return Result;
}
@@ -1583,7 +1582,7 @@ Sema::InstantiateClassTemplateSpecializationMembers(
TSK);
}
-Sema::OwningStmtResult
+StmtResult
Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!S)
return Owned(S);
@@ -1594,7 +1593,7 @@ Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
return Instantiator.TransformStmt(S);
}
-Sema::OwningExprResult
+ExprResult
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!E)
return Owned(E);
@@ -1615,6 +1614,15 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
}
+/// \brief Do template substitution on declaration name info.
+DeclarationNameInfo
+Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(),
+ NameInfo.getName());
+ return Instantiator.TransformDeclarationNameInfo(NameInfo);
+}
+
TemplateName
Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -1631,7 +1639,7 @@ bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
return Instantiator.TransformTemplateArgument(Input, Output);
}
-Decl *Sema::LocalInstantiationScope::getInstantiationOf(const Decl *D) {
+Decl *LocalInstantiationScope::getInstantiationOf(const Decl *D) {
for (LocalInstantiationScope *Current = this; Current;
Current = Current->Outer) {
// Check if we found something within this scope.
@@ -1650,8 +1658,7 @@ Decl *Sema::LocalInstantiationScope::getInstantiationOf(const Decl *D) {
return 0;
}
-void Sema::LocalInstantiationScope::InstantiatedLocal(const Decl *D,
- Decl *Inst) {
+void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
Decl *&Stored = LocalDecls[D];
assert((!Stored || Stored == Inst)&& "Already instantiated this local");
Stored = Inst;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 2fd35285324e..1c7869fecd86 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -9,8 +9,10 @@
// This file implements C++ template instantiation for declarations.
//
//===----------------------------------------------------------------------===/
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/PrettyDeclStackTrace.h"
+#include "clang/Sema/Template.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
@@ -19,7 +21,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
-#include "clang/Basic/PrettyStackTrace.h"
#include "clang/Lex/Preprocessor.h"
using namespace clang;
@@ -31,11 +32,7 @@ namespace {
DeclContext *Owner;
const MultiLevelTemplateArgumentList &TemplateArgs;
- void InstantiateAttrs(Decl *Tmpl, Decl *New);
-
public:
- typedef Sema::OwningExprResult OwningExprResult;
-
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
const MultiLevelTemplateArgumentList &TemplateArgs)
: SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
@@ -87,10 +84,6 @@ namespace {
return 0;
}
- const LangOptions &getLangOptions() {
- return SemaRef.getLangOptions();
- }
-
// Helper functions for instantiating methods.
TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
llvm::SmallVectorImpl<ParmVarDecl *> &Params);
@@ -144,28 +137,38 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
}
// FIXME: Is this still too simple?
-void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
- for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
- TmplAttr = TmplAttr->getNext()) {
+void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+ Decl *Tmpl, Decl *New) {
+ for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
+ i != e; ++i) {
+ const Attr *TmplAttr = *i;
// FIXME: This should be generalized to more than just the AlignedAttr.
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
- if (Aligned->isDependent()) {
+ if (Aligned->isAlignmentDependent()) {
// The alignment expression is not potentially evaluated.
- EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Action::Unevaluated);
-
- OwningExprResult Result = SemaRef.SubstExpr(Aligned->getAlignmentExpr(),
- TemplateArgs);
- if (!Result.isInvalid())
- // FIXME: Is this the correct source location?
- SemaRef.AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(),
- New, Result.takeAs<Expr>());
+ EnterExpressionEvaluationContext Unevaluated(*this,
+ Sema::Unevaluated);
+
+ if (Aligned->isAlignmentExpr()) {
+ ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
+ TemplateArgs);
+ if (!Result.isInvalid())
+ AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>());
+ }
+ else {
+ TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),
+ TemplateArgs,
+ Aligned->getLocation(),
+ DeclarationName());
+ if (Result)
+ AddAlignedAttr(Aligned->getLocation(), New, Result);
+ }
continue;
}
}
// FIXME: Is cloning correct for all attributes?
- Attr *NewAttr = TmplAttr->clone(SemaRef.Context);
+ Attr *NewAttr = TmplAttr->clone(Context);
New->addAttr(NewAttr);
}
}
@@ -234,7 +237,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
}
- InstantiateAttrs(D, Typedef);
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
Typedef->setAccess(D->getAccess());
Owner->addDecl(Typedef);
@@ -249,14 +252,14 @@ static bool InstantiateInitializationArguments(Sema &SemaRef,
Expr **Args, unsigned NumArgs,
const MultiLevelTemplateArgumentList &TemplateArgs,
llvm::SmallVectorImpl<SourceLocation> &FakeCommaLocs,
- ASTOwningVector<&ActionBase::DeleteExpr> &InitArgs) {
+ ASTOwningVector<Expr*> &InitArgs) {
for (unsigned I = 0; I != NumArgs; ++I) {
// When we hit the first defaulted argument, break out of the loop:
// we don't pass those default arguments on.
if (Args[I]->isDefaultArgument())
break;
- Sema::OwningExprResult Arg = SemaRef.SubstExpr(Args[I], TemplateArgs);
+ ExprResult Arg = SemaRef.SubstExpr(Args[I], TemplateArgs);
if (Arg.isInvalid())
return true;
@@ -288,7 +291,7 @@ static bool InstantiateInitializer(Sema &S, Expr *Init,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation &LParenLoc,
llvm::SmallVector<SourceLocation, 4> &CommaLocs,
- ASTOwningVector<&ActionBase::DeleteExpr> &NewArgs,
+ ASTOwningVector<Expr*> &NewArgs,
SourceLocation &RParenLoc) {
NewArgs.clear();
LParenLoc = SourceLocation();
@@ -331,7 +334,7 @@ static bool InstantiateInitializer(Sema &S, Expr *Init,
}
}
- Sema::OwningExprResult Result = S.SubstExpr(Init, TemplateArgs);
+ ExprResult Result = S.SubstExpr(Init, TemplateArgs);
if (Result.isInvalid())
return true;
@@ -363,7 +366,6 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
D->getStorageClassAsWritten());
Var->setThreadSpecified(D->isThreadSpecified());
Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());
- Var->setDeclaredInCondition(D->isDeclaredInCondition());
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Var))
@@ -399,7 +401,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
if (Owner->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
}
- InstantiateAttrs(D, Var);
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Var);
// Link instantiations of static data members back to the template from
// which they were instantiated.
@@ -418,25 +420,23 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// Instantiate the initializer.
SourceLocation LParenLoc, RParenLoc;
llvm::SmallVector<SourceLocation, 4> CommaLocs;
- ASTOwningVector<&ActionBase::DeleteExpr> InitArgs(SemaRef);
+ ASTOwningVector<Expr*> InitArgs(SemaRef);
if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc,
CommaLocs, InitArgs, RParenLoc)) {
// Attach the initializer to the declaration.
if (D->hasCXXDirectInitializer()) {
// Add the direct initializer to the declaration.
- SemaRef.AddCXXDirectInitializerToDecl(Sema::DeclPtrTy::make(Var),
+ SemaRef.AddCXXDirectInitializerToDecl(Var,
LParenLoc,
move_arg(InitArgs),
CommaLocs.data(),
RParenLoc);
} else if (InitArgs.size() == 1) {
- Expr *Init = (Expr*)(InitArgs.take()[0]);
- SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var),
- SemaRef.Owned(Init),
- false);
+ Expr *Init = InitArgs.take()[0];
+ SemaRef.AddInitializerToDecl(Var, Init, false);
} else {
assert(InitArgs.size() == 0);
- SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
+ SemaRef.ActOnUninitializedDecl(Var, false);
}
} else {
// FIXME: Not too happy about invalidating the declaration
@@ -446,12 +446,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
SemaRef.PopExpressionEvaluationContext();
} else if (!Var->isStaticDataMember() || Var->isOutOfLine())
- SemaRef.ActOnUninitializedDecl(Sema::DeclPtrTy::make(Var), false);
+ SemaRef.ActOnUninitializedDecl(Var, false);
// Diagnose unused local variables.
if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed())
SemaRef.DiagnoseUnusedDecl(Var);
-
+
return Var;
}
@@ -493,9 +493,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
BitWidth = 0;
else if (BitWidth) {
// The bit-width expression is not potentially evaluated.
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- OwningExprResult InstantiatedBitWidth
+ ExprResult InstantiatedBitWidth
= SemaRef.SubstExpr(BitWidth, TemplateArgs);
if (InstantiatedBitWidth.isInvalid()) {
Invalid = true;
@@ -518,7 +518,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
return 0;
}
- InstantiateAttrs(D, Field);
+ SemaRef.InstantiateAttrs(TemplateArgs, D, Field);
if (Invalid)
Field->setInvalidDecl();
@@ -529,7 +529,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
}
if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) {
if (Parent->isAnonymousStructOrUnion() &&
- Parent->getLookupContext()->isFunctionOrMethod())
+ Parent->getRedeclContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field);
}
@@ -581,20 +581,18 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
Expr *AssertExpr = D->getAssertExpr();
// The expression in a static assertion is not potentially evaluated.
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- OwningExprResult InstantiatedAssertExpr
+ ExprResult InstantiatedAssertExpr
= SemaRef.SubstExpr(AssertExpr, TemplateArgs);
if (InstantiatedAssertExpr.isInvalid())
return 0;
- OwningExprResult Message(SemaRef, D->getMessage());
+ ExprResult Message(D->getMessage());
D->getMessage()->Retain();
- Decl *StaticAssert
- = SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
- move(InstantiatedAssertExpr),
- move(Message)).getAs<Decl>();
- return StaticAssert;
+ return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(),
+ InstantiatedAssertExpr.get(),
+ Message.get());
}
Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
@@ -611,18 +609,18 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
if (D->getDeclContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum);
- llvm::SmallVector<Sema::DeclPtrTy, 4> Enumerators;
+ llvm::SmallVector<Decl*, 4> Enumerators;
EnumConstantDecl *LastEnumConst = 0;
for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(),
ECEnd = D->enumerator_end();
EC != ECEnd; ++EC) {
// The specified value for the enumerator.
- OwningExprResult Value = SemaRef.Owned((Expr *)0);
+ ExprResult Value = SemaRef.Owned((Expr *)0);
if (Expr *UninstValue = EC->getInitExpr()) {
// The enumerator's value expression is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Action::Unevaluated);
+ Sema::Unevaluated);
Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);
}
@@ -637,7 +635,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
EnumConstantDecl *EnumConst
= SemaRef.CheckEnumConstant(Enum, LastEnumConst,
EC->getLocation(), EC->getIdentifier(),
- move(Value));
+ Value.get());
if (isInvalid) {
if (EnumConst)
@@ -648,7 +646,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
if (EnumConst) {
EnumConst->setAccess(Enum->getAccess());
Enum->addDecl(EnumConst);
- Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst));
+ Enumerators.push_back(EnumConst);
LastEnumConst = EnumConst;
if (D->getDeclContext()->isFunctionOrMethod()) {
@@ -662,8 +660,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
// FIXME: Fixup LBraceLoc and RBraceLoc
// FIXME: Empty Scope and AttributeList (required to handle attribute packed).
SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(),
- Sema::DeclPtrTy::make(Enum),
- &Enumerators[0], Enumerators.size(),
+ Enum,
+ Enumerators.data(), Enumerators.size(),
0, 0);
return Enum;
@@ -679,7 +677,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Create a local instantiation scope for this class template, which
// will contain the instantiations of the template parameters.
- Sema::LocalInstantiationScope Scope(SemaRef);
+ LocalInstantiationScope Scope(SemaRef);
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
@@ -857,16 +855,7 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
if (!InstClassTemplate)
return 0;
- Decl *DCanon = D->getCanonicalDecl();
- for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
- P = InstClassTemplate->getPartialSpecializations().begin(),
- PEnd = InstClassTemplate->getPartialSpecializations().end();
- P != PEnd; ++P) {
- if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
- return &*P;
- }
-
- return 0;
+ return InstClassTemplate->findPartialSpecInstantiatedFromMember(D);
}
Decl *
@@ -875,7 +864,7 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
// will contain the instantiations of the template parameters and then get
// merged with the local instantiation scope for the function template
// itself.
- Sema::LocalInstantiationScope Scope(SemaRef);
+ LocalInstantiationScope Scope(SemaRef);
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
@@ -957,7 +946,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
// Make sure that anonymous structs and unions are recorded.
if (D->isAnonymousStructOrUnion()) {
Record->setAnonymousStructOrUnion(true);
- if (Record->getDeclContext()->getLookupContext()->isFunctionOrMethod())
+ if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
}
@@ -977,20 +966,16 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
void *InsertPos = 0;
if (FunctionTemplate && !TemplateParams) {
- llvm::FoldingSetNodeID ID;
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
- FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
- Innermost.second,
- SemaRef.Context);
- FunctionTemplateSpecializationInfo *Info
- = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
- InsertPos);
+ FunctionDecl *SpecFunc
+ = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
+ InsertPos);
// If we already have a function template specialization, return it.
- if (Info)
- return Info->Function;
+ if (SpecFunc)
+ return SpecFunc;
}
bool isFriend;
@@ -1003,7 +988,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Owner->isFunctionOrMethod() ||
!(isa<Decl>(Owner) &&
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
- Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+ LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
llvm::SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = D->getTypeSourceInfo();
@@ -1181,7 +1166,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
-
+
+ bool queuedInstantiation = false;
+
if (!SemaRef.getLangOptions().CPlusPlus0x &&
D->isThisDeclarationADefinition()) {
// Check for a function body.
@@ -1198,21 +1185,36 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(),
REnd = Function->redecls_end();
R != REnd; ++R) {
- if (*R != Function &&
- ((*R)->getFriendObjectKind() != Decl::FOK_None)) {
+ if (*R == Function)
+ continue;
+ switch (R->getFriendObjectKind()) {
+ case Decl::FOK_None:
+ if (!queuedInstantiation && R->isUsed(false)) {
+ if (MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid()) {
+ SourceLocation Loc = R->getLocation(); // FIXME
+ MSInfo->setPointOfInstantiation(Loc);
+ SemaRef.PendingLocalImplicitInstantiations.push_back(
+ std::make_pair(Function, Loc));
+ queuedInstantiation = true;
+ }
+ }
+ }
+ break;
+ default:
if (const FunctionDecl *RPattern
- = (*R)->getTemplateInstantiationPattern())
+ = R->getTemplateInstantiationPattern())
if (RPattern->hasBody(RPattern)) {
SemaRef.Diag(Function->getLocation(), diag::err_redefinition)
<< Function->getDeclName();
- SemaRef.Diag((*R)->getLocation(), diag::note_previous_definition);
+ SemaRef.Diag(R->getLocation(), diag::note_previous_definition);
Function->setInvalidDecl();
break;
}
}
}
}
-
}
if (Function->isOverloadedOperator() && !DC->isRecord() &&
@@ -1231,20 +1233,16 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// We are creating a function template specialization from a function
// template. Check whether there is already a function template
// specialization for this particular set of template arguments.
- llvm::FoldingSetNodeID ID;
std::pair<const TemplateArgument *, unsigned> Innermost
= TemplateArgs.getInnermost();
- FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first,
- Innermost.second,
- SemaRef.Context);
- FunctionTemplateSpecializationInfo *Info
- = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
- InsertPos);
+ FunctionDecl *SpecFunc
+ = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,
+ InsertPos);
// If we already have a function template specialization, return it.
- if (Info)
- return Info->Function;
+ if (SpecFunc)
+ return SpecFunc;
}
bool isFriend;
@@ -1256,7 +1254,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
bool MergeWithParentScope = (TemplateParams != 0) ||
!(isa<Decl>(Owner) &&
cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
- Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
+ LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
llvm::SmallVector<ParmVarDecl *, 4> Params;
TypeSourceInfo *TInfo = D->getTypeSourceInfo();
@@ -1313,39 +1311,27 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
CXXMethodDecl *Method = 0;
- DeclarationName Name = D->getDeclName();
+ DeclarationNameInfo NameInfo
+ = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
- QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
- Name = SemaRef.Context.DeclarationNames.getCXXConstructorName(
- SemaRef.Context.getCanonicalType(ClassTy));
Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
- Constructor->getLocation(),
- Name, T, TInfo,
+ NameInfo, T, TInfo,
Constructor->isExplicit(),
Constructor->isInlineSpecified(),
false);
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
- QualType ClassTy = SemaRef.Context.getTypeDeclType(Record);
- Name = SemaRef.Context.DeclarationNames.getCXXDestructorName(
- SemaRef.Context.getCanonicalType(ClassTy));
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
- Destructor->getLocation(), Name,
- T, Destructor->isInlineSpecified(),
+ NameInfo, T,
+ Destructor->isInlineSpecified(),
false);
} else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
- CanQualType ConvTy
- = SemaRef.Context.getCanonicalType(
- T->getAs<FunctionType>()->getResultType());
- Name = SemaRef.Context.DeclarationNames.getCXXConversionFunctionName(
- ConvTy);
Method = CXXConversionDecl::Create(SemaRef.Context, Record,
- Conversion->getLocation(), Name,
- T, TInfo,
+ NameInfo, T, TInfo,
Conversion->isInlineSpecified(),
Conversion->isExplicit());
} else {
- Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(),
- D->getDeclName(), T, TInfo,
+ Method = CXXMethodDecl::Create(SemaRef.Context, Record,
+ NameInfo, T, TInfo,
D->isStatic(),
D->getStorageClassAsWritten(),
D->isInlineSpecified());
@@ -1409,8 +1395,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (InitMethodInstantiation(Method, D))
Method->setInvalidDecl();
- LookupResult Previous(SemaRef, Name, SourceLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
+ Sema::ForRedeclaration);
if (!FunctionTemplate || TemplateParams || isFriend) {
SemaRef.LookupQualifiedName(Previous, Record);
@@ -1446,7 +1432,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
else
Owner->addDecl(DeclToAdd);
}
-
+
return Method;
}
@@ -1475,8 +1461,8 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TemplateTypeParmDecl *Inst =
TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- TTPT->getDepth() - 1, TTPT->getIndex(),
- TTPT->getName(),
+ TTPT->getDepth() - TemplateArgs.getNumLevels(),
+ TTPT->getIndex(),TTPT->getName(),
D->wasDeclaredWithTypename(),
D->isParameterPack());
@@ -1517,8 +1503,9 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
NonTypeTemplateParmDecl *Param
= NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- D->getDepth() - 1, D->getPosition(),
- D->getIdentifier(), T, DI);
+ D->getDepth() - TemplateArgs.getNumLevels(),
+ D->getPosition(), D->getIdentifier(), T,
+ DI);
if (Invalid)
Param->setInvalidDecl();
@@ -1539,7 +1526,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
{
// Perform the actual substitution of template parameters within a new,
// local instantiation scope.
- Sema::LocalInstantiationScope Scope(SemaRef);
+ LocalInstantiationScope Scope(SemaRef);
InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
return NULL;
@@ -1548,8 +1535,9 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
// Build the template template parameter.
TemplateTemplateParmDecl *Param
= TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(),
- D->getDepth() - 1, D->getPosition(),
- D->getIdentifier(), InstParams);
+ D->getDepth() - TemplateArgs.getNumLevels(),
+ D->getPosition(), D->getIdentifier(),
+ InstParams);
Param->setDefaultArgument(D->getDefaultArgument(), false);
// Introduce this template parameter's instantiation into the instantiation
@@ -1575,22 +1563,22 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
// The nested name specifier is non-dependent, so no transformation
- // is required.
+ // is required. The same holds for the name info.
+ DeclarationNameInfo NameInfo = D->getNameInfo();
// We only need to do redeclaration lookups if we're in a class
// scope (in fact, it's not really even possible in non-class
// scopes).
bool CheckRedeclaration = Owner->isRecord();
- LookupResult Prev(SemaRef, D->getDeclName(), D->getLocation(),
- Sema::LookupUsingDeclName, Sema::ForRedeclaration);
+ LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
+ Sema::ForRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
- D->getLocation(),
D->getNestedNameRange(),
D->getUsingLocation(),
D->getTargetNestedNameDecl(),
- D->getDeclName(),
+ NameInfo,
D->isTypeName());
CXXScopeSpec SS;
@@ -1666,10 +1654,12 @@ Decl * TemplateDeclInstantiator
SS.setRange(D->getTargetNestedNameRange());
SS.setScopeRep(NNS);
+ // Since NameInfo refers to a typename, it cannot be a C++ special name.
+ // Hence, no tranformation is required for it.
+ DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation());
NamedDecl *UD =
SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
- D->getUsingLoc(), SS, D->getLocation(),
- D->getDeclName(), 0,
+ D->getUsingLoc(), SS, NameInfo, 0,
/*instantiation*/ true,
/*typename*/ true, D->getTypenameLoc());
if (UD)
@@ -1691,10 +1681,12 @@ Decl * TemplateDeclInstantiator
SS.setRange(D->getTargetNestedNameRange());
SS.setScopeRep(NNS);
+ DeclarationNameInfo NameInfo
+ = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+
NamedDecl *UD =
SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
- D->getUsingLoc(), SS, D->getLocation(),
- D->getDeclName(), 0,
+ D->getUsingLoc(), SS, NameInfo, 0,
/*instantiation*/ true,
/*typename*/ false, SourceLocation());
if (UD)
@@ -1735,13 +1727,8 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
}
// Clean up if we had an error.
- if (Invalid) {
- for (ParamVector::iterator PI = Params.begin(), PE = Params.end();
- PI != PE; ++PI)
- if (*PI)
- (*PI)->Destroy(SemaRef.Context);
+ if (Invalid)
return NULL;
- }
TemplateParameterList *InstL
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
@@ -1767,7 +1754,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Create a local instantiation scope for this class template partial
// specialization, which will contain the instantiations of the template
// parameters.
- Sema::LocalInstantiationScope Scope(SemaRef);
+ LocalInstantiationScope Scope(SemaRef);
// Substitute into the template parameters of the class template partial
// specialization.
@@ -1804,15 +1791,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
- llvm::FoldingSetNodeID ID;
- ClassTemplatePartialSpecializationDecl::Profile(ID,
- Converted.getFlatArguments(),
- Converted.flatSize(),
- SemaRef.Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
- InsertPos);
+ = ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(),
+ Converted.flatSize(), InsertPos);
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
@@ -1871,7 +1853,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
InstTemplateArgs,
CanonType,
0,
- ClassTemplate->getPartialSpecializations().size());
+ ClassTemplate->getNextPartialSpecSequenceNumber());
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
return 0;
@@ -1881,8 +1863,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Add this partial specialization to the set of class template partial
// specializations.
- ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec,
- InsertPos);
+ ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos);
return false;
}
@@ -2003,7 +1984,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Proto->getExtInfo()));
}
- InstantiateAttrs(Tmpl, New);
+ SemaRef.InstantiateAttrs(TemplateArgs, Tmpl, New);
return false;
}
@@ -2078,8 +2059,12 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
Diag(PatternDecl->getLocation(),
diag::note_explicit_instantiation_here);
Function->setInvalidDecl();
+ } else if (Function->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
+ PendingInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
}
-
+
return;
}
@@ -2099,13 +2084,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// If we're performing recursive template instantiation, create our own
// queue of pending implicit instantiations that we will instantiate later,
// while we're still within our own instantiation context.
- std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations;
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
if (Recursive)
- PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+ PendingInstantiations.swap(SavedPendingInstantiations);
EnterExpressionEvaluationContext EvalContext(*this,
- Action::PotentiallyEvaluated);
- ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
+ Sema::PotentiallyEvaluated);
+ ActOnStartOfFunctionDef(0, Function);
// Introduce a new scope where local variable instantiations will be
// recorded, unless we're actually a member function within a local
@@ -2118,10 +2103,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
LocalInstantiationScope Scope(*this, MergeWithParentScope);
// Introduce the instantiated function parameters into the local
- // instantiation scope.
- for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I)
- Scope.InstantiatedLocal(PatternDecl->getParamDecl(I),
- Function->getParamDecl(I));
+ // instantiation scope, and set the parameter names to those used
+ // in the template.
+ for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
+ const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
+ ParmVarDecl *FunctionParam = Function->getParamDecl(I);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocal(PatternParam, FunctionParam);
+ }
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
@@ -2139,12 +2128,12 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
// Instantiate the function body.
- OwningStmtResult Body = SubstStmt(Pattern, TemplateArgs);
+ StmtResult Body = SubstStmt(Pattern, TemplateArgs);
if (Body.isInvalid())
Function->setInvalidDecl();
- ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body),
+ ActOnFinishFunctionBody(Function, Body.get(),
/*IsInstantiation=*/true);
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
@@ -2156,16 +2145,16 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// This class may have local implicit instantiations that need to be
// instantiation within this scope.
- PerformPendingImplicitInstantiations(/*LocalOnly=*/true);
+ PerformPendingInstantiations(/*LocalOnly=*/true);
Scope.Exit();
if (Recursive) {
// Instantiate any pending implicit instantiations found during the
// instantiation of this template.
- PerformPendingImplicitInstantiations();
+ PerformPendingInstantiations();
// Restore the set of pending implicit instantiations.
- PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+ PendingInstantiations.swap(SavedPendingInstantiations);
}
}
@@ -2210,8 +2199,12 @@ void Sema::InstantiateStaticDataMemberDefinition(
diag::err_explicit_instantiation_undefined_member)
<< 2 << Var->getDeclName() << Var->getDeclContext();
Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
- }
-
+ } else if (Var->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
+ PendingInstantiations.push_back(
+ std::make_pair(Var, PointOfInstantiation));
+ }
+
return;
}
@@ -2234,9 +2227,9 @@ void Sema::InstantiateStaticDataMemberDefinition(
// If we're performing recursive template instantiation, create our own
// queue of pending implicit instantiations that we will instantiate later,
// while we're still within our own instantiation context.
- std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations;
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
if (Recursive)
- PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+ PendingInstantiations.swap(SavedPendingInstantiations);
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
@@ -2260,10 +2253,10 @@ void Sema::InstantiateStaticDataMemberDefinition(
if (Recursive) {
// Instantiate any pending implicit instantiations found during the
// instantiation of this template.
- PerformPendingImplicitInstantiations();
+ PerformPendingInstantiations();
// Restore the set of pending implicit instantiations.
- PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations);
+ PendingInstantiations.swap(SavedPendingInstantiations);
}
}
@@ -2281,8 +2274,13 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
Inits != InitsEnd; ++Inits) {
CXXBaseOrMemberInitializer *Init = *Inits;
+ // Only instantiate written initializers, let Sema re-construct implicit
+ // ones.
+ if (!Init->isWritten())
+ continue;
+
SourceLocation LParenLoc, RParenLoc;
- ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
+ ASTOwningVector<Expr*> NewArgs(*this);
llvm::SmallVector<SourceLocation, 4> CommaLocs;
// Instantiate the initializer.
@@ -2341,7 +2339,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,
}
// Assign all the initializers to the new constructor.
- ActOnMemInitializers(DeclPtrTy::make(New),
+ ActOnMemInitializers(New,
/*FIXME: ColonLoc */
SourceLocation(),
NewInits.data(), NewInits.size(),
@@ -2588,7 +2586,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
DeclContext *ParentDC = D->getDeclContext();
if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
- ParentDC->isFunctionOrMethod()) {
+ (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) {
// D is a local of some kind. Look into the map of local
// declarations to their instantiations.
return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
@@ -2729,14 +2727,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
/// \brief Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
-void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
+void Sema::PerformPendingInstantiations(bool LocalOnly) {
while (!PendingLocalImplicitInstantiations.empty() ||
- (!LocalOnly && !PendingImplicitInstantiations.empty())) {
+ (!LocalOnly && !PendingInstantiations.empty())) {
PendingImplicitInstantiation Inst;
if (PendingLocalImplicitInstantiations.empty()) {
- Inst = PendingImplicitInstantiations.front();
- PendingImplicitInstantiations.pop_front();
+ Inst = PendingInstantiations.front();
+ PendingInstantiations.pop_front();
} else {
Inst = PendingLocalImplicitInstantiations.front();
PendingLocalImplicitInstantiations.pop_front();
@@ -2744,12 +2742,12 @@ void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
// Instantiate function definitions
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) {
- PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Function),
- Function->getLocation(), *this,
- Context.getSourceManager(),
- "instantiating function definition");
-
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
+ PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
+ "instantiating function definition");
+ bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
+ DefinitionRequired);
continue;
}
@@ -2768,20 +2766,24 @@ void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) {
case TSK_Undeclared:
assert(false && "Cannot instantitiate an undeclared specialization.");
case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
- continue; // No longer need implicit instantiation.
+ continue; // No longer need to instantiate this type.
+ case TSK_ExplicitInstantiationDefinition:
+ // We only need an instantiation if the pending instantiation *is* the
+ // explicit instantiation.
+ if (Var != Var->getMostRecentDeclaration()) continue;
case TSK_ImplicitInstantiation:
break;
}
- PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Var),
- Var->getLocation(), *this,
- Context.getSourceManager(),
- "instantiating static data member "
- "definition");
+ PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(),
+ "instantiating static data member "
+ "definition");
- InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true);
+ bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+ InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
+ DefinitionRequired);
}
}
@@ -2798,3 +2800,4 @@ void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
}
}
}
+
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index a4fc98cd958e..aa30b5c2da30 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -11,7 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -20,13 +21,12 @@
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
-#include <iostream>
-
/// \brief Perform adjustment on the parameter type of a function.
///
/// This routine adjusts the given parameter type @p T to the actual
@@ -266,8 +266,7 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
case DeclSpec::TST_enum:
case DeclSpec::TST_union:
case DeclSpec::TST_struct: {
- TypeDecl *D
- = dyn_cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep()));
+ TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
@@ -299,9 +298,11 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
- Result = TheSema.GetTypeFromParser(DS.getTypeRep());
-
- if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+ Result = TheSema.GetTypeFromParser(DS.getRepAsType());
+ if (Result.isNull())
+ TheDeclarator.setInvalidType(true);
+ else if (DeclSpec::ProtocolQualifierListTy PQ
+ = DS.getProtocolQualifiers()) {
if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
// Silently drop any existing protocol qualifiers.
// TODO: determine whether that's the right thing to do.
@@ -336,13 +337,13 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
}
case DeclSpec::TST_typeofType:
// FIXME: Preserve type source info.
- Result = TheSema.GetTypeFromParser(DS.getTypeRep());
+ Result = TheSema.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for typeof?");
// TypeQuals handled by caller.
Result = Context.getTypeOfType(Result);
break;
case DeclSpec::TST_typeofExpr: {
- Expr *E = static_cast<Expr *>(DS.getTypeRep());
+ Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for typeof?");
// TypeQuals handled by caller.
Result = TheSema.BuildTypeofExprType(E);
@@ -353,7 +354,7 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
break;
}
case DeclSpec::TST_decltype: {
- Expr *E = static_cast<Expr *>(DS.getTypeRep());
+ Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for decltype?");
// TypeQuals handled by caller.
Result = TheSema.BuildDecltypeType(E);
@@ -674,10 +675,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
!ArraySize->getType()->isIntegerType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
- ArraySize->Destroy(Context);
return QualType();
}
- llvm::APSInt ConstVal(32);
+ llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
@@ -707,7 +707,17 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
isSFINAEContext()? diag::err_typecheck_zero_array_size
: diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
+ } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
+ !T->isIncompleteType()) {
+ // Is the array too large?
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+ Diag(ArraySize->getLocStart(), diag::err_array_too_large)
+ << ConstVal.toString(10)
+ << ArraySize->getSourceRange();
}
+
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
@@ -740,11 +750,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
/// \brief Build an ext-vector type.
///
/// Run the required checks for the extended vector type.
-QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
+QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc) {
-
- Expr *Arg = (Expr *)ArraySize.get();
-
// unlike gcc's vector_size attribute, we do not allow vectors to be defined
// in conjunction with complex types (pointers, arrays, functions, etc.).
if (!T->isDependentType() &&
@@ -753,11 +760,11 @@ QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
return QualType();
}
- if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
llvm::APSInt vecSize(32);
- if (!Arg->isIntegerConstantExpr(vecSize, Context)) {
+ if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_not_int)
- << "ext_vector_type" << Arg->getSourceRange();
+ << "ext_vector_type" << ArraySize->getSourceRange();
return QualType();
}
@@ -767,7 +774,7 @@ QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
if (vectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size)
- << Arg->getSourceRange();
+ << ArraySize->getSourceRange();
return QualType();
}
@@ -775,8 +782,7 @@ QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
return Context.getExtVectorType(T, vectorSize);
}
- return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(),
- AttrLoc);
+ return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
/// \brief Build a function type.
@@ -812,7 +818,8 @@ QualType Sema::BuildFunctionType(QualType T,
QualType *ParamTypes,
unsigned NumParamTypes,
bool Variadic, unsigned Quals,
- SourceLocation Loc, DeclarationName Entity) {
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionType::ExtInfo &Info) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
@@ -834,8 +841,7 @@ QualType Sema::BuildFunctionType(QualType T,
return QualType();
return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic,
- Quals, false, false, 0, 0,
- FunctionType::ExtInfo());
+ Quals, false, false, 0, 0, Info);
}
/// \brief Build a member pointer type \c T Class::*.
@@ -883,6 +889,14 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
+ // In the Microsoft ABI, the class is allowed to be an incomplete
+ // type. In such cases, the compiler makes a worst-case assumption.
+ // We make no such assumption right now, so emit an error if the
+ // class isn't a complete type.
+ if (Context.Target.getCXXABI() == CXXABI_Microsoft &&
+ RequireCompleteType(Loc, Class, diag::err_incomplete_type))
+ return QualType();
+
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -912,8 +926,8 @@ QualType Sema::BuildBlockPointerType(QualType T,
return Context.getBlockPointerType(T);
}
-QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) {
- QualType QT = QualType::getFromOpaquePtr(Ty);
+QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
+ QualType QT = Ty.get();
if (QT.isNull()) {
if (TInfo) *TInfo = 0;
return QualType();
@@ -955,7 +969,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
- TagDecl* Owned = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+ TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
// Owned is embedded if it was defined here, or if it is the
// very first (i.e., canonical) declaration of this tag type.
Owned->setEmbeddedInDeclarator(Owned->isDefinition() ||
@@ -1174,7 +1188,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
- TagDecl *Tag = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+ TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
if (Tag->isDefinition())
Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
<< Context.getTypeDeclType(Tag);
@@ -1221,8 +1235,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
ArgTys.reserve(FTI.NumArgs);
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param =
- cast<ParmVarDecl>(FTI.ArgInfo[i].Param.getAs<Decl>());
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
@@ -1295,19 +1308,19 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
case DeclaratorChunk::MemberPointer:
// The scope spec must refer to a class, or be dependent.
+ CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
- if (DeclType.Mem.Scope().isInvalid()) {
+ if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
D.setInvalidType(true);
- } else if (isDependentScopeSpecifier(DeclType.Mem.Scope())
- || dyn_cast_or_null<CXXRecordDecl>(
- computeDeclContext(DeclType.Mem.Scope()))) {
+ } else if (isDependentScopeSpecifier(SS) ||
+ dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS))) {
NestedNameSpecifier *NNS
- = (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
+ = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
- ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
+ ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
NNS->getAsIdentifier());
break;
@@ -1315,11 +1328,15 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case NestedNameSpecifier::Global:
llvm_unreachable("Nested-name-specifier must name a type");
break;
-
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
ClsType = QualType(NNS->getAsType(), 0);
- if (NNSPrefix)
+ // Note: if NNS is dependent, then its prefix (if any) is already
+ // included in ClsType; this does not hold if the NNS is
+ // nondependent: in this case (if there is indeed a prefix)
+ // ClsType needs to be wrapped into an elaborated type.
+ if (NNSPrefix && !NNS->isDependent())
ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
break;
}
@@ -1455,7 +1472,7 @@ namespace {
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
// If we got no declarator info from previous Sema routines,
// just fill with the typespec loc.
@@ -1483,9 +1500,9 @@ namespace {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
- assert(DS.getTypeRep());
+ assert(DS.getRepAsType());
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
@@ -1508,7 +1525,7 @@ namespace {
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (Keyword == ETK_Typename) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
return;
@@ -1526,7 +1543,7 @@ namespace {
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (Keyword == ETK_Typename) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
return;
@@ -1546,7 +1563,7 @@ namespace {
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (Keyword == ETK_Typename) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
TInfo->getTypeLoc()));
@@ -1620,7 +1637,7 @@ namespace {
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
- ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
TL.setArg(tpi++, Param);
}
// FIXME: exception specs
@@ -1651,24 +1668,21 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
- TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
-
- // We have source information for the return type that was not in the
- // declaration specifiers; copy that information into the current type
- // location so that it will be retained. This occurs, for example, with
- // a C++ conversion function, where the return type occurs within the
- // declarator-id rather than in the declaration specifiers.
- if (ReturnTypeInfo && D.getDeclSpec().getTypeSpecType() == TST_unspecified) {
+ // If we have different source information for the return type, use
+ // that. This really only applies to C++ conversion functions.
+ if (ReturnTypeInfo) {
TypeLoc TL = ReturnTypeInfo->getTypeLoc();
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
+ } else {
+ TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
}
return TInfo;
}
/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
-QualType Sema::CreateLocInfoType(QualType T, TypeSourceInfo *TInfo) {
+ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
// FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
// and Sema during declaration parsing. Try deallocating/caching them when
// it's appropriate, instead of allocating them and keeping them around.
@@ -1676,7 +1690,7 @@ QualType Sema::CreateLocInfoType(QualType T, TypeSourceInfo *TInfo) {
new (LocT) LocInfoType(T, TInfo);
assert(LocT->getTypeClass() != T->getTypeClass() &&
"LocInfoType's TypeClass conflicts with an existing Type class");
- return QualType(LocT, 0);
+ return ParsedType::make(QualType(LocT, 0));
}
void LocInfoType::getAsStringInternal(std::string &Str,
@@ -1686,7 +1700,7 @@ void LocInfoType::getAsStringInternal(std::string &Str,
" GetTypeFromParser");
}
-Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
+TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
@@ -1710,8 +1724,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
<< Context.getTypeDeclType(OwnedTag);
}
- T = CreateLocInfoType(T, TInfo);
- return T.getAsOpaquePtr();
+ return CreateParsedType(T, TInfo);
}
@@ -1825,9 +1838,10 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Delay if this is not a function or pointer to block.
if (!Type->isFunctionPointerType()
&& !Type->isBlockPointerType()
- && !Type->isFunctionType())
+ && !Type->isFunctionType()
+ && !Type->isMemberFunctionPointerType())
return true;
-
+
// Otherwise we can process right away.
Type = S.Context.getNoReturnType(Type);
return false;
@@ -1842,7 +1856,8 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Delay if this is not a function or pointer to block.
if (!Type->isFunctionPointerType()
&& !Type->isBlockPointerType()
- && !Type->isFunctionType())
+ && !Type->isFunctionType()
+ && !Type->isMemberFunctionPointerType())
return true;
// Otherwise we can process right away.
@@ -1868,6 +1883,12 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
QualType T = Type;
if (const PointerType *PT = Type->getAs<PointerType>())
T = PT->getPointeeType();
+ else if (const BlockPointerType *BPT = Type->getAs<BlockPointerType>())
+ T = BPT->getPointeeType();
+ else if (const MemberPointerType *MPT = Type->getAs<MemberPointerType>())
+ T = MPT->getPointeeType();
+ else if (const ReferenceType *RT = Type->getAs<ReferenceType>())
+ T = RT->getPointeeType();
const FunctionType *Fn = T->getAs<FunctionType>();
// Delay if the type didn't work out to a function.
@@ -1880,6 +1901,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
+ case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
default: llvm_unreachable("unexpected attribute kind"); return false;
}
@@ -1946,8 +1968,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
return;
}
// the base type must be integer or float, and can't already be a vector.
- if (CurType->isVectorType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
+ if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
@@ -2008,6 +2029,7 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result,
case AttributeList::AT_fastcall:
case AttributeList::AT_stdcall:
case AttributeList::AT_thiscall:
+ case AttributeList::AT_pascal:
case AttributeList::AT_regparm:
// Don't process these on the DeclSpec.
if (IsDeclSpec ||
diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp
index 87e7b9d00b09..1854e7430853 100644
--- a/lib/Sema/TargetAttributesSema.cpp
+++ b/lib/Sema/TargetAttributesSema.cpp
@@ -12,9 +12,10 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
#include "TargetAttributesSema.h"
+#include "clang/Sema/SemaInternal.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/AST/DeclCXX.h"
#include "llvm/ADT/Triple.h"
using namespace clang;
@@ -51,8 +52,8 @@ static void HandleMSP430InterruptAttr(Decl *d,
return;
}
- d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
- d->addAttr(::new (S.Context) UsedAttr());
+ d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num));
+ d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context));
}
namespace {
@@ -97,7 +98,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D,
return;
}
- D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr());
+ D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getLoc(), S.Context));
}
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -109,7 +110,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLImportAttr());
+ D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
return;
}
@@ -146,7 +147,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) DLLImportAttr());
+ D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context));
}
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
@@ -158,7 +159,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute can be applied only to functions or variables.
if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLExportAttr());
+ D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
return;
}
@@ -177,7 +178,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
return;
}
- D->addAttr(::new (S.Context) DLLExportAttr());
+ D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
}
namespace {
diff --git a/lib/Sema/TargetAttributesSema.h b/lib/Sema/TargetAttributesSema.h
index 8794e4013ec7..410c900222f6 100644
--- a/lib/Sema/TargetAttributesSema.h
+++ b/lib/Sema/TargetAttributesSema.h
@@ -13,7 +13,7 @@
namespace clang {
class Scope;
class Decl;
- class Attr;
+ class AttributeList;
class Sema;
class TargetAttributesSema {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 17103c515f8b..e7bfbe6fe955 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -13,10 +13,12 @@
#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H
#define LLVM_CLANG_SEMA_TREETRANSFORM_H
-#include "Sema.h"
-#include "Lookup.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -24,13 +26,14 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/TypeLocBuilder.h"
-#include "clang/Parse/Ownership.h"
-#include "clang/Parse/Designator.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Designator.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
namespace clang {
+using namespace sema;
/// \brief A semantic tree transformation that allows one to transform one
/// abstract syntax tree into another.
@@ -89,14 +92,6 @@ protected:
Sema &SemaRef;
public:
- typedef Sema::OwningStmtResult OwningStmtResult;
- typedef Sema::OwningExprResult OwningExprResult;
- typedef Sema::StmtArg StmtArg;
- typedef Sema::ExprArg ExprArg;
- typedef Sema::MultiExprArg MultiExprArg;
- typedef Sema::MultiStmtArg MultiStmtArg;
- typedef Sema::DeclPtrTy DeclPtrTy;
-
/// \brief Initializes a new tree transformer.
TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
@@ -108,6 +103,9 @@ public:
return static_cast<const Derived&>(*this);
}
+ static inline ExprResult Owned(Expr *E) { return E; }
+ static inline StmtResult Owned(Stmt *S) { return S; }
+
/// \brief Retrieves a reference to the semantic analysis object used for
/// this tree transform.
Sema &getSema() const { return SemaRef; }
@@ -220,7 +218,7 @@ public:
/// other mechanism.
///
/// \returns the transformed statement.
- OwningStmtResult TransformStmt(Stmt *S);
+ StmtResult TransformStmt(Stmt *S);
/// \brief Transform the given expression.
///
@@ -230,7 +228,7 @@ public:
/// other mechanism.
///
/// \returns the transformed expression.
- OwningExprResult TransformExpr(Expr *E);
+ ExprResult TransformExpr(Expr *E);
/// \brief Transform the given declaration, which is referenced from a type
/// or expression.
@@ -276,9 +274,9 @@ public:
/// and destructor names and then (if needed) rebuilds the declaration name.
/// Identifiers and selectors are returned unmodified. Sublcasses may
/// override this function to provide alternate behavior.
- DeclarationName TransformDeclarationName(DeclarationName Name,
- SourceLocation Loc,
- QualType ObjectType = QualType());
+ DeclarationNameInfo
+ TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ QualType ObjectType = QualType());
/// \brief Transform the given template name.
///
@@ -337,13 +335,13 @@ public:
TransformTemplateSpecializationType(const TemplateSpecializationType *T,
QualType ObjectType);
- OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
- OwningExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
+ StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
+ ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E);
#define STMT(Node, Parent) \
- OwningStmtResult Transform##Node(Node *S);
+ StmtResult Transform##Node(Node *S);
#define EXPR(Node, Parent) \
- OwningExprResult Transform##Node(Node *E);
+ ExprResult Transform##Node(Node *E);
#define ABSTRACT_STMT(Stmt)
#include "clang/AST/StmtNodes.inc"
@@ -421,7 +419,7 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildVariableArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- ExprArg SizeExpr,
+ Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange);
@@ -432,7 +430,7 @@ public:
/// Subclasses may override this routine to provide different behavior.
QualType RebuildDependentSizedArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- ExprArg SizeExpr,
+ Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange);
@@ -458,7 +456,7 @@ public:
/// By default, performs semantic analysis when building the vector type.
/// Subclasses may override this routine to provide different behavior.
QualType RebuildDependentSizedExtVectorType(QualType ElementType,
- ExprArg SizeExpr,
+ Expr *SizeExpr,
SourceLocation AttributeLoc);
/// \brief Build a new function type.
@@ -468,7 +466,8 @@ public:
QualType RebuildFunctionProtoType(QualType T,
QualType *ParamTypes,
unsigned NumParamTypes,
- bool Variadic, unsigned Quals);
+ bool Variadic, unsigned Quals,
+ const FunctionType::ExtInfo &Info);
/// \brief Build a new unprototyped function type.
QualType RebuildFunctionNoProtoType(QualType ResultType);
@@ -496,7 +495,7 @@ public:
///
/// By default, performs semantic analysis when building the typeof type.
/// Subclasses may override this routine to provide different behavior.
- QualType RebuildTypeOfExprType(ExprArg Underlying);
+ QualType RebuildTypeOfExprType(Expr *Underlying);
/// \brief Build a new typeof(type) type.
///
@@ -507,7 +506,7 @@ public:
///
/// By default, performs semantic analysis when building the decltype type.
/// Subclasses may override this routine to provide different behavior.
- QualType RebuildDecltypeType(ExprArg Underlying);
+ QualType RebuildDecltypeType(Expr *Underlying);
/// \brief Build a new template specialization type.
///
@@ -558,7 +557,8 @@ public:
getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args);
if (T.isNull()) return QualType();
- return SemaRef.Context.getElaboratedType(Keyword, NNS, T);
+ // NOTE: NNS is already recorded in template specialization type T.
+ return SemaRef.Context.getElaboratedType(Keyword, /*NNS=*/0, T);
}
/// \brief Build a new typename type that refers to an identifier.
@@ -707,11 +707,11 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildCompoundStmt(SourceLocation LBraceLoc,
+ StmtResult RebuildCompoundStmt(SourceLocation LBraceLoc,
MultiStmtArg Statements,
SourceLocation RBraceLoc,
bool IsStmtExpr) {
- return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, move(Statements),
+ return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, Statements,
IsStmtExpr);
}
@@ -719,12 +719,12 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildCaseStmt(SourceLocation CaseLoc,
- ExprArg LHS,
+ StmtResult RebuildCaseStmt(SourceLocation CaseLoc,
+ Expr *LHS,
SourceLocation EllipsisLoc,
- ExprArg RHS,
+ Expr *RHS,
SourceLocation ColonLoc) {
- return getSema().ActOnCaseStmt(CaseLoc, move(LHS), EllipsisLoc, move(RHS),
+ return getSema().ActOnCaseStmt(CaseLoc, LHS, EllipsisLoc, RHS,
ColonLoc);
}
@@ -732,19 +732,19 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildCaseStmtBody(StmtArg S, StmtArg Body) {
- getSema().ActOnCaseStmtBody(S.get(), move(Body));
- return move(S);
+ StmtResult RebuildCaseStmtBody(Stmt *S, Stmt *Body) {
+ getSema().ActOnCaseStmtBody(S, Body);
+ return S;
}
/// \brief Build a new default statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildDefaultStmt(SourceLocation DefaultLoc,
+ StmtResult RebuildDefaultStmt(SourceLocation DefaultLoc,
SourceLocation ColonLoc,
- StmtArg SubStmt) {
- return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, move(SubStmt),
+ Stmt *SubStmt) {
+ return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt,
/*CurScope=*/0);
}
@@ -752,89 +752,85 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildLabelStmt(SourceLocation IdentLoc,
+ StmtResult RebuildLabelStmt(SourceLocation IdentLoc,
IdentifierInfo *Id,
SourceLocation ColonLoc,
- StmtArg SubStmt) {
- return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, move(SubStmt));
+ Stmt *SubStmt) {
+ return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, SubStmt);
}
/// \brief Build a new "if" statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
- VarDecl *CondVar, StmtArg Then,
- SourceLocation ElseLoc, StmtArg Else) {
- return getSema().ActOnIfStmt(IfLoc, Cond, DeclPtrTy::make(CondVar),
- move(Then), ElseLoc, move(Else));
+ StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
+ VarDecl *CondVar, Stmt *Then,
+ SourceLocation ElseLoc, Stmt *Else) {
+ return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else);
}
/// \brief Start building a new switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
- Sema::ExprArg Cond,
- VarDecl *CondVar) {
- return getSema().ActOnStartOfSwitchStmt(SwitchLoc, move(Cond),
- DeclPtrTy::make(CondVar));
+ StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc,
+ Expr *Cond, VarDecl *CondVar) {
+ return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond,
+ CondVar);
}
/// \brief Attach the body to the switch statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc,
- StmtArg Switch, StmtArg Body) {
- return getSema().ActOnFinishSwitchStmt(SwitchLoc, move(Switch),
- move(Body));
+ StmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body) {
+ return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body);
}
/// \brief Build a new while statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildWhileStmt(SourceLocation WhileLoc,
+ StmtResult RebuildWhileStmt(SourceLocation WhileLoc,
Sema::FullExprArg Cond,
VarDecl *CondVar,
- StmtArg Body) {
- return getSema().ActOnWhileStmt(WhileLoc, Cond,
- DeclPtrTy::make(CondVar), move(Body));
+ Stmt *Body) {
+ return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body);
}
/// \brief Build a new do-while statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildDoStmt(SourceLocation DoLoc, StmtArg Body,
+ StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body,
SourceLocation WhileLoc,
SourceLocation LParenLoc,
- ExprArg Cond,
+ Expr *Cond,
SourceLocation RParenLoc) {
- return getSema().ActOnDoStmt(DoLoc, move(Body), WhileLoc, LParenLoc,
- move(Cond), RParenLoc);
+ return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc,
+ Cond, RParenLoc);
}
/// \brief Build a new for statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildForStmt(SourceLocation ForLoc,
+ StmtResult RebuildForStmt(SourceLocation ForLoc,
SourceLocation LParenLoc,
- StmtArg Init, Sema::FullExprArg Cond,
+ Stmt *Init, Sema::FullExprArg Cond,
VarDecl *CondVar, Sema::FullExprArg Inc,
- SourceLocation RParenLoc, StmtArg Body) {
- return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), Cond,
- DeclPtrTy::make(CondVar),
- Inc, RParenLoc, move(Body));
+ SourceLocation RParenLoc, Stmt *Body) {
+ return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond,
+ CondVar,
+ Inc, RParenLoc, Body);
}
/// \brief Build a new goto statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildGotoStmt(SourceLocation GotoLoc,
+ StmtResult RebuildGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelStmt *Label) {
return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label->getID());
@@ -844,27 +840,27 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc,
+ StmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc,
SourceLocation StarLoc,
- ExprArg Target) {
- return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(Target));
+ Expr *Target) {
+ return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target);
}
/// \brief Build a new return statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildReturnStmt(SourceLocation ReturnLoc,
- ExprArg Result) {
+ StmtResult RebuildReturnStmt(SourceLocation ReturnLoc,
+ Expr *Result) {
- return getSema().ActOnReturnStmt(ReturnLoc, move(Result));
+ return getSema().ActOnReturnStmt(ReturnLoc, Result);
}
/// \brief Build a new declaration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
+ StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls,
SourceLocation StartLoc,
SourceLocation EndLoc) {
return getSema().Owned(
@@ -878,7 +874,7 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildAsmStmt(SourceLocation AsmLoc,
+ StmtResult RebuildAsmStmt(SourceLocation AsmLoc,
bool IsSimple,
bool IsVolatile,
unsigned NumOutputs,
@@ -886,13 +882,13 @@ public:
IdentifierInfo **Names,
MultiExprArg Constraints,
MultiExprArg Exprs,
- ExprArg AsmString,
+ Expr *AsmString,
MultiExprArg Clobbers,
SourceLocation RParenLoc,
bool MSAsm) {
return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs,
NumInputs, Names, move(Constraints),
- move(Exprs), move(AsmString), move(Clobbers),
+ Exprs, AsmString, Clobbers,
RParenLoc, MSAsm);
}
@@ -900,12 +896,12 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildObjCAtTryStmt(SourceLocation AtLoc,
- StmtArg TryBody,
+ StmtResult RebuildObjCAtTryStmt(SourceLocation AtLoc,
+ Stmt *TryBody,
MultiStmtArg CatchStmts,
- StmtArg Finally) {
- return getSema().ActOnObjCAtTryStmt(AtLoc, move(TryBody), move(CatchStmts),
- move(Finally));
+ Stmt *Finally) {
+ return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, move(CatchStmts),
+ Finally);
}
/// \brief Rebuild an Objective-C exception declaration.
@@ -923,59 +919,58 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildObjCAtCatchStmt(SourceLocation AtLoc,
+ StmtResult RebuildObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParenLoc,
VarDecl *Var,
- StmtArg Body) {
+ Stmt *Body) {
return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc,
- Sema::DeclPtrTy::make(Var),
- move(Body));
+ Var, Body);
}
/// \brief Build a new Objective-C @finally statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc,
- StmtArg Body) {
- return getSema().ActOnObjCAtFinallyStmt(AtLoc, move(Body));
+ StmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc,
+ Stmt *Body) {
+ return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body);
}
/// \brief Build a new Objective-C @throw statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc,
- ExprArg Operand) {
- return getSema().BuildObjCAtThrowStmt(AtLoc, move(Operand));
+ StmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc,
+ Expr *Operand) {
+ return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
}
/// \brief Build a new Objective-C @synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc,
- ExprArg Object,
- StmtArg Body) {
- return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, move(Object),
- move(Body));
+ StmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc,
+ Expr *Object,
+ Stmt *Body) {
+ return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object,
+ Body);
}
/// \brief Build a new Objective-C fast enumeration statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildObjCForCollectionStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc,
- StmtArg Element,
- ExprArg Collection,
- SourceLocation RParenLoc,
- StmtArg Body) {
+ StmtResult RebuildObjCForCollectionStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *Element,
+ Expr *Collection,
+ SourceLocation RParenLoc,
+ Stmt *Body) {
return getSema().ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
- move(Element),
- move(Collection),
+ Element,
+ Collection,
RParenLoc,
- move(Body));
+ Body);
}
/// \brief Build a new C++ exception declaration.
@@ -995,31 +990,30 @@ public:
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc,
- VarDecl *ExceptionDecl,
- StmtArg Handler) {
- return getSema().Owned(
- new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl,
- Handler.takeAs<Stmt>()));
+ StmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc,
+ VarDecl *ExceptionDecl,
+ Stmt *Handler) {
+ return Owned(new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl,
+ Handler));
}
/// \brief Build a new C++ try statement.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
- OwningStmtResult RebuildCXXTryStmt(SourceLocation TryLoc,
- StmtArg TryBlock,
- MultiStmtArg Handlers) {
- return getSema().ActOnCXXTryBlock(TryLoc, move(TryBlock), move(Handlers));
+ StmtResult RebuildCXXTryStmt(SourceLocation TryLoc,
+ Stmt *TryBlock,
+ MultiStmtArg Handlers) {
+ return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers));
}
/// \brief Build a new expression that references a declaration.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS,
- LookupResult &R,
- bool RequiresADL) {
+ ExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool RequiresADL) {
return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL);
}
@@ -1028,33 +1022,34 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
- SourceRange QualifierRange,
- ValueDecl *VD, SourceLocation Loc,
- TemplateArgumentListInfo *TemplateArgs) {
+ ExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange,
+ ValueDecl *VD,
+ const DeclarationNameInfo &NameInfo,
+ TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.setScopeRep(Qualifier);
SS.setRange(QualifierRange);
// FIXME: loses template args.
-
- return getSema().BuildDeclarationNameExpr(SS, Loc, VD);
+
+ return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD);
}
/// \brief Build a new expression in parentheses.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildParenExpr(ExprArg SubExpr, SourceLocation LParen,
+ ExprResult RebuildParenExpr(Expr *SubExpr, SourceLocation LParen,
SourceLocation RParen) {
- return getSema().ActOnParenExpr(LParen, RParen, move(SubExpr));
+ return getSema().ActOnParenExpr(LParen, RParen, SubExpr);
}
/// \brief Build a new pseudo-destructor expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
+ ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base,
SourceLocation OperatorLoc,
bool isArrow,
NestedNameSpecifier *Qualifier,
@@ -1068,19 +1063,19 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
- UnaryOperator::Opcode Opc,
- ExprArg SubExpr) {
- return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, move(SubExpr));
+ ExprResult RebuildUnaryOperator(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ Expr *SubExpr) {
+ return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, SubExpr);
}
/// \brief Build a new builtin offsetof expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc,
+ ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc,
TypeSourceInfo *Type,
- Action::OffsetOfComponent *Components,
+ Sema::OffsetOfComponent *Components,
unsigned NumComponents,
SourceLocation RParenLoc) {
return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components,
@@ -1091,7 +1086,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo,
+ ExprResult RebuildSizeOfAlignOf(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
return getSema().CreateSizeOfAlignOfExpr(TInfo, OpLoc, isSizeOf, R);
@@ -1102,15 +1097,13 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildSizeOfAlignOf(ExprArg SubExpr, SourceLocation OpLoc,
+ ExprResult RebuildSizeOfAlignOf(Expr *SubExpr, SourceLocation OpLoc,
bool isSizeOf, SourceRange R) {
- OwningExprResult Result
- = getSema().CreateSizeOfAlignOfExpr((Expr *)SubExpr.get(),
- OpLoc, isSizeOf, R);
+ ExprResult Result
+ = getSema().CreateSizeOfAlignOfExpr(SubExpr, OpLoc, isSizeOf, R);
if (Result.isInvalid())
- return getSema().ExprError();
+ return ExprError();
- SubExpr.release();
return move(Result);
}
@@ -1118,12 +1111,12 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildArraySubscriptExpr(ExprArg LHS,
+ ExprResult RebuildArraySubscriptExpr(Expr *LHS,
SourceLocation LBracketLoc,
- ExprArg RHS,
+ Expr *RHS,
SourceLocation RBracketLoc) {
- return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, move(LHS),
- LBracketLoc, move(RHS),
+ return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, LHS,
+ LBracketLoc, RHS,
RBracketLoc);
}
@@ -1131,11 +1124,11 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCallExpr(ExprArg Callee, SourceLocation LParenLoc,
+ ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
- return getSema().ActOnCallExpr(/*Scope=*/0, move(Callee), LParenLoc,
+ return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc,
move(Args), CommaLocs, RParenLoc);
}
@@ -1143,11 +1136,11 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildMemberExpr(ExprArg Base, SourceLocation OpLoc,
+ ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc,
bool isArrow,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
ValueDecl *Member,
NamedDecl *FoundDecl,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
@@ -1156,14 +1149,13 @@ public:
// We have a reference to an unnamed field.
assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
- Expr *BaseExpr = Base.takeAs<Expr>();
- if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier,
+ if (getSema().PerformObjectMemberConversion(Base, Qualifier,
FoundDecl, Member))
- return getSema().ExprError();
+ return ExprError();
MemberExpr *ME =
- new (getSema().Context) MemberExpr(BaseExpr, isArrow,
- Member, MemberLoc,
+ new (getSema().Context) MemberExpr(Base, isArrow,
+ Member, MemberNameInfo,
cast<FieldDecl>(Member)->getType());
return getSema().Owned(ME);
}
@@ -1174,19 +1166,16 @@ public:
SS.setScopeRep(Qualifier);
}
- Expr *BaseExpr = Base.takeAs<Expr>();
- getSema().DefaultFunctionArrayConversion(BaseExpr);
- QualType BaseType = BaseExpr->getType();
+ getSema().DefaultFunctionArrayConversion(Base);
+ QualType BaseType = Base->getType();
// FIXME: this involves duplicating earlier analysis in a lot of
// cases; we should avoid this when possible.
- LookupResult R(getSema(), Member->getDeclName(), MemberLoc,
- Sema::LookupMemberName);
+ LookupResult R(getSema(), MemberNameInfo, Sema::LookupMemberName);
R.addDecl(FoundDecl);
R.resolveKind();
- return getSema().BuildMemberReferenceExpr(getSema().Owned(BaseExpr),
- BaseType, OpLoc, isArrow,
+ return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
SS, FirstQualifierInScope,
R, ExplicitTemplateArgs);
}
@@ -1195,66 +1184,64 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
- BinaryOperator::Opcode Opc,
- ExprArg LHS, ExprArg RHS) {
- return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc,
- LHS.takeAs<Expr>(), RHS.takeAs<Expr>());
+ ExprResult RebuildBinaryOperator(SourceLocation OpLoc,
+ BinaryOperatorKind Opc,
+ Expr *LHS, Expr *RHS) {
+ return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, LHS, RHS);
}
/// \brief Build a new conditional operator expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildConditionalOperator(ExprArg Cond,
+ ExprResult RebuildConditionalOperator(Expr *Cond,
SourceLocation QuestionLoc,
- ExprArg LHS,
+ Expr *LHS,
SourceLocation ColonLoc,
- ExprArg RHS) {
- return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, move(Cond),
- move(LHS), move(RHS));
+ Expr *RHS) {
+ return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, Cond,
+ LHS, RHS);
}
/// \brief Build a new C-style cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc,
+ ExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc,
TypeSourceInfo *TInfo,
SourceLocation RParenLoc,
- ExprArg SubExpr) {
+ Expr *SubExpr) {
return getSema().BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc,
- move(SubExpr));
+ SubExpr);
}
/// \brief Build a new compound literal expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ ExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc,
TypeSourceInfo *TInfo,
SourceLocation RParenLoc,
- ExprArg Init) {
+ Expr *Init) {
return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc,
- move(Init));
+ Init);
}
/// \brief Build a new extended vector element access expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildExtVectorElementExpr(ExprArg Base,
+ ExprResult RebuildExtVectorElementExpr(Expr *Base,
SourceLocation OpLoc,
SourceLocation AccessorLoc,
IdentifierInfo &Accessor) {
CXXScopeSpec SS;
- QualType BaseType = ((Expr*) Base.get())->getType();
- return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
+ DeclarationNameInfo NameInfo(&Accessor, AccessorLoc);
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
OpLoc, /*IsArrow*/ false,
SS, /*FirstQualifierInScope*/ 0,
- DeclarationName(&Accessor),
- AccessorLoc,
+ NameInfo,
/* TemplateArgs */ 0);
}
@@ -1262,11 +1249,11 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildInitList(SourceLocation LBraceLoc,
+ ExprResult RebuildInitList(SourceLocation LBraceLoc,
MultiExprArg Inits,
SourceLocation RBraceLoc,
QualType ResultTy) {
- OwningExprResult Result
+ ExprResult Result
= SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc);
if (Result.isInvalid() || ResultTy->isDependentType())
return move(Result);
@@ -1282,16 +1269,16 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildDesignatedInitExpr(Designation &Desig,
+ ExprResult RebuildDesignatedInitExpr(Designation &Desig,
MultiExprArg ArrayExprs,
SourceLocation EqualOrColonLoc,
bool GNUSyntax,
- ExprArg Init) {
- OwningExprResult Result
+ Expr *Init) {
+ ExprResult Result
= SemaRef.ActOnDesignatedInitializer(Desig, EqualOrColonLoc, GNUSyntax,
- move(Init));
+ Init);
if (Result.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArrayExprs.release();
return move(Result);
@@ -1302,7 +1289,7 @@ public:
/// By default, builds the implicit value initialization without performing
/// any semantic analysis. Subclasses may override this routine to provide
/// different behavior.
- OwningExprResult RebuildImplicitValueInitExpr(QualType T) {
+ ExprResult RebuildImplicitValueInitExpr(QualType T) {
return SemaRef.Owned(new (SemaRef.Context) ImplicitValueInitExpr(T));
}
@@ -1310,17 +1297,19 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc, ExprArg SubExpr,
- QualType T, SourceLocation RParenLoc) {
- return getSema().ActOnVAArg(BuiltinLoc, move(SubExpr), T.getAsOpaquePtr(),
- RParenLoc);
+ ExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc,
+ Expr *SubExpr, TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc) {
+ return getSema().BuildVAArgExpr(BuiltinLoc,
+ SubExpr, TInfo,
+ RParenLoc);
}
/// \brief Build a new expression list in parentheses.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildParenListExpr(SourceLocation LParenLoc,
+ ExprResult RebuildParenListExpr(SourceLocation LParenLoc,
MultiExprArg SubExprs,
SourceLocation RParenLoc) {
return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc,
@@ -1332,7 +1321,7 @@ public:
/// By default, performs semantic analysis, using the name of the label
/// rather than attempting to map the label statement itself.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
+ ExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
SourceLocation LabelLoc,
LabelStmt *Label) {
return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label->getID());
@@ -1342,22 +1331,22 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildStmtExpr(SourceLocation LParenLoc,
- StmtArg SubStmt,
+ ExprResult RebuildStmtExpr(SourceLocation LParenLoc,
+ Stmt *SubStmt,
SourceLocation RParenLoc) {
- return getSema().ActOnStmtExpr(LParenLoc, move(SubStmt), RParenLoc);
+ return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc);
}
/// \brief Build a new __builtin_types_compatible_p expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
- QualType T1, QualType T2,
+ ExprResult RebuildTypesCompatibleExpr(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo1,
+ TypeSourceInfo *TInfo2,
SourceLocation RParenLoc) {
- return getSema().ActOnTypesCompatibleExpr(BuiltinLoc,
- T1.getAsOpaquePtr(),
- T2.getAsOpaquePtr(),
+ return getSema().BuildTypesCompatibleExpr(BuiltinLoc,
+ TInfo1, TInfo2,
RParenLoc);
}
@@ -1365,11 +1354,11 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildChooseExpr(SourceLocation BuiltinLoc,
- ExprArg Cond, ExprArg LHS, ExprArg RHS,
+ ExprResult RebuildChooseExpr(SourceLocation BuiltinLoc,
+ Expr *Cond, Expr *LHS, Expr *RHS,
SourceLocation RParenLoc) {
return SemaRef.ActOnChooseExpr(BuiltinLoc,
- move(Cond), move(LHS), move(RHS),
+ Cond, LHS, RHS,
RParenLoc);
}
@@ -1381,11 +1370,11 @@ public:
/// operator call into a use of a builtin operator, performing
/// argument-dependent lookup, etc. Subclasses may override this routine to
/// provide different behavior.
- OwningExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
+ ExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
SourceLocation OpLoc,
- ExprArg Callee,
- ExprArg First,
- ExprArg Second);
+ Expr *Callee,
+ Expr *First,
+ Expr *Second);
/// \brief Build a new C++ "named" cast expression, such as static_cast or
/// reinterpret_cast.
@@ -1393,57 +1382,57 @@ public:
/// By default, this routine dispatches to one of the more-specific routines
/// for a particular named case, e.g., RebuildCXXStaticCastExpr().
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
+ ExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc,
Stmt::StmtClass Class,
SourceLocation LAngleLoc,
TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
- ExprArg SubExpr,
+ Expr *SubExpr,
SourceLocation RParenLoc) {
switch (Class) {
case Stmt::CXXStaticCastExprClass:
return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
- move(SubExpr), RParenLoc);
+ SubExpr, RParenLoc);
case Stmt::CXXDynamicCastExprClass:
return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
- move(SubExpr), RParenLoc);
+ SubExpr, RParenLoc);
case Stmt::CXXReinterpretCastExprClass:
return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
- move(SubExpr),
+ SubExpr,
RParenLoc);
case Stmt::CXXConstCastExprClass:
return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, TInfo,
RAngleLoc, LParenLoc,
- move(SubExpr), RParenLoc);
+ SubExpr, RParenLoc);
default:
assert(false && "Invalid C++ named cast");
break;
}
- return getSema().ExprError();
+ return ExprError();
}
/// \brief Build a new C++ static_cast expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
+ ExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
- ExprArg SubExpr,
+ Expr *SubExpr,
SourceLocation RParenLoc) {
return getSema().BuildCXXNamedCast(OpLoc, tok::kw_static_cast,
- TInfo, move(SubExpr),
+ TInfo, SubExpr,
SourceRange(LAngleLoc, RAngleLoc),
SourceRange(LParenLoc, RParenLoc));
}
@@ -1452,15 +1441,15 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
+ ExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
- ExprArg SubExpr,
+ Expr *SubExpr,
SourceLocation RParenLoc) {
return getSema().BuildCXXNamedCast(OpLoc, tok::kw_dynamic_cast,
- TInfo, move(SubExpr),
+ TInfo, SubExpr,
SourceRange(LAngleLoc, RAngleLoc),
SourceRange(LParenLoc, RParenLoc));
}
@@ -1469,15 +1458,15 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
+ ExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
- ExprArg SubExpr,
+ Expr *SubExpr,
SourceLocation RParenLoc) {
return getSema().BuildCXXNamedCast(OpLoc, tok::kw_reinterpret_cast,
- TInfo, move(SubExpr),
+ TInfo, SubExpr,
SourceRange(LAngleLoc, RAngleLoc),
SourceRange(LParenLoc, RParenLoc));
}
@@ -1486,15 +1475,15 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
+ ExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc,
SourceLocation LAngleLoc,
TypeSourceInfo *TInfo,
SourceLocation RAngleLoc,
SourceLocation LParenLoc,
- ExprArg SubExpr,
+ Expr *SubExpr,
SourceLocation RParenLoc) {
return getSema().BuildCXXNamedCast(OpLoc, tok::kw_const_cast,
- TInfo, move(SubExpr),
+ TInfo, SubExpr,
SourceRange(LAngleLoc, RAngleLoc),
SourceRange(LParenLoc, RParenLoc));
}
@@ -1503,16 +1492,15 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXFunctionalCastExpr(SourceRange TypeRange,
+ ExprResult RebuildCXXFunctionalCastExpr(SourceRange TypeRange,
TypeSourceInfo *TInfo,
SourceLocation LParenLoc,
- ExprArg SubExpr,
+ Expr *Sub,
SourceLocation RParenLoc) {
- void *Sub = SubExpr.takeAs<Expr>();
return getSema().ActOnCXXTypeConstructExpr(TypeRange,
- TInfo->getType().getAsOpaquePtr(),
+ ParsedType::make(TInfo->getType()),
LParenLoc,
- Sema::MultiExprArg(getSema(), &Sub, 1),
+ MultiExprArg(&Sub, 1),
/*CommaLocs=*/0,
RParenLoc);
}
@@ -1521,7 +1509,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
+ ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
SourceLocation RParenLoc) {
@@ -1533,11 +1521,11 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
+ ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType,
SourceLocation TypeidLoc,
- ExprArg Operand,
+ Expr *Operand,
SourceLocation RParenLoc) {
- return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, move(Operand),
+ return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand,
RParenLoc);
}
@@ -1546,7 +1534,7 @@ public:
/// By default, builds a new "this" expression without performing any
/// semantic analysis. Subclasses may override this routine to provide
/// different behavior.
- OwningExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
+ ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc,
QualType ThisType,
bool isImplicit) {
return getSema().Owned(
@@ -1558,8 +1546,8 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, ExprArg Sub) {
- return getSema().ActOnCXXThrow(ThrowLoc, move(Sub));
+ ExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, Expr *Sub) {
+ return getSema().ActOnCXXThrow(ThrowLoc, Sub);
}
/// \brief Build a new C++ default-argument expression.
@@ -1567,7 +1555,7 @@ public:
/// By default, builds a new default-argument expression, which does not
/// require any semantic analysis. Subclasses may override this routine to
/// provide different behavior.
- OwningExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
+ ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc,
ParmVarDecl *Param) {
return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc,
Param));
@@ -1577,12 +1565,12 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXScalarValueInitExpr(SourceLocation TypeStartLoc,
+ ExprResult RebuildCXXScalarValueInitExpr(SourceLocation TypeStartLoc,
SourceLocation LParenLoc,
QualType T,
SourceLocation RParenLoc) {
return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeStartLoc),
- T.getAsOpaquePtr(), LParenLoc,
+ ParsedType::make(T), LParenLoc,
MultiExprArg(getSema(), 0, 0),
0, RParenLoc);
}
@@ -1591,7 +1579,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXNewExpr(SourceLocation StartLoc,
+ ExprResult RebuildCXXNewExpr(SourceLocation StartLoc,
bool UseGlobal,
SourceLocation PlacementLParen,
MultiExprArg PlacementArgs,
@@ -1600,7 +1588,7 @@ public:
QualType AllocType,
SourceLocation TypeLoc,
SourceRange TypeRange,
- ExprArg ArraySize,
+ Expr *ArraySize,
SourceLocation ConstructorLParen,
MultiExprArg ConstructorArgs,
SourceLocation ConstructorRParen) {
@@ -1612,7 +1600,7 @@ public:
AllocType,
TypeLoc,
TypeRange,
- move(ArraySize),
+ ArraySize,
ConstructorLParen,
move(ConstructorArgs),
ConstructorRParen);
@@ -1622,25 +1610,25 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc,
+ ExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc,
bool IsGlobalDelete,
bool IsArrayForm,
- ExprArg Operand) {
+ Expr *Operand) {
return getSema().ActOnCXXDelete(StartLoc, IsGlobalDelete, IsArrayForm,
- move(Operand));
+ Operand);
}
/// \brief Build a new unary type trait expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
+ ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait,
SourceLocation StartLoc,
SourceLocation LParenLoc,
QualType T,
SourceLocation RParenLoc) {
return getSema().ActOnUnaryTypeTrait(Trait, StartLoc, LParenLoc,
- T.getAsOpaquePtr(), RParenLoc);
+ ParsedType::make(T), RParenLoc);
}
/// \brief Build a new (previously unresolved) declaration reference
@@ -1648,27 +1636,26 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS,
+ ExprResult RebuildDependentScopeDeclRefExpr(NestedNameSpecifier *NNS,
SourceRange QualifierRange,
- DeclarationName Name,
- SourceLocation Location,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.setRange(QualifierRange);
SS.setScopeRep(NNS);
if (TemplateArgs)
- return getSema().BuildQualifiedTemplateIdExpr(SS, Name, Location,
+ return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo,
*TemplateArgs);
- return getSema().BuildQualifiedDeclarationNameExpr(SS, Name, Location);
+ return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo);
}
/// \brief Build a new template-id expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS,
+ ExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS,
LookupResult &R,
bool RequiresADL,
const TemplateArgumentListInfo &TemplateArgs) {
@@ -1679,32 +1666,35 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXConstructExpr(QualType T,
+ ExprResult RebuildCXXConstructExpr(QualType T,
SourceLocation Loc,
CXXConstructorDecl *Constructor,
bool IsElidable,
- MultiExprArg Args) {
- ASTOwningVector<&ActionBase::DeleteExpr> ConvertedArgs(SemaRef);
+ MultiExprArg Args,
+ bool RequiresZeroInit,
+ CXXConstructExpr::ConstructionKind ConstructKind) {
+ ASTOwningVector<Expr*> ConvertedArgs(SemaRef);
if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc,
ConvertedArgs))
- return getSema().ExprError();
+ return ExprError();
return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable,
- move_arg(ConvertedArgs));
+ move_arg(ConvertedArgs),
+ RequiresZeroInit, ConstructKind);
}
/// \brief Build a new object-construction expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXTemporaryObjectExpr(SourceLocation TypeBeginLoc,
+ ExprResult RebuildCXXTemporaryObjectExpr(SourceLocation TypeBeginLoc,
QualType T,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation *Commas,
SourceLocation RParenLoc) {
return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeBeginLoc),
- T.getAsOpaquePtr(),
+ ParsedType::make(T),
LParenLoc,
move(Args),
Commas,
@@ -1715,7 +1705,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXUnresolvedConstructExpr(SourceLocation TypeBeginLoc,
+ ExprResult RebuildCXXUnresolvedConstructExpr(SourceLocation TypeBeginLoc,
QualType T,
SourceLocation LParenLoc,
MultiExprArg Args,
@@ -1723,7 +1713,7 @@ public:
SourceLocation RParenLoc) {
return getSema().ActOnCXXTypeConstructExpr(SourceRange(TypeBeginLoc,
/*FIXME*/LParenLoc),
- T.getAsOpaquePtr(),
+ ParsedType::make(T),
LParenLoc,
move(Args),
Commas,
@@ -1734,31 +1724,31 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildCXXDependentScopeMemberExpr(ExprArg BaseE,
+ ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE,
QualType BaseType,
bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierInScope,
- DeclarationName Name,
- SourceLocation MemberLoc,
+ const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
- return SemaRef.BuildMemberReferenceExpr(move(BaseE), BaseType,
+ return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
SS, FirstQualifierInScope,
- Name, MemberLoc, TemplateArgs);
+ MemberNameInfo,
+ TemplateArgs);
}
/// \brief Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildUnresolvedMemberExpr(ExprArg BaseE,
+ ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE,
QualType BaseType,
SourceLocation OperatorLoc,
bool IsArrow,
@@ -1771,7 +1761,7 @@ public:
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
- return SemaRef.BuildMemberReferenceExpr(move(BaseE), BaseType,
+ return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
SS, FirstQualifierInScope,
R, TemplateArgs);
@@ -1781,7 +1771,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
+ ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc,
TypeSourceInfo *EncodeTypeInfo,
SourceLocation RParenLoc) {
return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo,
@@ -1789,7 +1779,7 @@ public:
}
/// \brief Build a new Objective-C class message.
- OwningExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
+ ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo,
Selector Sel,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
@@ -1803,15 +1793,14 @@ public:
}
/// \brief Build a new Objective-C instance message.
- OwningExprResult RebuildObjCMessageExpr(ExprArg Receiver,
+ ExprResult RebuildObjCMessageExpr(Expr *Receiver,
Selector Sel,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
MultiExprArg Args,
SourceLocation RBracLoc) {
- QualType ReceiverType = static_cast<Expr *>(Receiver.get())->getType();
- return SemaRef.BuildInstanceMessage(move(Receiver),
- ReceiverType,
+ return SemaRef.BuildInstanceMessage(Receiver,
+ Receiver->getType(),
/*SuperLoc=*/SourceLocation(),
Sel, Method, LBracLoc, RBracLoc,
move(Args));
@@ -1821,26 +1810,25 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildObjCIvarRefExpr(ExprArg BaseArg, ObjCIvarDecl *Ivar,
+ ExprResult RebuildObjCIvarRefExpr(Expr *BaseArg, ObjCIvarDecl *Ivar,
SourceLocation IvarLoc,
bool IsArrow, bool IsFreeIvar) {
// FIXME: We lose track of the IsFreeIvar bit.
CXXScopeSpec SS;
- Expr *Base = BaseArg.takeAs<Expr>();
+ Expr *Base = BaseArg;
LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc,
Sema::LookupMemberName);
- OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+ ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IvarLoc,
- SS, DeclPtrTy(),
+ SS, 0,
false);
if (Result.isInvalid())
- return getSema().ExprError();
+ return ExprError();
if (Result.get())
return move(Result);
- return getSema().BuildMemberReferenceExpr(getSema().Owned(Base),
- Base->getType(),
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
/*FIXME:*/IvarLoc, IsArrow, SS,
/*FirstQualifierInScope=*/0,
R,
@@ -1851,26 +1839,24 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildObjCPropertyRefExpr(ExprArg BaseArg,
+ ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg,
ObjCPropertyDecl *Property,
SourceLocation PropertyLoc) {
CXXScopeSpec SS;
- Expr *Base = BaseArg.takeAs<Expr>();
+ Expr *Base = BaseArg;
LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
Sema::LookupMemberName);
bool IsArrow = false;
- OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+ ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/PropertyLoc,
- SS, DeclPtrTy(),
- false);
+ SS, 0, false);
if (Result.isInvalid())
- return getSema().ExprError();
+ return ExprError();
if (Result.get())
return move(Result);
- return getSema().BuildMemberReferenceExpr(getSema().Owned(Base),
- Base->getType(),
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
/*FIXME:*/PropertyLoc, IsArrow,
SS,
/*FirstQualifierInScope=*/0,
@@ -1883,43 +1869,41 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildObjCImplicitSetterGetterRefExpr(
+ ExprResult RebuildObjCImplicitSetterGetterRefExpr(
ObjCMethodDecl *Getter,
QualType T,
ObjCMethodDecl *Setter,
SourceLocation NameLoc,
- ExprArg Base) {
+ Expr *Base) {
// Since these expressions can only be value-dependent, we do not need to
// perform semantic analysis again.
- return getSema().Owned(
+ return Owned(
new (getSema().Context) ObjCImplicitSetterGetterRefExpr(Getter, T,
Setter,
NameLoc,
- Base.takeAs<Expr>()));
+ Base));
}
/// \brief Build a new Objective-C "isa" expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildObjCIsaExpr(ExprArg BaseArg, SourceLocation IsaLoc,
+ ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc,
bool IsArrow) {
CXXScopeSpec SS;
- Expr *Base = BaseArg.takeAs<Expr>();
+ Expr *Base = BaseArg;
LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc,
Sema::LookupMemberName);
- OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
+ ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow,
/*FIME:*/IsaLoc,
- SS, DeclPtrTy(),
- false);
+ SS, 0, false);
if (Result.isInvalid())
- return getSema().ExprError();
+ return ExprError();
if (Result.get())
return move(Result);
- return getSema().BuildMemberReferenceExpr(getSema().Owned(Base),
- Base->getType(),
+ return getSema().BuildMemberReferenceExpr(Base, Base->getType(),
/*FIXME:*/IsaLoc, IsArrow, SS,
/*FirstQualifierInScope=*/0,
R,
@@ -1930,7 +1914,7 @@ public:
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- OwningExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc,
+ ExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc,
MultiExprArg SubExprs,
SourceLocation RParenLoc) {
// Find the declaration for __builtin_shufflevector
@@ -1954,12 +1938,12 @@ public:
Subs, NumSubExprs,
Builtin->getCallResultType(),
RParenLoc);
- OwningExprResult OwnedCall(SemaRef.Owned(TheCall));
+ ExprResult OwnedCall(SemaRef.Owned(TheCall));
// Type-check the __builtin_shufflevector expression.
- OwningExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
+ ExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall);
if (Result.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
OwnedCall.release();
return move(Result);
@@ -1967,7 +1951,7 @@ public:
};
template<typename Derived>
-Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
+StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
if (!S)
return SemaRef.Owned(S);
@@ -1986,11 +1970,11 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
#define EXPR(Node, Parent) case Stmt::Node##Class:
#include "clang/AST/StmtNodes.inc"
{
- Sema::OwningExprResult E = getDerived().TransformExpr(cast<Expr>(S));
+ ExprResult E = getDerived().TransformExpr(cast<Expr>(S));
if (E.isInvalid())
- return getSema().StmtError();
+ return StmtError();
- return getSema().ActOnExprStmt(getSema().MakeFullExpr(E));
+ return getSema().ActOnExprStmt(getSema().MakeFullExpr(E.take()));
}
}
@@ -1999,7 +1983,7 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
template<typename Derived>
-Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
+ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
if (!E)
return SemaRef.Owned(E);
@@ -2094,12 +2078,13 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,
}
template<typename Derived>
-DeclarationName
-TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
- SourceLocation Loc,
- QualType ObjectType) {
+DeclarationNameInfo
+TreeTransform<Derived>
+::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+ QualType ObjectType) {
+ DeclarationName Name = NameInfo.getName();
if (!Name)
- return Name;
+ return DeclarationNameInfo();
switch (Name.getNameKind()) {
case DeclarationName::Identifier:
@@ -2109,24 +2094,41 @@ TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXLiteralOperatorName:
case DeclarationName::CXXUsingDirective:
- return Name;
+ return NameInfo;
case DeclarationName::CXXConstructorName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXConversionFunctionName: {
- TemporaryBase Rebase(*this, Loc, Name);
- QualType T = getDerived().TransformType(Name.getCXXNameType(),
- ObjectType);
- if (T.isNull())
- return DeclarationName();
+ TypeSourceInfo *NewTInfo;
+ CanQualType NewCanTy;
+ if (TypeSourceInfo *OldTInfo = NameInfo.getNamedTypeInfo()) {
+ NewTInfo = getDerived().TransformType(OldTInfo, ObjectType);
+ if (!NewTInfo)
+ return DeclarationNameInfo();
+ NewCanTy = SemaRef.Context.getCanonicalType(NewTInfo->getType());
+ }
+ else {
+ NewTInfo = 0;
+ TemporaryBase Rebase(*this, NameInfo.getLoc(), Name);
+ QualType NewT = getDerived().TransformType(Name.getCXXNameType(),
+ ObjectType);
+ if (NewT.isNull())
+ return DeclarationNameInfo();
+ NewCanTy = SemaRef.Context.getCanonicalType(NewT);
+ }
- return SemaRef.Context.DeclarationNames.getCXXSpecialName(
- Name.getNameKind(),
- SemaRef.Context.getCanonicalType(T));
+ DeclarationName NewName
+ = SemaRef.Context.DeclarationNames.getCXXSpecialName(Name.getNameKind(),
+ NewCanTy);
+ DeclarationNameInfo NewNameInfo(NameInfo);
+ NewNameInfo.setName(NewName);
+ NewNameInfo.setNamedTypeInfo(NewTInfo);
+ return NewNameInfo;
}
}
- return DeclarationName();
+ assert(0 && "Unknown name kind.");
+ return DeclarationNameInfo();
}
template<typename Derived>
@@ -2268,14 +2270,9 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
Expr *SourceExpr = Input.getSourceDeclExpression();
if (SourceExpr) {
EnterExpressionEvaluationContext Unevaluated(getSema(),
- Action::Unevaluated);
- Sema::OwningExprResult E = getDerived().TransformExpr(SourceExpr);
- if (E.isInvalid())
- SourceExpr = NULL;
- else {
- SourceExpr = E.takeAs<Expr>();
- SourceExpr->Retain();
- }
+ Sema::Unevaluated);
+ ExprResult E = getDerived().TransformExpr(SourceExpr);
+ SourceExpr = (E.isInvalid() ? 0 : E.take());
}
Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr);
@@ -2298,18 +2295,15 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(getSema(),
- Action::Unevaluated);
+ Sema::Unevaluated);
Expr *InputExpr = Input.getSourceExpression();
if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
- Sema::OwningExprResult E
+ ExprResult E
= getDerived().TransformExpr(InputExpr);
if (E.isInvalid()) return true;
-
- Expr *ETaken = E.takeAs<Expr>();
- ETaken->Retain();
- Output = TemplateArgumentLoc(TemplateArgument(ETaken), ETaken);
+ Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take());
return false;
}
@@ -2631,7 +2625,7 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB,
Expr *Size = TL.getSizeExpr();
if (Size) {
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
Size = getDerived().TransformExpr(Size).template takeAs<Expr>();
}
NewTL.setSizeExpr(Size);
@@ -2679,14 +2673,14 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
return QualType();
// Array bounds are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- Sema::OwningExprResult SizeResult
+ ExprResult SizeResult
= getDerived().TransformExpr(T->getSizeExpr());
if (SizeResult.isInvalid())
return QualType();
- Expr *Size = static_cast<Expr*>(SizeResult.get());
+ Expr *Size = SizeResult.take();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
@@ -2694,13 +2688,12 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB,
Size != T->getSizeExpr()) {
Result = getDerived().RebuildVariableArrayType(ElementType,
T->getSizeModifier(),
- move(SizeResult),
+ Size,
T->getIndexTypeCVRQualifiers(),
TL.getBracketsRange());
if (Result.isNull())
return QualType();
}
- else SizeResult.take();
VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result);
NewTL.setLBracketLoc(TL.getLBracketLoc());
@@ -2721,9 +2714,9 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
return QualType();
// Array bounds are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- Sema::OwningExprResult SizeResult
+ ExprResult SizeResult
= getDerived().TransformExpr(T->getSizeExpr());
if (SizeResult.isInvalid())
return QualType();
@@ -2736,7 +2729,7 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
Size != T->getSizeExpr()) {
Result = getDerived().RebuildDependentSizedArrayType(ElementType,
T->getSizeModifier(),
- move(SizeResult),
+ Size,
T->getIndexTypeCVRQualifiers(),
TL.getBracketsRange());
if (Result.isNull())
@@ -2767,9 +2760,9 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
return QualType();
// Vector sizes are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
if (Size.isInvalid())
return QualType();
@@ -2778,12 +2771,11 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
ElementType != T->getElementType() ||
Size.get() != T->getSizeExpr()) {
Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
- move(Size),
+ Size.take(),
T->getAttributeLoc());
if (Result.isNull())
return QualType();
}
- else Size.take();
// Result might be dependent or not.
if (isa<DependentSizedExtVectorType>(Result)) {
@@ -2911,18 +2903,25 @@ QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
QualType ObjectType) {
- // Transform the parameters. We do this first for the benefit of template
- // instantiations, so that the ParmVarDecls get/ placed into the template
- // instantiation scope before we transform the function type.
+ // Transform the parameters and return type.
+ //
+ // We instantiate in source order, with the return type first followed by
+ // the parameters, because users tend to expect this (even if they shouldn't
+ // rely on it!).
+ //
+ // FIXME: When we implement late-specified return types, we'll need to
+ // instantiate the return tpe *after* the parameter types in that case,
+ // since the return type can then refer to the parameters themselves (via
+ // decltype, sizeof, etc.).
llvm::SmallVector<QualType, 4> ParamTypes;
llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
- if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
- return QualType();
-
FunctionProtoType *T = TL.getTypePtr();
QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
if (ResultType.isNull())
return QualType();
+
+ if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
+ return QualType();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
@@ -2932,7 +2931,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParamTypes.data(),
ParamTypes.size(),
T->isVariadic(),
- T->getTypeQuals());
+ T->getTypeQuals(),
+ T->getExtInfo());
if (Result.isNull())
return QualType();
}
@@ -3022,16 +3022,16 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
TypeOfExprTypeLoc TL,
QualType ObjectType) {
// typeof expressions are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- Sema::OwningExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
+ ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
if (E.isInvalid())
return QualType();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
E.get() != TL.getUnderlyingExpr()) {
- Result = getDerived().RebuildTypeOfExprType(move(E));
+ Result = getDerived().RebuildTypeOfExprType(E.get());
if (Result.isNull())
return QualType();
}
@@ -3077,16 +3077,16 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
DecltypeType *T = TL.getTypePtr();
// decltype expressions are not potentially evaluated contexts
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
- Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
+ ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
if (E.isInvalid())
return QualType();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
E.get() != T->getUnderlyingExpr()) {
- Result = getDerived().RebuildDecltypeType(move(E));
+ Result = getDerived().RebuildDecltypeType(E.get());
if (Result.isNull())
return QualType();
}
@@ -3432,33 +3432,45 @@ TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB,
// Statement transformation
//===----------------------------------------------------------------------===//
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformNullStmt(NullStmt *S) {
return SemaRef.Owned(S->Retain());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S) {
return getDerived().TransformCompoundStmt(S, false);
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
bool IsStmtExpr) {
+ bool SubStmtInvalid = false;
bool SubStmtChanged = false;
- ASTOwningVector<&ActionBase::DeleteStmt> Statements(getSema());
+ ASTOwningVector<Stmt*> Statements(getSema());
for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
B != BEnd; ++B) {
- OwningStmtResult Result = getDerived().TransformStmt(*B);
- if (Result.isInvalid())
- return getSema().StmtError();
+ StmtResult Result = getDerived().TransformStmt(*B);
+ if (Result.isInvalid()) {
+ // Immediately fail if this was a DeclStmt, since it's very
+ // likely that this will cause problems for future statements.
+ if (isa<DeclStmt>(*B))
+ return StmtError();
+
+ // Otherwise, just keep processing substatements and fail later.
+ SubStmtInvalid = true;
+ continue;
+ }
SubStmtChanged = SubStmtChanged || Result.get() != *B;
Statements.push_back(Result.takeAs<Stmt>());
}
+ if (SubStmtInvalid)
+ return StmtError();
+
if (!getDerived().AlwaysRebuild() &&
!SubStmtChanged)
return SemaRef.Owned(S->Retain());
@@ -3470,75 +3482,75 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S,
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) {
- OwningExprResult LHS(SemaRef), RHS(SemaRef);
+ ExprResult LHS, RHS;
{
// The case value expressions are not potentially evaluated.
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
// Transform the left-hand case value.
LHS = getDerived().TransformExpr(S->getLHS());
if (LHS.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the right-hand case value (for the GNU case-range extension).
RHS = getDerived().TransformExpr(S->getRHS());
if (RHS.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
}
// Build the case statement.
// Case statements are always rebuilt so that they will attached to their
// transformed switch statement.
- OwningStmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(),
- move(LHS),
+ StmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(),
+ LHS.get(),
S->getEllipsisLoc(),
- move(RHS),
+ RHS.get(),
S->getColonLoc());
if (Case.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the statement following the case
- OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
if (SubStmt.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Attach the body to the case statement
- return getDerived().RebuildCaseStmtBody(move(Case), move(SubStmt));
+ return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) {
// Transform the statement following the default case
- OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
if (SubStmt.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Default statements are always rebuilt
return getDerived().RebuildDefaultStmt(S->getDefaultLoc(), S->getColonLoc(),
- move(SubStmt));
+ SubStmt.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
- OwningStmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
if (SubStmt.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// FIXME: Pass the real colon location in.
SourceLocation ColonLoc = SemaRef.PP.getLocForEndOfToken(S->getIdentLoc());
return getDerived().RebuildLabelStmt(S->getIdentLoc(), S->getID(), ColonLoc,
- move(SubStmt));
+ SubStmt.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the condition
- OwningExprResult Cond(SemaRef);
+ ExprResult Cond;
VarDecl *ConditionVar = 0;
if (S->getConditionVariable()) {
ConditionVar
@@ -3547,56 +3559,56 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
S->getConditionVariable()->getLocation(),
S->getConditionVariable()));
if (!ConditionVar)
- return SemaRef.StmtError();
+ return StmtError();
} else {
Cond = getDerived().TransformExpr(S->getCond());
if (Cond.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Convert the condition to a boolean value.
if (S->getCond()) {
- OwningExprResult CondE = getSema().ActOnBooleanCondition(0,
+ ExprResult CondE = getSema().ActOnBooleanCondition(0,
S->getIfLoc(),
- move(Cond));
+ Cond.get());
if (CondE.isInvalid())
- return getSema().StmtError();
+ return StmtError();
- Cond = move(CondE);
+ Cond = CondE.get();
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
- if (!S->getConditionVariable() && S->getCond() && !FullCond->get())
- return SemaRef.StmtError();
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+ return StmtError();
// Transform the "then" branch.
- OwningStmtResult Then = getDerived().TransformStmt(S->getThen());
+ StmtResult Then = getDerived().TransformStmt(S->getThen());
if (Then.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the "else" branch.
- OwningStmtResult Else = getDerived().TransformStmt(S->getElse());
+ StmtResult Else = getDerived().TransformStmt(S->getElse());
if (Else.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (!getDerived().AlwaysRebuild() &&
- FullCond->get() == S->getCond() &&
+ FullCond.get() == S->getCond() &&
ConditionVar == S->getConditionVariable() &&
Then.get() == S->getThen() &&
Else.get() == S->getElse())
return SemaRef.Owned(S->Retain());
return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
- move(Then),
- S->getElseLoc(), move(Else));
+ Then.get(),
+ S->getElseLoc(), Else.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
// Transform the condition.
- OwningExprResult Cond(SemaRef);
+ ExprResult Cond;
VarDecl *ConditionVar = 0;
if (S->getConditionVariable()) {
ConditionVar
@@ -3605,36 +3617,36 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
S->getConditionVariable()->getLocation(),
S->getConditionVariable()));
if (!ConditionVar)
- return SemaRef.StmtError();
+ return StmtError();
} else {
Cond = getDerived().TransformExpr(S->getCond());
if (Cond.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
}
// Rebuild the switch statement.
- OwningStmtResult Switch
- = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), move(Cond),
+ StmtResult Switch
+ = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond.get(),
ConditionVar);
if (Switch.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the body of the switch statement.
- OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Complete the switch statement.
- return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), move(Switch),
- move(Body));
+ return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), Switch.get(),
+ Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
// Transform the condition
- OwningExprResult Cond(SemaRef);
+ ExprResult Cond;
VarDecl *ConditionVar = 0;
if (S->getConditionVariable()) {
ConditionVar
@@ -3643,76 +3655,76 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
S->getConditionVariable()->getLocation(),
S->getConditionVariable()));
if (!ConditionVar)
- return SemaRef.StmtError();
+ return StmtError();
} else {
Cond = getDerived().TransformExpr(S->getCond());
if (Cond.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (S->getCond()) {
// Convert the condition to a boolean value.
- OwningExprResult CondE = getSema().ActOnBooleanCondition(0,
+ ExprResult CondE = getSema().ActOnBooleanCondition(0,
S->getWhileLoc(),
- move(Cond));
+ Cond.get());
if (CondE.isInvalid())
- return getSema().StmtError();
- Cond = move(CondE);
+ return StmtError();
+ Cond = CondE;
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
- if (!S->getConditionVariable() && S->getCond() && !FullCond->get())
- return SemaRef.StmtError();
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+ return StmtError();
// Transform the body
- OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (!getDerived().AlwaysRebuild() &&
- FullCond->get() == S->getCond() &&
+ FullCond.get() == S->getCond() &&
ConditionVar == S->getConditionVariable() &&
Body.get() == S->getBody())
- return SemaRef.Owned(S->Retain());
+ return Owned(S);
return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond,
- ConditionVar, move(Body));
+ ConditionVar, Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformDoStmt(DoStmt *S) {
// Transform the body
- OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the condition
- OwningExprResult Cond = getDerived().TransformExpr(S->getCond());
+ ExprResult Cond = getDerived().TransformExpr(S->getCond());
if (Cond.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (!getDerived().AlwaysRebuild() &&
Cond.get() == S->getCond() &&
Body.get() == S->getBody())
return SemaRef.Owned(S->Retain());
- return getDerived().RebuildDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(),
- /*FIXME:*/S->getWhileLoc(), move(Cond),
+ return getDerived().RebuildDoStmt(S->getDoLoc(), Body.get(), S->getWhileLoc(),
+ /*FIXME:*/S->getWhileLoc(), Cond.get(),
S->getRParenLoc());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
// Transform the initialization statement
- OwningStmtResult Init = getDerived().TransformStmt(S->getInit());
+ StmtResult Init = getDerived().TransformStmt(S->getInit());
if (Init.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the condition
- OwningExprResult Cond(SemaRef);
+ ExprResult Cond;
VarDecl *ConditionVar = 0;
if (S->getConditionVariable()) {
ConditionVar
@@ -3721,57 +3733,57 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
S->getConditionVariable()->getLocation(),
S->getConditionVariable()));
if (!ConditionVar)
- return SemaRef.StmtError();
+ return StmtError();
} else {
Cond = getDerived().TransformExpr(S->getCond());
if (Cond.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (S->getCond()) {
// Convert the condition to a boolean value.
- OwningExprResult CondE = getSema().ActOnBooleanCondition(0,
+ ExprResult CondE = getSema().ActOnBooleanCondition(0,
S->getForLoc(),
- move(Cond));
+ Cond.get());
if (CondE.isInvalid())
- return getSema().StmtError();
+ return StmtError();
- Cond = move(CondE);
+ Cond = CondE.get();
}
}
- Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond));
- if (!S->getConditionVariable() && S->getCond() && !FullCond->get())
- return SemaRef.StmtError();
+ Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take()));
+ if (!S->getConditionVariable() && S->getCond() && !FullCond.get())
+ return StmtError();
// Transform the increment
- OwningExprResult Inc = getDerived().TransformExpr(S->getInc());
+ ExprResult Inc = getDerived().TransformExpr(S->getInc());
if (Inc.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
- Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc));
- if (S->getInc() && !FullInc->get())
- return SemaRef.StmtError();
+ Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc.get()));
+ if (S->getInc() && !FullInc.get())
+ return StmtError();
// Transform the body
- OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (!getDerived().AlwaysRebuild() &&
Init.get() == S->getInit() &&
- FullCond->get() == S->getCond() &&
+ FullCond.get() == S->getCond() &&
Inc.get() == S->getInc() &&
Body.get() == S->getBody())
return SemaRef.Owned(S->Retain());
return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
- move(Init), FullCond, ConditionVar,
- FullInc, S->getRParenLoc(), move(Body));
+ Init.get(), FullCond, ConditionVar,
+ FullInc, S->getRParenLoc(), Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
// Goto statements must always be rebuilt, to resolve the label.
return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(),
@@ -3779,46 +3791,46 @@ TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) {
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) {
- OwningExprResult Target = getDerived().TransformExpr(S->getTarget());
+ ExprResult Target = getDerived().TransformExpr(S->getTarget());
if (Target.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (!getDerived().AlwaysRebuild() &&
Target.get() == S->getTarget())
return SemaRef.Owned(S->Retain());
return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(),
- move(Target));
+ Target.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) {
return SemaRef.Owned(S->Retain());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) {
return SemaRef.Owned(S->Retain());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) {
- Sema::OwningExprResult Result = getDerived().TransformExpr(S->getRetValue());
+ ExprResult Result = getDerived().TransformExpr(S->getRetValue());
if (Result.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// FIXME: We always rebuild the return statement because there is no way
// to tell whether the return type of the function has changed.
- return getDerived().RebuildReturnStmt(S->getReturnLoc(), move(Result));
+ return getDerived().RebuildReturnStmt(S->getReturnLoc(), Result.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
bool DeclChanged = false;
llvm::SmallVector<Decl *, 4> Decls;
@@ -3827,7 +3839,7 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
Decl *Transformed = getDerived().TransformDefinition((*D)->getLocation(),
*D);
if (!Transformed)
- return SemaRef.StmtError();
+ return StmtError();
if (Transformed != *D)
DeclChanged = true;
@@ -3843,22 +3855,22 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) {
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformSwitchCase(SwitchCase *S) {
assert(false && "SwitchCase is abstract and cannot be transformed");
return SemaRef.Owned(S->Retain());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
- ASTOwningVector<&ActionBase::DeleteExpr> Constraints(getSema());
- ASTOwningVector<&ActionBase::DeleteExpr> Exprs(getSema());
+ ASTOwningVector<Expr*> Constraints(getSema());
+ ASTOwningVector<Expr*> Exprs(getSema());
llvm::SmallVector<IdentifierInfo *, 4> Names;
- OwningExprResult AsmString(SemaRef);
- ASTOwningVector<&ActionBase::DeleteExpr> Clobbers(getSema());
+ ExprResult AsmString;
+ ASTOwningVector<Expr*> Clobbers(getSema());
bool ExprsChanged = false;
@@ -3871,13 +3883,13 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
// Transform the output expr.
Expr *OutputExpr = S->getOutputExpr(I);
- OwningExprResult Result = getDerived().TransformExpr(OutputExpr);
+ ExprResult Result = getDerived().TransformExpr(OutputExpr);
if (Result.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
ExprsChanged |= Result.get() != OutputExpr;
- Exprs.push_back(Result.takeAs<Expr>());
+ Exprs.push_back(Result.get());
}
// Go through the inputs.
@@ -3889,13 +3901,13 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
// Transform the input expr.
Expr *InputExpr = S->getInputExpr(I);
- OwningExprResult Result = getDerived().TransformExpr(InputExpr);
+ ExprResult Result = getDerived().TransformExpr(InputExpr);
if (Result.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
ExprsChanged |= Result.get() != InputExpr;
- Exprs.push_back(Result.takeAs<Expr>());
+ Exprs.push_back(Result.get());
}
if (!getDerived().AlwaysRebuild() && !ExprsChanged)
@@ -3916,7 +3928,7 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
Names.data(),
move_arg(Constraints),
move_arg(Exprs),
- move(AsmString),
+ AsmString.get(),
move_arg(Clobbers),
S->getRParenLoc(),
S->isMSAsm());
@@ -3924,31 +3936,31 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) {
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
// Transform the body of the @try.
- OwningStmtResult TryBody = getDerived().TransformStmt(S->getTryBody());
+ StmtResult TryBody = getDerived().TransformStmt(S->getTryBody());
if (TryBody.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the @catch statements (if present).
bool AnyCatchChanged = false;
- ASTOwningVector<&ActionBase::DeleteStmt> CatchStmts(SemaRef);
+ ASTOwningVector<Stmt*> CatchStmts(SemaRef);
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
- OwningStmtResult Catch = getDerived().TransformStmt(S->getCatchStmt(I));
+ StmtResult Catch = getDerived().TransformStmt(S->getCatchStmt(I));
if (Catch.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
if (Catch.get() != S->getCatchStmt(I))
AnyCatchChanged = true;
CatchStmts.push_back(Catch.release());
}
// Transform the @finally statement (if present).
- OwningStmtResult Finally(SemaRef);
+ StmtResult Finally;
if (S->getFinallyStmt()) {
Finally = getDerived().TransformStmt(S->getFinallyStmt());
if (Finally.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
}
// If nothing changed, just retain this statement.
@@ -3959,12 +3971,12 @@ TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) {
return SemaRef.Owned(S->Retain());
// Build a new statement.
- return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), move(TryBody),
- move_arg(CatchStmts), move(Finally));
+ return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), TryBody.get(),
+ move_arg(CatchStmts), Finally.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
// Transform the @catch parameter, if there is one.
VarDecl *Var = 0;
@@ -3973,7 +3985,7 @@ TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
if (FromVar->getTypeSourceInfo()) {
TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo());
if (!TSInfo)
- return SemaRef.StmtError();
+ return StmtError();
}
QualType T;
@@ -3982,30 +3994,30 @@ TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) {
else {
T = getDerived().TransformType(FromVar->getType());
if (T.isNull())
- return SemaRef.StmtError();
+ return StmtError();
}
Var = getDerived().RebuildObjCExceptionDecl(FromVar, TSInfo, T);
if (!Var)
- return SemaRef.StmtError();
+ return StmtError();
}
- OwningStmtResult Body = getDerived().TransformStmt(S->getCatchBody());
+ StmtResult Body = getDerived().TransformStmt(S->getCatchBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
return getDerived().RebuildObjCAtCatchStmt(S->getAtCatchLoc(),
S->getRParenLoc(),
- Var, move(Body));
+ Var, Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
// Transform the body.
- OwningStmtResult Body = getDerived().TransformStmt(S->getFinallyBody());
+ StmtResult Body = getDerived().TransformStmt(S->getFinallyBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// If nothing changed, just retain this statement.
if (!getDerived().AlwaysRebuild() &&
@@ -4014,39 +4026,39 @@ TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
// Build a new statement.
return getDerived().RebuildObjCAtFinallyStmt(S->getAtFinallyLoc(),
- move(Body));
+ Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) {
- OwningExprResult Operand(SemaRef);
+ ExprResult Operand;
if (S->getThrowExpr()) {
Operand = getDerived().TransformExpr(S->getThrowExpr());
if (Operand.isInvalid())
- return getSema().StmtError();
+ return StmtError();
}
if (!getDerived().AlwaysRebuild() &&
Operand.get() == S->getThrowExpr())
return getSema().Owned(S->Retain());
- return getDerived().RebuildObjCAtThrowStmt(S->getThrowLoc(), move(Operand));
+ return getDerived().RebuildObjCAtThrowStmt(S->getThrowLoc(), Operand.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformObjCAtSynchronizedStmt(
ObjCAtSynchronizedStmt *S) {
// Transform the object we are locking.
- OwningExprResult Object = getDerived().TransformExpr(S->getSynchExpr());
+ ExprResult Object = getDerived().TransformExpr(S->getSynchExpr());
if (Object.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the body.
- OwningStmtResult Body = getDerived().TransformStmt(S->getSynchBody());
+ StmtResult Body = getDerived().TransformStmt(S->getSynchBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// If nothing change, just retain the current statement.
if (!getDerived().AlwaysRebuild() &&
@@ -4056,27 +4068,27 @@ TreeTransform<Derived>::TransformObjCAtSynchronizedStmt(
// Build a new statement.
return getDerived().RebuildObjCAtSynchronizedStmt(S->getAtSynchronizedLoc(),
- move(Object), move(Body));
+ Object.get(), Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformObjCForCollectionStmt(
ObjCForCollectionStmt *S) {
// Transform the element statement.
- OwningStmtResult Element = getDerived().TransformStmt(S->getElement());
+ StmtResult Element = getDerived().TransformStmt(S->getElement());
if (Element.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the collection expression.
- OwningExprResult Collection = getDerived().TransformExpr(S->getCollection());
+ ExprResult Collection = getDerived().TransformExpr(S->getCollection());
if (Collection.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the body.
- OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+ StmtResult Body = getDerived().TransformStmt(S->getBody());
if (Body.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// If nothing changed, just retain this statement.
if (!getDerived().AlwaysRebuild() &&
@@ -4088,15 +4100,15 @@ TreeTransform<Derived>::TransformObjCForCollectionStmt(
// Build a new statement.
return getDerived().RebuildObjCForCollectionStmt(S->getForLoc(),
/*FIXME:*/S->getForLoc(),
- move(Element),
- move(Collection),
+ Element.get(),
+ Collection.get(),
S->getRParenLoc(),
- move(Body));
+ Body.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
// Transform the exception declaration, if any.
VarDecl *Var = 0;
@@ -4107,7 +4119,7 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
QualType T = getDerived().TransformType(ExceptionDecl->getType());
if (T.isNull())
- return SemaRef.StmtError();
+ return StmtError();
Var = getDerived().RebuildExceptionDecl(ExceptionDecl,
T,
@@ -4116,20 +4128,14 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
ExceptionDecl->getLocation(),
/*FIXME: Inaccurate*/
SourceRange(ExceptionDecl->getLocation()));
- if (!Var || Var->isInvalidDecl()) {
- if (Var)
- Var->Destroy(SemaRef.Context);
- return SemaRef.StmtError();
- }
+ if (!Var || Var->isInvalidDecl())
+ return StmtError();
}
// Transform the actual exception handler.
- OwningStmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock());
- if (Handler.isInvalid()) {
- if (Var)
- Var->Destroy(SemaRef.Context);
- return SemaRef.StmtError();
- }
+ StmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock());
+ if (Handler.isInvalid())
+ return StmtError();
if (!getDerived().AlwaysRebuild() &&
!Var &&
@@ -4138,26 +4144,26 @@ TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) {
return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(),
Var,
- move(Handler));
+ Handler.get());
}
template<typename Derived>
-Sema::OwningStmtResult
+StmtResult
TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
// Transform the try block itself.
- OwningStmtResult TryBlock
+ StmtResult TryBlock
= getDerived().TransformCompoundStmt(S->getTryBlock());
if (TryBlock.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
// Transform the handlers.
bool HandlerChanged = false;
- ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef);
+ ASTOwningVector<Stmt*> Handlers(SemaRef);
for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
- OwningStmtResult Handler
+ StmtResult Handler
= getDerived().TransformCXXCatchStmt(S->getHandler(I));
if (Handler.isInvalid())
- return SemaRef.StmtError();
+ return StmtError();
HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I);
Handlers.push_back(Handler.takeAs<Stmt>());
@@ -4168,7 +4174,7 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
!HandlerChanged)
return SemaRef.Owned(S->Retain());
- return getDerived().RebuildCXXTryStmt(S->getTryLoc(), move(TryBlock),
+ return getDerived().RebuildCXXTryStmt(S->getTryLoc(), TryBlock.get(),
move_arg(Handlers));
}
@@ -4176,32 +4182,40 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) {
// Expression transformation
//===----------------------------------------------------------------------===//
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
NestedNameSpecifier *Qualifier = 0;
if (E->getQualifier()) {
Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange());
if (!Qualifier)
- return SemaRef.ExprError();
+ return ExprError();
}
ValueDecl *ND
= cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
E->getDecl()));
if (!ND)
- return SemaRef.ExprError();
+ return ExprError();
- if (!getDerived().AlwaysRebuild() &&
+ DeclarationNameInfo NameInfo = E->getNameInfo();
+ if (NameInfo.getName()) {
+ NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo);
+ if (!NameInfo.getName())
+ return ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
Qualifier == E->getQualifier() &&
ND == E->getDecl() &&
- !E->hasExplicitTemplateArgumentList()) {
+ NameInfo.getName() == E->getDecl()->getDeclName() &&
+ !E->hasExplicitTemplateArgs()) {
// Mark it referenced in the new context regardless.
// FIXME: this is a bit instantiation-specific.
@@ -4211,88 +4225,88 @@ TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) {
}
TemplateArgumentListInfo TransArgs, *TemplateArgs = 0;
- if (E->hasExplicitTemplateArgumentList()) {
+ if (E->hasExplicitTemplateArgs()) {
TemplateArgs = &TransArgs;
TransArgs.setLAngleLoc(E->getLAngleLoc());
TransArgs.setRAngleLoc(E->getRAngleLoc());
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
- return SemaRef.ExprError();
+ return ExprError();
TransArgs.addArgument(Loc);
}
}
return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(),
- ND, E->getLocation(), TemplateArgs);
+ ND, NameInfo, TemplateArgs);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildParenExpr(move(SubExpr), E->getLParen(),
+ return getDerived().RebuildParenExpr(SubExpr.get(), E->getLParen(),
E->getRParen());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
return getDerived().RebuildUnaryOperator(E->getOperatorLoc(),
E->getOpcode(),
- move(SubExpr));
+ SubExpr.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// Transform the type.
TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo());
if (!Type)
- return getSema().ExprError();
+ return ExprError();
// Transform all of the components into components similar to what the
// parser uses.
@@ -4301,7 +4315,7 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
// the fields again. However, __builtin_offsetof is rare enough in
// template code that we don't care.
bool ExprChanged = false;
- typedef Action::OffsetOfComponent Component;
+ typedef Sema::OffsetOfComponent Component;
typedef OffsetOfExpr::OffsetOfNode Node;
llvm::SmallVector<Component, 4> Components;
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
@@ -4313,13 +4327,13 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
switch (ON.getKind()) {
case Node::Array: {
Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex());
- OwningExprResult Index = getDerived().TransformExpr(FromIndex);
+ ExprResult Index = getDerived().TransformExpr(FromIndex);
if (Index.isInvalid())
- return getSema().ExprError();
+ return ExprError();
ExprChanged = ExprChanged || Index.get() != FromIndex;
Comp.isBrackets = true;
- Comp.U.E = Index.takeAs<Expr>(); // FIXME: leaked
+ Comp.U.E = Index.get();
break;
}
@@ -4353,14 +4367,14 @@ TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (E->isArgumentType()) {
TypeSourceInfo *OldT = E->getArgumentTypeInfo();
TypeSourceInfo *NewT = getDerived().TransformType(OldT);
if (!NewT)
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() && OldT == NewT)
return SemaRef.Owned(E->Retain());
@@ -4370,36 +4384,36 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
E->getSourceRange());
}
- Sema::OwningExprResult SubExpr(SemaRef);
+ ExprResult SubExpr;
{
// C++0x [expr.sizeof]p1:
// The operand is either an expression, which is an unevaluated operand
// [...]
- EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr())
return SemaRef.Owned(E->Retain());
}
- return getDerived().RebuildSizeOfAlignOf(move(SubExpr), E->getOperatorLoc(),
+ return getDerived().RebuildSizeOfAlignOf(SubExpr.get(), E->getOperatorLoc(),
E->isSizeOf(),
E->getSourceRange());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
- OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
if (RHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
@@ -4407,35 +4421,35 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
RHS.get() == E->getRHS())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildArraySubscriptExpr(move(LHS),
+ return getDerived().RebuildArraySubscriptExpr(LHS.get(),
/*FIXME:*/E->getLHS()->getLocStart(),
- move(RHS),
+ RHS.get(),
E->getRBracketLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
// Transform the callee.
- OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
+ ExprResult Callee = getDerived().TransformExpr(E->getCallee());
if (Callee.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// Transform arguments.
bool ArgChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+ ASTOwningVector<Expr*> Args(SemaRef);
llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
- OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+ ExprResult Arg = getDerived().TransformExpr(E->getArg(I));
if (Arg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// FIXME: Wrong source location information for the ','.
FakeCommaLocs.push_back(
SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd()));
ArgChanged = ArgChanged || Arg.get() != E->getArg(I);
- Args.push_back(Arg.takeAs<Expr>());
+ Args.push_back(Arg.get());
}
if (!getDerived().AlwaysRebuild() &&
@@ -4446,18 +4460,18 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
// FIXME: Wrong source location information for the '('.
SourceLocation FakeLParenLoc
= ((Expr *)Callee.get())->getSourceRange().getBegin();
- return getDerived().RebuildCallExpr(move(Callee), FakeLParenLoc,
+ return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc,
move_arg(Args),
FakeCommaLocs.data(),
E->getRParenLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
NestedNameSpecifier *Qualifier = 0;
if (E->hasQualifier()) {
@@ -4465,14 +4479,14 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange());
if (Qualifier == 0)
- return SemaRef.ExprError();
+ return ExprError();
}
ValueDecl *Member
= cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getMemberLoc(),
E->getMemberDecl()));
if (!Member)
- return SemaRef.ExprError();
+ return ExprError();
NamedDecl *FoundDecl = E->getFoundDecl();
if (FoundDecl == E->getMemberDecl()) {
@@ -4481,7 +4495,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
FoundDecl = cast_or_null<NamedDecl>(
getDerived().TransformDecl(E->getMemberLoc(), FoundDecl));
if (!FoundDecl)
- return SemaRef.ExprError();
+ return ExprError();
}
if (!getDerived().AlwaysRebuild() &&
@@ -4489,7 +4503,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
Qualifier == E->getQualifier() &&
Member == E->getMemberDecl() &&
FoundDecl == E->getFoundDecl() &&
- !E->hasExplicitTemplateArgumentList()) {
+ !E->hasExplicitTemplateArgs()) {
// Mark it referenced in the new context regardless.
// FIXME: this is a bit instantiation-specific.
@@ -4498,13 +4512,13 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
}
TemplateArgumentListInfo TransArgs;
- if (E->hasExplicitTemplateArgumentList()) {
+ if (E->hasExplicitTemplateArgs()) {
TransArgs.setLAngleLoc(E->getLAngleLoc());
TransArgs.setRAngleLoc(E->getRAngleLoc());
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
- return SemaRef.ExprError();
+ return ExprError();
TransArgs.addArgument(Loc);
}
}
@@ -4519,28 +4533,28 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
// nested-name-qualifier (and therefore could do the lookup).
NamedDecl *FirstQualifierInScope = 0;
- return getDerived().RebuildMemberExpr(move(Base), FakeOperatorLoc,
+ return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
E->isArrow(),
Qualifier,
E->getQualifierRange(),
- E->getMemberLoc(),
+ E->getMemberNameInfo(),
Member,
FoundDecl,
- (E->hasExplicitTemplateArgumentList()
+ (E->hasExplicitTemplateArgs()
? &TransArgs : 0),
FirstQualifierInScope);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
- OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
if (RHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
LHS.get() == E->getLHS() &&
@@ -4548,30 +4562,30 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) {
return SemaRef.Owned(E->Retain());
return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(),
- move(LHS), move(RHS));
+ LHS.get(), RHS.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCompoundAssignOperator(
CompoundAssignOperator *E) {
return getDerived().TransformBinaryOperator(E);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
- OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
+ ExprResult Cond = getDerived().TransformExpr(E->getCond());
if (Cond.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
if (RHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
Cond.get() == E->getCond() &&
@@ -4579,15 +4593,15 @@ TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) {
RHS.get() == E->getRHS())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildConditionalOperator(move(Cond),
+ return getDerived().RebuildConditionalOperator(Cond.get(),
E->getQuestionLoc(),
- move(LHS),
+ LHS.get(),
E->getColonLoc(),
- move(RHS));
+ RHS.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
// Implicit casts are eliminated during transformation, since they
// will be recomputed by semantic analysis after transformation.
@@ -4595,7 +4609,7 @@ TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
TypeSourceInfo *OldT;
TypeSourceInfo *NewT;
@@ -4608,13 +4622,13 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
OldT = E->getTypeInfoAsWritten();
NewT = getDerived().TransformType(OldT);
if (!NewT)
- return SemaRef.ExprError();
+ return ExprError();
}
- OwningExprResult SubExpr
+ ExprResult SubExpr
= getDerived().TransformExpr(E->getSubExprAsWritten());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
OldT == NewT &&
@@ -4624,20 +4638,20 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) {
return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(),
NewT,
E->getRParenLoc(),
- move(SubExpr));
+ SubExpr.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
TypeSourceInfo *OldT = E->getTypeSourceInfo();
TypeSourceInfo *NewT = getDerived().TransformType(OldT);
if (!NewT)
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult Init = getDerived().TransformExpr(E->getInitializer());
+ ExprResult Init = getDerived().TransformExpr(E->getInitializer());
if (Init.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
OldT == NewT &&
@@ -4650,15 +4664,15 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) {
return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT,
/*FIXME:*/E->getInitializer()->getLocEnd(),
- move(Init));
+ Init.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
@@ -4667,24 +4681,24 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) {
// FIXME: Bad source location
SourceLocation FakeOperatorLoc
= SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd());
- return getDerived().RebuildExtVectorElementExpr(move(Base), FakeOperatorLoc,
+ return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc,
E->getAccessorLoc(),
E->getAccessor());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
bool InitChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
+ ASTOwningVector<Expr*, 4> Inits(SemaRef);
for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) {
- OwningExprResult Init = getDerived().TransformExpr(E->getInit(I));
+ ExprResult Init = getDerived().TransformExpr(E->getInit(I));
if (Init.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
InitChanged = InitChanged || Init.get() != E->getInit(I);
- Inits.push_back(Init.takeAs<Expr>());
+ Inits.push_back(Init.get());
}
if (!getDerived().AlwaysRebuild() && !InitChanged)
@@ -4695,17 +4709,17 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
Designation Desig;
// transform the initializer value
- OwningExprResult Init = getDerived().TransformExpr(E->getInit());
+ ExprResult Init = getDerived().TransformExpr(E->getInit());
if (Init.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// transform the designators.
- ASTOwningVector<&ActionBase::DeleteExpr, 4> ArrayExprs(SemaRef);
+ ASTOwningVector<Expr*, 4> ArrayExprs(SemaRef);
bool ExprChanged = false;
for (DesignatedInitExpr::designators_iterator D = E->designators_begin(),
DEnd = E->designators_end();
@@ -4718,9 +4732,9 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
}
if (D->isArrayDesignator()) {
- OwningExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D));
+ ExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D));
if (Index.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
Desig.AddDesignator(Designator::getArray(Index.get(),
D->getLBracketLoc()));
@@ -4731,14 +4745,14 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
}
assert(D->isArrayRangeDesignator() && "New kind of designator?");
- OwningExprResult Start
+ ExprResult Start
= getDerived().TransformExpr(E->getArrayRangeStart(*D));
if (Start.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D));
+ ExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D));
if (End.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
Desig.AddDesignator(Designator::getArrayRange(Start.get(),
End.get(),
@@ -4759,11 +4773,11 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) {
return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs),
E->getEqualOrColonLoc(),
- E->usesGNUSyntax(), move(Init));
+ E->usesGNUSyntax(), Init.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformImplicitValueInitExpr(
ImplicitValueInitExpr *E) {
TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
@@ -4772,7 +4786,7 @@ TreeTransform<Derived>::TransformImplicitValueInitExpr(
// need to transform the type?
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
T == E->getType())
@@ -4782,44 +4796,37 @@ TreeTransform<Derived>::TransformImplicitValueInitExpr(
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) {
- // FIXME: Do we want the type as written?
- QualType T;
+ TypeSourceInfo *TInfo = getDerived().TransformType(E->getWrittenTypeInfo());
+ if (!TInfo)
+ return ExprError();
- {
- // FIXME: Source location isn't quite accurate.
- TemporaryBase Rebase(*this, E->getBuiltinLoc(), DeclarationName());
- T = getDerived().TransformType(E->getType());
- if (T.isNull())
- return SemaRef.ExprError();
- }
-
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
- T == E->getType() &&
+ TInfo == E->getWrittenTypeInfo() &&
SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), move(SubExpr),
- T, E->getRParenLoc());
+ return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), SubExpr.get(),
+ TInfo, E->getRParenLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
bool ArgumentChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef);
+ ASTOwningVector<Expr*, 4> Inits(SemaRef);
for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) {
- OwningExprResult Init = getDerived().TransformExpr(E->getExpr(I));
+ ExprResult Init = getDerived().TransformExpr(E->getExpr(I));
if (Init.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || Init.get() != E->getExpr(I);
- Inits.push_back(Init.takeAs<Expr>());
+ Inits.push_back(Init.get());
}
return getDerived().RebuildParenListExpr(E->getLParenLoc(),
@@ -4833,69 +4840,67 @@ TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) {
/// rebuilds the expression, so that the label identifier can be resolved to
/// the corresponding label statement by semantic analysis.
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) {
return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(),
E->getLabel());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) {
- OwningStmtResult SubStmt
+ StmtResult SubStmt
= getDerived().TransformCompoundStmt(E->getSubStmt(), true);
if (SubStmt.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
SubStmt.get() == E->getSubStmt())
return SemaRef.Owned(E->Retain());
return getDerived().RebuildStmtExpr(E->getLParenLoc(),
- move(SubStmt),
+ SubStmt.get(),
E->getRParenLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) {
- QualType T1, T2;
- {
- // FIXME: Source location isn't quite accurate.
- TemporaryBase Rebase(*this, E->getBuiltinLoc(), DeclarationName());
-
- T1 = getDerived().TransformType(E->getArgType1());
- if (T1.isNull())
- return SemaRef.ExprError();
+ TypeSourceInfo *TInfo1;
+ TypeSourceInfo *TInfo2;
+
+ TInfo1 = getDerived().TransformType(E->getArgTInfo1());
+ if (!TInfo1)
+ return ExprError();
- T2 = getDerived().TransformType(E->getArgType2());
- if (T2.isNull())
- return SemaRef.ExprError();
- }
+ TInfo2 = getDerived().TransformType(E->getArgTInfo2());
+ if (!TInfo2)
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
- T1 == E->getArgType1() &&
- T2 == E->getArgType2())
+ TInfo1 == E->getArgTInfo1() &&
+ TInfo2 == E->getArgTInfo2())
return SemaRef.Owned(E->Retain());
return getDerived().RebuildTypesCompatibleExpr(E->getBuiltinLoc(),
- T1, T2, E->getRParenLoc());
+ TInfo1, TInfo2,
+ E->getRParenLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
- OwningExprResult Cond = getDerived().TransformExpr(E->getCond());
+ ExprResult Cond = getDerived().TransformExpr(E->getCond());
if (Cond.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult LHS = getDerived().TransformExpr(E->getLHS());
+ ExprResult LHS = getDerived().TransformExpr(E->getLHS());
if (LHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult RHS = getDerived().TransformExpr(E->getRHS());
+ ExprResult RHS = getDerived().TransformExpr(E->getRHS());
if (RHS.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
Cond.get() == E->getCond() &&
@@ -4904,18 +4909,18 @@ TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) {
return SemaRef.Owned(E->Retain());
return getDerived().RebuildChooseExpr(E->getBuiltinLoc(),
- move(Cond), move(LHS), move(RHS),
+ Cond.get(), LHS.get(), RHS.get(),
E->getRParenLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
switch (E->getOperator()) {
case OO_New:
@@ -4923,16 +4928,16 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
case OO_Array_New:
case OO_Array_Delete:
llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr");
- return SemaRef.ExprError();
+ return ExprError();
case OO_Call: {
// This is a call to an object's operator().
assert(E->getNumArgs() >= 1 && "Object call is missing arguments");
// Transform the object itself.
- OwningExprResult Object = getDerived().TransformExpr(E->getArg(0));
+ ExprResult Object = getDerived().TransformExpr(E->getArg(0));
if (Object.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// FIXME: Poor location information
SourceLocation FakeLParenLoc
@@ -4940,15 +4945,15 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
static_cast<Expr *>(Object.get())->getLocEnd());
// Transform the call arguments.
- ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+ ASTOwningVector<Expr*> Args(SemaRef);
llvm::SmallVector<SourceLocation, 4> FakeCommaLocs;
for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) {
if (getDerived().DropCallArgument(E->getArg(I)))
break;
- OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+ ExprResult Arg = getDerived().TransformExpr(E->getArg(I));
if (Arg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// FIXME: Poor source location information.
SourceLocation FakeCommaLoc
@@ -4958,7 +4963,7 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
Args.push_back(Arg.release());
}
- return getDerived().RebuildCallExpr(move(Object), FakeLParenLoc,
+ return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc,
move_arg(Args),
FakeCommaLocs.data(),
E->getLocEnd());
@@ -4974,27 +4979,27 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
case OO_Conditional:
llvm_unreachable("conditional operator is not actually overloadable");
- return SemaRef.ExprError();
+ return ExprError();
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("not an overloaded operator?");
- return SemaRef.ExprError();
+ return ExprError();
}
- OwningExprResult Callee = getDerived().TransformExpr(E->getCallee());
+ ExprResult Callee = getDerived().TransformExpr(E->getCallee());
if (Callee.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult First = getDerived().TransformExpr(E->getArg(0));
+ ExprResult First = getDerived().TransformExpr(E->getArg(0));
if (First.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- OwningExprResult Second(SemaRef);
+ ExprResult Second;
if (E->getNumArgs() == 2) {
Second = getDerived().TransformExpr(E->getArg(1));
if (Second.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
}
if (!getDerived().AlwaysRebuild() &&
@@ -5005,19 +5010,19 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(),
E->getOperatorLoc(),
- move(Callee),
- move(First),
- move(Second));
+ Callee.get(),
+ First.get(),
+ Second.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
return getDerived().TransformCallExpr(E);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
TypeSourceInfo *OldT;
TypeSourceInfo *NewT;
@@ -5030,13 +5035,13 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
OldT = E->getTypeInfoAsWritten();
NewT = getDerived().TransformType(OldT);
if (!NewT)
- return SemaRef.ExprError();
+ return ExprError();
}
- OwningExprResult SubExpr
+ ExprResult SubExpr
= getDerived().TransformExpr(E->getSubExprAsWritten());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
OldT == NewT &&
@@ -5056,37 +5061,37 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) {
NewT,
FakeRAngleLoc,
FakeRAngleLoc,
- move(SubExpr),
+ SubExpr.get(),
FakeRParenLoc);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) {
return getDerived().TransformCXXNamedCastExpr(E);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
return getDerived().TransformCXXNamedCastExpr(E);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXReinterpretCastExpr(
CXXReinterpretCastExpr *E) {
return getDerived().TransformCXXNamedCastExpr(E);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) {
return getDerived().TransformCXXNamedCastExpr(E);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
CXXFunctionalCastExpr *E) {
TypeSourceInfo *OldT;
@@ -5097,13 +5102,13 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
OldT = E->getTypeInfoAsWritten();
NewT = getDerived().TransformType(OldT);
if (!NewT)
- return SemaRef.ExprError();
+ return ExprError();
}
- OwningExprResult SubExpr
+ ExprResult SubExpr
= getDerived().TransformExpr(E->getSubExprAsWritten());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
OldT == NewT &&
@@ -5115,18 +5120,18 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
/*FIXME:*/SourceRange(E->getTypeBeginLoc()),
NewT,
/*FIXME:*/E->getSubExpr()->getLocStart(),
- move(SubExpr),
+ SubExpr.get(),
E->getRParenLoc());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
if (E->isTypeOperand()) {
TypeSourceInfo *TInfo
= getDerived().TransformType(E->getTypeOperandSourceInfo());
if (!TInfo)
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
TInfo == E->getTypeOperandSourceInfo())
@@ -5142,11 +5147,11 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
// after we perform semantic analysis, so the expression is potentially
// potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Action::PotentiallyPotentiallyEvaluated);
+ Sema::PotentiallyPotentiallyEvaluated);
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
+ ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
SubExpr.get() == E->getExprOperand())
@@ -5154,31 +5159,31 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
return getDerived().RebuildCXXTypeidExpr(E->getType(),
E->getLocStart(),
- move(SubExpr),
+ SubExpr.get(),
E->getLocEnd());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr(
CXXNullPtrLiteralExpr *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
T == E->getType())
@@ -5188,27 +5193,27 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
+ ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr());
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
SubExpr.get() == E->getSubExpr())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), move(SubExpr));
+ return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), SubExpr.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
ParmVarDecl *Param
= cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getLocStart(),
E->getParam()));
if (!Param)
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
Param == E->getParam())
@@ -5218,13 +5223,13 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
T == E->getType())
@@ -5237,40 +5242,40 @@ TreeTransform<Derived>::TransformCXXScalarValueInitExpr(CXXScalarValueInitExpr *
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
// Transform the type that we're allocating
TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName());
QualType AllocType = getDerived().TransformType(E->getAllocatedType());
if (AllocType.isNull())
- return SemaRef.ExprError();
+ return ExprError();
// Transform the size of the array we're allocating (if any).
- OwningExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
+ ExprResult ArraySize = getDerived().TransformExpr(E->getArraySize());
if (ArraySize.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// Transform the placement arguments (if any).
bool ArgumentChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> PlacementArgs(SemaRef);
+ ASTOwningVector<Expr*> PlacementArgs(SemaRef);
for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {
- OwningExprResult Arg = getDerived().TransformExpr(E->getPlacementArg(I));
+ ExprResult Arg = getDerived().TransformExpr(E->getPlacementArg(I));
if (Arg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || Arg.get() != E->getPlacementArg(I);
PlacementArgs.push_back(Arg.take());
}
// transform the constructor arguments (if any).
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef);
+ ASTOwningVector<Expr*> ConstructorArgs(SemaRef);
for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) {
if (getDerived().DropCallArgument(E->getConstructorArg(I)))
break;
- OwningExprResult Arg = getDerived().TransformExpr(E->getConstructorArg(I));
+ ExprResult Arg = getDerived().TransformExpr(E->getConstructorArg(I));
if (Arg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || Arg.get() != E->getConstructorArg(I);
ConstructorArgs.push_back(Arg.take());
@@ -5283,7 +5288,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
getDerived().TransformDecl(E->getLocStart(),
E->getConstructor()));
if (!Constructor)
- return SemaRef.ExprError();
+ return ExprError();
}
FunctionDecl *OperatorNew = 0;
@@ -5292,7 +5297,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
getDerived().TransformDecl(E->getLocStart(),
E->getOperatorNew()));
if (!OperatorNew)
- return SemaRef.ExprError();
+ return ExprError();
}
FunctionDecl *OperatorDelete = 0;
@@ -5301,7 +5306,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
getDerived().TransformDecl(E->getLocStart(),
E->getOperatorDelete()));
if (!OperatorDelete)
- return SemaRef.ExprError();
+ return ExprError();
}
if (!getDerived().AlwaysRebuild() &&
@@ -5334,10 +5339,10 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
} else if (const ConstantArrayType *ConsArrayT
= dyn_cast<ConstantArrayType>(ArrayT)) {
ArraySize
- = SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
- ConsArrayT->getSize(),
- SemaRef.Context.getSizeType(),
- /*FIXME:*/E->getLocStart()));
+ = SemaRef.Owned(IntegerLiteral::Create(SemaRef.Context,
+ ConsArrayT->getSize(),
+ SemaRef.Context.getSizeType(),
+ /*FIXME:*/E->getLocStart()));
AllocType = ConsArrayT->getElementType();
} else if (const DependentSizedArrayType *DepArrayT
= dyn_cast<DependentSizedArrayType>(ArrayT)) {
@@ -5356,18 +5361,18 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) {
AllocType,
/*FIXME:*/E->getLocStart(),
/*FIXME:*/SourceRange(),
- move(ArraySize),
+ ArraySize.get(),
/*FIXME:*/E->getLocStart(),
move_arg(ConstructorArgs),
E->getLocEnd());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
- OwningExprResult Operand = getDerived().TransformExpr(E->getArgument());
+ ExprResult Operand = getDerived().TransformExpr(E->getArgument());
if (Operand.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// Transform the delete operator, if known.
FunctionDecl *OperatorDelete = 0;
@@ -5376,7 +5381,7 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
getDerived().TransformDecl(E->getLocStart(),
E->getOperatorDelete()));
if (!OperatorDelete)
- return SemaRef.ExprError();
+ return ExprError();
}
if (!getDerived().AlwaysRebuild() &&
@@ -5392,41 +5397,41 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
return getDerived().RebuildCXXDeleteExpr(E->getLocStart(),
E->isGlobalDelete(),
E->isArrayForm(),
- move(Operand));
+ Operand.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
CXXPseudoDestructorExpr *E) {
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- Sema::TypeTy *ObjectTypePtr = 0;
+ ParsedType ObjectTypePtr;
bool MayBePseudoDestructor = false;
- Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
+ Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
ObjectTypePtr,
MayBePseudoDestructor);
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+ QualType ObjectType = ObjectTypePtr.get();
NestedNameSpecifier *Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
ObjectType);
if (E->getQualifier() && !Qualifier)
- return SemaRef.ExprError();
+ return ExprError();
PseudoDestructorTypeStorage Destroyed;
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformType(E->getDestroyedTypeInfo(), ObjectType);
if (!DestroyedTypeInfo)
- return SemaRef.ExprError();
+ return ExprError();
Destroyed = DestroyedTypeInfo;
} else if (ObjectType->isDependentType()) {
// We aren't likely to be able to resolve the identifier down to a type
@@ -5441,14 +5446,14 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
SS.setRange(E->getQualifierRange());
}
- Sema::TypeTy *T = SemaRef.getDestructorName(E->getTildeLoc(),
+ ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(),
*E->getDestroyedTypeIdentifier(),
E->getDestroyedTypeLoc(),
/*Scope=*/0,
SS, ObjectTypePtr,
false);
if (!T)
- return SemaRef.ExprError();
+ return ExprError();
Destroyed
= SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T),
@@ -5460,10 +5465,10 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo(),
ObjectType);
if (!ScopeTypeInfo)
- return SemaRef.ExprError();
+ return ExprError();
}
- return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
+ return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(),
E->getOperatorLoc(),
E->isArrow(),
Qualifier,
@@ -5475,7 +5480,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformUnresolvedLookupExpr(
UnresolvedLookupExpr *Old) {
TemporaryBase Rebase(*this, Old->getNameLoc(), DeclarationName());
@@ -5495,7 +5500,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
if (isa<UsingShadowDecl>(*I))
continue;
else
- return SemaRef.ExprError();
+ return ExprError();
}
// Expand using declarations.
@@ -5521,7 +5526,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
Qualifier = getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
Old->getQualifierRange());
if (!Qualifier)
- return SemaRef.ExprError();
+ return ExprError();
SS.setScopeRep(Qualifier);
SS.setRange(Old->getQualifierRange());
@@ -5533,7 +5538,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
Old->getNameLoc(),
Old->getNamingClass()));
if (!NamingClass)
- return SemaRef.ExprError();
+ return ExprError();
R.setNamingClass(NamingClass);
}
@@ -5548,7 +5553,7 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I], Loc))
- return SemaRef.ExprError();
+ return ExprError();
TransArgs.addArgument(Loc);
}
@@ -5557,13 +5562,13 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName());
QualType T = getDerived().TransformType(E->getQueriedType());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
T == E->getQueriedType())
@@ -5581,29 +5586,31 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
- DependentScopeDeclRefExpr *E) {
+ DependentScopeDeclRefExpr *E) {
NestedNameSpecifier *NNS
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange());
if (!NNS)
- return SemaRef.ExprError();
+ return ExprError();
- DeclarationName Name
- = getDerived().TransformDeclarationName(E->getDeclName(), E->getLocation());
- if (!Name)
- return SemaRef.ExprError();
+ DeclarationNameInfo NameInfo
+ = getDerived().TransformDeclarationNameInfo(E->getNameInfo());
+ if (!NameInfo.getName())
+ return ExprError();
if (!E->hasExplicitTemplateArgs()) {
if (!getDerived().AlwaysRebuild() &&
NNS == E->getQualifier() &&
- Name == E->getDeclName())
+ // Note: it is sufficient to compare the Name component of NameInfo:
+ // if name has not changed, DNLoc has not changed either.
+ NameInfo.getName() == E->getDeclName())
return SemaRef.Owned(E->Retain());
return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
E->getQualifierRange(),
- Name, E->getLocation(),
+ NameInfo,
/*TemplateArgs*/ 0);
}
@@ -5611,18 +5618,18 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
- return SemaRef.ExprError();
+ return ExprError();
TransArgs.addArgument(Loc);
}
return getDerived().RebuildDependentScopeDeclRefExpr(NNS,
E->getQualifierRange(),
- Name, E->getLocation(),
+ NameInfo,
&TransArgs);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
// CXXConstructExprs are always implicit, so when we have a
// 1-argument construction we just transform that argument.
@@ -5634,17 +5641,17 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
CXXConstructorDecl *Constructor
= cast_or_null<CXXConstructorDecl>(
getDerived().TransformDecl(E->getLocStart(),
E->getConstructor()));
if (!Constructor)
- return SemaRef.ExprError();
+ return ExprError();
bool ArgumentChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+ ASTOwningVector<Expr*> Args(SemaRef);
for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(),
ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg) {
@@ -5653,12 +5660,12 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
break;
}
- OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+ ExprResult TransArg = getDerived().TransformExpr(*Arg);
if (TransArg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
- Args.push_back(TransArg.takeAs<Expr>());
+ Args.push_back(TransArg.get());
}
if (!getDerived().AlwaysRebuild() &&
@@ -5673,7 +5680,9 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
Constructor, E->isElidable(),
- move_arg(Args));
+ move_arg(Args),
+ E->requiresZeroInitialization(),
+ E->getConstructionKind());
}
/// \brief Transform a C++ temporary-binding expression.
@@ -5681,51 +5690,41 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just
/// transform the subexpression and return that.
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
return getDerived().TransformExpr(E->getSubExpr());
}
-/// \brief Transform a C++ reference-binding expression.
-///
-/// Since CXXBindReferenceExpr nodes are implicitly generated, we just
-/// transform the subexpression and return that.
-template<typename Derived>
-Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
- return getDerived().TransformExpr(E->getSubExpr());
-}
-
/// \brief Transform a C++ expression that contains temporaries that should
/// be destroyed after the expression is evaluated.
///
/// Since CXXExprWithTemporaries nodes are implicitly generated, we
/// just transform the subexpression and return that.
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXExprWithTemporaries(
CXXExprWithTemporaries *E) {
return getDerived().TransformExpr(E->getSubExpr());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
CXXTemporaryObjectExpr *E) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getType());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
CXXConstructorDecl *Constructor
= cast_or_null<CXXConstructorDecl>(
getDerived().TransformDecl(E->getLocStart(),
E->getConstructor()));
if (!Constructor)
- return SemaRef.ExprError();
+ return ExprError();
bool ArgumentChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+ ASTOwningVector<Expr*> Args(SemaRef);
Args.reserve(E->getNumArgs());
for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(),
ArgEnd = E->arg_end();
@@ -5735,9 +5734,9 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
break;
}
- OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+ ExprResult TransArg = getDerived().TransformExpr(*Arg);
if (TransArg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
Args.push_back((Expr *)TransArg.release());
@@ -5768,28 +5767,28 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr(
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
CXXUnresolvedConstructExpr *E) {
TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName());
QualType T = getDerived().TransformType(E->getTypeAsWritten());
if (T.isNull())
- return SemaRef.ExprError();
+ return ExprError();
bool ArgumentChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+ ASTOwningVector<Expr*> Args(SemaRef);
llvm::SmallVector<SourceLocation, 8> FakeCommaLocs;
for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(),
ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg) {
- OwningExprResult TransArg = getDerived().TransformExpr(*Arg);
+ ExprResult TransArg = getDerived().TransformExpr(*Arg);
if (TransArg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || TransArg.get() != *Arg;
FakeCommaLocs.push_back(
SemaRef.PP.getLocForEndOfToken((*Arg)->getLocEnd()));
- Args.push_back(TransArg.takeAs<Expr>());
+ Args.push_back(TransArg.get());
}
if (!getDerived().AlwaysRebuild() &&
@@ -5807,11 +5806,11 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr(
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
- CXXDependentScopeMemberExpr *E) {
+ CXXDependentScopeMemberExpr *E) {
// Transform the base of the expression.
- OwningExprResult Base(SemaRef, (Expr*) 0);
+ ExprResult Base((Expr*) 0);
Expr *OldBase;
QualType BaseType;
QualType ObjectType;
@@ -5819,20 +5818,20 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
OldBase = E->getBase();
Base = getDerived().TransformExpr(OldBase);
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// Start the member reference and compute the object's type.
- Sema::TypeTy *ObjectTy = 0;
+ ParsedType ObjectTy;
bool MayBePseudoDestructor = false;
- Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
+ Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(),
E->getOperatorLoc(),
E->isArrow()? tok::arrow : tok::period,
ObjectTy,
MayBePseudoDestructor);
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- ObjectType = QualType::getFromOpaquePtr(ObjectTy);
+ ObjectType = ObjectTy.get();
BaseType = ((Expr*) Base.get())->getType();
} else {
OldBase = 0;
@@ -5854,14 +5853,14 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
ObjectType,
FirstQualifierInScope);
if (!Qualifier)
- return SemaRef.ExprError();
+ return ExprError();
}
- DeclarationName Name
- = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc(),
- ObjectType);
- if (!Name)
- return SemaRef.ExprError();
+ DeclarationNameInfo NameInfo
+ = getDerived().TransformDeclarationNameInfo(E->getMemberNameInfo(),
+ ObjectType);
+ if (!NameInfo.getName())
+ return ExprError();
if (!E->hasExplicitTemplateArgs()) {
// This is a reference to a member without an explicitly-specified
@@ -5870,19 +5869,18 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
Base.get() == OldBase &&
BaseType == E->getBaseType() &&
Qualifier == E->getQualifier() &&
- Name == E->getMember() &&
+ NameInfo.getName() == E->getMember() &&
FirstQualifierInScope == E->getFirstQualifierFoundInScope())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildCXXDependentScopeMemberExpr(move(Base),
+ return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
BaseType,
E->isArrow(),
E->getOperatorLoc(),
Qualifier,
E->getQualifierRange(),
FirstQualifierInScope,
- Name,
- E->getMemberLoc(),
+ NameInfo,
/*TemplateArgs*/ 0);
}
@@ -5890,32 +5888,31 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], Loc))
- return SemaRef.ExprError();
+ return ExprError();
TransArgs.addArgument(Loc);
}
- return getDerived().RebuildCXXDependentScopeMemberExpr(move(Base),
+ return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
BaseType,
E->isArrow(),
E->getOperatorLoc(),
Qualifier,
E->getQualifierRange(),
FirstQualifierInScope,
- Name,
- E->getMemberLoc(),
+ NameInfo,
&TransArgs);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) {
// Transform the base of the expression.
- OwningExprResult Base(SemaRef, (Expr*) 0);
+ ExprResult Base((Expr*) 0);
QualType BaseType;
if (!Old->isImplicitAccess()) {
Base = getDerived().TransformExpr(Old->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
BaseType = ((Expr*) Base.get())->getType();
} else {
BaseType = getDerived().TransformType(Old->getBaseType());
@@ -5927,10 +5924,10 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
= getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
Old->getQualifierRange());
if (Qualifier == 0)
- return SemaRef.ExprError();
+ return ExprError();
}
- LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
+ LookupResult R(SemaRef, Old->getMemberNameInfo(),
Sema::LookupOrdinaryName);
// Transform all the decls.
@@ -5945,7 +5942,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
if (isa<UsingShadowDecl>(*I))
continue;
else
- return SemaRef.ExprError();
+ return ExprError();
}
// Expand using declarations.
@@ -5969,7 +5966,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
Old->getMemberLoc(),
Old->getNamingClass()));
if (!NamingClass)
- return SemaRef.ExprError();
+ return ExprError();
R.setNamingClass(NamingClass);
}
@@ -5982,7 +5979,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I],
Loc))
- return SemaRef.ExprError();
+ return ExprError();
TransArgs.addArgument(Loc);
}
}
@@ -5993,7 +5990,7 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
// nested-name-qualifier (and therefore could do the lookup).
NamedDecl *FirstQualifierInScope = 0;
- return getDerived().RebuildUnresolvedMemberExpr(move(Base),
+ return getDerived().RebuildUnresolvedMemberExpr(Base.get(),
BaseType,
Old->getOperatorLoc(),
Old->isArrow(),
@@ -6006,18 +6003,18 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old)
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
TypeSourceInfo *EncodedTypeInfo
= getDerived().TransformType(E->getEncodedTypeSourceInfo());
if (!EncodedTypeInfo)
- return SemaRef.ExprError();
+ return ExprError();
if (!getDerived().AlwaysRebuild() &&
EncodedTypeInfo == E->getEncodedTypeSourceInfo())
@@ -6029,18 +6026,18 @@ TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
// Transform arguments.
bool ArgChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef);
+ ASTOwningVector<Expr*> Args(SemaRef);
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
- OwningExprResult Arg = getDerived().TransformExpr(E->getArg(I));
+ ExprResult Arg = getDerived().TransformExpr(E->getArg(I));
if (Arg.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgChanged = ArgChanged || Arg.get() != E->getArg(I);
- Args.push_back(Arg.takeAs<Expr>());
+ Args.push_back(Arg.get());
}
if (E->getReceiverKind() == ObjCMessageExpr::Class) {
@@ -6048,7 +6045,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
TypeSourceInfo *ReceiverTypeInfo
= getDerived().TransformType(E->getClassReceiverTypeInfo());
if (!ReceiverTypeInfo)
- return SemaRef.ExprError();
+ return ExprError();
// If nothing changed, just retain the existing message send.
if (!getDerived().AlwaysRebuild() &&
@@ -6067,10 +6064,10 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
// Instance message: transform the receiver
assert(E->getReceiverKind() == ObjCMessageExpr::Instance &&
"Only class and instance messages may be instantiated");
- OwningExprResult Receiver
+ ExprResult Receiver
= getDerived().TransformExpr(E->getInstanceReceiver());
if (Receiver.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// If nothing changed, just retain the existing message send.
if (!getDerived().AlwaysRebuild() &&
@@ -6078,7 +6075,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
return SemaRef.Owned(E->Retain());
// Build a new instance message send.
- return getDerived().RebuildObjCMessageExpr(move(Receiver),
+ return getDerived().RebuildObjCMessageExpr(Receiver.get(),
E->getSelector(),
E->getMethodDecl(),
E->getLeftLoc(),
@@ -6087,24 +6084,24 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) {
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
// Transform the base expression.
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// We don't need to transform the ivar; it will never change.
@@ -6113,18 +6110,18 @@ TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) {
Base.get() == E->getBase())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildObjCIvarRefExpr(move(Base), E->getDecl(),
+ return getDerived().RebuildObjCIvarRefExpr(Base.get(), E->getDecl(),
E->getLocation(),
E->isArrow(), E->isFreeIvar());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
// Transform the base expression.
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// We don't need to transform the property; it will never change.
@@ -6133,12 +6130,12 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
Base.get() == E->getBase())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildObjCPropertyRefExpr(move(Base), E->getProperty(),
+ return getDerived().RebuildObjCPropertyRefExpr(Base.get(), E->getProperty(),
E->getLocation());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
ObjCImplicitSetterGetterRefExpr *E) {
// If this implicit setter/getter refers to class methods, it cannot have any
@@ -6147,9 +6144,9 @@ TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
return SemaRef.Owned(E->Retain());
// Transform the base expression.
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// We don't need to transform the getters/setters; they will never change.
@@ -6163,46 +6160,46 @@ TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr(
E->getType(),
E->getSetterMethod(),
E->getLocation(),
- move(Base));
+ Base.get());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) {
// Can never occur in a dependent context.
return SemaRef.Owned(E->Retain());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) {
// Transform the base expression.
- OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
if (Base.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// If nothing changed, just retain the existing expression.
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase())
return SemaRef.Owned(E->Retain());
- return getDerived().RebuildObjCIsaExpr(move(Base), E->getIsaMemberLoc(),
+ return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(),
E->isArrow());
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
bool ArgumentChanged = false;
- ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef);
+ ASTOwningVector<Expr*> SubExprs(SemaRef);
for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) {
- OwningExprResult SubExpr = getDerived().TransformExpr(E->getExpr(I));
+ ExprResult SubExpr = getDerived().TransformExpr(E->getExpr(I));
if (SubExpr.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
ArgumentChanged = ArgumentChanged || SubExpr.get() != E->getExpr(I);
- SubExprs.push_back(SubExpr.takeAs<Expr>());
+ SubExprs.push_back(SubExpr.get());
}
if (!getDerived().AlwaysRebuild() &&
@@ -6215,7 +6212,7 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) {
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
SourceLocation CaretLoc(E->getExprLoc());
@@ -6246,9 +6243,9 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
}
// Transform the body
- OwningStmtResult Body = getDerived().TransformStmt(E->getBody());
+ StmtResult Body = getDerived().TransformStmt(E->getBody());
if (Body.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
// Set the parameters on the block decl.
if (!Params.empty())
CurBlock->TheDecl->setParams(Params.data(), Params.size());
@@ -6258,14 +6255,15 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
ParamTypes.data(),
ParamTypes.size(),
BD->isVariadic(),
- 0);
+ 0,
+ BExprFunctionType->getExtInfo());
CurBlock->FunctionType = FunctionType;
- return SemaRef.ActOnBlockStmtExpr(CaretLoc, move(Body), /*Scope=*/0);
+ return SemaRef.ActOnBlockStmtExpr(CaretLoc, Body.get(), /*Scope=*/0);
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
NestedNameSpecifier *Qualifier = 0;
@@ -6273,8 +6271,8 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
= cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(),
E->getDecl()));
if (!ND)
- return SemaRef.ExprError();
-
+ return ExprError();
+
if (!getDerived().AlwaysRebuild() &&
ND == E->getDecl()) {
// Mark it referenced in the new context regardless.
@@ -6284,8 +6282,9 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) {
return SemaRef.Owned(E->Retain());
}
+ DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation());
return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(),
- ND, E->getLocation(), 0);
+ ND, NameInfo, 0);
}
//===----------------------------------------------------------------------===//
@@ -6350,7 +6349,8 @@ TreeTransform<Derived>::RebuildArrayType(QualType ElementType,
break;
}
- IntegerLiteral ArraySize(*Size, SizeType, /*FIXME*/BracketsRange.getBegin());
+ IntegerLiteral ArraySize(SemaRef.Context, *Size, SizeType,
+ /*FIXME*/BracketsRange.getBegin());
return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize,
IndexTypeQuals, BracketsRange,
getDerived().getBaseEntity());
@@ -6381,11 +6381,11 @@ template<typename Derived>
QualType
TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- ExprArg SizeExpr,
+ Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
- SizeExpr.takeAs<Expr>(),
+ SizeExpr,
IndexTypeQuals, BracketsRange);
}
@@ -6393,11 +6393,11 @@ template<typename Derived>
QualType
TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType,
ArrayType::ArraySizeModifier SizeMod,
- ExprArg SizeExpr,
+ Expr *SizeExpr,
unsigned IndexTypeQuals,
SourceRange BracketsRange) {
return getDerived().RebuildArrayType(ElementType, SizeMod, 0,
- SizeExpr.takeAs<Expr>(),
+ SizeExpr,
IndexTypeQuals, BracketsRange);
}
@@ -6416,18 +6416,17 @@ QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy),
NumElements, true);
IntegerLiteral *VectorSize
- = new (SemaRef.Context) IntegerLiteral(numElements, SemaRef.Context.IntTy,
- AttributeLoc);
- return SemaRef.BuildExtVectorType(ElementType, SemaRef.Owned(VectorSize),
- AttributeLoc);
+ = IntegerLiteral::Create(SemaRef.Context, numElements, SemaRef.Context.IntTy,
+ AttributeLoc);
+ return SemaRef.BuildExtVectorType(ElementType, VectorSize, AttributeLoc);
}
template<typename Derived>
QualType
TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType,
- ExprArg SizeExpr,
+ Expr *SizeExpr,
SourceLocation AttributeLoc) {
- return SemaRef.BuildExtVectorType(ElementType, move(SizeExpr), AttributeLoc);
+ return SemaRef.BuildExtVectorType(ElementType, SizeExpr, AttributeLoc);
}
template<typename Derived>
@@ -6435,11 +6434,13 @@ QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,
QualType *ParamTypes,
unsigned NumParamTypes,
bool Variadic,
- unsigned Quals) {
+ unsigned Quals,
+ const FunctionType::ExtInfo &Info) {
return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
Quals,
getDerived().getBaseLocation(),
- getDerived().getBaseEntity());
+ getDerived().getBaseEntity(),
+ Info);
}
template<typename Derived>
@@ -6473,8 +6474,8 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
- return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
+QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E) {
+ return SemaRef.BuildTypeofExprType(E);
}
template<typename Derived>
@@ -6483,8 +6484,8 @@ QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) {
}
template<typename Derived>
-QualType TreeTransform<Derived>::RebuildDecltypeType(ExprArg E) {
- return SemaRef.BuildDecltypeType(E.takeAs<Expr>());
+QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E) {
+ return SemaRef.BuildDecltypeType(E);
}
template<typename Derived>
@@ -6563,7 +6564,7 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
/*FIXME:*/getDerived().getBaseLocation(),
SS,
Name,
- ObjectType.getAsOpaquePtr(),
+ ParsedType::make(ObjectType),
/*EnteringContext=*/false,
Template);
return Template.template getAsVal<TemplateName>();
@@ -6586,56 +6587,52 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
/*FIXME:*/getDerived().getBaseLocation(),
SS,
Name,
- ObjectType.getAsOpaquePtr(),
+ ParsedType::make(ObjectType),
/*EnteringContext=*/false,
Template);
return Template.template getAsVal<TemplateName>();
}
template<typename Derived>
-Sema::OwningExprResult
+ExprResult
TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
SourceLocation OpLoc,
- ExprArg Callee,
- ExprArg First,
- ExprArg Second) {
- Expr *FirstExpr = (Expr *)First.get();
- Expr *SecondExpr = (Expr *)Second.get();
- Expr *CalleeExpr = ((Expr *)Callee.get())->IgnoreParenCasts();
- bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus);
+ Expr *OrigCallee,
+ Expr *First,
+ Expr *Second) {
+ Expr *Callee = OrigCallee->IgnoreParenCasts();
+ bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus);
// Determine whether this should be a builtin operation.
if (Op == OO_Subscript) {
- if (!FirstExpr->getType()->isOverloadableType() &&
- !SecondExpr->getType()->isOverloadableType())
- return getSema().CreateBuiltinArraySubscriptExpr(move(First),
- CalleeExpr->getLocStart(),
- move(Second), OpLoc);
+ if (!First->getType()->isOverloadableType() &&
+ !Second->getType()->isOverloadableType())
+ return getSema().CreateBuiltinArraySubscriptExpr(First,
+ Callee->getLocStart(),
+ 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()) {
+ return SemaRef.BuildOverloadedArrowExpr(0, First, OpLoc);
+ } else if (Second == 0 || isPostIncDec) {
+ if (!First->getType()->isOverloadableType()) {
// The argument is not of overloadable type, so try to create a
// built-in unary operation.
- UnaryOperator::Opcode Opc
+ UnaryOperatorKind Opc
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
- return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(First));
+ return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First);
}
} else {
- if (!FirstExpr->getType()->isOverloadableType() &&
- !SecondExpr->getType()->isOverloadableType()) {
+ if (!First->getType()->isOverloadableType() &&
+ !Second->getType()->isOverloadableType()) {
// Neither of the arguments is an overloadable type, so try to
// create a built-in binary operation.
- BinaryOperator::Opcode Opc = BinaryOperator::getOverloadedOpcode(Op);
- OwningExprResult Result
- = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, FirstExpr, SecondExpr);
+ BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+ ExprResult Result
+ = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second);
if (Result.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- First.release();
- Second.release();
return move(Result);
}
}
@@ -6644,49 +6641,46 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// used during overload resolution.
UnresolvedSet<16> Functions;
- if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) {
+ if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) {
assert(ULE->requiresADL());
// FIXME: Do we have to check
// IsAcceptableNonMemberOperatorCandidate for each of these?
Functions.append(ULE->decls_begin(), ULE->decls_end());
} else {
- Functions.addDecl(cast<DeclRefExpr>(CalleeExpr)->getDecl());
+ Functions.addDecl(cast<DeclRefExpr>(Callee)->getDecl());
}
// Add any functions found via argument-dependent lookup.
- Expr *Args[2] = { FirstExpr, SecondExpr };
- unsigned NumArgs = 1 + (SecondExpr != 0);
+ Expr *Args[2] = { First, Second };
+ unsigned NumArgs = 1 + (Second != 0);
// Create the overloaded operator invocation for unary operators.
if (NumArgs == 1 || isPostIncDec) {
- UnaryOperator::Opcode Opc
+ UnaryOperatorKind Opc
= UnaryOperator::getOverloadedOpcode(Op, isPostIncDec);
- return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(First));
+ return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First);
}
if (Op == OO_Subscript)
- return SemaRef.CreateOverloadedArraySubscriptExpr(CalleeExpr->getLocStart(),
+ return SemaRef.CreateOverloadedArraySubscriptExpr(Callee->getLocStart(),
OpLoc,
- move(First),
- move(Second));
+ First,
+ Second);
// Create the overloaded operator invocation for binary operators.
- BinaryOperator::Opcode Opc =
- BinaryOperator::getOverloadedOpcode(Op);
- OwningExprResult Result
+ BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op);
+ ExprResult Result
= SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]);
if (Result.isInvalid())
- return SemaRef.ExprError();
+ return ExprError();
- First.release();
- Second.release();
return move(Result);
}
template<typename Derived>
-Sema::OwningExprResult
-TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(ExprArg Base,
+ExprResult
+TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
SourceLocation OperatorLoc,
bool isArrow,
NestedNameSpecifier *Qualifier,
@@ -6701,32 +6695,32 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(ExprArg Base,
SS.setScopeRep(Qualifier);
}
- Expr *BaseE = (Expr *)Base.get();
- QualType BaseType = BaseE->getType();
- if (BaseE->isTypeDependent() || Destroyed.getIdentifier() ||
+ QualType BaseType = Base->getType();
+ if (Base->isTypeDependent() || Destroyed.getIdentifier() ||
(!isArrow && !BaseType->getAs<RecordType>()) ||
(isArrow && BaseType->getAs<PointerType>() &&
!BaseType->getAs<PointerType>()->getPointeeType()
->template getAs<RecordType>())){
// This pseudo-destructor expression is still a pseudo-destructor.
- return SemaRef.BuildPseudoDestructorExpr(move(Base), OperatorLoc,
+ return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc,
isArrow? tok::arrow : tok::period,
SS, ScopeType, CCLoc, TildeLoc,
Destroyed,
/*FIXME?*/true);
}
-
+
TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
- DeclarationName Name
- = SemaRef.Context.DeclarationNames.getCXXDestructorName(
- SemaRef.Context.getCanonicalType(DestroyedType->getType()));
-
+ DeclarationName Name(SemaRef.Context.DeclarationNames.getCXXDestructorName(
+ SemaRef.Context.getCanonicalType(DestroyedType->getType())));
+ DeclarationNameInfo NameInfo(Name, Destroyed.getLocation());
+ NameInfo.setNamedTypeInfo(DestroyedType);
+
// FIXME: the ScopeType should be tacked onto SS.
-
- return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
+
+ return getSema().BuildMemberReferenceExpr(Base, BaseType,
OperatorLoc, isArrow,
SS, /*FIXME: FirstQualifier*/ 0,
- Name, Destroyed.getLocation(),
+ NameInfo,
/*TemplateArgs*/ 0);
}
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp
new file mode 100644
index 000000000000..77c1aff44b39
--- /dev/null
+++ b/lib/Serialization/ASTCommon.cpp
@@ -0,0 +1,69 @@
+//===--- ASTCommon.cpp - Common stuff for ASTReader/ASTWriter----*- 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 common functions that both ASTReader and ASTWriter use.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTCommon.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace clang;
+
+serialization::TypeIdx
+serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
+ unsigned ID = 0;
+ switch (BT->getKind()) {
+ case BuiltinType::Void: ID = PREDEF_TYPE_VOID_ID; break;
+ case BuiltinType::Bool: ID = PREDEF_TYPE_BOOL_ID; break;
+ case BuiltinType::Char_U: ID = PREDEF_TYPE_CHAR_U_ID; break;
+ case BuiltinType::UChar: ID = PREDEF_TYPE_UCHAR_ID; break;
+ case BuiltinType::UShort: ID = PREDEF_TYPE_USHORT_ID; break;
+ case BuiltinType::UInt: ID = PREDEF_TYPE_UINT_ID; break;
+ case BuiltinType::ULong: ID = PREDEF_TYPE_ULONG_ID; break;
+ case BuiltinType::ULongLong: ID = PREDEF_TYPE_ULONGLONG_ID; break;
+ case BuiltinType::UInt128: ID = PREDEF_TYPE_UINT128_ID; break;
+ case BuiltinType::Char_S: ID = PREDEF_TYPE_CHAR_S_ID; break;
+ case BuiltinType::SChar: ID = PREDEF_TYPE_SCHAR_ID; break;
+ case BuiltinType::WChar: ID = PREDEF_TYPE_WCHAR_ID; break;
+ case BuiltinType::Short: ID = PREDEF_TYPE_SHORT_ID; break;
+ case BuiltinType::Int: ID = PREDEF_TYPE_INT_ID; break;
+ case BuiltinType::Long: ID = PREDEF_TYPE_LONG_ID; break;
+ case BuiltinType::LongLong: ID = PREDEF_TYPE_LONGLONG_ID; break;
+ case BuiltinType::Int128: ID = PREDEF_TYPE_INT128_ID; break;
+ case BuiltinType::Float: ID = PREDEF_TYPE_FLOAT_ID; break;
+ case BuiltinType::Double: ID = PREDEF_TYPE_DOUBLE_ID; break;
+ case BuiltinType::LongDouble: ID = PREDEF_TYPE_LONGDOUBLE_ID; break;
+ case BuiltinType::NullPtr: ID = PREDEF_TYPE_NULLPTR_ID; break;
+ case BuiltinType::Char16: ID = PREDEF_TYPE_CHAR16_ID; break;
+ case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break;
+ case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break;
+ case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break;
+ case BuiltinType::ObjCId: ID = PREDEF_TYPE_OBJC_ID; break;
+ case BuiltinType::ObjCClass: ID = PREDEF_TYPE_OBJC_CLASS; break;
+ case BuiltinType::ObjCSel: ID = PREDEF_TYPE_OBJC_SEL; break;
+ case BuiltinType::UndeducedAuto:
+ assert(0 && "Should not see undeduced auto here");
+ break;
+ }
+
+ return TypeIdx(ID);
+}
+
+unsigned serialization::ComputeHash(Selector Sel) {
+ unsigned N = Sel.getNumArgs();
+ if (N == 0)
+ ++N;
+ unsigned R = 5381;
+ for (unsigned I = 0; I != N; ++I)
+ if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
+ R = llvm::HashString(II->getName(), R);
+ return R;
+}
diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h
new file mode 100644
index 000000000000..a0e2ecd8aa1b
--- /dev/null
+++ b/lib/Serialization/ASTCommon.h
@@ -0,0 +1,50 @@
+//===- ASTCommon.h - Common stuff for ASTReader/ASTWriter -*- 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 common functions that both ASTReader and ASTWriter use.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H
+#define LLVM_CLANG_SERIALIZATION_LIB_AST_COMMON_H
+
+#include "clang/Serialization/ASTBitCodes.h"
+
+namespace clang {
+
+namespace serialization {
+
+TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
+
+template <typename IdxForTypeTy>
+TypeID MakeTypeID(QualType T, IdxForTypeTy IdxForType) {
+ if (T.isNull())
+ return PREDEF_TYPE_NULL_ID;
+
+ unsigned FastQuals = T.getLocalFastQualifiers();
+ T.removeFastQualifiers();
+
+ if (T.hasLocalNonFastQualifiers())
+ return IdxForType(T).asTypeID(FastQuals);
+
+ assert(!T.hasLocalQualifiers());
+
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
+ return TypeIdxFromBuiltin(BT).asTypeID(FastQuals);
+
+ return IdxForType(T).asTypeID(FastQuals);
+}
+
+unsigned ComputeHash(Selector Sel);
+
+} // namespace serialization
+
+} // namespace clang
+
+#endif
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Serialization/ASTReader.cpp
index 00aee491d644..f07215cb8f51 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1,4 +1,4 @@
-//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===//
+//===--- ASTReader.cpp - AST File Reader ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,18 +7,22 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the PCHReader class, which reads a precompiled header.
+// This file defines the ASTReader class, which reads AST files.
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/ASTReader.h"
+#include "clang/Serialization/ASTDeserializationListener.h"
+#include "ASTCommon.h"
#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/PCHDeserializationListener.h"
#include "clang/Frontend/Utils.h"
-#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/Scope.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/MacroInfo.h"
@@ -41,12 +45,13 @@
#include <cstdio>
#include <sys/stat.h>
using namespace clang;
+using namespace clang::serialization;
//===----------------------------------------------------------------------===//
-// PCH reader validator implementation
+// PCH validator implementation
//===----------------------------------------------------------------------===//
-PCHReaderListener::~PCHReaderListener() {}
+ASTReaderListener::~ASTReaderListener() {}
bool
PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
@@ -170,6 +175,7 @@ static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L,
// Do it the hard way. At this point, both vectors must be non-empty.
llvm::StringRef LR = L[0], RR = R[0].Data;
unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size();
+ (void) RN;
for (;;) {
// Compare the current pieces.
if (LR.size() == RR.size()) {
@@ -241,9 +247,6 @@ bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
// If the concatenation of all the PCH buffers is equal to the adjusted
// command line, we're done.
- // We build a SmallVector of the command line here, because we'll eventually
- // need to support an arbitrary amount of pieces anyway (when we have chained
- // PCH reading).
llvm::SmallVector<llvm::StringRef, 2> CommandLine;
CommandLine.push_back(Left);
CommandLine.push_back(Right);
@@ -409,60 +412,31 @@ void PCHValidator::ReadCounter(unsigned Value) {
}
//===----------------------------------------------------------------------===//
-// PCH reader implementation
+// AST reader implementation
//===----------------------------------------------------------------------===//
-PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
- const char *isysroot)
- : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
- SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
- Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
- StatCache(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0),
- IdentifierOffsets(0),
- MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
- TotalSelectorsInMethodPool(0), SelectorOffsets(0),
- TotalNumSelectors(0), MacroDefinitionOffsets(0),
- NumPreallocatedPreprocessingEntities(0),
- isysroot(isysroot), NumStatHits(0), NumStatMisses(0),
- NumSLocEntriesRead(0), NumStatementsRead(0),
- NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
- NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
- CurrentlyLoadingTypeOrDecl(0) {
- RelocatablePCH = false;
-}
-
-PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
- Diagnostic &Diags, const char *isysroot)
- : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
- Diags(Diags), SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
- IdentifierTableData(0), IdentifierLookupTable(0),
- IdentifierOffsets(0),
- MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
- TotalSelectorsInMethodPool(0), SelectorOffsets(0),
- TotalNumSelectors(0), MacroDefinitionOffsets(0),
- NumPreallocatedPreprocessingEntities(0),
- isysroot(isysroot), NumStatHits(0), NumStatMisses(0),
- NumSLocEntriesRead(0), NumStatementsRead(0),
- NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
- NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
- CurrentlyLoadingTypeOrDecl(0) {
- RelocatablePCH = false;
+void
+ASTReader::setDeserializationListener(ASTDeserializationListener *Listener) {
+ DeserializationListener = Listener;
+ if (DeserializationListener)
+ DeserializationListener->SetReader(this);
}
-PCHReader::~PCHReader() {}
-
namespace {
-class PCHMethodPoolLookupTrait {
- PCHReader &Reader;
+class ASTSelectorLookupTrait {
+ ASTReader &Reader;
public:
- typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
+ struct data_type {
+ SelectorID ID;
+ ObjCMethodList Instance, Factory;
+ };
typedef Selector external_key_type;
typedef external_key_type internal_key_type;
- explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
+ explicit ASTSelectorLookupTrait(ASTReader &Reader) : Reader(Reader) { }
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
@@ -470,14 +444,7 @@ public:
}
static unsigned ComputeHash(Selector Sel) {
- unsigned N = Sel.getNumArgs();
- if (N == 0)
- ++N;
- unsigned R = 5381;
- for (unsigned I = 0; I != N; ++I)
- if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
- R = llvm::HashString(II->getName(), R);
- return R;
+ return serialization::ComputeHash(Sel);
}
// This hopefully will just get inlined and removed by the optimizer.
@@ -513,20 +480,22 @@ public:
data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
using namespace clang::io;
- unsigned NumInstanceMethods = ReadUnalignedLE16(d);
- unsigned NumFactoryMethods = ReadUnalignedLE16(d);
data_type Result;
+ Result.ID = ReadUnalignedLE32(d);
+ unsigned NumInstanceMethods = ReadUnalignedLE16(d);
+ unsigned NumFactoryMethods = ReadUnalignedLE16(d);
+
// Load instance methods
ObjCMethodList *Prev = 0;
for (unsigned I = 0; I != NumInstanceMethods; ++I) {
ObjCMethodDecl *Method
= cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
- if (!Result.first.Method) {
+ if (!Result.Instance.Method) {
// This is the first method, which is the easy case.
- Result.first.Method = Method;
- Prev = &Result.first;
+ Result.Instance.Method = Method;
+ Prev = &Result.Instance;
continue;
}
@@ -541,10 +510,10 @@ public:
for (unsigned I = 0; I != NumFactoryMethods; ++I) {
ObjCMethodDecl *Method
= cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
- if (!Result.second.Method) {
+ if (!Result.Factory.Method) {
// This is the first method, which is the easy case.
- Result.second.Method = Method;
- Prev = &Result.second;
+ Result.Factory.Method = Method;
+ Prev = &Result.Factory;
continue;
}
@@ -561,16 +530,17 @@ public:
} // end anonymous namespace
/// \brief The on-disk hash table used for the global method pool.
-typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
- PCHMethodPoolLookupTable;
+typedef OnDiskChainedHashTable<ASTSelectorLookupTrait>
+ ASTSelectorLookupTable;
namespace {
-class PCHIdentifierLookupTrait {
- PCHReader &Reader;
+class ASTIdentifierLookupTrait {
+ ASTReader &Reader;
+ llvm::BitstreamCursor &Stream;
// If we know the IdentifierInfo in advance, it is here and we will
// not build a new one. Used when deserializing information about an
- // identifier that was constructed before the PCH file was read.
+ // identifier that was constructed before the AST file was read.
IdentifierInfo *KnownII;
public:
@@ -580,8 +550,9 @@ public:
typedef external_key_type internal_key_type;
- explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
- : Reader(Reader), KnownII(II) { }
+ ASTIdentifierLookupTrait(ASTReader &Reader, llvm::BitstreamCursor &Stream,
+ IdentifierInfo *II = 0)
+ : Reader(Reader), Stream(Stream), KnownII(II) { }
static bool EqualKey(const internal_key_type& a,
const internal_key_type& b) {
@@ -615,26 +586,28 @@ public:
const unsigned char* d,
unsigned DataLen) {
using namespace clang::io;
- pch::IdentID ID = ReadUnalignedLE32(d);
+ IdentID ID = ReadUnalignedLE32(d);
bool IsInteresting = ID & 0x01;
// Wipe out the "is interesting" bit.
ID = ID >> 1;
if (!IsInteresting) {
- // For unintersting identifiers, just build the IdentifierInfo
+ // For uninteresting identifiers, just build the IdentifierInfo
// and associate it with the persistent ID.
IdentifierInfo *II = KnownII;
if (!II)
- II = &Reader.getIdentifierTable().CreateIdentifierInfo(
- k.first, k.first + k.second);
+ II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
Reader.SetIdentifierInfo(ID, II);
+ II->setIsFromAST();
return II;
}
unsigned Bits = ReadUnalignedLE16(d);
bool CPlusPlusOperatorKeyword = Bits & 0x01;
Bits >>= 1;
+ bool HasRevertedTokenIDToIdentifier = Bits & 0x01;
+ Bits >>= 1;
bool Poisoned = Bits & 0x01;
Bits >>= 1;
bool ExtensionToken = Bits & 0x01;
@@ -651,12 +624,13 @@ public:
// the new IdentifierInfo.
IdentifierInfo *II = KnownII;
if (!II)
- II = &Reader.getIdentifierTable().CreateIdentifierInfo(
- k.first, k.first + k.second);
+ II = &Reader.getIdentifierTable().getOwn(k.first, k.first + k.second);
Reader.SetIdentifierInfo(ID, II);
// Set or check the various bits in the IdentifierInfo structure.
- // FIXME: Load token IDs lazily, too?
+ // Token IDs are read-only.
+ if (HasRevertedTokenIDToIdentifier)
+ II->RevertTokenIDToIdentifier();
II->setObjCOrBuiltinID(ObjCOrBuiltinID);
assert(II->isExtensionToken() == ExtensionToken &&
"Incorrect extension token flag");
@@ -670,7 +644,7 @@ public:
// definition.
if (hasMacroDefinition) {
uint32_t Offset = ReadUnalignedLE32(d);
- Reader.ReadMacroRecord(Offset);
+ Reader.ReadMacroRecord(Stream, Offset);
DataLen -= 4;
}
@@ -684,6 +658,7 @@ public:
Reader.SetGloballyVisibleDecls(II, DeclIDs);
}
+ II->setIsFromAST();
return II;
}
};
@@ -692,23 +667,245 @@ public:
/// \brief The on-disk hash table used to contain information about
/// all of the identifiers in the program.
-typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
- PCHIdentifierLookupTable;
+typedef OnDiskChainedHashTable<ASTIdentifierLookupTrait>
+ ASTIdentifierLookupTable;
+
+namespace {
+class ASTDeclContextNameLookupTrait {
+ ASTReader &Reader;
+
+public:
+ /// \brief Pair of begin/end iterators for DeclIDs.
+ typedef std::pair<DeclID *, DeclID *> data_type;
+
+ /// \brief Special internal key for declaration names.
+ /// The hash table creates keys for comparison; we do not create
+ /// a DeclarationName for the internal key to avoid deserializing types.
+ struct DeclNameKey {
+ DeclarationName::NameKind Kind;
+ uint64_t Data;
+ DeclNameKey() : Kind((DeclarationName::NameKind)0), Data(0) { }
+ };
+
+ typedef DeclarationName external_key_type;
+ typedef DeclNameKey internal_key_type;
+
+ explicit ASTDeclContextNameLookupTrait(ASTReader &Reader) : Reader(Reader) { }
+
+ static bool EqualKey(const internal_key_type& a,
+ const internal_key_type& b) {
+ return a.Kind == b.Kind && a.Data == b.Data;
+ }
+
+ unsigned ComputeHash(const DeclNameKey &Key) const {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(Key.Kind);
+
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ case DeclarationName::CXXLiteralOperatorName:
+ ID.AddString(((IdentifierInfo*)Key.Data)->getName());
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ ID.AddInteger(serialization::ComputeHash(Selector(Key.Data)));
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ ID.AddInteger((TypeID)Key.Data);
+ break;
+ case DeclarationName::CXXOperatorName:
+ ID.AddInteger((OverloadedOperatorKind)Key.Data);
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return ID.ComputeHash();
+ }
+
+ internal_key_type GetInternalKey(const external_key_type& Name) const {
+ DeclNameKey Key;
+ Key.Kind = Name.getNameKind();
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ Key.Data = (uint64_t)Name.getAsIdentifierInfo();
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Key.Data = (uint64_t)Name.getObjCSelector().getAsOpaquePtr();
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ Key.Data = Reader.GetTypeID(Name.getCXXNameType());
+ break;
+ case DeclarationName::CXXOperatorName:
+ Key.Data = Name.getCXXOverloadedOperator();
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Key.Data = (uint64_t)Name.getCXXLiteralIdentifier();
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return Key;
+ }
+
+ external_key_type GetExternalKey(const internal_key_type& Key) const {
+ ASTContext *Context = Reader.getContext();
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ return DeclarationName((IdentifierInfo*)Key.Data);
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ return DeclarationName(Selector(Key.Data));
+
+ case DeclarationName::CXXConstructorName:
+ return Context->DeclarationNames.getCXXConstructorName(
+ Context->getCanonicalType(Reader.GetType(Key.Data)));
+
+ case DeclarationName::CXXDestructorName:
+ return Context->DeclarationNames.getCXXDestructorName(
+ Context->getCanonicalType(Reader.GetType(Key.Data)));
+
+ case DeclarationName::CXXConversionFunctionName:
+ return Context->DeclarationNames.getCXXConversionFunctionName(
+ Context->getCanonicalType(Reader.GetType(Key.Data)));
+
+ case DeclarationName::CXXOperatorName:
+ return Context->DeclarationNames.getCXXOperatorName(
+ (OverloadedOperatorKind)Key.Data);
+
+ case DeclarationName::CXXLiteralOperatorName:
+ return Context->DeclarationNames.getCXXLiteralOperatorName(
+ (IdentifierInfo*)Key.Data);
+
+ case DeclarationName::CXXUsingDirective:
+ return DeclarationName::getUsingDirectiveName();
+ }
+
+ llvm_unreachable("Invalid Name Kind ?");
+ }
+
+ static std::pair<unsigned, unsigned>
+ ReadKeyDataLength(const unsigned char*& d) {
+ using namespace clang::io;
+ unsigned KeyLen = ReadUnalignedLE16(d);
+ unsigned DataLen = ReadUnalignedLE16(d);
+ return std::make_pair(KeyLen, DataLen);
+ }
+
+ internal_key_type ReadKey(const unsigned char* d, unsigned) {
+ using namespace clang::io;
+
+ DeclNameKey Key;
+ Key.Kind = (DeclarationName::NameKind)*d++;
+ switch (Key.Kind) {
+ case DeclarationName::Identifier:
+ Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
+ break;
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Key.Data =
+ (uint64_t)Reader.DecodeSelector(ReadUnalignedLE32(d)).getAsOpaquePtr();
+ break;
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ Key.Data = ReadUnalignedLE32(d); // TypeID
+ break;
+ case DeclarationName::CXXOperatorName:
+ Key.Data = *d++; // OverloadedOperatorKind
+ break;
+ case DeclarationName::CXXLiteralOperatorName:
+ Key.Data = (uint64_t)Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
+ break;
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return Key;
+ }
+
+ data_type ReadData(internal_key_type, const unsigned char* d,
+ unsigned DataLen) {
+ using namespace clang::io;
+ unsigned NumDecls = ReadUnalignedLE16(d);
+ DeclID *Start = (DeclID *)d;
+ return std::make_pair(Start, Start + NumDecls);
+ }
+};
+
+} // end anonymous namespace
+
+/// \brief The on-disk hash table used for the DeclContext's Name lookup table.
+typedef OnDiskChainedHashTable<ASTDeclContextNameLookupTrait>
+ ASTDeclContextNameLookupTable;
+
+bool ASTReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
+ const std::pair<uint64_t, uint64_t> &Offsets,
+ DeclContextInfo &Info) {
+ SavedStreamPosition SavedPosition(Cursor);
+ // First the lexical decls.
+ if (Offsets.first != 0) {
+ Cursor.JumpToBit(Offsets.first);
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+ if (RecCode != DECL_CONTEXT_LEXICAL) {
+ Error("Expected lexical block");
+ return true;
+ }
+
+ Info.LexicalDecls = reinterpret_cast<const DeclID*>(Blob);
+ Info.NumLexicalDecls = BlobLen / sizeof(DeclID);
+ } else {
+ Info.LexicalDecls = 0;
+ Info.NumLexicalDecls = 0;
+ }
+
+ // Now the lookup table.
+ if (Offsets.second != 0) {
+ Cursor.JumpToBit(Offsets.second);
+
+ RecordData Record;
+ const char *Blob;
+ unsigned BlobLen;
+ unsigned Code = Cursor.ReadCode();
+ unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
+ if (RecCode != DECL_CONTEXT_VISIBLE) {
+ Error("Expected visible lookup table block");
+ return true;
+ }
+ Info.NameLookupTableData
+ = ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)Blob + Record[0],
+ (const unsigned char *)Blob,
+ ASTDeclContextNameLookupTrait(*this));
+ } else {
+ Info.NameLookupTableData = 0;
+ }
-void PCHReader::Error(const char *Msg) {
+ return false;
+}
+
+void ASTReader::Error(const char *Msg) {
Diag(diag::err_fe_pch_malformed) << Msg;
}
-/// \brief Check the contents of the concatenation of all predefines buffers in
-/// the PCH chain against the contents of the predefines buffer of the current
-/// compiler invocation.
-///
-/// The contents should be the same. If not, then some command-line option
-/// changed the preprocessor state and we must probably reject the PCH file.
-///
-/// \returns true if there was a mismatch (in which case the PCH file
-/// should be ignored), or false otherwise.
-bool PCHReader::CheckPredefinesBuffers() {
+/// \brief Tell the AST listener about the predefines buffers in the chain.
+bool ASTReader::CheckPredefinesBuffers() {
if (Listener)
return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
ActualOriginalFileName,
@@ -722,7 +919,7 @@ bool PCHReader::CheckPredefinesBuffers() {
/// \brief Read the line table in the source manager block.
/// \returns true if ther was an error.
-bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
+bool ASTReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
unsigned Idx = 0;
LineTableInfo &LineTable = SourceMgr.getLineTable();
@@ -766,7 +963,7 @@ bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
namespace {
-class PCHStatData {
+class ASTStatData {
public:
const bool hasStat;
const ino_t ino;
@@ -775,19 +972,19 @@ public:
const time_t mtime;
const off_t size;
- PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
+ ASTStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
: hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
- PCHStatData()
+ ASTStatData()
: hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
};
-class PCHStatLookupTrait {
+class ASTStatLookupTrait {
public:
typedef const char *external_key_type;
typedef const char *internal_key_type;
- typedef PCHStatData data_type;
+ typedef ASTStatData data_type;
static unsigned ComputeHash(const char *path) {
return llvm::HashString(path);
@@ -830,13 +1027,13 @@ class PCHStatLookupTrait {
///
/// This cache is very similar to the stat cache used by pretokenized
/// headers.
-class PCHStatCache : public StatSysCallCache {
- typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
+class ASTStatCache : public StatSysCallCache {
+ typedef OnDiskChainedHashTable<ASTStatLookupTrait> CacheTy;
CacheTy *Cache;
unsigned &NumStatHits, &NumStatMisses;
public:
- PCHStatCache(const unsigned char *Buckets,
+ ASTStatCache(const unsigned char *Buckets,
const unsigned char *Base,
unsigned &NumStatHits,
unsigned &NumStatMisses)
@@ -844,20 +1041,20 @@ public:
Cache = CacheTy::Create(Buckets, Base);
}
- ~PCHStatCache() { delete Cache; }
+ ~ASTStatCache() { delete Cache; }
int stat(const char *path, struct stat *buf) {
- // Do the lookup for the file's data in the PCH file.
+ // Do the lookup for the file's data in the AST file.
CacheTy::iterator I = Cache->find(path);
- // If we don't get a hit in the PCH file just forward to 'stat'.
+ // If we don't get a hit in the AST file just forward to 'stat'.
if (I == Cache->end()) {
++NumStatMisses;
return StatSysCallCache::stat(path, buf);
}
++NumStatHits;
- PCHStatData Data = *I;
+ ASTStatData Data = *I;
if (!Data.hasStat)
return 1;
@@ -873,25 +1070,27 @@ public:
} // end anonymous namespace
-/// \brief Read the source manager block
-PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
+/// \brief Read a source manager block
+ASTReader::ASTReadResult ASTReader::ReadSourceManagerBlock(PerFileData &F) {
using namespace SrcMgr;
+ llvm::BitstreamCursor &SLocEntryCursor = F.SLocEntryCursor;
+
// Set the source-location entry cursor to the current position in
// the stream. This cursor will be used to read the contents of the
// source manager block initially, and then lazily read
// source-location entries as needed.
- SLocEntryCursor = Stream;
+ SLocEntryCursor = F.Stream;
// The stream itself is going to skip over the source manager block.
- if (Stream.SkipBlock()) {
- Error("malformed block record in PCH file");
+ if (F.Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
return Failure;
}
// Enter the source manager block.
- if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
- Error("malformed source manager block record in PCH file");
+ if (SLocEntryCursor.EnterSubBlock(SOURCE_MANAGER_BLOCK_ID)) {
+ Error("malformed source manager block record in AST file");
return Failure;
}
@@ -900,7 +1099,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
unsigned Code = SLocEntryCursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
if (SLocEntryCursor.ReadBlockEnd()) {
- Error("error at end of Source Manager block in PCH file");
+ Error("error at end of Source Manager block in AST file");
return Failure;
}
return Success;
@@ -910,7 +1109,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
// No known subblocks, always skip them.
SLocEntryCursor.ReadSubBlockID();
if (SLocEntryCursor.SkipBlock()) {
- Error("malformed block record in PCH file");
+ Error("malformed block record in AST file");
return Failure;
}
continue;
@@ -929,37 +1128,58 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
default: // Default behavior: ignore.
break;
- case pch::SM_LINE_TABLE:
+ case SM_LINE_TABLE:
if (ParseLineTable(Record))
return Failure;
break;
- case pch::SM_SLOC_FILE_ENTRY:
- case pch::SM_SLOC_BUFFER_ENTRY:
- case pch::SM_SLOC_INSTANTIATION_ENTRY:
+ case SM_SLOC_FILE_ENTRY:
+ case SM_SLOC_BUFFER_ENTRY:
+ case SM_SLOC_INSTANTIATION_ENTRY:
// Once we hit one of the source location entries, we're done.
return Success;
}
}
}
+/// \brief Get a cursor that's correctly positioned for reading the source
+/// location entry with the given ID.
+llvm::BitstreamCursor &ASTReader::SLocCursorForID(unsigned ID) {
+ assert(ID != 0 && ID <= TotalNumSLocEntries &&
+ "SLocCursorForID should only be called for real IDs.");
+
+ ID -= 1;
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ F = Chain[N - I - 1];
+ if (ID < F->LocalNumSLocEntries)
+ break;
+ ID -= F->LocalNumSLocEntries;
+ }
+ assert(F && F->LocalNumSLocEntries > ID && "Chain corrupted");
+
+ F->SLocEntryCursor.JumpToBit(F->SLocOffsets[ID]);
+ return F->SLocEntryCursor;
+}
+
/// \brief Read in the source location entry with the given ID.
-PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
+ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) {
if (ID == 0)
return Success;
if (ID > TotalNumSLocEntries) {
- Error("source location entry ID out-of-range for PCH file");
+ Error("source location entry ID out-of-range for AST file");
return Failure;
}
+ llvm::BitstreamCursor &SLocEntryCursor = SLocCursorForID(ID);
+
++NumSLocEntriesRead;
- SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
unsigned Code = SLocEntryCursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK ||
Code == llvm::bitc::ENTER_SUBBLOCK ||
Code == llvm::bitc::DEFINE_ABBREV) {
- Error("incorrectly-formatted source location entry in PCH file");
+ Error("incorrectly-formatted source location entry in AST file");
return Failure;
}
@@ -968,17 +1188,17 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
unsigned BlobLen;
switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
default:
- Error("incorrectly-formatted source location entry in PCH file");
+ Error("incorrectly-formatted source location entry in AST file");
return Failure;
- case pch::SM_SLOC_FILE_ENTRY: {
+ case SM_SLOC_FILE_ENTRY: {
std::string Filename(BlobStart, BlobStart + BlobLen);
MaybeAddSystemRootToFilename(Filename);
const FileEntry *File = FileMgr.getFile(Filename);
if (File == 0) {
std::string ErrorStr = "could not find file '";
ErrorStr += Filename;
- ErrorStr += "' referenced by PCH file";
+ ErrorStr += "' referenced by AST file";
Error(ErrorStr.c_str());
return Failure;
}
@@ -988,14 +1208,15 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
return Failure;
}
- if ((off_t)Record[4] != File->getSize()
+ if (!DisableValidation &&
+ ((off_t)Record[4] != File->getSize()
#if !defined(LLVM_ON_WIN32)
// In our regression testing, the Windows file system seems to
// have inconsistent modification times that sometimes
// erroneously trigger this error-handling path.
- || (time_t)Record[5] != File->getModificationTime()
+ || (time_t)Record[5] != File->getModificationTime()
#endif
- ) {
+ )) {
Diag(diag::err_fe_pch_file_modified)
<< Filename;
return Failure;
@@ -1020,7 +1241,7 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
break;
}
- case pch::SM_SLOC_BUFFER_ENTRY: {
+ case SM_SLOC_BUFFER_ENTRY: {
const char *Name = BlobStart;
unsigned Offset = Record[0];
unsigned Code = SLocEntryCursor.ReadCode();
@@ -1028,8 +1249,8 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
unsigned RecCode
= SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
- if (RecCode != pch::SM_SLOC_BUFFER_BLOB) {
- Error("PCH record has invalid code");
+ if (RecCode != SM_SLOC_BUFFER_BLOB) {
+ Error("AST record has invalid code");
return Failure;
}
@@ -1049,7 +1270,7 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
break;
}
- case pch::SM_SLOC_INSTANTIATION_ENTRY: {
+ case SM_SLOC_INSTANTIATION_ENTRY: {
SourceLocation SpellingLoc
= SourceLocation::getFromRawEncoding(Record[1]);
SourceMgr.createInstantiationLoc(SpellingLoc,
@@ -1068,10 +1289,10 @@ PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
/// specified cursor. Read the abbreviations that are at the top of the block
/// and then leave the cursor pointing into the block.
-bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
+bool ASTReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
unsigned BlockID) {
if (Cursor.EnterSubBlock(BlockID)) {
- Error("malformed block record in PCH file");
+ Error("malformed block record in AST file");
return Failure;
}
@@ -1085,7 +1306,7 @@ bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
}
}
-void PCHReader::ReadMacroRecord(uint64_t Offset) {
+void ASTReader::ReadMacroRecord(llvm::BitstreamCursor &Stream, uint64_t Offset){
assert(PP && "Forgot to set Preprocessor ?");
// Keep track of where we are in the stream, then jump back there
@@ -1107,7 +1328,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
// No known subblocks, always skip them.
Stream.ReadSubBlockID();
if (Stream.SkipBlock()) {
- Error("malformed block record in PCH file");
+ Error("malformed block record in AST file");
return;
}
continue;
@@ -1120,11 +1341,11 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
// Read a record.
Record.clear();
- pch::PreprocessorRecordTypes RecType =
- (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
+ PreprocessorRecordTypes RecType =
+ (PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
switch (RecType) {
- case pch::PP_MACRO_OBJECT_LIKE:
- case pch::PP_MACRO_FUNCTION_LIKE: {
+ case PP_MACRO_OBJECT_LIKE:
+ case PP_MACRO_FUNCTION_LIKE: {
// If we already have a macro, that means that we've hit the end
// of the definition of the macro we were looking for. We're
// done.
@@ -1133,7 +1354,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
if (II == 0) {
- Error("macro must have a name in PCH file");
+ Error("macro must have a name in AST file");
return;
}
SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
@@ -1141,9 +1362,10 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
MacroInfo *MI = PP->AllocateMacroInfo(Loc);
MI->setIsUsed(isUsed);
+ MI->setIsFromAST();
unsigned NextIndex = 3;
- if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
+ if (RecType == PP_MACRO_FUNCTION_LIKE) {
// Decode function-like macro info.
bool isC99VarArgs = Record[3];
bool isGNUVarArgs = Record[4];
@@ -1178,7 +1400,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
break;
}
- case pch::PP_TOKEN: {
+ case PP_TOKEN: {
// If we see a TOKEN before a PP_MACRO_*, then the file is
// erroneous, just pretend we didn't see this.
if (Macro == 0) break;
@@ -1195,7 +1417,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
break;
}
- case pch::PP_MACRO_INSTANTIATION: {
+ case PP_MACRO_INSTANTIATION: {
// If we already have a macro, that means that we've hit the end
// of the definition of the macro we were looking for. We're
// done.
@@ -1203,7 +1425,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
return;
if (!PP->getPreprocessingRecord()) {
- Error("missing preprocessing record in PCH file");
+ Error("missing preprocessing record in AST file");
return;
}
@@ -1221,7 +1443,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
return;
}
- case pch::PP_MACRO_DEFINITION: {
+ case PP_MACRO_DEFINITION: {
// If we already have a macro, that means that we've hit the end
// of the definition of the macro we were looking for. We're
// done.
@@ -1229,7 +1451,7 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
return;
if (!PP->getPreprocessingRecord()) {
- Error("missing preprocessing record in PCH file");
+ Error("missing preprocessing record in AST file");
return;
}
@@ -1256,81 +1478,97 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) {
}
}
-void PCHReader::ReadDefinedMacros() {
- // If there was no preprocessor block, do nothing.
- if (!MacroCursor.getBitStreamReader())
- return;
+void ASTReader::ReadDefinedMacros() {
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ llvm::BitstreamCursor &MacroCursor = Chain[N - I - 1]->MacroCursor;
- llvm::BitstreamCursor Cursor = MacroCursor;
- if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) {
- Error("malformed preprocessor block record in PCH file");
- return;
- }
+ // If there was no preprocessor block, skip this file.
+ if (!MacroCursor.getBitStreamReader())
+ continue;
- RecordData Record;
- while (true) {
- unsigned Code = Cursor.ReadCode();
- if (Code == llvm::bitc::END_BLOCK) {
- if (Cursor.ReadBlockEnd())
- Error("error at end of preprocessor block in PCH file");
+ llvm::BitstreamCursor Cursor = MacroCursor;
+ if (Cursor.EnterSubBlock(PREPROCESSOR_BLOCK_ID)) {
+ Error("malformed preprocessor block record in AST file");
return;
}
- if (Code == llvm::bitc::ENTER_SUBBLOCK) {
- // No known subblocks, always skip them.
- Cursor.ReadSubBlockID();
- if (Cursor.SkipBlock()) {
- Error("malformed block record in PCH file");
- return;
+ RecordData Record;
+ while (true) {
+ unsigned Code = Cursor.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (Cursor.ReadBlockEnd()) {
+ Error("error at end of preprocessor block in AST file");
+ return;
+ }
+ break;
}
- continue;
- }
- if (Code == llvm::bitc::DEFINE_ABBREV) {
- Cursor.ReadAbbrevRecord();
- continue;
- }
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ Cursor.ReadSubBlockID();
+ if (Cursor.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return;
+ }
+ continue;
+ }
- // Read a record.
- const char *BlobStart;
- unsigned BlobLen;
- Record.clear();
- switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
- default: // Default behavior: ignore.
- break;
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ Cursor.ReadAbbrevRecord();
+ continue;
+ }
- case pch::PP_MACRO_OBJECT_LIKE:
- case pch::PP_MACRO_FUNCTION_LIKE:
- DecodeIdentifierInfo(Record[0]);
- break;
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
- case pch::PP_TOKEN:
- // Ignore tokens.
- break;
+ case PP_MACRO_OBJECT_LIKE:
+ case PP_MACRO_FUNCTION_LIKE:
+ DecodeIdentifierInfo(Record[0]);
+ break;
+
+ case PP_TOKEN:
+ // Ignore tokens.
+ break;
- case pch::PP_MACRO_INSTANTIATION:
- case pch::PP_MACRO_DEFINITION:
- // Read the macro record.
- ReadMacroRecord(Cursor.GetCurrentBitNo());
- break;
+ case PP_MACRO_INSTANTIATION:
+ case PP_MACRO_DEFINITION:
+ // Read the macro record.
+ ReadMacroRecord(Chain[N - I - 1]->Stream, Cursor.GetCurrentBitNo());
+ break;
+ }
}
}
}
-MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) {
+MacroDefinition *ASTReader::getMacroDefinition(IdentID ID) {
if (ID == 0 || ID >= MacroDefinitionsLoaded.size())
return 0;
-
- if (!MacroDefinitionsLoaded[ID])
- ReadMacroRecord(MacroDefinitionOffsets[ID]);
-
+
+ if (!MacroDefinitionsLoaded[ID]) {
+ unsigned Index = ID;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ if (Index < F.LocalNumMacroDefinitions) {
+ ReadMacroRecord(F.Stream, F.MacroDefinitionOffsets[Index]);
+ break;
+ }
+ Index -= F.LocalNumMacroDefinitions;
+ }
+ assert(MacroDefinitionsLoaded[ID] && "Broken chain");
+ }
+
return MacroDefinitionsLoaded[ID];
}
/// \brief If we are loading a relocatable PCH file, and the filename is
/// not an absolute path, add the system root to the beginning of the file
/// name.
-void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
+void ASTReader::MaybeAddSystemRootToFilename(std::string &Filename) {
// If this is not a relocatable PCH file, there's nothing to do.
if (!RelocatablePCH)
return;
@@ -1351,20 +1589,23 @@ void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
Filename.insert(Filename.begin(), isysroot, isysroot + Length);
}
-PCHReader::PCHReadResult
-PCHReader::ReadPCHBlock() {
- if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
- Error("malformed block record in PCH file");
+ASTReader::ASTReadResult
+ASTReader::ReadASTBlock(PerFileData &F) {
+ llvm::BitstreamCursor &Stream = F.Stream;
+
+ if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Error("malformed block record in AST file");
return Failure;
}
- // Read all of the records and blocks for the PCH file.
+ // Read all of the records and blocks for the ASt file.
RecordData Record;
+ bool First = true;
while (!Stream.AtEndOfStream()) {
unsigned Code = Stream.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
if (Stream.ReadBlockEnd()) {
- Error("error at end of module block in PCH file");
+ Error("error at end of module block in AST file");
return Failure;
}
@@ -1373,38 +1614,38 @@ PCHReader::ReadPCHBlock() {
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
switch (Stream.ReadSubBlockID()) {
- case pch::DECLTYPES_BLOCK_ID:
+ case DECLTYPES_BLOCK_ID:
// We lazily load the decls block, but we want to set up the
// DeclsCursor cursor to point into it. Clone our current bitcode
// cursor to it, enter the block and read the abbrevs in that block.
// With the main cursor, we just skip over it.
- DeclsCursor = Stream;
+ F.DeclsCursor = Stream;
if (Stream.SkipBlock() || // Skip with the main cursor.
// Read the abbrevs.
- ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
- Error("malformed block record in PCH file");
+ ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
+ Error("malformed block record in AST file");
return Failure;
}
break;
- case pch::PREPROCESSOR_BLOCK_ID:
- MacroCursor = Stream;
+ case PREPROCESSOR_BLOCK_ID:
+ F.MacroCursor = Stream;
if (PP)
PP->setExternalSource(this);
if (Stream.SkipBlock()) {
- Error("malformed block record in PCH file");
+ Error("malformed block record in AST file");
return Failure;
}
break;
- case pch::SOURCE_MANAGER_BLOCK_ID:
- switch (ReadSourceManagerBlock()) {
+ case SOURCE_MANAGER_BLOCK_ID:
+ switch (ReadSourceManagerBlock(F)) {
case Success:
break;
case Failure:
- Error("malformed source manager block in PCH file");
+ Error("malformed source manager block in AST file");
return Failure;
case IgnorePCH:
@@ -1412,6 +1653,7 @@ PCHReader::ReadPCHBlock() {
}
break;
}
+ First = false;
continue;
}
@@ -1424,37 +1666,14 @@ PCHReader::ReadPCHBlock() {
Record.clear();
const char *BlobStart = 0;
unsigned BlobLen = 0;
- switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
+ switch ((ASTRecordTypes)Stream.ReadRecord(Code, Record,
&BlobStart, &BlobLen)) {
default: // Default behavior: ignore.
break;
- case pch::TYPE_OFFSET:
- if (!TypesLoaded.empty()) {
- Error("duplicate TYPE_OFFSET record in PCH file");
- return Failure;
- }
- TypeOffsets = (const uint32_t *)BlobStart;
- TypesLoaded.resize(Record[0]);
- break;
-
- case pch::DECL_OFFSET:
- if (!DeclsLoaded.empty()) {
- Error("duplicate DECL_OFFSET record in PCH file");
- return Failure;
- }
- DeclOffsets = (const uint32_t *)BlobStart;
- DeclsLoaded.resize(Record[0]);
- break;
-
- case pch::LANGUAGE_OPTIONS:
- if (ParseLanguageOptions(Record))
- return IgnorePCH;
- break;
-
- case pch::METADATA: {
- if (Record[0] != pch::VERSION_MAJOR) {
- Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
+ case METADATA: {
+ if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+ Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
: diag::warn_pch_version_too_new);
return IgnorePCH;
}
@@ -1468,195 +1687,419 @@ PCHReader::ReadPCHBlock() {
break;
}
- case pch::IDENTIFIER_TABLE:
- IdentifierTableData = BlobStart;
- if (Record[0]) {
- IdentifierLookupTable
- = PCHIdentifierLookupTable::Create(
- (const unsigned char *)IdentifierTableData + Record[0],
- (const unsigned char *)IdentifierTableData,
- PCHIdentifierLookupTrait(*this));
- if (PP)
- PP->getIdentifierTable().setExternalIdentifierLookup(this);
+ case CHAINED_METADATA: {
+ if (!First) {
+ Error("CHAINED_METADATA is not first record in block");
+ return Failure;
+ }
+ if (Record[0] != VERSION_MAJOR && !DisableValidation) {
+ Diag(Record[0] < VERSION_MAJOR? diag::warn_pch_version_too_old
+ : diag::warn_pch_version_too_new);
+ return IgnorePCH;
+ }
+
+ // Load the chained file.
+ switch(ReadASTCore(llvm::StringRef(BlobStart, BlobLen))) {
+ case Failure: return Failure;
+ // If we have to ignore the dependency, we'll have to ignore this too.
+ case IgnorePCH: return IgnorePCH;
+ case Success: break;
}
break;
+ }
- case pch::IDENTIFIER_OFFSET:
- if (!IdentifiersLoaded.empty()) {
- Error("duplicate IDENTIFIER_OFFSET record in PCH file");
+ case TYPE_OFFSET:
+ if (F.LocalNumTypes != 0) {
+ Error("duplicate TYPE_OFFSET record in AST file");
return Failure;
}
- IdentifierOffsets = (const uint32_t *)BlobStart;
- IdentifiersLoaded.resize(Record[0]);
- if (PP)
- PP->getHeaderSearchInfo().SetExternalLookup(this);
+ F.TypeOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumTypes = Record[0];
break;
- case pch::EXTERNAL_DEFINITIONS:
- if (!ExternalDefinitions.empty()) {
- Error("duplicate EXTERNAL_DEFINITIONS record in PCH file");
+ case DECL_OFFSET:
+ if (F.LocalNumDecls != 0) {
+ Error("duplicate DECL_OFFSET record in AST file");
return Failure;
}
- ExternalDefinitions.swap(Record);
+ F.DeclOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumDecls = Record[0];
break;
- case pch::SPECIAL_TYPES:
- SpecialTypes.swap(Record);
+ case TU_UPDATE_LEXICAL: {
+ DeclContextInfo Info = {
+ /* No visible information */ 0,
+ reinterpret_cast<const DeclID *>(BlobStart),
+ BlobLen / sizeof(DeclID)
+ };
+ DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info);
break;
+ }
- case pch::STATISTICS:
- TotalNumStatements = Record[0];
- TotalNumMacros = Record[1];
- TotalLexicalDeclContexts = Record[2];
- TotalVisibleDeclContexts = Record[3];
+ case UPDATE_VISIBLE: {
+ serialization::DeclID ID = Record[0];
+ void *Table = ASTDeclContextNameLookupTable::Create(
+ (const unsigned char *)BlobStart + Record[1],
+ (const unsigned char *)BlobStart,
+ ASTDeclContextNameLookupTrait(*this));
+ if (ID == 1) { // Is it the TU?
+ DeclContextInfo Info = {
+ Table, /* No lexical inforamtion */ 0, 0
+ };
+ DeclContextOffsets[Context->getTranslationUnitDecl()].push_back(Info);
+ } else
+ PendingVisibleUpdates[ID].push_back(Table);
break;
+ }
- case pch::TENTATIVE_DEFINITIONS:
- if (!TentativeDefinitions.empty()) {
- Error("duplicate TENTATIVE_DEFINITIONS record in PCH file");
- return Failure;
+ case REDECLS_UPDATE_LATEST: {
+ assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs");
+ for (unsigned i = 0, e = Record.size(); i < e; i += 2) {
+ DeclID First = Record[i], Latest = Record[i+1];
+ assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() ||
+ Latest > FirstLatestDeclIDs[First]) &&
+ "The new latest is supposed to come after the previous latest");
+ FirstLatestDeclIDs[First] = Latest;
}
- TentativeDefinitions.swap(Record);
break;
+ }
- case pch::UNUSED_STATIC_FUNCS:
- if (!UnusedStaticFuncs.empty()) {
- Error("duplicate UNUSED_STATIC_FUNCS record in PCH file");
- return Failure;
+ case LANGUAGE_OPTIONS:
+ if (ParseLanguageOptions(Record) && !DisableValidation)
+ return IgnorePCH;
+ break;
+
+ case IDENTIFIER_TABLE:
+ F.IdentifierTableData = BlobStart;
+ if (Record[0]) {
+ F.IdentifierLookupTable
+ = ASTIdentifierLookupTable::Create(
+ (const unsigned char *)F.IdentifierTableData + Record[0],
+ (const unsigned char *)F.IdentifierTableData,
+ ASTIdentifierLookupTrait(*this, F.Stream));
+ if (PP)
+ PP->getIdentifierTable().setExternalIdentifierLookup(this);
}
- UnusedStaticFuncs.swap(Record);
break;
- case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
- if (!LocallyScopedExternalDecls.empty()) {
- Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
+ case IDENTIFIER_OFFSET:
+ if (F.LocalNumIdentifiers != 0) {
+ Error("duplicate IDENTIFIER_OFFSET record in AST file");
return Failure;
}
- LocallyScopedExternalDecls.swap(Record);
+ F.IdentifierOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumIdentifiers = Record[0];
+ break;
+
+ case EXTERNAL_DEFINITIONS:
+ // Optimization for the first block.
+ if (ExternalDefinitions.empty())
+ ExternalDefinitions.swap(Record);
+ else
+ ExternalDefinitions.insert(ExternalDefinitions.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case SPECIAL_TYPES:
+ // Optimization for the first block
+ if (SpecialTypes.empty())
+ SpecialTypes.swap(Record);
+ else
+ SpecialTypes.insert(SpecialTypes.end(), Record.begin(), Record.end());
+ break;
+
+ case STATISTICS:
+ TotalNumStatements += Record[0];
+ TotalNumMacros += Record[1];
+ TotalLexicalDeclContexts += Record[2];
+ TotalVisibleDeclContexts += Record[3];
+ break;
+
+ case TENTATIVE_DEFINITIONS:
+ // Optimization for the first block.
+ if (TentativeDefinitions.empty())
+ TentativeDefinitions.swap(Record);
+ else
+ TentativeDefinitions.insert(TentativeDefinitions.end(),
+ Record.begin(), Record.end());
break;
- case pch::SELECTOR_OFFSETS:
- SelectorOffsets = (const uint32_t *)BlobStart;
- TotalNumSelectors = Record[0];
- SelectorsLoaded.resize(TotalNumSelectors);
+ case UNUSED_FILESCOPED_DECLS:
+ // Optimization for the first block.
+ if (UnusedFileScopedDecls.empty())
+ UnusedFileScopedDecls.swap(Record);
+ else
+ UnusedFileScopedDecls.insert(UnusedFileScopedDecls.end(),
+ Record.begin(), Record.end());
break;
- case pch::METHOD_POOL:
- MethodPoolLookupTableData = (const unsigned char *)BlobStart;
+ case WEAK_UNDECLARED_IDENTIFIERS:
+ // Later blocks overwrite earlier ones.
+ WeakUndeclaredIdentifiers.swap(Record);
+ break;
+
+ case LOCALLY_SCOPED_EXTERNAL_DECLS:
+ // Optimization for the first block.
+ if (LocallyScopedExternalDecls.empty())
+ LocallyScopedExternalDecls.swap(Record);
+ else
+ LocallyScopedExternalDecls.insert(LocallyScopedExternalDecls.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case SELECTOR_OFFSETS:
+ F.SelectorOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumSelectors = Record[0];
+ break;
+
+ case METHOD_POOL:
+ F.SelectorLookupTableData = (const unsigned char *)BlobStart;
if (Record[0])
- MethodPoolLookupTable
- = PCHMethodPoolLookupTable::Create(
- MethodPoolLookupTableData + Record[0],
- MethodPoolLookupTableData,
- PCHMethodPoolLookupTrait(*this));
- TotalSelectorsInMethodPool = Record[1];
+ F.SelectorLookupTable
+ = ASTSelectorLookupTable::Create(
+ F.SelectorLookupTableData + Record[0],
+ F.SelectorLookupTableData,
+ ASTSelectorLookupTrait(*this));
+ TotalNumMethodPoolEntries += Record[1];
break;
- case pch::PP_COUNTER_VALUE:
+ case REFERENCED_SELECTOR_POOL: {
+ ReferencedSelectorsData.insert(ReferencedSelectorsData.end(),
+ Record.begin(), Record.end());
+ break;
+ }
+
+ case PP_COUNTER_VALUE:
if (!Record.empty() && Listener)
Listener->ReadCounter(Record[0]);
break;
- case pch::SOURCE_LOCATION_OFFSETS:
- SLocOffsets = (const uint32_t *)BlobStart;
- TotalNumSLocEntries = Record[0];
+ case SOURCE_LOCATION_OFFSETS:
+ F.SLocOffsets = (const uint32_t *)BlobStart;
+ F.LocalNumSLocEntries = Record[0];
+ // We cannot delay this until the entire chain is loaded, because then
+ // source location preloads would also have to be delayed.
+ // FIXME: Is there a reason not to do that?
+ TotalNumSLocEntries += F.LocalNumSLocEntries;
SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]);
break;
- case pch::SOURCE_LOCATION_PRELOADS:
+ case SOURCE_LOCATION_PRELOADS:
for (unsigned I = 0, N = Record.size(); I != N; ++I) {
- PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
+ ASTReadResult Result = ReadSLocEntryRecord(Record[I]);
if (Result != Success)
return Result;
}
break;
- case pch::STAT_CACHE: {
- PCHStatCache *MyStatCache =
- new PCHStatCache((const unsigned char *)BlobStart + Record[0],
+ case STAT_CACHE: {
+ ASTStatCache *MyStatCache =
+ new ASTStatCache((const unsigned char *)BlobStart + Record[0],
(const unsigned char *)BlobStart,
NumStatHits, NumStatMisses);
FileMgr.addStatCache(MyStatCache);
- StatCache = MyStatCache;
+ F.StatCache = MyStatCache;
break;
}
- case pch::EXT_VECTOR_DECLS:
- if (!ExtVectorDecls.empty()) {
- Error("duplicate EXT_VECTOR_DECLS record in PCH file");
- return Failure;
- }
- ExtVectorDecls.swap(Record);
+ case EXT_VECTOR_DECLS:
+ // Optimization for the first block.
+ if (ExtVectorDecls.empty())
+ ExtVectorDecls.swap(Record);
+ else
+ ExtVectorDecls.insert(ExtVectorDecls.end(),
+ Record.begin(), Record.end());
break;
- case pch::VTABLE_USES:
- if (!VTableUses.empty()) {
- Error("duplicate VTABLE_USES record in PCH file");
- return Failure;
- }
+ case VTABLE_USES:
+ // Later tables overwrite earlier ones.
VTableUses.swap(Record);
break;
- case pch::DYNAMIC_CLASSES:
- if (!DynamicClasses.empty()) {
- Error("duplicate DYNAMIC_CLASSES record in PCH file");
- return Failure;
- }
- DynamicClasses.swap(Record);
+ case DYNAMIC_CLASSES:
+ // Optimization for the first block.
+ if (DynamicClasses.empty())
+ DynamicClasses.swap(Record);
+ else
+ DynamicClasses.insert(DynamicClasses.end(),
+ Record.begin(), Record.end());
+ break;
+
+ case PENDING_IMPLICIT_INSTANTIATIONS:
+ // Optimization for the first block.
+ if (PendingInstantiations.empty())
+ PendingInstantiations.swap(Record);
+ else
+ PendingInstantiations.insert(PendingInstantiations.end(),
+ Record.begin(), Record.end());
break;
- case pch::ORIGINAL_FILE_NAME:
+ case SEMA_DECL_REFS:
+ // Later tables overwrite earlier ones.
+ SemaDeclRefs.swap(Record);
+ break;
+
+ case ORIGINAL_FILE_NAME:
+ // The primary AST will be the last to get here, so it will be the one
+ // that's used.
ActualOriginalFileName.assign(BlobStart, BlobLen);
OriginalFileName = ActualOriginalFileName;
MaybeAddSystemRootToFilename(OriginalFileName);
break;
- case pch::VERSION_CONTROL_BRANCH_REVISION: {
+ case VERSION_CONTROL_BRANCH_REVISION: {
const std::string &CurBranch = getClangFullRepositoryVersion();
- llvm::StringRef PCHBranch(BlobStart, BlobLen);
- if (llvm::StringRef(CurBranch) != PCHBranch) {
- Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
+ llvm::StringRef ASTBranch(BlobStart, BlobLen);
+ if (llvm::StringRef(CurBranch) != ASTBranch && !DisableValidation) {
+ Diag(diag::warn_pch_different_branch) << ASTBranch << CurBranch;
return IgnorePCH;
}
break;
}
-
- case pch::MACRO_DEFINITION_OFFSETS:
- MacroDefinitionOffsets = (const uint32_t *)BlobStart;
- if (PP) {
- if (!PP->getPreprocessingRecord())
- PP->createPreprocessingRecord();
- PP->getPreprocessingRecord()->SetExternalSource(*this, Record[0]);
- } else {
- NumPreallocatedPreprocessingEntities = Record[0];
+
+ case MACRO_DEFINITION_OFFSETS:
+ F.MacroDefinitionOffsets = (const uint32_t *)BlobStart;
+ F.NumPreallocatedPreprocessingEntities = Record[0];
+ F.LocalNumMacroDefinitions = Record[1];
+ break;
+
+ case DECL_REPLACEMENTS: {
+ if (Record.size() % 2 != 0) {
+ Error("invalid DECL_REPLACEMENTS block in AST file");
+ return Failure;
}
-
- MacroDefinitionsLoaded.resize(Record[1]);
+ for (unsigned I = 0, N = Record.size(); I != N; I += 2)
+ ReplacedDecls[static_cast<DeclID>(Record[I])] =
+ std::make_pair(&F, Record[I+1]);
break;
}
+
+ case ADDITIONAL_TEMPLATE_SPECIALIZATIONS: {
+ AdditionalTemplateSpecializations &ATS =
+ AdditionalTemplateSpecializationsPending[Record[0]];
+ ATS.insert(ATS.end(), Record.begin()+1, Record.end());
+ break;
+ }
+ }
+ First = false;
}
- Error("premature end of bitstream in PCH file");
+ Error("premature end of bitstream in AST file");
return Failure;
}
-PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
- // Set the PCH file name.
- this->FileName = FileName;
+ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName) {
+ switch(ReadASTCore(FileName)) {
+ case Failure: return Failure;
+ case IgnorePCH: return IgnorePCH;
+ case Success: break;
+ }
+
+ // Here comes stuff that we only do once the entire chain is loaded.
+
+ // Allocate space for loaded identifiers, decls and types.
+ unsigned TotalNumIdentifiers = 0, TotalNumTypes = 0, TotalNumDecls = 0,
+ TotalNumPreallocatedPreprocessingEntities = 0, TotalNumMacroDefs = 0,
+ TotalNumSelectors = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ TotalNumIdentifiers += Chain[I]->LocalNumIdentifiers;
+ TotalNumTypes += Chain[I]->LocalNumTypes;
+ TotalNumDecls += Chain[I]->LocalNumDecls;
+ TotalNumPreallocatedPreprocessingEntities +=
+ Chain[I]->NumPreallocatedPreprocessingEntities;
+ TotalNumMacroDefs += Chain[I]->LocalNumMacroDefinitions;
+ TotalNumSelectors += Chain[I]->LocalNumSelectors;
+ }
+ IdentifiersLoaded.resize(TotalNumIdentifiers);
+ TypesLoaded.resize(TotalNumTypes);
+ DeclsLoaded.resize(TotalNumDecls);
+ MacroDefinitionsLoaded.resize(TotalNumMacroDefs);
+ if (PP) {
+ if (TotalNumIdentifiers > 0)
+ PP->getHeaderSearchInfo().SetExternalLookup(this);
+ if (TotalNumPreallocatedPreprocessingEntities > 0) {
+ if (!PP->getPreprocessingRecord())
+ PP->createPreprocessingRecord();
+ PP->getPreprocessingRecord()->SetExternalSource(*this,
+ TotalNumPreallocatedPreprocessingEntities);
+ }
+ }
+ SelectorsLoaded.resize(TotalNumSelectors);
+
+ // Check the predefines buffers.
+ if (!DisableValidation && CheckPredefinesBuffers())
+ return IgnorePCH;
+
+ if (PP) {
+ // Initialization of keywords and pragmas occurs before the
+ // AST file is read, so there may be some identifiers that were
+ // loaded into the IdentifierTable before we intercepted the
+ // creation of identifiers. Iterate through the list of known
+ // identifiers and determine whether we have to establish
+ // preprocessor definitions or top-level identifier declaration
+ // chains for those identifiers.
+ //
+ // We copy the IdentifierInfo pointers to a small vector first,
+ // since de-serializing declarations or macro definitions can add
+ // new entries into the identifier table, invalidating the
+ // iterators.
+ llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
+ for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
+ IdEnd = PP->getIdentifierTable().end();
+ Id != IdEnd; ++Id)
+ Identifiers.push_back(Id->second);
+ // We need to search the tables in all files.
+ for (unsigned J = 0, M = Chain.size(); J != M; ++J) {
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Chain[J]->IdentifierLookupTable;
+ // Not all AST files necessarily have identifier tables, only the useful
+ // ones.
+ if (!IdTable)
+ continue;
+ for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
+ IdentifierInfo *II = Identifiers[I];
+ // Look in the on-disk hash tables for an entry for this identifier
+ ASTIdentifierLookupTrait Info(*this, Chain[J]->Stream, II);
+ std::pair<const char*,unsigned> Key(II->getNameStart(),II->getLength());
+ ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
+ if (Pos == IdTable->end())
+ continue;
+
+ // Dereferencing the iterator has the effect of populating the
+ // IdentifierInfo node with the various declarations it needs.
+ (void)*Pos;
+ }
+ }
+ }
+
+ if (Context)
+ InitializeContext(*Context);
+
+ return Success;
+}
+
+ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName) {
+ Chain.push_back(new PerFileData());
+ PerFileData &F = *Chain.back();
+
+ // Set the AST file name.
+ F.FileName = FileName;
- // Open the PCH file.
+ // Open the AST file.
//
// FIXME: This shouldn't be here, we should just take a raw_ostream.
std::string ErrStr;
- Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
- if (!Buffer) {
+ F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
+ if (!F.Buffer) {
Error(ErrStr.c_str());
return IgnorePCH;
}
// Initialize the stream
- StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
- (const unsigned char *)Buffer->getBufferEnd());
- Stream.init(StreamFile);
+ F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(),
+ (const unsigned char *)F.Buffer->getBufferEnd());
+ llvm::BitstreamCursor &Stream = F.Stream;
+ Stream.init(F.StreamFile);
+ F.SizeInBits = F.Buffer->getBufferSize() * 8;
// Sniff for the signature.
if (Stream.Read(8) != 'C' ||
@@ -1671,22 +2114,22 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
unsigned Code = Stream.ReadCode();
if (Code != llvm::bitc::ENTER_SUBBLOCK) {
- Error("invalid record at top-level of PCH file");
+ Error("invalid record at top-level of AST file");
return Failure;
}
unsigned BlockID = Stream.ReadSubBlockID();
- // We only know the PCH subblock ID.
+ // We only know the AST subblock ID.
switch (BlockID) {
case llvm::bitc::BLOCKINFO_BLOCK_ID:
if (Stream.ReadBlockInfoBlock()) {
- Error("malformed BlockInfoBlock in PCH file");
+ Error("malformed BlockInfoBlock in AST file");
return Failure;
}
break;
- case pch::PCH_BLOCK_ID:
- switch (ReadPCHBlock()) {
+ case AST_BLOCK_ID:
+ switch (ReadASTBlock(F)) {
case Success:
break;
@@ -1695,87 +2138,46 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
case IgnorePCH:
// FIXME: We could consider reading through to the end of this
- // PCH block, skipping subblocks, to see if there are other
- // PCH blocks elsewhere.
+ // AST block, skipping subblocks, to see if there are other
+ // AST blocks elsewhere.
// Clear out any preallocated source location entries, so that
// the source manager does not try to resolve them later.
SourceMgr.ClearPreallocatedSLocEntries();
// Remove the stat cache.
- if (StatCache)
- FileMgr.removeStatCache((PCHStatCache*)StatCache);
+ if (F.StatCache)
+ FileMgr.removeStatCache((ASTStatCache*)F.StatCache);
return IgnorePCH;
}
break;
default:
if (Stream.SkipBlock()) {
- Error("malformed block record in PCH file");
+ Error("malformed block record in AST file");
return Failure;
}
break;
}
}
- // Check the predefines buffer.
- if (CheckPredefinesBuffers())
- return IgnorePCH;
-
- if (PP) {
- // Initialization of keywords and pragmas occurs before the
- // PCH file is read, so there may be some identifiers that were
- // loaded into the IdentifierTable before we intercepted the
- // creation of identifiers. Iterate through the list of known
- // identifiers and determine whether we have to establish
- // preprocessor definitions or top-level identifier declaration
- // chains for those identifiers.
- //
- // We copy the IdentifierInfo pointers to a small vector first,
- // since de-serializing declarations or macro definitions can add
- // new entries into the identifier table, invalidating the
- // iterators.
- llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
- for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
- IdEnd = PP->getIdentifierTable().end();
- Id != IdEnd; ++Id)
- Identifiers.push_back(Id->second);
- PCHIdentifierLookupTable *IdTable
- = (PCHIdentifierLookupTable *)IdentifierLookupTable;
- for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
- IdentifierInfo *II = Identifiers[I];
- // Look in the on-disk hash table for an entry for
- PCHIdentifierLookupTrait Info(*this, II);
- std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
- PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
- if (Pos == IdTable->end())
- continue;
-
- // Dereferencing the iterator has the effect of populating the
- // IdentifierInfo node with the various declarations it needs.
- (void)*Pos;
- }
- }
-
- if (Context)
- InitializeContext(*Context);
-
return Success;
}
-void PCHReader::setPreprocessor(Preprocessor &pp) {
+void ASTReader::setPreprocessor(Preprocessor &pp) {
PP = &pp;
-
- if (NumPreallocatedPreprocessingEntities) {
+
+ unsigned TotalNum = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I)
+ TotalNum += Chain[I]->NumPreallocatedPreprocessingEntities;
+ if (TotalNum) {
if (!PP->getPreprocessingRecord())
PP->createPreprocessingRecord();
- PP->getPreprocessingRecord()->SetExternalSource(*this,
- NumPreallocatedPreprocessingEntities);
- NumPreallocatedPreprocessingEntities = 0;
+ PP->getPreprocessingRecord()->SetExternalSource(*this, TotalNum);
}
}
-void PCHReader::InitializeContext(ASTContext &Ctx) {
+void ASTReader::InitializeContext(ASTContext &Ctx) {
Context = &Ctx;
assert(Context && "Passed null context!");
@@ -1789,22 +2191,22 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
// Load the special types.
Context->setBuiltinVaListType(
- GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
- if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
+ GetType(SpecialTypes[SPECIAL_TYPE_BUILTIN_VA_LIST]));
+ if (unsigned Id = SpecialTypes[SPECIAL_TYPE_OBJC_ID])
Context->setObjCIdType(GetType(Id));
- if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
+ if (unsigned Sel = SpecialTypes[SPECIAL_TYPE_OBJC_SELECTOR])
Context->setObjCSelType(GetType(Sel));
- if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
+ if (unsigned Proto = SpecialTypes[SPECIAL_TYPE_OBJC_PROTOCOL])
Context->setObjCProtoType(GetType(Proto));
- if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
+ if (unsigned Class = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS])
Context->setObjCClassType(GetType(Class));
- if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_CF_CONSTANT_STRING])
Context->setCFConstantStringType(GetType(String));
if (unsigned FastEnum
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
+ = SpecialTypes[SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
Context->setObjCFastEnumerationStateType(GetType(FastEnum));
- if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) {
+ if (unsigned File = SpecialTypes[SPECIAL_TYPE_FILE]) {
QualType FileType = GetType(File);
if (FileType.isNull()) {
Error("FILE type is NULL");
@@ -1815,13 +2217,13 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
else {
const TagType *Tag = FileType->getAs<TagType>();
if (!Tag) {
- Error("Invalid FILE type in PCH file");
+ Error("Invalid FILE type in AST file");
return;
}
Context->setFILEDecl(Tag->getDecl());
}
}
- if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) {
+ if (unsigned Jmp_buf = SpecialTypes[SPECIAL_TYPE_jmp_buf]) {
QualType Jmp_bufType = GetType(Jmp_buf);
if (Jmp_bufType.isNull()) {
Error("jmp_bug type is NULL");
@@ -1832,13 +2234,13 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
else {
const TagType *Tag = Jmp_bufType->getAs<TagType>();
if (!Tag) {
- Error("Invalid jmp_bug type in PCH file");
+ Error("Invalid jmp_buf type in AST file");
return;
}
Context->setjmp_bufDecl(Tag->getDecl());
}
}
- if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) {
+ if (unsigned Sigjmp_buf = SpecialTypes[SPECIAL_TYPE_sigjmp_buf]) {
QualType Sigjmp_bufType = GetType(Sigjmp_buf);
if (Sigjmp_bufType.isNull()) {
Error("sigjmp_buf type is NULL");
@@ -1848,40 +2250,40 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {
Context->setsigjmp_bufDecl(Typedef->getDecl());
else {
const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
- assert(Tag && "Invalid sigjmp_buf type in PCH file");
+ assert(Tag && "Invalid sigjmp_buf type in AST file");
Context->setsigjmp_bufDecl(Tag->getDecl());
}
}
if (unsigned ObjCIdRedef
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION])
+ = SpecialTypes[SPECIAL_TYPE_OBJC_ID_REDEFINITION])
Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
if (unsigned ObjCClassRedef
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
+ = SpecialTypes[SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
- if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_BLOCK_DESCRIPTOR])
Context->setBlockDescriptorType(GetType(String));
if (unsigned String
- = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
+ = SpecialTypes[SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
Context->setBlockDescriptorExtendedType(GetType(String));
if (unsigned ObjCSelRedef
- = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION])
+ = SpecialTypes[SPECIAL_TYPE_OBJC_SEL_REDEFINITION])
Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef);
- if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_NS_CONSTANT_STRING])
+ if (unsigned String = SpecialTypes[SPECIAL_TYPE_NS_CONSTANT_STRING])
Context->setNSConstantStringType(GetType(String));
- if (SpecialTypes[pch::SPECIAL_TYPE_INT128_INSTALLED])
+ if (SpecialTypes[SPECIAL_TYPE_INT128_INSTALLED])
Context->setInt128Installed();
}
/// \brief Retrieve the name of the original source file name
-/// directly from the PCH file, without actually loading the PCH
+/// directly from the AST file, without actually loading the AST
/// file.
-std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
+std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
Diagnostic &Diags) {
- // Open the PCH file.
+ // Open the AST file.
std::string ErrStr;
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
- Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
+ Buffer.reset(llvm::MemoryBuffer::getFile(ASTFileName.c_str(), &ErrStr));
if (!Buffer) {
Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr;
return std::string();
@@ -1899,7 +2301,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
Stream.Read(8) != 'P' ||
Stream.Read(8) != 'C' ||
Stream.Read(8) != 'H') {
- Diags.Report(diag::err_fe_not_a_pch_file) << PCHFileName;
+ Diags.Report(diag::err_fe_not_a_pch_file) << ASTFileName;
return std::string();
}
@@ -1910,18 +2312,18 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
if (Code == llvm::bitc::ENTER_SUBBLOCK) {
unsigned BlockID = Stream.ReadSubBlockID();
- // We only know the PCH subblock ID.
+ // We only know the AST subblock ID.
switch (BlockID) {
- case pch::PCH_BLOCK_ID:
- if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
- Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
+ case AST_BLOCK_ID:
+ if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
+ Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
return std::string();
}
break;
default:
if (Stream.SkipBlock()) {
- Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName;
+ Diags.Report(diag::err_fe_pch_malformed_block) << ASTFileName;
return std::string();
}
break;
@@ -1931,7 +2333,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
if (Code == llvm::bitc::END_BLOCK) {
if (Stream.ReadBlockEnd()) {
- Diags.Report(diag::err_fe_pch_error_at_end_block) << PCHFileName;
+ Diags.Report(diag::err_fe_pch_error_at_end_block) << ASTFileName;
return std::string();
}
continue;
@@ -1946,7 +2348,7 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
const char *BlobStart = 0;
unsigned BlobLen = 0;
if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
- == pch::ORIGINAL_FILE_NAME)
+ == ORIGINAL_FILE_NAME)
return std::string(BlobStart, BlobLen);
}
@@ -1956,18 +2358,11 @@ std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName,
/// \brief Parse the record that corresponds to a LangOptions data
/// structure.
///
-/// This routine compares the language options used to generate the
-/// PCH file against the language options set for the current
-/// compilation. For each option, we classify differences between the
-/// two compiler states as either "benign" or "important". Benign
-/// differences don't matter, and we accept them without complaint
-/// (and without modifying the language options). Differences between
-/// the states for important options cause the PCH file to be
-/// unusable, so we emit a warning and return true to indicate that
-/// there was an error.
+/// This routine parses the language options from the AST file and then gives
+/// them to the AST listener if one is set.
///
-/// \returns true if the PCH file is unacceptable, false otherwise.
-bool PCHReader::ParseLanguageOptions(
+/// \returns true if the listener deems the file unacceptable, false otherwise.
+bool ASTReader::ParseLanguageOptions(
const llvm::SmallVectorImpl<uint64_t> &Record) {
if (Listener) {
LangOptions LangOpts;
@@ -2038,30 +2433,47 @@ bool PCHReader::ParseLanguageOptions(
return false;
}
-void PCHReader::ReadPreprocessedEntities() {
+void ASTReader::ReadPreprocessedEntities() {
ReadDefinedMacros();
}
-/// \brief Read and return the type at the given offset.
+/// \brief Get the correct cursor and offset for loading a type.
+ASTReader::RecordLocation ASTReader::TypeCursorForIndex(unsigned Index) {
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ F = Chain[N - I - 1];
+ if (Index < F->LocalNumTypes)
+ break;
+ Index -= F->LocalNumTypes;
+ }
+ assert(F && F->LocalNumTypes > Index && "Broken chain");
+ return RecordLocation(&F->DeclsCursor, F->TypeOffsets[Index]);
+}
+
+/// \brief Read and return the type with the given index..
///
-/// This routine actually reads the record corresponding to the type
-/// at the given offset in the bitstream. It is a helper routine for
-/// GetType, which deals with reading type IDs.
-QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
+/// The index is the type ID, shifted and minus the number of predefs. This
+/// routine actually reads the record corresponding to the type at the given
+/// location. It is a helper routine for GetType, which deals with reading type
+/// IDs.
+QualType ASTReader::ReadTypeRecord(unsigned Index) {
+ RecordLocation Loc = TypeCursorForIndex(Index);
+ llvm::BitstreamCursor &DeclsCursor = *Loc.first;
+
// Keep track of where we are in the stream, then jump back there
// after reading this type.
SavedStreamPosition SavedPosition(DeclsCursor);
ReadingKindTracker ReadingKind(Read_Type, *this);
-
+
// Note that we are loading a type record.
- LoadingTypeOrDecl Loading(*this);
+ Deserializing AType(this);
- DeclsCursor.JumpToBit(Offset);
+ DeclsCursor.JumpToBit(Loc.second);
RecordData Record;
unsigned Code = DeclsCursor.ReadCode();
- switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
- case pch::TYPE_EXT_QUAL: {
+ switch ((TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
+ case TYPE_EXT_QUAL: {
if (Record.size() != 2) {
Error("Incorrect encoding of extended qualifier type");
return QualType();
@@ -2071,7 +2483,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getQualifiedType(Base, Quals);
}
- case pch::TYPE_COMPLEX: {
+ case TYPE_COMPLEX: {
if (Record.size() != 1) {
Error("Incorrect encoding of complex type");
return QualType();
@@ -2080,7 +2492,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getComplexType(ElemType);
}
- case pch::TYPE_POINTER: {
+ case TYPE_POINTER: {
if (Record.size() != 1) {
Error("Incorrect encoding of pointer type");
return QualType();
@@ -2089,7 +2501,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getPointerType(PointeeType);
}
- case pch::TYPE_BLOCK_POINTER: {
+ case TYPE_BLOCK_POINTER: {
if (Record.size() != 1) {
Error("Incorrect encoding of block pointer type");
return QualType();
@@ -2098,7 +2510,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getBlockPointerType(PointeeType);
}
- case pch::TYPE_LVALUE_REFERENCE: {
+ case TYPE_LVALUE_REFERENCE: {
if (Record.size() != 1) {
Error("Incorrect encoding of lvalue reference type");
return QualType();
@@ -2107,7 +2519,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getLValueReferenceType(PointeeType);
}
- case pch::TYPE_RVALUE_REFERENCE: {
+ case TYPE_RVALUE_REFERENCE: {
if (Record.size() != 1) {
Error("Incorrect encoding of rvalue reference type");
return QualType();
@@ -2116,7 +2528,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getRValueReferenceType(PointeeType);
}
- case pch::TYPE_MEMBER_POINTER: {
+ case TYPE_MEMBER_POINTER: {
if (Record.size() != 2) {
Error("Incorrect encoding of member pointer type");
return QualType();
@@ -2126,7 +2538,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
}
- case pch::TYPE_CONSTANT_ARRAY: {
+ case TYPE_CONSTANT_ARRAY: {
QualType ElementType = GetType(Record[0]);
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
unsigned IndexTypeQuals = Record[2];
@@ -2136,27 +2548,27 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
ASM, IndexTypeQuals);
}
- case pch::TYPE_INCOMPLETE_ARRAY: {
+ case TYPE_INCOMPLETE_ARRAY: {
QualType ElementType = GetType(Record[0]);
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
unsigned IndexTypeQuals = Record[2];
return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
}
- case pch::TYPE_VARIABLE_ARRAY: {
+ case TYPE_VARIABLE_ARRAY: {
QualType ElementType = GetType(Record[0]);
ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
unsigned IndexTypeQuals = Record[2];
SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
- return Context->getVariableArrayType(ElementType, ReadExpr(),
+ return Context->getVariableArrayType(ElementType, ReadExpr(DeclsCursor),
ASM, IndexTypeQuals,
SourceRange(LBLoc, RBLoc));
}
- case pch::TYPE_VECTOR: {
+ case TYPE_VECTOR: {
if (Record.size() != 3) {
- Error("incorrect encoding of vector type in PCH file");
+ Error("incorrect encoding of vector type in AST file");
return QualType();
}
@@ -2167,9 +2579,9 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
(VectorType::AltiVecSpecific)AltiVecSpec);
}
- case pch::TYPE_EXT_VECTOR: {
+ case TYPE_EXT_VECTOR: {
if (Record.size() != 3) {
- Error("incorrect encoding of extended vector type in PCH file");
+ Error("incorrect encoding of extended vector type in AST file");
return QualType();
}
@@ -2178,7 +2590,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getExtVectorType(ElementType, NumElements);
}
- case pch::TYPE_FUNCTION_NO_PROTO: {
+ case TYPE_FUNCTION_NO_PROTO: {
if (Record.size() != 4) {
Error("incorrect encoding of no-proto function type");
return QualType();
@@ -2188,7 +2600,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getFunctionNoProtoType(ResultType, Info);
}
- case pch::TYPE_FUNCTION_PROTO: {
+ case TYPE_FUNCTION_PROTO: {
QualType ResultType = GetType(Record[0]);
bool NoReturn = Record[1];
unsigned RegParm = Record[2];
@@ -2214,11 +2626,11 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
CallConv));
}
- case pch::TYPE_UNRESOLVED_USING:
+ case TYPE_UNRESOLVED_USING:
return Context->getTypeDeclType(
cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
- case pch::TYPE_TYPEDEF: {
+ case TYPE_TYPEDEF: {
if (Record.size() != 2) {
Error("incorrect encoding of typedef type");
return QualType();
@@ -2228,22 +2640,22 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getTypedefType(Decl, Canonical);
}
- case pch::TYPE_TYPEOF_EXPR:
- return Context->getTypeOfExprType(ReadExpr());
+ case TYPE_TYPEOF_EXPR:
+ return Context->getTypeOfExprType(ReadExpr(DeclsCursor));
- case pch::TYPE_TYPEOF: {
+ case TYPE_TYPEOF: {
if (Record.size() != 1) {
- Error("incorrect encoding of typeof(type) in PCH file");
+ Error("incorrect encoding of typeof(type) in AST file");
return QualType();
}
QualType UnderlyingType = GetType(Record[0]);
return Context->getTypeOfType(UnderlyingType);
}
- case pch::TYPE_DECLTYPE:
- return Context->getDecltypeType(ReadExpr());
+ case TYPE_DECLTYPE:
+ return Context->getDecltypeType(ReadExpr(DeclsCursor));
- case pch::TYPE_RECORD: {
+ case TYPE_RECORD: {
if (Record.size() != 2) {
Error("incorrect encoding of record type");
return QualType();
@@ -2254,7 +2666,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return T;
}
- case pch::TYPE_ENUM: {
+ case TYPE_ENUM: {
if (Record.size() != 2) {
Error("incorrect encoding of enum type");
return QualType();
@@ -2265,7 +2677,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return T;
}
- case pch::TYPE_ELABORATED: {
+ case TYPE_ELABORATED: {
unsigned Idx = 0;
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
@@ -2273,13 +2685,13 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getElaboratedType(Keyword, NNS, NamedType);
}
- case pch::TYPE_OBJC_INTERFACE: {
+ case TYPE_OBJC_INTERFACE: {
unsigned Idx = 0;
ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
return Context->getObjCInterfaceType(ItfD);
}
- case pch::TYPE_OBJC_OBJECT: {
+ case TYPE_OBJC_OBJECT: {
unsigned Idx = 0;
QualType Base = GetType(Record[Idx++]);
unsigned NumProtos = Record[Idx++];
@@ -2289,13 +2701,13 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getObjCObjectType(Base, Protos.data(), NumProtos);
}
- case pch::TYPE_OBJC_OBJECT_POINTER: {
+ case TYPE_OBJC_OBJECT_POINTER: {
unsigned Idx = 0;
QualType Pointee = GetType(Record[Idx++]);
return Context->getObjCObjectPointerType(Pointee);
}
- case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
+ case TYPE_SUBST_TEMPLATE_TYPE_PARM: {
unsigned Idx = 0;
QualType Parm = GetType(Record[Idx++]);
QualType Replacement = GetType(Record[Idx++]);
@@ -2304,16 +2716,16 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Replacement);
}
- case pch::TYPE_INJECTED_CLASS_NAME: {
+ case TYPE_INJECTED_CLASS_NAME: {
CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0]));
QualType TST = GetType(Record[1]); // probably derivable
// FIXME: ASTContext::getInjectedClassNameType is not currently suitable
- // for PCH reading, too much interdependencies.
+ // for AST reading, too much interdependencies.
return
QualType(new (*Context, TypeAlignment) InjectedClassNameType(D, TST), 0);
}
- case pch::TYPE_TEMPLATE_TYPE_PARM: {
+ case TYPE_TEMPLATE_TYPE_PARM: {
unsigned Idx = 0;
unsigned Depth = Record[Idx++];
unsigned Index = Record[Idx++];
@@ -2322,7 +2734,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getTemplateTypeParmType(Depth, Index, Pack, Name);
}
- case pch::TYPE_DEPENDENT_NAME: {
+ case TYPE_DEPENDENT_NAME: {
unsigned Idx = 0;
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
@@ -2331,7 +2743,7 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
return Context->getDependentNameType(Keyword, NNS, Name, Canon);
}
- case pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
+ case TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: {
unsigned Idx = 0;
ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++];
NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx);
@@ -2340,12 +2752,12 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
llvm::SmallVector<TemplateArgument, 8> Args;
Args.reserve(NumArgs);
while (NumArgs--)
- Args.push_back(ReadTemplateArgument(Record, Idx));
+ Args.push_back(ReadTemplateArgument(DeclsCursor, Record, Idx));
return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name,
Args.size(), Args.data());
}
- case pch::TYPE_DEPENDENT_SIZED_ARRAY: {
+ case TYPE_DEPENDENT_SIZED_ARRAY: {
unsigned Idx = 0;
// ArrayType
@@ -2355,19 +2767,19 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
unsigned IndexTypeQuals = Record[Idx++];
// DependentSizedArrayType
- Expr *NumElts = ReadExpr();
+ Expr *NumElts = ReadExpr(DeclsCursor);
SourceRange Brackets = ReadSourceRange(Record, Idx);
return Context->getDependentSizedArrayType(ElementType, NumElts, ASM,
IndexTypeQuals, Brackets);
}
- case pch::TYPE_TEMPLATE_SPECIALIZATION: {
+ case TYPE_TEMPLATE_SPECIALIZATION: {
unsigned Idx = 0;
bool IsDependent = Record[Idx++];
TemplateName Name = ReadTemplateName(Record, Idx);
llvm::SmallVector<TemplateArgument, 8> Args;
- ReadTemplateArgumentList(Args, Record, Idx);
+ ReadTemplateArgumentList(Args, DeclsCursor, Record, Idx);
QualType Canon = GetType(Record[Idx++]);
QualType T;
if (Canon.isNull())
@@ -2387,14 +2799,15 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
namespace {
class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
- PCHReader &Reader;
- const PCHReader::RecordData &Record;
+ ASTReader &Reader;
+ llvm::BitstreamCursor &DeclsCursor;
+ const ASTReader::RecordData &Record;
unsigned &Idx;
public:
- TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
- unsigned &Idx)
- : Reader(Reader), Record(Record), Idx(Idx) { }
+ TypeLocReader(ASTReader &Reader, llvm::BitstreamCursor &Cursor,
+ const ASTReader::RecordData &Record, unsigned &Idx)
+ : Reader(Reader), DeclsCursor(Cursor), Record(Record), Idx(Idx) { }
// We want compile-time assurance that we've enumerated all of
// these, so unfortunately we have to declare them first, then
@@ -2444,7 +2857,7 @@ void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
if (Record[Idx++])
- TL.setSizeExpr(Reader.ReadExpr());
+ TL.setSizeExpr(Reader.ReadExpr(DeclsCursor));
else
TL.setSizeExpr(0);
}
@@ -2499,7 +2912,7 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
}
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -2525,7 +2938,7 @@ void TypeLocReader::VisitTemplateSpecializationTypeLoc(
for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
TL.setArgLocInfo(i,
Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
- Record, Idx));
+ DeclsCursor, Record, Idx));
}
void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -2549,7 +2962,7 @@ void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc(
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
TL.setArgLocInfo(I,
Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(),
- Record, Idx));
+ DeclsCursor, Record, Idx));
}
void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -2565,87 +2978,112 @@ void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-TypeSourceInfo *PCHReader::GetTypeSourceInfo(const RecordData &Record,
+TypeSourceInfo *ASTReader::GetTypeSourceInfo(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record,
unsigned &Idx) {
QualType InfoTy = GetType(Record[Idx++]);
if (InfoTy.isNull())
return 0;
TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy);
- TypeLocReader TLR(*this, Record, Idx);
+ TypeLocReader TLR(*this, DeclsCursor, Record, Idx);
for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
TLR.Visit(TL);
return TInfo;
}
-QualType PCHReader::GetType(pch::TypeID ID) {
+QualType ASTReader::GetType(TypeID ID) {
unsigned FastQuals = ID & Qualifiers::FastMask;
unsigned Index = ID >> Qualifiers::FastWidth;
- if (Index < pch::NUM_PREDEF_TYPE_IDS) {
+ if (Index < NUM_PREDEF_TYPE_IDS) {
QualType T;
- switch ((pch::PredefinedTypeIDs)Index) {
- case pch::PREDEF_TYPE_NULL_ID: return QualType();
- case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
- case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
+ switch ((PredefinedTypeIDs)Index) {
+ case PREDEF_TYPE_NULL_ID: return QualType();
+ case PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
+ case PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
- case pch::PREDEF_TYPE_CHAR_U_ID:
- case pch::PREDEF_TYPE_CHAR_S_ID:
+ case PREDEF_TYPE_CHAR_U_ID:
+ case PREDEF_TYPE_CHAR_S_ID:
// FIXME: Check that the signedness of CharTy is correct!
T = Context->CharTy;
break;
- case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
- case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
- case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
- case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
- case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
- case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
- case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
- case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
- case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
- case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
- case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
- case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
- case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
- case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
- case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
- case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
- case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
- case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
- case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
- case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
- case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
- case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
- case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
- case pch::PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break;
+ case PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
+ case PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
+ case PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
+ case PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
+ case PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
+ case PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
+ case PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
+ case PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
+ case PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
+ case PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
+ case PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
+ case PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
+ case PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
+ case PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
+ case PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
+ case PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
+ case PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
+ case PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
+ case PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
+ case PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
+ case PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
+ case PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
+ case PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
+ case PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break;
}
assert(!T.isNull() && "Unknown predefined type");
return T.withFastQualifiers(FastQuals);
}
- Index -= pch::NUM_PREDEF_TYPE_IDS;
- //assert(Index < TypesLoaded.size() && "Type index out-of-range");
+ Index -= NUM_PREDEF_TYPE_IDS;
+ assert(Index < TypesLoaded.size() && "Type index out-of-range");
if (TypesLoaded[Index].isNull()) {
- TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
- TypesLoaded[Index]->setFromPCH();
+ TypesLoaded[Index] = ReadTypeRecord(Index);
+ TypesLoaded[Index]->setFromAST();
+ TypeIdxs[TypesLoaded[Index]] = TypeIdx::fromTypeID(ID);
if (DeserializationListener)
- DeserializationListener->TypeRead(ID, TypesLoaded[Index]);
+ DeserializationListener->TypeRead(TypeIdx::fromTypeID(ID),
+ TypesLoaded[Index]);
}
return TypesLoaded[Index].withFastQualifiers(FastQuals);
}
+TypeID ASTReader::GetTypeID(QualType T) const {
+ return MakeTypeID(T,
+ std::bind1st(std::mem_fun(&ASTReader::GetTypeIdx), this));
+}
+
+TypeIdx ASTReader::GetTypeIdx(QualType T) const {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
+
+ TypeIdxMap::const_iterator I = TypeIdxs.find(T);
+ // GetTypeIdx is mostly used for computing the hash of DeclarationNames and
+ // comparing keys of ASTDeclContextNameLookupTable.
+ // If the type didn't come from the AST file use a specially marked index
+ // so that any hash/key comparison fail since no such index is stored
+ // in a AST file.
+ if (I == TypeIdxs.end())
+ return TypeIdx(-1);
+ return I->second;
+}
+
TemplateArgumentLocInfo
-PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ASTReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+ llvm::BitstreamCursor &DeclsCursor,
const RecordData &Record,
unsigned &Index) {
switch (Kind) {
case TemplateArgument::Expression:
- return ReadExpr();
+ return ReadExpr(DeclsCursor);
case TemplateArgument::Type:
- return GetTypeSourceInfo(Record, Index);
+ return GetTypeSourceInfo(DeclsCursor, Record, Index);
case TemplateArgument::Template: {
SourceRange QualifierRange = ReadSourceRange(Record, Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(Record, Index);
@@ -2662,43 +3100,45 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
}
TemplateArgumentLoc
-PCHReader::ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Index) {
- TemplateArgument Arg = ReadTemplateArgument(Record, Index);
+ASTReader::ReadTemplateArgumentLoc(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Index) {
+ TemplateArgument Arg = ReadTemplateArgument(DeclsCursor, Record, Index);
if (Arg.getKind() == TemplateArgument::Expression) {
if (Record[Index++]) // bool InfoHasSameExpr.
return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr()));
}
return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(),
+ DeclsCursor,
Record, Index));
}
-Decl *PCHReader::GetExternalDecl(uint32_t ID) {
+Decl *ASTReader::GetExternalDecl(uint32_t ID) {
return GetDecl(ID);
}
-TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() {
+TranslationUnitDecl *ASTReader::GetTranslationUnitDecl() {
if (!DeclsLoaded[0]) {
- ReadDeclRecord(DeclOffsets[0], 0);
+ ReadDeclRecord(0, 1);
if (DeserializationListener)
- DeserializationListener->DeclRead(0, DeclsLoaded[0]);
+ DeserializationListener->DeclRead(1, DeclsLoaded[0]);
}
return cast<TranslationUnitDecl>(DeclsLoaded[0]);
}
-Decl *PCHReader::GetDecl(pch::DeclID ID) {
+Decl *ASTReader::GetDecl(DeclID ID) {
if (ID == 0)
return 0;
if (ID > DeclsLoaded.size()) {
- Error("declaration ID out-of-range for PCH file");
+ Error("declaration ID out-of-range for AST file");
return 0;
}
unsigned Index = ID - 1;
if (!DeclsLoaded[Index]) {
- ReadDeclRecord(DeclOffsets[Index], Index);
+ ReadDeclRecord(Index, ID);
if (DeserializationListener)
DeserializationListener->DeclRead(ID, DeclsLoaded[Index]);
}
@@ -2711,109 +3151,122 @@ Decl *PCHReader::GetDecl(pch::DeclID ID) {
/// This operation will read a new statement from the external
/// source each time it is called, and is meant to be used via a
/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
-Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) {
- // Since we know tha this statement is part of a decl, make sure to use the
- // decl cursor to read it.
- DeclsCursor.JumpToBit(Offset);
- return ReadStmtFromStream(DeclsCursor);
+Stmt *ASTReader::GetExternalDeclStmt(uint64_t Offset) {
+ // Offset here is a global offset across the entire chain.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ if (Offset < F.SizeInBits) {
+ // Since we know that this statement is part of a decl, make sure to use
+ // the decl cursor to read it.
+ F.DeclsCursor.JumpToBit(Offset);
+ return ReadStmtFromStream(F.DeclsCursor);
+ }
+ Offset -= F.SizeInBits;
+ }
+ llvm_unreachable("Broken chain");
}
-bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC,
+bool ASTReader::FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Decls) {
assert(DC->hasExternalLexicalStorage() &&
"DeclContext has no lexical decls in storage");
- uint64_t Offset = DeclContextOffsets[DC].first;
- if (Offset == 0) {
- Error("DeclContext has no lexical decls in storage");
- return true;
- }
-
- // Keep track of where we are in the stream, then jump back there
- // after reading this context.
- SavedStreamPosition SavedPosition(DeclsCursor);
+ // There might be lexical decls in multiple parts of the chain, for the TU
+ // at least.
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end();
+ I != E; ++I) {
+ // IDs can be 0 if this context doesn't contain declarations.
+ if (!I->LexicalDecls)
+ continue;
- // Load the record containing all of the declarations lexically in
- // this context.
- DeclsCursor.JumpToBit(Offset);
- RecordData Record;
- unsigned Code = DeclsCursor.ReadCode();
- unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
- if (RecCode != pch::DECL_CONTEXT_LEXICAL) {
- Error("Expected lexical block");
- return true;
+ // Load all of the declaration IDs
+ for (const DeclID *ID = I->LexicalDecls,
+ *IDE = ID + I->NumLexicalDecls;
+ ID != IDE; ++ID)
+ Decls.push_back(GetDecl(*ID));
}
- // Load all of the declaration IDs
- for (RecordData::iterator I = Record.begin(), E = Record.end(); I != E; ++I)
- Decls.push_back(GetDecl(*I));
++NumLexicalDeclContextsRead;
return false;
}
DeclContext::lookup_result
-PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) {
assert(DC->hasExternalVisibleStorage() &&
"DeclContext has no visible decls in storage");
- uint64_t Offset = DeclContextOffsets[DC].second;
- if (Offset == 0) {
- Error("DeclContext has no visible decls in storage");
- return DeclContext::lookup_result(DeclContext::lookup_iterator(),
- DeclContext::lookup_iterator());
- }
+ if (!Name)
+ return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
+ DeclContext::lookup_iterator(0));
+
+ llvm::SmallVector<NamedDecl *, 64> Decls;
+ // There might be visible decls in multiple parts of the chain, for the TU
+ // and namespaces. For any given name, the last available results replace
+ // all earlier ones. For this reason, we walk in reverse.
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ for (DeclContextInfos::reverse_iterator I = Infos.rbegin(), E = Infos.rend();
+ I != E; ++I) {
+ if (!I->NameLookupTableData)
+ continue;
- // Keep track of where we are in the stream, then jump back there
- // after reading this context.
- SavedStreamPosition SavedPosition(DeclsCursor);
+ ASTDeclContextNameLookupTable *LookupTable =
+ (ASTDeclContextNameLookupTable*)I->NameLookupTableData;
+ ASTDeclContextNameLookupTable::iterator Pos = LookupTable->find(Name);
+ if (Pos == LookupTable->end())
+ continue;
- // Load the record containing all of the declarations visible in
- // this context.
- DeclsCursor.JumpToBit(Offset);
- RecordData Record;
- unsigned Code = DeclsCursor.ReadCode();
- unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
- if (RecCode != pch::DECL_CONTEXT_VISIBLE) {
- Error("Expected visible block");
- return DeclContext::lookup_result(DeclContext::lookup_iterator(),
- DeclContext::lookup_iterator());
+ ASTDeclContextNameLookupTrait::data_type Data = *Pos;
+ for (; Data.first != Data.second; ++Data.first)
+ Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first)));
+ break;
}
- llvm::SmallVector<VisibleDeclaration, 64> Decls;
- if (Record.empty()) {
- SetExternalVisibleDecls(DC, Decls);
- return DeclContext::lookup_result(DeclContext::lookup_iterator(),
- DeclContext::lookup_iterator());
- }
+ ++NumVisibleDeclContextsRead;
- unsigned Idx = 0;
- while (Idx < Record.size()) {
- Decls.push_back(VisibleDeclaration());
- Decls.back().Name = ReadDeclarationName(Record, Idx);
+ SetExternalVisibleDeclsForName(DC, Name, Decls);
+ return const_cast<DeclContext*>(DC)->lookup(Name);
+}
- unsigned Size = Record[Idx++];
- llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
- LoadedDecls.reserve(Size);
- for (unsigned I = 0; I < Size; ++I)
- LoadedDecls.push_back(Record[Idx++]);
- }
+void ASTReader::MaterializeVisibleDecls(const DeclContext *DC) {
+ assert(DC->hasExternalVisibleStorage() &&
+ "DeclContext has no visible decls in storage");
- ++NumVisibleDeclContextsRead;
+ llvm::SmallVector<NamedDecl *, 64> Decls;
+ // There might be visible decls in multiple parts of the chain, for the TU
+ // and namespaces.
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ for (DeclContextInfos::iterator I = Infos.begin(), E = Infos.end();
+ I != E; ++I) {
+ if (!I->NameLookupTableData)
+ continue;
- SetExternalVisibleDecls(DC, Decls);
- return const_cast<DeclContext*>(DC)->lookup(Name);
+ ASTDeclContextNameLookupTable *LookupTable =
+ (ASTDeclContextNameLookupTable*)I->NameLookupTableData;
+ for (ASTDeclContextNameLookupTable::item_iterator
+ ItemI = LookupTable->item_begin(),
+ ItemEnd = LookupTable->item_end() ; ItemI != ItemEnd; ++ItemI) {
+ ASTDeclContextNameLookupTable::item_iterator::value_type Val
+ = *ItemI;
+ ASTDeclContextNameLookupTrait::data_type Data = Val.second;
+ Decls.clear();
+ for (; Data.first != Data.second; ++Data.first)
+ Decls.push_back(cast<NamedDecl>(GetDecl(*Data.first)));
+ MaterializeVisibleDeclsForName(DC, Val.first, Decls);
+ }
+ }
}
-void PCHReader::PassInterestingDeclsToConsumer() {
+void ASTReader::PassInterestingDeclsToConsumer() {
assert(Consumer);
while (!InterestingDecls.empty()) {
DeclGroupRef DG(InterestingDecls.front());
InterestingDecls.pop_front();
- Consumer->HandleTopLevelDecl(DG);
+ Consumer->HandleInterestingDecl(DG);
}
}
-void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
+void ASTReader::StartTranslationUnit(ASTConsumer *Consumer) {
this->Consumer = Consumer;
if (!Consumer)
@@ -2828,8 +3281,8 @@ void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
PassInterestingDeclsToConsumer();
}
-void PCHReader::PrintStats() {
- std::fprintf(stderr, "*** PCH Statistics:\n");
+void ASTReader::PrintStats() {
+ std::fprintf(stderr, "*** AST File Statistics:\n");
unsigned NumTypesLoaded
= TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
@@ -2864,10 +3317,10 @@ void PCHReader::PrintStats() {
std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
- if (TotalNumSelectors)
+ if (!SelectorsLoaded.empty())
std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
- NumSelectorsLoaded, TotalNumSelectors,
- ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
+ NumSelectorsLoaded, (unsigned)SelectorsLoaded.size(),
+ ((float)NumSelectorsLoaded/SelectorsLoaded.size() * 100));
if (TotalNumStatements)
std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
NumStatementsRead, TotalNumStatements,
@@ -2886,25 +3339,27 @@ void PCHReader::PrintStats() {
NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
* 100));
- if (TotalSelectorsInMethodPool) {
+ if (TotalNumMethodPoolEntries) {
std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
- NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
- ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
+ NumMethodPoolEntriesRead, TotalNumMethodPoolEntries,
+ ((float)NumMethodPoolEntriesRead/TotalNumMethodPoolEntries
* 100));
std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
}
std::fprintf(stderr, "\n");
}
-void PCHReader::InitializeSema(Sema &S) {
+void ASTReader::InitializeSema(Sema &S) {
SemaObj = &S;
S.ExternalSource = this;
// Makes sure any declarations that were deserialized "too early"
// still get added to the identifier's declaration chains.
- for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
- SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
- SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
+ if (SemaObj->TUScope) {
+ for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
+ SemaObj->TUScope->AddDecl(PreloadedDecls[I]);
+ SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
+ }
}
PreloadedDecls.clear();
@@ -2915,11 +3370,26 @@ void PCHReader::InitializeSema(Sema &S) {
SemaObj->TentativeDefinitions.push_back(Var);
}
- // If there were any unused static functions, deserialize them and add to
- // Sema's list of unused static functions.
- for (unsigned I = 0, N = UnusedStaticFuncs.size(); I != N; ++I) {
- FunctionDecl *FD = cast<FunctionDecl>(GetDecl(UnusedStaticFuncs[I]));
- SemaObj->UnusedStaticFuncs.push_back(FD);
+ // If there were any unused file scoped decls, deserialize them and add to
+ // Sema's list of unused file scoped decls.
+ for (unsigned I = 0, N = UnusedFileScopedDecls.size(); I != N; ++I) {
+ DeclaratorDecl *D = cast<DeclaratorDecl>(GetDecl(UnusedFileScopedDecls[I]));
+ SemaObj->UnusedFileScopedDecls.push_back(D);
+ }
+
+ // If there were any weak undeclared identifiers, deserialize them and add to
+ // Sema's list of weak undeclared identifiers.
+ if (!WeakUndeclaredIdentifiers.empty()) {
+ unsigned Idx = 0;
+ for (unsigned I = 0, N = WeakUndeclaredIdentifiers[Idx++]; I != N; ++I) {
+ IdentifierInfo *WeakId = GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx);
+ IdentifierInfo *AliasId=GetIdentifierInfo(WeakUndeclaredIdentifiers,Idx);
+ SourceLocation Loc = ReadSourceLocation(WeakUndeclaredIdentifiers, Idx);
+ bool Used = WeakUndeclaredIdentifiers[Idx++];
+ Sema::WeakInfo WI(AliasId, Loc);
+ WI.setUsed(Used);
+ SemaObj->WeakUndeclaredIdentifiers.insert(std::make_pair(WeakId, WI));
+ }
}
// If there were any locally-scoped external declarations,
@@ -2941,13 +3411,15 @@ void PCHReader::InitializeSema(Sema &S) {
// If there were any VTable uses, deserialize the information and add it
// to Sema's vector and map of VTable uses.
- unsigned Idx = 0;
- for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) {
- CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
- SourceLocation Loc = ReadSourceLocation(VTableUses, Idx);
- bool DefinitionRequired = VTableUses[Idx++];
- SemaObj->VTableUses.push_back(std::make_pair(Class, Loc));
- SemaObj->VTablesUsed[Class] = DefinitionRequired;
+ if (!VTableUses.empty()) {
+ unsigned Idx = 0;
+ for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) {
+ CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++]));
+ SourceLocation Loc = ReadSourceLocation(VTableUses, Idx);
+ bool DefinitionRequired = VTableUses[Idx++];
+ SemaObj->VTableUses.push_back(std::make_pair(Class, Loc));
+ SemaObj->VTablesUsed[Class] = DefinitionRequired;
+ }
}
// If there were any dynamic classes declarations, deserialize them
@@ -2955,51 +3427,104 @@ void PCHReader::InitializeSema(Sema &S) {
for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I)
SemaObj->DynamicClasses.push_back(
cast<CXXRecordDecl>(GetDecl(DynamicClasses[I])));
+
+ // If there were any pending implicit instantiations, deserialize them
+ // and add them to Sema's queue of such instantiations.
+ assert(PendingInstantiations.size() % 2 == 0 && "Expected pairs of entries");
+ for (unsigned Idx = 0, N = PendingInstantiations.size(); Idx < N;) {
+ ValueDecl *D=cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
+ SourceLocation Loc = ReadSourceLocation(PendingInstantiations, Idx);
+ SemaObj->PendingInstantiations.push_back(std::make_pair(D, Loc));
+ }
+
+ // Load the offsets of the declarations that Sema references.
+ // They will be lazily deserialized when needed.
+ if (!SemaDeclRefs.empty()) {
+ assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!");
+ SemaObj->StdNamespace = SemaDeclRefs[0];
+ SemaObj->StdBadAlloc = SemaDeclRefs[1];
+ }
+
+ // If there are @selector references added them to its pool. This is for
+ // implementation of -Wselector.
+ if (!ReferencedSelectorsData.empty()) {
+ unsigned int DataSize = ReferencedSelectorsData.size()-1;
+ unsigned I = 0;
+ while (I < DataSize) {
+ Selector Sel = DecodeSelector(ReferencedSelectorsData[I++]);
+ SourceLocation SelLoc =
+ SourceLocation::getFromRawEncoding(ReferencedSelectorsData[I++]);
+ SemaObj->ReferencedSelectors.insert(std::make_pair(Sel, SelLoc));
+ }
+ }
}
-IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
- // Try to find this name within our on-disk hash table
- PCHIdentifierLookupTable *IdTable
- = (PCHIdentifierLookupTable *)IdentifierLookupTable;
- std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
- PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
- if (Pos == IdTable->end())
- return 0;
+IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) {
+ // Try to find this name within our on-disk hash tables. We start with the
+ // most recent one, since that one contains the most up-to-date info.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ ASTIdentifierLookupTable *IdTable
+ = (ASTIdentifierLookupTable *)Chain[I]->IdentifierLookupTable;
+ if (!IdTable)
+ continue;
+ std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
+ ASTIdentifierLookupTable::iterator Pos = IdTable->find(Key);
+ if (Pos == IdTable->end())
+ continue;
- // Dereferencing the iterator has the effect of building the
- // IdentifierInfo node and populating it with the various
- // declarations it needs.
- return *Pos;
+ // Dereferencing the iterator has the effect of building the
+ // IdentifierInfo node and populating it with the various
+ // declarations it needs.
+ return *Pos;
+ }
+ return 0;
}
std::pair<ObjCMethodList, ObjCMethodList>
-PCHReader::ReadMethodPool(Selector Sel) {
- if (!MethodPoolLookupTable)
- return std::pair<ObjCMethodList, ObjCMethodList>();
+ASTReader::ReadMethodPool(Selector Sel) {
+ // Find this selector in a hash table. We want to find the most recent entry.
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[I];
+ if (!F.SelectorLookupTable)
+ continue;
- // Try to find this selector within our on-disk hash table.
- PCHMethodPoolLookupTable *PoolTable
- = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
- PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
- if (Pos == PoolTable->end()) {
- ++NumMethodPoolMisses;
- return std::pair<ObjCMethodList, ObjCMethodList>();;
+ ASTSelectorLookupTable *PoolTable
+ = (ASTSelectorLookupTable*)F.SelectorLookupTable;
+ ASTSelectorLookupTable::iterator Pos = PoolTable->find(Sel);
+ if (Pos != PoolTable->end()) {
+ ++NumSelectorsRead;
+ // FIXME: Not quite happy with the statistics here. We probably should
+ // disable this tracking when called via LoadSelector.
+ // Also, should entries without methods count as misses?
+ ++NumMethodPoolEntriesRead;
+ ASTSelectorLookupTrait::data_type Data = *Pos;
+ if (DeserializationListener)
+ DeserializationListener->SelectorRead(Data.ID, Sel);
+ return std::make_pair(Data.Instance, Data.Factory);
+ }
}
- ++NumMethodPoolSelectorsRead;
- return *Pos;
+ ++NumMethodPoolMisses;
+ return std::pair<ObjCMethodList, ObjCMethodList>();
+}
+
+void ASTReader::LoadSelector(Selector Sel) {
+ // It would be complicated to avoid reading the methods anyway. So don't.
+ ReadMethodPool(Sel);
}
-void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
+void ASTReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
assert(ID && "Non-zero identifier ID required");
assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
IdentifiersLoaded[ID - 1] = II;
+ if (DeserializationListener)
+ DeserializationListener->IdentifierRead(ID, II);
}
/// \brief Set the globally-visible declarations associated with the given
/// identifier.
///
-/// If the PCH reader is currently in a state where the given declaration IDs
+/// If the AST reader is currently in a state where the given declaration IDs
/// cannot safely be resolved, they are queued until it is safe to resolve
/// them.
///
@@ -3013,10 +3538,10 @@ void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
/// this call is non-recursive, and therefore the globally-visible declarations
/// will not be placed onto the pending queue.
void
-PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
+ASTReader::SetGloballyVisibleDecls(IdentifierInfo *II,
const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
bool Nonrecursive) {
- if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) {
+ if (NumCurrentElementsDeserializing && !Nonrecursive) {
PendingIdentifierInfos.push_back(PendingIdentifierInfo());
PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
PII.II = II;
@@ -3028,11 +3553,13 @@ PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
if (SemaObj) {
- // Introduce this declaration into the translation-unit scope
- // and add it to the declaration chain for this identifier, so
- // that (unqualified) name lookup will find it.
- SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
- SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
+ if (SemaObj->TUScope) {
+ // Introduce this declaration into the translation-unit scope
+ // and add it to the declaration chain for this identifier, so
+ // that (unqualified) name lookup will find it.
+ SemaObj->TUScope->AddDecl(D);
+ SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
+ }
} else {
// Queue this declaration so that it will be added to the
// translation unit scope and identifier's declaration chain
@@ -3042,74 +3569,92 @@ PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
}
}
-IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
+IdentifierInfo *ASTReader::DecodeIdentifierInfo(unsigned ID) {
if (ID == 0)
return 0;
- if (!IdentifierTableData || IdentifiersLoaded.empty()) {
- Error("no identifier table in PCH file");
+ if (IdentifiersLoaded.empty()) {
+ Error("no identifier table in AST file");
return 0;
}
assert(PP && "Forgot to set Preprocessor ?");
- if (!IdentifiersLoaded[ID - 1]) {
- uint32_t Offset = IdentifierOffsets[ID - 1];
- const char *Str = IdentifierTableData + Offset;
+ ID -= 1;
+ if (!IdentifiersLoaded[ID]) {
+ unsigned Index = ID;
+ const char *Str = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData *F = Chain[N - I - 1];
+ if (Index < F->LocalNumIdentifiers) {
+ uint32_t Offset = F->IdentifierOffsets[Index];
+ Str = F->IdentifierTableData + Offset;
+ break;
+ }
+ Index -= F->LocalNumIdentifiers;
+ }
+ assert(Str && "Broken Chain");
- // All of the strings in the PCH file are preceded by a 16-bit
- // length. Extract that 16-bit length to avoid having to execute
- // strlen().
+ // All of the strings in the AST file are preceded by a 16-bit length.
+ // Extract that 16-bit length to avoid having to execute strlen().
// NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
// unsigned integers. This is important to avoid integer overflow when
// we cast them to 'unsigned'.
const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
unsigned StrLen = (((unsigned) StrLenPtr[0])
| (((unsigned) StrLenPtr[1]) << 8)) - 1;
- IdentifiersLoaded[ID - 1]
+ IdentifiersLoaded[ID]
= &PP->getIdentifierTable().get(Str, StrLen);
+ if (DeserializationListener)
+ DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]);
}
- return IdentifiersLoaded[ID - 1];
+ return IdentifiersLoaded[ID];
}
-void PCHReader::ReadSLocEntry(unsigned ID) {
+void ASTReader::ReadSLocEntry(unsigned ID) {
ReadSLocEntryRecord(ID);
}
-Selector PCHReader::DecodeSelector(unsigned ID) {
+Selector ASTReader::DecodeSelector(unsigned ID) {
if (ID == 0)
return Selector();
- if (!MethodPoolLookupTableData)
- return Selector();
-
- if (ID > TotalNumSelectors) {
- Error("selector ID out of range in PCH file");
+ if (ID > SelectorsLoaded.size()) {
+ Error("selector ID out of range in AST file");
return Selector();
}
- unsigned Index = ID - 1;
- if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
+ if (SelectorsLoaded[ID - 1].getAsOpaquePtr() == 0) {
// Load this selector from the selector table.
- // FIXME: endianness portability issues with SelectorOffsets table
- PCHMethodPoolLookupTrait Trait(*this);
- SelectorsLoaded[Index]
- = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
+ unsigned Idx = ID - 1;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ PerFileData &F = *Chain[N - I - 1];
+ if (Idx < F.LocalNumSelectors) {
+ ASTSelectorLookupTrait Trait(*this);
+ SelectorsLoaded[ID - 1] =
+ Trait.ReadKey(F.SelectorLookupTableData + F.SelectorOffsets[Idx], 0);
+ if (DeserializationListener)
+ DeserializationListener->SelectorRead(ID, SelectorsLoaded[ID - 1]);
+ break;
+ }
+ Idx -= F.LocalNumSelectors;
+ }
}
- return SelectorsLoaded[Index];
+ return SelectorsLoaded[ID - 1];
}
-Selector PCHReader::GetExternalSelector(uint32_t ID) {
+Selector ASTReader::GetExternalSelector(uint32_t ID) {
return DecodeSelector(ID);
}
-uint32_t PCHReader::GetNumExternalSelectors() {
- return TotalNumSelectors + 1;
+uint32_t ASTReader::GetNumExternalSelectors() {
+ // ID 0 (the null selector) is considered an external selector.
+ return getTotalNumSelectors() + 1;
}
DeclarationName
-PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
switch (Kind) {
case DeclarationName::Identifier:
@@ -3149,7 +3694,7 @@ PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
}
TemplateName
-PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++];
switch (Kind) {
case TemplateName::Template:
@@ -3186,7 +3731,8 @@ PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) {
}
TemplateArgument
-PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadTemplateArgument(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx) {
switch ((TemplateArgument::ArgKind)Record[Idx++]) {
case TemplateArgument::Null:
return TemplateArgument();
@@ -3202,13 +3748,13 @@ PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) {
case TemplateArgument::Template:
return TemplateArgument(ReadTemplateName(Record, Idx));
case TemplateArgument::Expression:
- return TemplateArgument(ReadExpr());
+ return TemplateArgument(ReadExpr(DeclsCursor));
case TemplateArgument::Pack: {
unsigned NumArgs = Record[Idx++];
llvm::SmallVector<TemplateArgument, 8> Args;
Args.reserve(NumArgs);
while (NumArgs--)
- Args.push_back(ReadTemplateArgument(Record, Idx));
+ Args.push_back(ReadTemplateArgument(DeclsCursor, Record, Idx));
TemplateArgument TemplArg;
TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true);
return TemplArg;
@@ -3220,7 +3766,7 @@ PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) {
}
TemplateParameterList *
-PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) {
SourceLocation TemplateLoc = ReadSourceLocation(Record, Idx);
SourceLocation LAngleLoc = ReadSourceLocation(Record, Idx);
SourceLocation RAngleLoc = ReadSourceLocation(Record, Idx);
@@ -3238,17 +3784,18 @@ PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) {
}
void
-PCHReader::
+ASTReader::
ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs,
+ llvm::BitstreamCursor &DeclsCursor,
const RecordData &Record, unsigned &Idx) {
unsigned NumTemplateArgs = Record[Idx++];
TemplArgs.reserve(NumTemplateArgs);
while (NumTemplateArgs--)
- TemplArgs.push_back(ReadTemplateArgument(Record, Idx));
+ TemplArgs.push_back(ReadTemplateArgument(DeclsCursor, Record, Idx));
}
/// \brief Read a UnresolvedSet structure.
-void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set,
+void ASTReader::ReadUnresolvedSet(UnresolvedSetImpl &Set,
const RecordData &Record, unsigned &Idx) {
unsigned NumDecls = Record[Idx++];
while (NumDecls--) {
@@ -3259,17 +3806,82 @@ void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set,
}
CXXBaseSpecifier
-PCHReader::ReadCXXBaseSpecifier(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadCXXBaseSpecifier(llvm::BitstreamCursor &DeclsCursor,
+ const RecordData &Record, unsigned &Idx) {
bool isVirtual = static_cast<bool>(Record[Idx++]);
bool isBaseOfClass = static_cast<bool>(Record[Idx++]);
AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
- QualType T = GetType(Record[Idx++]);
+ TypeSourceInfo *TInfo = GetTypeSourceInfo(DeclsCursor, Record, Idx);
SourceRange Range = ReadSourceRange(Record, Idx);
- return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, T);
+ return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo);
+}
+
+std::pair<CXXBaseOrMemberInitializer **, unsigned>
+ASTReader::ReadCXXBaseOrMemberInitializers(llvm::BitstreamCursor &Cursor,
+ const RecordData &Record,
+ unsigned &Idx) {
+ CXXBaseOrMemberInitializer **BaseOrMemberInitializers = 0;
+ unsigned NumInitializers = Record[Idx++];
+ if (NumInitializers) {
+ ASTContext &C = *getContext();
+
+ BaseOrMemberInitializers
+ = new (C) CXXBaseOrMemberInitializer*[NumInitializers];
+ for (unsigned i=0; i != NumInitializers; ++i) {
+ TypeSourceInfo *BaseClassInfo = 0;
+ bool IsBaseVirtual = false;
+ FieldDecl *Member = 0;
+
+ bool IsBaseInitializer = Record[Idx++];
+ if (IsBaseInitializer) {
+ BaseClassInfo = GetTypeSourceInfo(Cursor, Record, Idx);
+ IsBaseVirtual = Record[Idx++];
+ } else {
+ Member = cast<FieldDecl>(GetDecl(Record[Idx++]));
+ }
+ SourceLocation MemberLoc = ReadSourceLocation(Record, Idx);
+ Expr *Init = ReadExpr(Cursor);
+ FieldDecl *AnonUnionMember
+ = cast_or_null<FieldDecl>(GetDecl(Record[Idx++]));
+ SourceLocation LParenLoc = ReadSourceLocation(Record, Idx);
+ SourceLocation RParenLoc = ReadSourceLocation(Record, Idx);
+ bool IsWritten = Record[Idx++];
+ unsigned SourceOrderOrNumArrayIndices;
+ llvm::SmallVector<VarDecl *, 8> Indices;
+ if (IsWritten) {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ } else {
+ SourceOrderOrNumArrayIndices = Record[Idx++];
+ Indices.reserve(SourceOrderOrNumArrayIndices);
+ for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
+ Indices.push_back(cast<VarDecl>(GetDecl(Record[Idx++])));
+ }
+
+ CXXBaseOrMemberInitializer *BOMInit;
+ if (IsBaseInitializer) {
+ BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo,
+ IsBaseVirtual, LParenLoc,
+ Init, RParenLoc);
+ } else if (IsWritten) {
+ BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc,
+ LParenLoc, Init, RParenLoc);
+ } else {
+ BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc,
+ LParenLoc, Init, RParenLoc,
+ Indices.data(),
+ Indices.size());
+ }
+
+ BOMInit->setAnonUnionMember(AnonUnionMember);
+ BaseOrMemberInitializers[i] = BOMInit;
+ }
+ }
+
+ return std::make_pair(BaseOrMemberInitializers, NumInitializers);
}
NestedNameSpecifier *
-PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
unsigned N = Record[Idx++];
NestedNameSpecifier *NNS = 0, *Prev = 0;
for (unsigned I = 0; I != N; ++I) {
@@ -3308,14 +3920,14 @@ PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
}
SourceRange
-PCHReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) {
+ASTReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) {
SourceLocation beg = SourceLocation::getFromRawEncoding(Record[Idx++]);
SourceLocation end = SourceLocation::getFromRawEncoding(Record[Idx++]);
return SourceRange(beg, end);
}
/// \brief Read an integral value
-llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
+llvm::APInt ASTReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
unsigned BitWidth = Record[Idx++];
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
@@ -3324,61 +3936,61 @@ llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
}
/// \brief Read a signed integral value
-llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
+llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
bool isUnsigned = Record[Idx++];
return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
}
/// \brief Read a floating-point value
-llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
+llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
return llvm::APFloat(ReadAPInt(Record, Idx));
}
// \brief Read a string
-std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
+std::string ASTReader::ReadString(const RecordData &Record, unsigned &Idx) {
unsigned Len = Record[Idx++];
std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Idx += Len;
return Result;
}
-CXXTemporary *PCHReader::ReadCXXTemporary(const RecordData &Record,
+CXXTemporary *ASTReader::ReadCXXTemporary(const RecordData &Record,
unsigned &Idx) {
CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++]));
return CXXTemporary::Create(*Context, Decl);
}
-DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
+DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
return Diag(SourceLocation(), DiagID);
}
-DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
+DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
}
/// \brief Retrieve the identifier table associated with the
/// preprocessor.
-IdentifierTable &PCHReader::getIdentifierTable() {
+IdentifierTable &ASTReader::getIdentifierTable() {
assert(PP && "Forgot to set Preprocessor ?");
return PP->getIdentifierTable();
}
/// \brief Record that the given ID maps to the given switch-case
/// statement.
-void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
+void ASTReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
SwitchCaseStmts[ID] = SC;
}
/// \brief Retrieve the switch-case statement with the given ID.
-SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
+SwitchCase *ASTReader::getSwitchCaseWithID(unsigned ID) {
assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
return SwitchCaseStmts[ID];
}
/// \brief Record that the given label statement has been
/// deserialized and has the given ID.
-void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
+void ASTReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
assert(LabelStmts.find(ID) == LabelStmts.end() &&
"Deserialized label twice");
LabelStmts[ID] = S;
@@ -3409,7 +4021,7 @@ void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
/// referencing that label occur, this operation may complete
/// immediately (updating the statement) or it may queue the
/// statement to be back-patched later.
-void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
+void ASTReader::SetLabelOf(GotoStmt *S, unsigned ID) {
std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
if (Label != LabelStmts.end()) {
// We've already seen this label, so set the label of the goto and
@@ -3429,7 +4041,7 @@ void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
/// referencing that label occur, this operation may complete
/// immediately (updating the statement) or it may queue the
/// statement to be back-patched later.
-void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
+void ASTReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
if (Label != LabelStmts.end()) {
// We've already seen this label, so set the label of the
@@ -3442,28 +4054,94 @@ void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
}
}
-
-PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader)
- : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) {
- Reader.CurrentlyLoadingTypeOrDecl = this;
-}
-
-PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() {
- if (!Parent) {
+void ASTReader::FinishedDeserializing() {
+ assert(NumCurrentElementsDeserializing &&
+ "FinishedDeserializing not paired with StartedDeserializing");
+ if (NumCurrentElementsDeserializing == 1) {
// If any identifiers with corresponding top-level declarations have
// been loaded, load those declarations now.
- while (!Reader.PendingIdentifierInfos.empty()) {
- Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II,
- Reader.PendingIdentifierInfos.front().DeclIDs,
- true);
- Reader.PendingIdentifierInfos.pop_front();
+ while (!PendingIdentifierInfos.empty()) {
+ SetGloballyVisibleDecls(PendingIdentifierInfos.front().II,
+ PendingIdentifierInfos.front().DeclIDs, true);
+ PendingIdentifierInfos.pop_front();
}
// We are not in recursive loading, so it's safe to pass the "interesting"
// decls to the consumer.
- if (Reader.Consumer)
- Reader.PassInterestingDeclsToConsumer();
+ if (Consumer)
+ PassInterestingDeclsToConsumer();
}
+ --NumCurrentElementsDeserializing;
+}
- Reader.CurrentlyLoadingTypeOrDecl = Parent;
+ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
+ const char *isysroot, bool DisableValidation)
+ : Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
+ SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
+ Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
+ Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation),
+ NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0),
+ TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0),
+ NumMacrosRead(0), TotalNumMacros(0), NumSelectorsRead(0),
+ NumMethodPoolEntriesRead(0), NumMethodPoolMisses(0),
+ TotalNumMethodPoolEntries(0), NumLexicalDeclContextsRead(0),
+ TotalLexicalDeclContexts(0), NumVisibleDeclContextsRead(0),
+ TotalVisibleDeclContexts(0), NumCurrentElementsDeserializing(0) {
+ RelocatablePCH = false;
}
+
+ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ Diagnostic &Diags, const char *isysroot,
+ bool DisableValidation)
+ : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
+ Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
+ isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0),
+ NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0),
+ NumStatementsRead(0), TotalNumStatements(0), NumMacrosRead(0),
+ TotalNumMacros(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0),
+ NumMethodPoolMisses(0), TotalNumMethodPoolEntries(0),
+ NumLexicalDeclContextsRead(0), TotalLexicalDeclContexts(0),
+ NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0),
+ NumCurrentElementsDeserializing(0) {
+ RelocatablePCH = false;
+}
+
+ASTReader::~ASTReader() {
+ for (unsigned i = 0, e = Chain.size(); i != e; ++i)
+ delete Chain[e - i - 1];
+ // Delete all visible decl lookup tables
+ for (DeclContextOffsetsMap::iterator I = DeclContextOffsets.begin(),
+ E = DeclContextOffsets.end();
+ I != E; ++I) {
+ for (DeclContextInfos::iterator J = I->second.begin(), F = I->second.end();
+ J != F; ++J) {
+ if (J->NameLookupTableData)
+ delete static_cast<ASTDeclContextNameLookupTable*>(
+ J->NameLookupTableData);
+ }
+ }
+ for (DeclContextVisibleUpdatesPending::iterator
+ I = PendingVisibleUpdates.begin(),
+ E = PendingVisibleUpdates.end();
+ I != E; ++I) {
+ for (DeclContextVisibleUpdates::iterator J = I->second.begin(),
+ F = I->second.end();
+ J != F; ++J)
+ delete static_cast<ASTDeclContextNameLookupTable*>(*J);
+ }
+}
+
+ASTReader::PerFileData::PerFileData()
+ : StatCache(0), LocalNumSLocEntries(0), LocalNumTypes(0), TypeOffsets(0),
+ LocalNumDecls(0), DeclOffsets(0), LocalNumIdentifiers(0),
+ IdentifierOffsets(0), IdentifierTableData(0), IdentifierLookupTable(0),
+ LocalNumMacroDefinitions(0), MacroDefinitionOffsets(0),
+ NumPreallocatedPreprocessingEntities(0), SelectorLookupTable(0),
+ SelectorLookupTableData(0), SelectorOffsets(0), LocalNumSelectors(0)
+{}
+
+ASTReader::PerFileData::~PerFileData() {
+ delete static_cast<ASTIdentifierLookupTable *>(IdentifierLookupTable);
+ delete static_cast<ASTSelectorLookupTable *>(SelectorLookupTable);
+}
+
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 742f0e46b92c..7adbe1220ff7 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1,4 +1,4 @@
-//===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
+//===--- ASTReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the PCHReader::ReadDeclRecord method, which is the
+// This file implements the ASTReader::ReadDeclRecord method, which is the
// entrypoint for loading a decl.
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/ASTReader.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclVisitor.h"
@@ -21,23 +21,29 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
using namespace clang;
-
+using namespace clang::serialization;
//===----------------------------------------------------------------------===//
// Declaration deserialization
//===----------------------------------------------------------------------===//
namespace clang {
- class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> {
- PCHReader &Reader;
- const PCHReader::RecordData &Record;
+ class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
+ ASTReader &Reader;
+ llvm::BitstreamCursor &Cursor;
+ const DeclID ThisDeclID;
+ const ASTReader::RecordData &Record;
unsigned &Idx;
- pch::TypeID TypeIDForTypeDecl;
+ TypeID TypeIDForTypeDecl;
+
+ uint64_t GetCurrentCursorOffset();
public:
- PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record,
+ ASTDeclReader(ASTReader &Reader, llvm::BitstreamCursor &Cursor,
+ DeclID thisDeclID, const ASTReader::RecordData &Record,
unsigned &Idx)
- : Reader(Reader), Record(Record), Idx(Idx), TypeIDForTypeDecl(0) { }
+ : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record),
+ Idx(Idx), TypeIDForTypeDecl(0) { }
void Visit(Decl *D);
@@ -74,6 +80,7 @@ namespace clang {
void VisitParmVarDecl(ParmVarDecl *PD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
void VisitTemplateDecl(TemplateDecl *D);
+ void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@@ -88,6 +95,7 @@ namespace clang {
void VisitBlockDecl(BlockDecl *BD);
std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+ template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
// FIXME: Reorder according to DeclNodes.td?
void VisitObjCMethodDecl(ObjCMethodDecl *D);
@@ -108,8 +116,21 @@ namespace clang {
};
}
-void PCHDeclReader::Visit(Decl *D) {
- DeclVisitor<PCHDeclReader, void>::Visit(D);
+uint64_t ASTDeclReader::GetCurrentCursorOffset() {
+ uint64_t Off = 0;
+ for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) {
+ ASTReader::PerFileData &F = *Reader.Chain[N - I - 1];
+ if (&Cursor == &F.DeclsCursor) {
+ Off += F.DeclsCursor.GetCurrentBitNo();
+ break;
+ }
+ Off += F.SizeInBits;
+ }
+ return Off;
+}
+
+void ASTDeclReader::Visit(Decl *D) {
+ DeclVisitor<ASTDeclReader, void>::Visit(D);
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
// if we have a fully initialized TypeDecl, we can safely read its type now.
@@ -117,51 +138,53 @@ void PCHDeclReader::Visit(Decl *D) {
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// FunctionDecl's body was written last after all other Stmts/Exprs.
if (Record[Idx++])
- FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo());
+ FD->setLazyBody(GetCurrentCursorOffset());
}
}
-void PCHDeclReader::VisitDecl(Decl *D) {
+void ASTDeclReader::VisitDecl(Decl *D) {
D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
D->setLexicalDeclContext(
cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setInvalidDecl(Record[Idx++]);
- if (Record[Idx++])
- D->initAttrs(Reader.ReadAttributes());
+ if (Record[Idx++]) {
+ AttrVec Attrs;
+ Reader.ReadAttributes(Cursor, Attrs);
+ D->setAttrs(Attrs);
+ }
D->setImplicit(Record[Idx++]);
D->setUsed(Record[Idx++]);
D->setAccess((AccessSpecifier)Record[Idx++]);
D->setPCHLevel(Record[Idx++] + 1);
}
-void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
+void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
VisitDecl(TU);
TU->setAnonymousNamespace(
cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
+void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
VisitDecl(ND);
ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
}
-void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
+void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
VisitNamedDecl(TD);
// Delay type reading until after we have fully initialized the decl.
TypeIDForTypeDecl = Record[Idx++];
}
-void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
+void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
VisitTypeDecl(TD);
- TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
}
-void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
+void ASTDeclReader::VisitTagDecl(TagDecl *TD) {
VisitTypeDecl(TD);
TD->IdentifierNamespace = Record[Idx++];
- TD->setPreviousDeclaration(
- cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++])));
+ VisitRedeclarable(TD);
TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
TD->setDefinition(Record[Idx++]);
TD->setEmbeddedInDeclarator(Record[Idx++]);
@@ -172,7 +195,7 @@ void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
+void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
VisitTagDecl(ED);
ED->setIntegerType(Reader.GetType(Record[Idx++]));
ED->setPromotionType(Reader.GetType(Record[Idx++]));
@@ -182,35 +205,36 @@ void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
+void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
VisitTagDecl(RD);
RD->setHasFlexibleArrayMember(Record[Idx++]);
RD->setAnonymousStructOrUnion(Record[Idx++]);
RD->setHasObjectMember(Record[Idx++]);
}
-void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
+void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
VisitNamedDecl(VD);
VD->setType(Reader.GetType(Record[Idx++]));
}
-void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
+void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
VisitValueDecl(ECD);
if (Record[Idx++])
- ECD->setInitExpr(Reader.ReadExpr());
+ ECD->setInitExpr(Reader.ReadExpr(Cursor));
ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
}
-void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
VisitValueDecl(DD);
- TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx);
+ TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
if (TInfo)
DD->setTypeSourceInfo(TInfo);
// FIXME: read optional qualifier and its range.
}
-void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
+void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
VisitDeclaratorDecl(FD);
+ // FIXME: read DeclarationNameLoc.
FD->IdentifierNamespace = Record[Idx++];
switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
@@ -237,7 +261,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
// Template arguments.
llvm::SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, Record, Idx);
+ Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
// Template args as written.
llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
@@ -246,7 +270,8 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
unsigned NumTemplateArgLocs = Record[Idx++];
TemplArgLocs.reserve(NumTemplateArgLocs);
for (unsigned i=0; i != NumTemplateArgLocs; ++i)
- TemplArgLocs.push_back(Reader.ReadTemplateArgumentLoc(Record, Idx));
+ TemplArgLocs.push_back(
+ Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx));
LAngleLoc = Reader.ReadSourceLocation(Record, Idx);
RAngleLoc = Reader.ReadSourceLocation(Record, Idx);
@@ -254,11 +279,12 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
- FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
- TemplArgs.data(), TSK,
- TemplArgLocs.size(),
- TemplArgLocs.data(),
- LAngleLoc, RAngleLoc, POI);
+ if (FD->isCanonicalDecl()) // if canonical add to template's set.
+ FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
+ TemplArgs.data(), TSK,
+ TemplArgLocs.size(),
+ TemplArgLocs.data(),
+ LAngleLoc, RAngleLoc, POI);
break;
}
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
@@ -272,7 +298,7 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
TemplateArgumentListInfo TemplArgs;
unsigned NumArgs = Record[Idx++];
while (NumArgs--)
- TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx));
+ TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Cursor,Record, Idx));
TemplArgs.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx));
TemplArgs.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx));
@@ -282,15 +308,12 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
}
}
- // FunctionDecl's body is handled last at PCHReaderDecl::Visit,
+ // FunctionDecl's body is handled last at ASTDeclReader::Visit,
// after everything else is read.
- // Avoid side effects and invariant checking of FunctionDecl's
- // setPreviousDeclaration.
- FD->redeclarable_base::setPreviousDeclaration(
- cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])));
- FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
- FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]);
+ VisitRedeclarable(FD);
+ FD->setStorageClass((StorageClass)Record[Idx++]);
+ FD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
FD->setInlineSpecified(Record[Idx++]);
FD->setVirtualAsWritten(Record[Idx++]);
FD->setPure(Record[Idx++]);
@@ -311,23 +334,24 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setParams(Params.data(), NumParams);
}
-void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
VisitNamedDecl(MD);
if (Record[Idx++]) {
// In practice, this won't be executed (since method definitions
// don't occur in header files).
- MD->setBody(Reader.ReadStmt());
+ MD->setBody(Reader.ReadStmt(Cursor));
MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
}
MD->setInstanceMethod(Record[Idx++]);
MD->setVariadic(Record[Idx++]);
MD->setSynthesized(Record[Idx++]);
+ MD->setDefined(Record[Idx++]);
MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
MD->setNumSelectorArgs(unsigned(Record[Idx++]));
MD->setResultType(Reader.GetType(Record[Idx++]));
- MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
@@ -338,18 +362,20 @@ void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
NumParams);
}
-void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
+void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
VisitNamedDecl(CD);
SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]);
SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]);
CD->setAtEndRange(SourceRange(A, B));
}
-void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
+void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
VisitObjCContainerDecl(ID);
ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
(Reader.GetDecl(Record[Idx++])));
+
+ // Read the directly referenced protocols and their SourceLocations.
unsigned NumProtocols = Record[Idx++];
llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
Protocols.reserve(NumProtocols);
@@ -361,6 +387,17 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
*Reader.getContext());
+
+ // Read the transitive closure of protocols referenced by this class.
+ NumProtocols = Record[Idx++];
+ Protocols.clear();
+ Protocols.reserve(NumProtocols);
+ for (unsigned I = 0; I != NumProtocols; ++I)
+ Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+ ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols,
+ *Reader.getContext());
+
+ // Read the ivars.
unsigned NumIvars = Record[Idx++];
llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
IVars.reserve(NumIvars);
@@ -368,6 +405,8 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
ID->setCategoryList(
cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+ // We will rebuild this list lazily.
+ ID->setIvarList(0);
ID->setForwardDecl(Record[Idx++]);
ID->setImplicitInterfaceDecl(Record[Idx++]);
ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -375,12 +414,16 @@ void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
+void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
VisitFieldDecl(IVD);
IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
+ // This field will be built lazily.
+ IVD->setNextIvar(0);
+ bool synth = Record[Idx++];
+ IVD->setSynthesize(synth);
}
-void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
+void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
VisitObjCContainerDecl(PD);
PD->setForwardDecl(Record[Idx++]);
PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -397,11 +440,11 @@ void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
*Reader.getContext());
}
-void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
+void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
VisitFieldDecl(FD);
}
-void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
+void ASTDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
VisitDecl(CD);
unsigned NumClassRefs = Record[Idx++];
llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs;
@@ -416,7 +459,7 @@ void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
NumClassRefs);
}
-void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
+void ASTDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
VisitDecl(FPD);
unsigned NumProtoRefs = Record[Idx++];
llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
@@ -431,7 +474,7 @@ void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
*Reader.getContext());
}
-void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
+void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
VisitObjCContainerDecl(CD);
CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
unsigned NumProtoRefs = Record[Idx++];
@@ -446,19 +489,20 @@ void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
*Reader.getContext());
CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
+ CD->setHasSynthBitfield(Record[Idx++]);
CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
+void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
VisitNamedDecl(CAD);
CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- D->setType(Reader.GetTypeSourceInfo(Record, Idx));
+ D->setType(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
// FIXME: stable encoding
D->setPropertyAttributes(
(ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
@@ -477,40 +521,43 @@ void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
+void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
VisitObjCContainerDecl(D);
D->setClassInterface(
cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
VisitObjCImplDecl(D);
D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx));
}
-void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
VisitObjCImplDecl(D);
D->setSuperClass(
cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
- // FIXME. Add reading of IvarInitializers and NumIvarInitializers.
+ llvm::tie(D->IvarInitializers, D->NumIvarInitializers)
+ = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
+ D->setHasSynthBitfield(Record[Idx++]);
}
-void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
VisitDecl(D);
D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
D->setPropertyDecl(
cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
D->setPropertyIvarDecl(
cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
- // FIXME. read GetterCXXConstructor and SetterCXXAssignment
+ D->setGetterCXXConstructor(Reader.ReadExpr(Cursor));
+ D->setSetterCXXAssignment(Reader.ReadExpr(Cursor));
}
-void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
+void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
VisitDeclaratorDecl(FD);
FD->setMutable(Record[Idx++]);
if (Record[Idx++])
- FD->setBitWidth(Reader.ReadExpr());
+ FD->setBitWidth(Reader.ReadExpr(Cursor));
if (!FD->getDeclName()) {
FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
if (Tmpl)
@@ -518,19 +565,17 @@ void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
}
}
-void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
+void ASTDeclReader::VisitVarDecl(VarDecl *VD) {
VisitDeclaratorDecl(VD);
- VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
- VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]);
+ VD->setStorageClass((StorageClass)Record[Idx++]);
+ VD->setStorageClassAsWritten((StorageClass)Record[Idx++]);
VD->setThreadSpecified(Record[Idx++]);
VD->setCXXDirectInitializer(Record[Idx++]);
- VD->setDeclaredInCondition(Record[Idx++]);
VD->setExceptionVariable(Record[Idx++]);
VD->setNRVOVariable(Record[Idx++]);
- VD->setPreviousDeclaration(
- cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
+ VisitRedeclarable(VD);
if (Record[Idx++])
- VD->setInit(Reader.ReadExpr());
+ VD->setInit(Reader.ReadExpr(Cursor));
if (Record[Idx++]) { // HasMemberSpecializationInfo.
VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++]));
@@ -540,27 +585,27 @@ void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
}
}
-void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
+void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
VisitVarDecl(PD);
}
-void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
+void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
VisitVarDecl(PD);
PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
PD->setHasInheritedDefaultArg(Record[Idx++]);
if (Record[Idx++]) // hasUninstantiatedDefaultArg.
- PD->setUninstantiatedDefaultArg(Reader.ReadExpr());
+ PD->setUninstantiatedDefaultArg(Reader.ReadExpr(Cursor));
}
-void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
+void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
VisitDecl(AD);
- AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr()));
+ AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(Cursor)));
}
-void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
+void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
VisitDecl(BD);
- BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt()));
- BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Record, Idx));
+ BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(Cursor)));
+ BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
Params.reserve(NumParams);
@@ -569,13 +614,13 @@ void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
BD->setParams(Params.data(), NumParams);
}
-void PCHDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
VisitDecl(D);
D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]);
D->setHasBraces(Record[Idx++]);
}
-void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
+void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
VisitNamedDecl(D);
D->setLBracLoc(Reader.ReadSourceLocation(Record, Idx));
D->setRBracLoc(Reader.ReadSourceLocation(Record, Idx));
@@ -588,21 +633,21 @@ void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
VisitNamedDecl(D);
-
- D->setAliasLoc(Reader.ReadSourceLocation(Record, Idx));
+ D->NamespaceLoc = Reader.ReadSourceLocation(Record, Idx);
D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
- D->setTargetNameLoc(Reader.ReadSourceLocation(Record, Idx));
- D->setAliasedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+ D->IdentLoc = Reader.ReadSourceLocation(Record, Idx);
+ D->Namespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
}
-void PCHDeclReader::VisitUsingDecl(UsingDecl *D) {
+void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
D->setUsingLocation(Reader.ReadSourceLocation(Record, Idx));
D->setNestedNameRange(Reader.ReadSourceRange(Record, Idx));
D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));
+ // FIXME: read the DNLoc component.
// FIXME: It would probably be more efficient to read these into a vector
// and then re-cosntruct the shadow decl set over that vector since it
@@ -619,7 +664,7 @@ void PCHDeclReader::VisitUsingDecl(UsingDecl *D) {
Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern);
}
-void PCHDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
+void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
VisitNamedDecl(D);
D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++])));
@@ -629,34 +674,34 @@ void PCHDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern);
}
-void PCHDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
- D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx));
- D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
- D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
- D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx));
- D->setNominatedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
- D->setCommonAncestor(cast_or_null<DeclContext>(
- Reader.GetDecl(Record[Idx++])));
+ D->UsingLoc = Reader.ReadSourceLocation(Record, Idx);
+ D->NamespaceLoc = Reader.ReadSourceLocation(Record, Idx);
+ D->QualifierRange = Reader.ReadSourceRange(Record, Idx);
+ D->Qualifier = Reader.ReadNestedNameSpecifier(Record, Idx);
+ D->NominatedNamespace = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ D->CommonAncestor = cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]));
}
-void PCHDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ // FIXME: read the DNLoc component.
}
-void PCHDeclReader::VisitUnresolvedUsingTypenameDecl(
+void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
- D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
- D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
- D->setTypenameLoc(Reader.ReadSourceLocation(Record, Idx));
- D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+ D->TargetNestedNameRange = Reader.ReadSourceRange(Record, Idx);
+ D->UsingLocation = Reader.ReadSourceLocation(Record, Idx);
+ D->TypenameLocation = Reader.ReadSourceLocation(Record, Idx);
+ D->TargetNestedNameSpecifier = Reader.ReadNestedNameSpecifier(Record, Idx);
}
-void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
+void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
ASTContext &C = *Reader.getContext();
// We need to allocate the DefinitionData struct ahead of VisitRecordDecl
@@ -666,7 +711,7 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
enum DataOwnership { Data_NoDefData, Data_Owner, Data_NotOwner };
switch ((DataOwnership)Record[Idx++]) {
default:
- assert(0 && "Out of sync with PCHDeclWriter or messed up reading");
+ assert(0 && "Out of sync with ASTDeclWriter or messed up reading");
case Data_NoDefData:
break;
case Data_Owner:
@@ -705,17 +750,17 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
Data.DeclaredDestructor = Record[Idx++];
// setBases() is unsuitable since it may try to iterate the bases of an
- // unitialized base.
+ // uninitialized base.
Data.NumBases = Record[Idx++];
Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases];
for (unsigned i = 0; i != Data.NumBases; ++i)
- Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx);
+ Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx);
// FIXME: Make VBases lazily computed when needed to avoid storing them.
Data.NumVBases = Record[Idx++];
Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases];
for (unsigned i = 0; i != Data.NumVBases; ++i)
- Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Record, Idx);
+ Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx);
Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx);
Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx);
@@ -729,7 +774,7 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
};
switch ((CXXRecKind)Record[Idx++]) {
default:
- assert(false && "Out of sync with PCHDeclWriter::VisitCXXRecordDecl?");
+ assert(false && "Out of sync with ASTDeclWriter::VisitCXXRecordDecl?");
case CXXRecNotTemplate:
break;
case CXXRecTemplate:
@@ -747,7 +792,7 @@ void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
}
}
-void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
+void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
VisitFunctionDecl(D);
unsigned NumOverridenMethods = Record[Idx++];
while (NumOverridenMethods--) {
@@ -758,102 +803,57 @@ void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
}
}
-void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
D->IsExplicitSpecified = Record[Idx++];
D->ImplicitlyDefined = Record[Idx++];
-
- unsigned NumInitializers = Record[Idx++];
- D->NumBaseOrMemberInitializers = NumInitializers;
- if (NumInitializers) {
- ASTContext &C = *Reader.getContext();
-
- D->BaseOrMemberInitializers
- = new (C) CXXBaseOrMemberInitializer*[NumInitializers];
- for (unsigned i=0; i != NumInitializers; ++i) {
- TypeSourceInfo *BaseClassInfo = 0;
- bool IsBaseVirtual = false;
- FieldDecl *Member = 0;
-
- bool IsBaseInitializer = Record[Idx++];
- if (IsBaseInitializer) {
- BaseClassInfo = Reader.GetTypeSourceInfo(Record, Idx);
- IsBaseVirtual = Record[Idx++];
- } else {
- Member = cast<FieldDecl>(Reader.GetDecl(Record[Idx++]));
- }
- SourceLocation MemberLoc = Reader.ReadSourceLocation(Record, Idx);
- Expr *Init = Reader.ReadExpr();
- FieldDecl *AnonUnionMember
- = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
- SourceLocation LParenLoc = Reader.ReadSourceLocation(Record, Idx);
- SourceLocation RParenLoc = Reader.ReadSourceLocation(Record, Idx);
- bool IsWritten = Record[Idx++];
- unsigned SourceOrderOrNumArrayIndices;
- llvm::SmallVector<VarDecl *, 8> Indices;
- if (IsWritten) {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- } else {
- SourceOrderOrNumArrayIndices = Record[Idx++];
- Indices.reserve(SourceOrderOrNumArrayIndices);
- for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
- Indices.push_back(cast<VarDecl>(Reader.GetDecl(Record[Idx++])));
- }
-
- CXXBaseOrMemberInitializer *BOMInit;
- if (IsBaseInitializer) {
- BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo,
- IsBaseVirtual, LParenLoc,
- Init, RParenLoc);
- } else if (IsWritten) {
- BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc,
- LParenLoc, Init, RParenLoc);
- } else {
- BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc,
- LParenLoc, Init, RParenLoc,
- Indices.data(),
- Indices.size());
- }
-
- BOMInit->setAnonUnionMember(AnonUnionMember);
- D->BaseOrMemberInitializers[i] = BOMInit;
- }
- }
+ llvm::tie(D->BaseOrMemberInitializers, D->NumBaseOrMemberInitializers)
+ = Reader.ReadCXXBaseOrMemberInitializers(Cursor, Record, Idx);
}
-void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
D->ImplicitlyDefined = Record[Idx++];
D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
}
-void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
+void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
VisitCXXMethodDecl(D);
D->IsExplicitSpecified = Record[Idx++];
}
-void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
+void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
VisitDecl(D);
D->setColonLoc(Reader.ReadSourceLocation(Record, Idx));
}
-void PCHDeclReader::VisitFriendDecl(FriendDecl *D) {
+void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
VisitDecl(D);
if (Record[Idx++])
- D->Friend = Reader.GetTypeSourceInfo(Record, Idx);
+ D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
else
D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
D->FriendLoc = Reader.ReadSourceLocation(Record, Idx);
}
-void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
- assert(false && "cannot read FriendTemplateDecl");
+void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+ VisitDecl(D);
+ unsigned NumParams = Record[Idx++];
+ D->NumParams = NumParams;
+ D->Params = new TemplateParameterList*[NumParams];
+ for (unsigned i = 0; i != NumParams; ++i)
+ D->Params[i] = Reader.ReadTemplateParameterList(Record, Idx);
+ if (Record[Idx++]) // HasFriendDecl
+ D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+ else
+ D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
+ D->FriendLoc = Reader.ReadSourceLocation(Record, Idx);
}
-void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
+void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
NamedDecl *TemplatedDecl
@@ -863,14 +863,56 @@ void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
D->init(TemplatedDecl, TemplateParams);
}
-void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitTemplateDecl(D);
D->IdentifierNamespace = Record[Idx++];
- ClassTemplateDecl *PrevDecl =
- cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
- D->setPreviousDeclaration(PrevDecl);
+ RedeclarableTemplateDecl *PrevDecl =
+ cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+ assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) &&
+ "PrevDecl kind mismatch");
+ if (PrevDecl)
+ D->CommonOrPrev = PrevDecl;
if (PrevDecl == 0) {
+ if (RedeclarableTemplateDecl *RTD
+ = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
+ assert(RTD->getKind() == D->getKind() &&
+ "InstantiatedFromMemberTemplate kind mismatch");
+ D->setInstantiatedFromMemberTemplateImpl(RTD);
+ if (Record[Idx++])
+ D->setMemberSpecialization();
+ }
+
+ RedeclarableTemplateDecl *LatestDecl =
+ cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
+
+ // This decl is a first one and the latest declaration that it points to is
+ // in the same AST file. However, if this actually needs to point to a
+ // redeclaration in another AST file, we need to update it by checking
+ // the FirstLatestDeclIDs map which tracks this kind of decls.
+ assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
+ ASTReader::FirstLatestDeclIDMap::iterator I
+ = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+ if (I != Reader.FirstLatestDeclIDs.end()) {
+ Decl *NewLatest = Reader.GetDecl(I->second);
+ assert((LatestDecl->getLocation().isInvalid() ||
+ NewLatest->getLocation().isInvalid() ||
+ Reader.SourceMgr.isBeforeInTranslationUnit(
+ LatestDecl->getLocation(),
+ NewLatest->getLocation())) &&
+ "The new latest is supposed to come after the previous latest");
+ LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
+ }
+
+ assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
+ D->getCommonPtr()->Latest = LatestDecl;
+ }
+}
+
+void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
+ if (D->getPreviousDeclaration() == 0) {
// This ClassTemplateDecl owns a CommonPtr; read it.
// FoldingSets are filled in VisitClassTemplateSpecializationDecl.
@@ -884,17 +926,10 @@ void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Reader.GetDecl(Record[Idx++]));
// InjectedClassNameType is computed.
-
- if (ClassTemplateDecl *CTD
- = cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
- D->setInstantiatedFromMemberTemplate(CTD);
- if (Record[Idx++])
- D->setMemberSpecialization();
- }
}
}
-void PCHDeclReader::VisitClassTemplateSpecializationDecl(
+void ASTDeclReader::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
VisitCXXRecordDecl(D);
@@ -903,28 +938,28 @@ void PCHDeclReader::VisitClassTemplateSpecializationDecl(
D->setInstantiationOf(CTD);
} else {
llvm::SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, Record, Idx);
+ Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
D->setInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(InstD),
TemplArgs.data(), TemplArgs.size());
}
}
// Explicit info.
- if (TypeSourceInfo *TyInfo = Reader.GetTypeSourceInfo(Record, Idx)) {
+ if (TypeSourceInfo *TyInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx)) {
D->setTypeAsWritten(TyInfo);
D->setExternLoc(Reader.ReadSourceLocation(Record, Idx));
D->setTemplateKeywordLoc(Reader.ReadSourceLocation(Record, Idx));
}
llvm::SmallVector<TemplateArgument, 8> TemplArgs;
- Reader.ReadTemplateArgumentList(TemplArgs, Record, Idx);
+ Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
D->initTemplateArgs(TemplArgs.data(), TemplArgs.size());
SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
if (POI.isValid())
D->setPointOfInstantiation(POI);
D->setSpecializationKind((TemplateSpecializationKind)Record[Idx++]);
- if (Record[Idx++]) { // IsKeptInFoldingSet.
+ if (D->isCanonicalDecl()) { // It's kept in the folding set.
ClassTemplateDecl *CanonPattern
= cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
if (ClassTemplatePartialSpecializationDecl *Partial
@@ -936,7 +971,7 @@ void PCHDeclReader::VisitClassTemplateSpecializationDecl(
}
}
-void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
+void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) {
VisitClassTemplateSpecializationDecl(D);
@@ -945,7 +980,7 @@ void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
TemplateArgumentListInfo ArgInfos;
unsigned NumArgs = Record[Idx++];
while (NumArgs--)
- ArgInfos.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx));
+ ArgInfos.addArgument(Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx));
D->initTemplateArgsAsWritten(ArgInfos);
D->setSequenceNumber(Record[Idx++]);
@@ -960,14 +995,10 @@ void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
}
}
-void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
- VisitTemplateDecl(D);
+void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
- D->IdentifierNamespace = Record[Idx++];
- FunctionTemplateDecl *PrevDecl =
- cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
- D->setPreviousDeclaration(PrevDecl);
- if (PrevDecl == 0) {
+ if (D->getPreviousDeclaration() == 0) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
// Read the function specialization declarations.
@@ -976,68 +1007,112 @@ void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
unsigned NumSpecs = Record[Idx++];
while (NumSpecs--)
Reader.GetDecl(Record[Idx++]);
-
- if (FunctionTemplateDecl *CTD
- = cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
- D->setInstantiatedFromMemberTemplate(CTD);
- if (Record[Idx++])
- D->setMemberSpecialization();
- }
}
}
-void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
VisitTypeDecl(D);
D->setDeclaredWithTypename(Record[Idx++]);
D->setParameterPack(Record[Idx++]);
bool Inherited = Record[Idx++];
- TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Record, Idx);
+ TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
D->setDefaultArgument(DefArg, Inherited);
}
-void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
VisitVarDecl(D);
// TemplateParmPosition.
D->setDepth(Record[Idx++]);
D->setPosition(Record[Idx++]);
// Rest of NonTypeTemplateParmDecl.
if (Record[Idx++]) {
- Expr *DefArg = Reader.ReadExpr();
+ Expr *DefArg = Reader.ReadExpr(Cursor);
bool Inherited = Record[Idx++];
D->setDefaultArgument(DefArg, Inherited);
}
}
-void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
VisitTemplateDecl(D);
// TemplateParmPosition.
D->setDepth(Record[Idx++]);
D->setPosition(Record[Idx++]);
// Rest of TemplateTemplateParmDecl.
- TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(Record, Idx);
+ TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx);
bool IsInherited = Record[Idx++];
D->setDefaultArgument(Arg, IsInherited);
}
-void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
- assert(false && "cannot read StaticAssertDecl");
+void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ VisitDecl(D);
+ D->AssertExpr = Reader.ReadExpr(Cursor);
+ D->Message = cast<StringLiteral>(Reader.ReadExpr(Cursor));
}
std::pair<uint64_t, uint64_t>
-PCHDeclReader::VisitDeclContext(DeclContext *DC) {
+ASTDeclReader::VisitDeclContext(DeclContext *DC) {
uint64_t LexicalOffset = Record[Idx++];
uint64_t VisibleOffset = Record[Idx++];
return std::make_pair(LexicalOffset, VisibleOffset);
}
+template <typename T>
+void ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
+ enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+ RedeclKind Kind = (RedeclKind)Record[Idx++];
+ switch (Kind) {
+ default:
+ assert(0 && "Out of sync with ASTDeclWriter::VisitRedeclarable or messed up"
+ " reading");
+ case NoRedeclaration:
+ break;
+ case PointsToPrevious:
+ D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
+ cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+ break;
+ case PointsToLatest:
+ D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
+ cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
+ break;
+ }
+
+ assert(!(Kind == PointsToPrevious &&
+ Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
+ Reader.FirstLatestDeclIDs.end()) &&
+ "This decl is not first, it should not be in the map");
+ if (Kind == PointsToPrevious)
+ return;
+
+ // This decl is a first one and the latest declaration that it points to is in
+ // the same AST file. However, if this actually needs to point to a
+ // redeclaration in another AST file, we need to update it by checking the
+ // FirstLatestDeclIDs map which tracks this kind of decls.
+ assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
+ "Invalid ThisDeclID ?");
+ ASTReader::FirstLatestDeclIDMap::iterator I
+ = Reader.FirstLatestDeclIDs.find(ThisDeclID);
+ if (I != Reader.FirstLatestDeclIDs.end()) {
+ Decl *NewLatest = Reader.GetDecl(I->second);
+ assert((D->getMostRecentDeclaration()->getLocation().isInvalid() ||
+ NewLatest->getLocation().isInvalid() ||
+ Reader.SourceMgr.isBeforeInTranslationUnit(
+ D->getMostRecentDeclaration()->getLocation(),
+ NewLatest->getLocation())) &&
+ "The new latest is supposed to come after the previous latest");
+ D->RedeclLink
+ = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
+ }
+}
+
//===----------------------------------------------------------------------===//
// Attribute Reading
//===----------------------------------------------------------------------===//
/// \brief Reads attributes from the current stream position.
-Attr *PCHReader::ReadAttributes() {
+void ASTReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor,
+ AttrVec &Attrs) {
unsigned Code = DeclsCursor.ReadCode();
assert(Code == llvm::bitc::UNABBREV_RECORD &&
"Expected unabbreviated record"); (void)Code;
@@ -1045,181 +1120,25 @@ Attr *PCHReader::ReadAttributes() {
RecordData Record;
unsigned Idx = 0;
unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
- assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
+ assert(RecCode == DECL_ATTR && "Expected attribute record");
(void)RecCode;
-#define SIMPLE_ATTR(Name) \
- case attr::Name: \
- New = ::new (*Context) Name##Attr(); \
- break
-
-#define STRING_ATTR(Name) \
- case attr::Name: \
- New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx)); \
- break
-
-#define UNSIGNED_ATTR(Name) \
- case attr::Name: \
- New = ::new (*Context) Name##Attr(Record[Idx++]); \
- break
-
- Attr *Attrs = 0;
while (Idx < Record.size()) {
Attr *New = 0;
attr::Kind Kind = (attr::Kind)Record[Idx++];
- bool IsInherited = Record[Idx++];
-
- switch (Kind) {
- default:
- assert(0 && "Unknown attribute!");
- break;
- STRING_ATTR(Alias);
- SIMPLE_ATTR(AlignMac68k);
- UNSIGNED_ATTR(Aligned);
- SIMPLE_ATTR(AlwaysInline);
- SIMPLE_ATTR(AnalyzerNoReturn);
- STRING_ATTR(Annotate);
- STRING_ATTR(AsmLabel);
- SIMPLE_ATTR(BaseCheck);
-
- case attr::Blocks:
- New = ::new (*Context) BlocksAttr(
- (BlocksAttr::BlocksAttrTypes)Record[Idx++]);
- break;
-
- SIMPLE_ATTR(CDecl);
-
- case attr::Cleanup:
- New = ::new (*Context) CleanupAttr(
- cast<FunctionDecl>(GetDecl(Record[Idx++])));
- break;
-
- SIMPLE_ATTR(Const);
- UNSIGNED_ATTR(Constructor);
- SIMPLE_ATTR(DLLExport);
- SIMPLE_ATTR(DLLImport);
- SIMPLE_ATTR(Deprecated);
- UNSIGNED_ATTR(Destructor);
- SIMPLE_ATTR(FastCall);
- SIMPLE_ATTR(Final);
-
- case attr::Format: {
- std::string Type = ReadString(Record, Idx);
- unsigned FormatIdx = Record[Idx++];
- unsigned FirstArg = Record[Idx++];
- New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg);
- break;
- }
-
- case attr::FormatArg: {
- unsigned FormatIdx = Record[Idx++];
- New = ::new (*Context) FormatArgAttr(FormatIdx);
- break;
- }
-
- case attr::Sentinel: {
- int sentinel = Record[Idx++];
- int nullPos = Record[Idx++];
- New = ::new (*Context) SentinelAttr(sentinel, nullPos);
- break;
- }
-
- SIMPLE_ATTR(GNUInline);
- SIMPLE_ATTR(Hiding);
-
- case attr::IBAction:
- New = ::new (*Context) IBActionAttr();
- break;
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[Idx++]);
+ bool isInherited = Record[Idx++];
- case attr::IBOutlet:
- New = ::new (*Context) IBOutletAttr();
- break;
-
- case attr::IBOutletCollection: {
- ObjCInterfaceDecl *D =
- cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
- New = ::new (*Context) IBOutletCollectionAttr(D);
- break;
- }
-
- SIMPLE_ATTR(Malloc);
- SIMPLE_ATTR(NoDebug);
- SIMPLE_ATTR(NoInline);
- SIMPLE_ATTR(NoReturn);
- SIMPLE_ATTR(NoThrow);
-
- case attr::NonNull: {
- unsigned Size = Record[Idx++];
- llvm::SmallVector<unsigned, 16> ArgNums;
- ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
- Idx += Size;
- New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size);
- break;
- }
-
- case attr::ReqdWorkGroupSize: {
- unsigned X = Record[Idx++];
- unsigned Y = Record[Idx++];
- unsigned Z = Record[Idx++];
- New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
- break;
- }
-
- SIMPLE_ATTR(ObjCException);
- SIMPLE_ATTR(ObjCNSObject);
- SIMPLE_ATTR(CFReturnsNotRetained);
- SIMPLE_ATTR(CFReturnsRetained);
- SIMPLE_ATTR(NSReturnsNotRetained);
- SIMPLE_ATTR(NSReturnsRetained);
- SIMPLE_ATTR(Overloadable);
- SIMPLE_ATTR(Override);
- SIMPLE_ATTR(Packed);
- UNSIGNED_ATTR(MaxFieldAlignment);
- SIMPLE_ATTR(Pure);
- UNSIGNED_ATTR(Regparm);
- STRING_ATTR(Section);
- SIMPLE_ATTR(StdCall);
- SIMPLE_ATTR(ThisCall);
- SIMPLE_ATTR(TransparentUnion);
- SIMPLE_ATTR(Unavailable);
- SIMPLE_ATTR(Unused);
- SIMPLE_ATTR(Used);
-
- case attr::Visibility:
- New = ::new (*Context) VisibilityAttr(
- (VisibilityAttr::VisibilityTypes)Record[Idx++]);
- break;
-
- SIMPLE_ATTR(WarnUnusedResult);
- SIMPLE_ATTR(Weak);
- SIMPLE_ATTR(WeakRef);
- SIMPLE_ATTR(WeakImport);
- }
+#include "clang/Serialization/AttrPCHRead.inc"
assert(New && "Unable to decode attribute?");
- New->setInherited(IsInherited);
- New->setNext(Attrs);
- Attrs = New;
- }
-#undef UNSIGNED_ATTR
-#undef STRING_ATTR
-#undef SIMPLE_ATTR
-
- // The list of attributes was built backwards. Reverse the list
- // before returning it.
- Attr *PrevAttr = 0, *NextAttr = 0;
- while (Attrs) {
- NextAttr = Attrs->getNext();
- Attrs->setNext(PrevAttr);
- PrevAttr = Attrs;
- Attrs = NextAttr;
+ New->setInherited(isInherited);
+ Attrs.push_back(New);
}
-
- return PrevAttr;
}
//===----------------------------------------------------------------------===//
-// PCHReader Implementation
+// ASTReader Implementation
//===----------------------------------------------------------------------===//
/// \brief Note that we have loaded the declaration with the given
@@ -1228,7 +1147,7 @@ Attr *PCHReader::ReadAttributes() {
/// This routine notes that this declaration has already been loaded,
/// so that future GetDecl calls will return this declaration rather
/// than trying to load a new declaration.
-inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
+inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
assert(!DeclsLoaded[Index] && "Decl loaded twice?");
DeclsLoaded[Index] = D;
}
@@ -1244,14 +1163,36 @@ static bool isConsumerInterestedIn(Decl *D) {
if (isa<FileScopeAsmDecl>(D))
return true;
if (VarDecl *Var = dyn_cast<VarDecl>(D))
- return Var->isFileVarDecl() && Var->getInit();
+ return Var->isFileVarDecl() &&
+ Var->isThisDeclarationADefinition() == VarDecl::Definition;
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
return Func->isThisDeclarationADefinition();
- return isa<ObjCProtocolDecl>(D);
+ return isa<ObjCProtocolDecl>(D) || isa<ObjCImplementationDecl>(D);
+}
+
+/// \brief Get the correct cursor and offset for loading a type.
+ASTReader::RecordLocation
+ASTReader::DeclCursorForIndex(unsigned Index, DeclID ID) {
+ // See if there's an override.
+ DeclReplacementMap::iterator It = ReplacedDecls.find(ID);
+ if (It != ReplacedDecls.end())
+ return RecordLocation(&It->second.first->DeclsCursor, It->second.second);
+
+ PerFileData *F = 0;
+ for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
+ F = Chain[N - I - 1];
+ if (Index < F->LocalNumDecls)
+ break;
+ Index -= F->LocalNumDecls;
+ }
+ assert(F && F->LocalNumDecls > Index && "Broken chain");
+ return RecordLocation(&F->DeclsCursor, F->DeclOffsets[Index]);
}
-/// \brief Read the declaration at the given offset from the PCH file.
-Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
+/// \brief Read the declaration at the given offset from the AST file.
+Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
+ RecordLocation Loc = DeclCursorForIndex(Index, ID);
+ llvm::BitstreamCursor &DeclsCursor = *Loc.first;
// Keep track of where we are in the stream, then jump back there
// after reading this declaration.
SavedStreamPosition SavedPosition(DeclsCursor);
@@ -1259,205 +1200,205 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
ReadingKindTracker ReadingKind(Read_Decl, *this);
// Note that we are loading a declaration record.
- LoadingTypeOrDecl Loading(*this);
+ Deserializing ADecl(this);
- DeclsCursor.JumpToBit(Offset);
+ DeclsCursor.JumpToBit(Loc.second);
RecordData Record;
unsigned Code = DeclsCursor.ReadCode();
unsigned Idx = 0;
- PCHDeclReader Reader(*this, Record, Idx);
+ ASTDeclReader Reader(*this, DeclsCursor, ID, Record, Idx);
Decl *D = 0;
- switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
- case pch::DECL_ATTR:
- case pch::DECL_CONTEXT_LEXICAL:
- case pch::DECL_CONTEXT_VISIBLE:
+ switch ((DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
+ case DECL_ATTR:
+ case DECL_CONTEXT_LEXICAL:
+ case DECL_CONTEXT_VISIBLE:
assert(false && "Record cannot be de-serialized with ReadDeclRecord");
break;
- case pch::DECL_TRANSLATION_UNIT:
+ case DECL_TRANSLATION_UNIT:
assert(Index == 0 && "Translation unit must be at index 0");
D = Context->getTranslationUnitDecl();
break;
- case pch::DECL_TYPEDEF:
+ case DECL_TYPEDEF:
D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
- case pch::DECL_ENUM:
+ case DECL_ENUM:
D = EnumDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_RECORD:
+ case DECL_RECORD:
D = RecordDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_ENUM_CONSTANT:
+ case DECL_ENUM_CONSTANT:
D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
0, llvm::APSInt());
break;
- case pch::DECL_FUNCTION:
+ case DECL_FUNCTION:
D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
QualType(), 0);
break;
- case pch::DECL_LINKAGE_SPEC:
+ case DECL_LINKAGE_SPEC:
D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(),
(LinkageSpecDecl::LanguageIDs)0,
false);
break;
- case pch::DECL_NAMESPACE:
+ case DECL_NAMESPACE:
D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0);
break;
- case pch::DECL_NAMESPACE_ALIAS:
+ case DECL_NAMESPACE_ALIAS:
D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(),
SourceLocation(), 0, SourceRange(), 0,
SourceLocation(), 0);
break;
- case pch::DECL_USING:
- D = UsingDecl::Create(*Context, 0, SourceLocation(), SourceRange(),
- SourceLocation(), 0, DeclarationName(), false);
+ case DECL_USING:
+ D = UsingDecl::Create(*Context, 0, SourceRange(), SourceLocation(),
+ 0, DeclarationNameInfo(), false);
break;
- case pch::DECL_USING_SHADOW:
+ case DECL_USING_SHADOW:
D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
- case pch::DECL_USING_DIRECTIVE:
+ case DECL_USING_DIRECTIVE:
D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(),
SourceLocation(), SourceRange(), 0,
SourceLocation(), 0, 0);
break;
- case pch::DECL_UNRESOLVED_USING_VALUE:
+ case DECL_UNRESOLVED_USING_VALUE:
D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(),
- SourceRange(), 0, SourceLocation(),
- DeclarationName());
+ SourceRange(), 0,
+ DeclarationNameInfo());
break;
- case pch::DECL_UNRESOLVED_USING_TYPENAME:
+ case DECL_UNRESOLVED_USING_TYPENAME:
D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(),
SourceLocation(), SourceRange(),
0, SourceLocation(),
DeclarationName());
break;
- case pch::DECL_CXX_RECORD:
+ case DECL_CXX_RECORD:
D = CXXRecordDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_CXX_METHOD:
- D = CXXMethodDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
+ case DECL_CXX_METHOD:
+ D = CXXMethodDecl::Create(*Context, 0, DeclarationNameInfo(),
QualType(), 0);
break;
- case pch::DECL_CXX_CONSTRUCTOR:
+ case DECL_CXX_CONSTRUCTOR:
D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_CXX_DESTRUCTOR:
+ case DECL_CXX_DESTRUCTOR:
D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_CXX_CONVERSION:
+ case DECL_CXX_CONVERSION:
D = CXXConversionDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_ACCESS_SPEC:
+ case DECL_ACCESS_SPEC:
D = AccessSpecDecl::Create(*Context, AS_none, 0, SourceLocation(),
SourceLocation());
break;
- case pch::DECL_FRIEND:
+ case DECL_FRIEND:
D = FriendDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_FRIEND_TEMPLATE:
- assert(false && "cannot read FriendTemplateDecl");
+ case DECL_FRIEND_TEMPLATE:
+ D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_CLASS_TEMPLATE:
+ case DECL_CLASS_TEMPLATE:
D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(),
DeclarationName(), 0, 0, 0);
break;
- case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION:
+ case DECL_CLASS_TEMPLATE_SPECIALIZATION:
D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
+ case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
D = ClassTemplatePartialSpecializationDecl::Create(*Context,
Decl::EmptyShell());
break;
- case pch::DECL_FUNCTION_TEMPLATE:
+ case DECL_FUNCTION_TEMPLATE:
D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(),
DeclarationName(), 0, 0);
break;
- case pch::DECL_TEMPLATE_TYPE_PARM:
+ case DECL_TEMPLATE_TYPE_PARM:
D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell());
break;
- case pch::DECL_NON_TYPE_TEMPLATE_PARM:
+ case DECL_NON_TYPE_TEMPLATE_PARM:
D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
QualType(),0);
break;
- case pch::DECL_TEMPLATE_TEMPLATE_PARM:
+ case DECL_TEMPLATE_TEMPLATE_PARM:
D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0);
break;
- case pch::DECL_STATIC_ASSERT:
- assert(false && "cannot read StaticAssertDecl");
+ case DECL_STATIC_ASSERT:
+ D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
- case pch::DECL_OBJC_METHOD:
+ case DECL_OBJC_METHOD:
D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),
Selector(), QualType(), 0, 0);
break;
- case pch::DECL_OBJC_INTERFACE:
+ case DECL_OBJC_INTERFACE:
D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0);
break;
- case pch::DECL_OBJC_IVAR:
+ case DECL_OBJC_IVAR:
D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
ObjCIvarDecl::None);
break;
- case pch::DECL_OBJC_PROTOCOL:
+ case DECL_OBJC_PROTOCOL:
D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0);
break;
- case pch::DECL_OBJC_AT_DEFS_FIELD:
+ case DECL_OBJC_AT_DEFS_FIELD:
D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0,
QualType(), 0);
break;
- case pch::DECL_OBJC_CLASS:
+ case DECL_OBJC_CLASS:
D = ObjCClassDecl::Create(*Context, 0, SourceLocation());
break;
- case pch::DECL_OBJC_FORWARD_PROTOCOL:
+ case DECL_OBJC_FORWARD_PROTOCOL:
D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
break;
- case pch::DECL_OBJC_CATEGORY:
+ case DECL_OBJC_CATEGORY:
D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(),
SourceLocation(), SourceLocation(), 0);
break;
- case pch::DECL_OBJC_CATEGORY_IMPL:
+ case DECL_OBJC_CATEGORY_IMPL:
D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
- case pch::DECL_OBJC_IMPLEMENTATION:
+ case DECL_OBJC_IMPLEMENTATION:
D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
- case pch::DECL_OBJC_COMPATIBLE_ALIAS:
+ case DECL_OBJC_COMPATIBLE_ALIAS:
D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
break;
- case pch::DECL_OBJC_PROPERTY:
+ case DECL_OBJC_PROPERTY:
D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
0);
break;
- case pch::DECL_OBJC_PROPERTY_IMPL:
+ case DECL_OBJC_PROPERTY_IMPL:
D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),
SourceLocation(), 0,
ObjCPropertyImplDecl::Dynamic, 0);
break;
- case pch::DECL_FIELD:
+ case DECL_FIELD:
D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,
false);
break;
- case pch::DECL_VAR:
+ case DECL_VAR:
D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
- VarDecl::None, VarDecl::None);
+ SC_None, SC_None);
break;
- case pch::DECL_IMPLICIT_PARAM:
+ case DECL_IMPLICIT_PARAM:
D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
break;
- case pch::DECL_PARM_VAR:
+ case DECL_PARM_VAR:
D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
- VarDecl::None, VarDecl::None, 0);
+ SC_None, SC_None, 0);
break;
- case pch::DECL_FILE_SCOPE_ASM:
+ case DECL_FILE_SCOPE_ASM:
D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
break;
- case pch::DECL_BLOCK:
+ case DECL_BLOCK:
D = BlockDecl::Create(*Context, 0, SourceLocation());
break;
}
- assert(D && "Unknown declaration reading PCH file");
+ assert(D && "Unknown declaration reading AST file");
LoadedDecl(Index, D);
Reader.Visit(D);
@@ -1468,7 +1409,44 @@ Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) {
if (Offsets.first || Offsets.second) {
DC->setHasExternalLexicalStorage(Offsets.first != 0);
DC->setHasExternalVisibleStorage(Offsets.second != 0);
- DeclContextOffsets[DC] = Offsets;
+ DeclContextInfo Info;
+ if (ReadDeclContextStorage(DeclsCursor, Offsets, Info))
+ return 0;
+ DeclContextInfos &Infos = DeclContextOffsets[DC];
+ // Reading the TU will happen after reading its lexical update blocks,
+ // so we need to make sure we insert in front. For all other contexts,
+ // the vector is empty here anyway, so there's no loss in efficiency.
+ Infos.insert(Infos.begin(), Info);
+
+ // Now add the pending visible updates for this decl context, if it has
+ // any.
+ DeclContextVisibleUpdatesPending::iterator I =
+ PendingVisibleUpdates.find(ID);
+ if (I != PendingVisibleUpdates.end()) {
+ DeclContextVisibleUpdates &U = I->second;
+ Info.LexicalDecls = 0;
+ Info.NumLexicalDecls = 0;
+ for (DeclContextVisibleUpdates::iterator UI = U.begin(), UE = U.end();
+ UI != UE; ++UI) {
+ Info.NameLookupTableData = *UI;
+ Infos.push_back(Info);
+ }
+ PendingVisibleUpdates.erase(I);
+ }
+ }
+ }
+
+ // If this is a template, read additional specializations that may be in a
+ // different part of the chain.
+ if (isa<RedeclarableTemplateDecl>(D)) {
+ AdditionalTemplateSpecializationsMap::iterator F =
+ AdditionalTemplateSpecializationsPending.find(ID);
+ if (F != AdditionalTemplateSpecializationsPending.end()) {
+ for (AdditionalTemplateSpecializations::iterator I = F->second.begin(),
+ E = F->second.end();
+ I != E; ++I)
+ GetDecl(*I);
+ AdditionalTemplateSpecializationsPending.erase(F);
}
}
assert(Idx == Record.size());
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index ace62d787ed9..ee5d40a3698e 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -1,4 +1,4 @@
-//===--- PCHReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===//
+//===--- ASTReaderStmt.cpp - Stmt/Expr Deserialization ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,26 +8,28 @@
//===----------------------------------------------------------------------===//
//
// Statement/expression deserialization. This implements the
-// PCHReader::ReadStmt method.
+// ASTReader::ReadStmt method.
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/ASTReader.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtVisitor.h"
using namespace clang;
+using namespace clang::serialization;
namespace clang {
- class PCHStmtReader : public StmtVisitor<PCHStmtReader> {
- PCHReader &Reader;
- const PCHReader::RecordData &Record;
+ class ASTStmtReader : public StmtVisitor<ASTStmtReader> {
+ ASTReader &Reader;
+ llvm::BitstreamCursor &DeclsCursor;
+ const ASTReader::RecordData &Record;
unsigned &Idx;
public:
- PCHStmtReader(PCHReader &Reader, const PCHReader::RecordData &Record,
- unsigned &Idx)
- : Reader(Reader), Record(Record), Idx(Idx) { }
+ ASTStmtReader(ASTReader &Reader, llvm::BitstreamCursor &Cursor,
+ const ASTReader::RecordData &Record, unsigned &Idx)
+ : Reader(Reader), DeclsCursor(Cursor), Record(Record), Idx(Idx) { }
/// \brief The number of record fields required for the Stmt class
/// itself.
@@ -116,6 +118,10 @@ namespace clang {
void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *);
void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
+ // C++ Statements
+ void VisitCXXCatchStmt(CXXCatchStmt *S);
+ void VisitCXXTryStmt(CXXTryStmt *S);
+
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
void VisitCXXConstructExpr(CXXConstructExpr *E);
void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
@@ -132,7 +138,6 @@ namespace clang {
void VisitCXXThrowExpr(CXXThrowExpr *E);
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
- void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E);
void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
void VisitCXXNewExpr(CXXNewExpr *E);
@@ -153,27 +158,28 @@ namespace clang {
};
}
-void PCHStmtReader::
+void ASTStmtReader::
ReadExplicitTemplateArgumentList(ExplicitTemplateArgumentList &ArgList,
unsigned NumTemplateArgs) {
TemplateArgumentListInfo ArgInfo;
ArgInfo.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx));
ArgInfo.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx));
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- ArgInfo.addArgument(Reader.ReadTemplateArgumentLoc(Record, Idx));
+ ArgInfo.addArgument(
+ Reader.ReadTemplateArgumentLoc(DeclsCursor, Record, Idx));
ArgList.initializeFrom(ArgInfo);
}
-void PCHStmtReader::VisitStmt(Stmt *S) {
+void ASTStmtReader::VisitStmt(Stmt *S) {
assert(Idx == NumStmtFields && "Incorrect statement field count");
}
-void PCHStmtReader::VisitNullStmt(NullStmt *S) {
+void ASTStmtReader::VisitNullStmt(NullStmt *S) {
VisitStmt(S);
S->setSemiLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) {
+void ASTStmtReader::VisitCompoundStmt(CompoundStmt *S) {
VisitStmt(S);
llvm::SmallVector<Stmt *, 16> Stmts;
unsigned NumStmts = Record[Idx++];
@@ -184,12 +190,12 @@ void PCHStmtReader::VisitCompoundStmt(CompoundStmt *S) {
S->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitSwitchCase(SwitchCase *S) {
+void ASTStmtReader::VisitSwitchCase(SwitchCase *S) {
VisitStmt(S);
Reader.RecordSwitchCaseID(S, Record[Idx++]);
}
-void PCHStmtReader::VisitCaseStmt(CaseStmt *S) {
+void ASTStmtReader::VisitCaseStmt(CaseStmt *S) {
VisitSwitchCase(S);
S->setLHS(Reader.ReadSubExpr());
S->setRHS(Reader.ReadSubExpr());
@@ -199,14 +205,14 @@ void PCHStmtReader::VisitCaseStmt(CaseStmt *S) {
S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitDefaultStmt(DefaultStmt *S) {
+void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
VisitSwitchCase(S);
S->setSubStmt(Reader.ReadSubStmt());
S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitLabelStmt(LabelStmt *S) {
+void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
VisitStmt(S);
S->setID(Reader.GetIdentifierInfo(Record, Idx));
S->setSubStmt(Reader.ReadSubStmt());
@@ -214,7 +220,7 @@ void PCHStmtReader::VisitLabelStmt(LabelStmt *S) {
Reader.RecordLabelStmt(S, Record[Idx++]);
}
-void PCHStmtReader::VisitIfStmt(IfStmt *S) {
+void ASTStmtReader::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
S->setConditionVariable(*Reader.getContext(),
cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
@@ -225,7 +231,7 @@ void PCHStmtReader::VisitIfStmt(IfStmt *S) {
S->setElseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
+void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
S->setConditionVariable(*Reader.getContext(),
cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
@@ -247,7 +253,7 @@ void PCHStmtReader::VisitSwitchStmt(SwitchStmt *S) {
}
}
-void PCHStmtReader::VisitWhileStmt(WhileStmt *S) {
+void ASTStmtReader::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S);
S->setConditionVariable(*Reader.getContext(),
cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
@@ -256,7 +262,7 @@ void PCHStmtReader::VisitWhileStmt(WhileStmt *S) {
S->setWhileLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitDoStmt(DoStmt *S) {
+void ASTStmtReader::VisitDoStmt(DoStmt *S) {
VisitStmt(S);
S->setCond(Reader.ReadSubExpr());
S->setBody(Reader.ReadSubStmt());
@@ -265,7 +271,7 @@ void PCHStmtReader::VisitDoStmt(DoStmt *S) {
S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitForStmt(ForStmt *S) {
+void ASTStmtReader::VisitForStmt(ForStmt *S) {
VisitStmt(S);
S->setInit(Reader.ReadSubStmt());
S->setCond(Reader.ReadSubExpr());
@@ -278,38 +284,38 @@ void PCHStmtReader::VisitForStmt(ForStmt *S) {
S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitGotoStmt(GotoStmt *S) {
+void ASTStmtReader::VisitGotoStmt(GotoStmt *S) {
VisitStmt(S);
Reader.SetLabelOf(S, Record[Idx++]);
S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+void ASTStmtReader::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
VisitStmt(S);
S->setGotoLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setTarget(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitContinueStmt(ContinueStmt *S) {
+void ASTStmtReader::VisitContinueStmt(ContinueStmt *S) {
VisitStmt(S);
S->setContinueLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitBreakStmt(BreakStmt *S) {
+void ASTStmtReader::VisitBreakStmt(BreakStmt *S) {
VisitStmt(S);
S->setBreakLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitReturnStmt(ReturnStmt *S) {
+void ASTStmtReader::VisitReturnStmt(ReturnStmt *S) {
VisitStmt(S);
S->setRetValue(Reader.ReadSubExpr());
S->setReturnLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setNRVOCandidate(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHStmtReader::VisitDeclStmt(DeclStmt *S) {
+void ASTStmtReader::VisitDeclStmt(DeclStmt *S) {
VisitStmt(S);
S->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
S->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -328,7 +334,7 @@ void PCHStmtReader::VisitDeclStmt(DeclStmt *S) {
}
}
-void PCHStmtReader::VisitAsmStmt(AsmStmt *S) {
+void ASTStmtReader::VisitAsmStmt(AsmStmt *S) {
VisitStmt(S);
unsigned NumOutputs = Record[Idx++];
unsigned NumInputs = Record[Idx++];
@@ -362,7 +368,7 @@ void PCHStmtReader::VisitAsmStmt(AsmStmt *S) {
Clobbers.data(), NumClobbers);
}
-void PCHStmtReader::VisitExpr(Expr *E) {
+void ASTStmtReader::VisitExpr(Expr *E) {
VisitStmt(E);
E->setType(Reader.GetType(Record[Idx++]));
E->setTypeDependent(Record[Idx++]);
@@ -370,13 +376,13 @@ void PCHStmtReader::VisitExpr(Expr *E) {
assert(Idx == NumExprFields && "Incorrect expression field count");
}
-void PCHStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
+void ASTStmtReader::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setIdentType((PredefinedExpr::IdentType)Record[Idx++]);
}
-void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
+void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
bool HasQualifier = Record[Idx++];
@@ -391,32 +397,33 @@ void PCHStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
}
if (NumTemplateArgs)
- ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(),
+ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
+ // FIXME: read DeclarationNameLoc.
E->setLocation(Reader.ReadSourceLocation(Record, Idx));
}
-void PCHStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
+void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
VisitExpr(E);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
- E->setValue(Reader.ReadAPInt(Record, Idx));
+ E->setValue(*Reader.getContext(), Reader.ReadAPInt(Record, Idx));
}
-void PCHStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
+void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
- E->setValue(Reader.ReadAPFloat(Record, Idx));
+ E->setValue(*Reader.getContext(), Reader.ReadAPFloat(Record, Idx));
E->setExact(Record[Idx++]);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+void ASTStmtReader::VisitImaginaryLiteral(ImaginaryLiteral *E) {
VisitExpr(E);
E->setSubExpr(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitStringLiteral(StringLiteral *E) {
+void ASTStmtReader::VisitStringLiteral(StringLiteral *E) {
VisitExpr(E);
unsigned Len = Record[Idx++];
assert(Record[Idx] == E->getNumConcatenated() &&
@@ -434,21 +441,21 @@ void PCHStmtReader::VisitStringLiteral(StringLiteral *E) {
E->setStrTokenLoc(I, SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
+void ASTStmtReader::VisitCharacterLiteral(CharacterLiteral *E) {
VisitExpr(E);
E->setValue(Record[Idx++]);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setWide(Record[Idx++]);
}
-void PCHStmtReader::VisitParenExpr(ParenExpr *E) {
+void ASTStmtReader::VisitParenExpr(ParenExpr *E) {
VisitExpr(E);
E->setLParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParen(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setSubExpr(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitParenListExpr(ParenListExpr *E) {
+void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
unsigned NumExprs = Record[Idx++];
E->Exprs = new (*Reader.getContext()) Stmt*[NumExprs];
@@ -459,14 +466,14 @@ void PCHStmtReader::VisitParenListExpr(ParenListExpr *E) {
E->RParenLoc = Reader.ReadSourceLocation(Record, Idx);
}
-void PCHStmtReader::VisitUnaryOperator(UnaryOperator *E) {
+void ASTStmtReader::VisitUnaryOperator(UnaryOperator *E) {
VisitExpr(E);
E->setSubExpr(Reader.ReadSubExpr());
E->setOpcode((UnaryOperator::Opcode)Record[Idx++]);
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
+void ASTStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
typedef OffsetOfExpr::OffsetOfNode Node;
VisitExpr(E);
assert(E->getNumComponents() == Record[Idx]);
@@ -475,7 +482,7 @@ void PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
++Idx;
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) {
Node::Kind Kind = static_cast<Node::Kind>(Record[Idx++]);
SourceLocation Start = SourceLocation::getFromRawEncoding(Record[Idx++]);
@@ -496,38 +503,40 @@ void PCHStmtReader::VisitOffsetOfExpr(OffsetOfExpr *E) {
E->setComponent(I, Node(Start, Reader.GetIdentifier(Record[Idx++]), End));
break;
- case Node::Base:
- // FIXME: Implement this!
- llvm_unreachable("PCH for offsetof(base-specifier) not implemented");
+ case Node::Base: {
+ CXXBaseSpecifier *Base = new (*Reader.getContext()) CXXBaseSpecifier();
+ *Base = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx);
+ E->setComponent(I, Node(Base));
break;
}
+ }
}
for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
E->setIndexExpr(I, Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+void ASTStmtReader::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
VisitExpr(E);
E->setSizeof(Record[Idx++]);
if (Record[Idx] == 0) {
E->setArgument(Reader.ReadSubExpr());
++Idx;
} else {
- E->setArgument(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setArgument(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
}
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
VisitExpr(E);
E->setLHS(Reader.ReadSubExpr());
E->setRHS(Reader.ReadSubExpr());
E->setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCallExpr(CallExpr *E) {
+void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
E->setNumArgs(*Reader.getContext(), Record[Idx++]);
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -536,34 +545,34 @@ void PCHStmtReader::VisitCallExpr(CallExpr *E) {
E->setArg(I, Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitMemberExpr(MemberExpr *E) {
+void ASTStmtReader::VisitMemberExpr(MemberExpr *E) {
// Don't call VisitExpr, this is fully initialized at creation.
assert(E->getStmtClass() == Stmt::MemberExprClass &&
"It's a subclass, we must advance Idx!");
}
-void PCHStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
+void ASTStmtReader::VisitObjCIsaExpr(ObjCIsaExpr *E) {
VisitExpr(E);
E->setBase(Reader.ReadSubExpr());
E->setIsaMemberLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setArrow(Record[Idx++]);
}
-void PCHStmtReader::VisitCastExpr(CastExpr *E) {
+void ASTStmtReader::VisitCastExpr(CastExpr *E) {
VisitExpr(E);
+ unsigned NumBaseSpecs = Record[Idx++];
+ assert(NumBaseSpecs == E->path_size());
E->setSubExpr(Reader.ReadSubExpr());
E->setCastKind((CastExpr::CastKind)Record[Idx++]);
- CXXBaseSpecifierArray &BasePath = E->getBasePath();
- unsigned NumBaseSpecs = Record[Idx++];
+ CastExpr::path_iterator BaseI = E->path_begin();
while (NumBaseSpecs--) {
- // FIXME: These gets leaked.
CXXBaseSpecifier *BaseSpec = new (*Reader.getContext()) CXXBaseSpecifier;
- *BaseSpec = Reader.ReadCXXBaseSpecifier(Record, Idx);
- BasePath.push_back(BaseSpec);
+ *BaseSpec = Reader.ReadCXXBaseSpecifier(DeclsCursor, Record, Idx);
+ *BaseI++ = BaseSpec;
}
}
-void PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) {
+void ASTStmtReader::VisitBinaryOperator(BinaryOperator *E) {
VisitExpr(E);
E->setLHS(Reader.ReadSubExpr());
E->setRHS(Reader.ReadSubExpr());
@@ -571,53 +580,54 @@ void PCHStmtReader::VisitBinaryOperator(BinaryOperator *E) {
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+void ASTStmtReader::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
VisitBinaryOperator(E);
E->setComputationLHSType(Reader.GetType(Record[Idx++]));
E->setComputationResultType(Reader.GetType(Record[Idx++]));
}
-void PCHStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
+void ASTStmtReader::VisitConditionalOperator(ConditionalOperator *E) {
VisitExpr(E);
E->setCond(Reader.ReadSubExpr());
E->setLHS(Reader.ReadSubExpr());
E->setRHS(Reader.ReadSubExpr());
+ E->setSAVE(Reader.ReadSubExpr());
E->setQuestionLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+void ASTStmtReader::VisitImplicitCastExpr(ImplicitCastExpr *E) {
VisitCastExpr(E);
- E->setLvalueCast(Record[Idx++]);
+ E->setValueKind(static_cast<ExprValueKind>(Record[Idx++]));
}
-void PCHStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+void ASTStmtReader::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
- E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setTypeInfoAsWritten(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
}
-void PCHStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
+void ASTStmtReader::VisitCStyleCastExpr(CStyleCastExpr *E) {
VisitExplicitCastExpr(E);
E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+void ASTStmtReader::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
- E->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
E->setInitializer(Reader.ReadSubExpr());
E->setFileScope(Record[Idx++]);
}
-void PCHStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
+void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
VisitExpr(E);
E->setBase(Reader.ReadSubExpr());
E->setAccessor(Reader.GetIdentifierInfo(Record, Idx));
E->setAccessorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitInitListExpr(InitListExpr *E) {
+void ASTStmtReader::VisitInitListExpr(InitListExpr *E) {
VisitExpr(E);
unsigned NumInits = Record[Idx++];
E->reserveInits(*Reader.getContext(), NumInits);
@@ -631,7 +641,7 @@ void PCHStmtReader::VisitInitListExpr(InitListExpr *E) {
E->sawArrayRangeDesignator(Record[Idx++]);
}
-void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+void ASTStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
typedef DesignatedInitExpr::Designator Designator;
VisitExpr(E);
@@ -644,8 +654,8 @@ void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
llvm::SmallVector<Designator, 4> Designators;
while (Idx < Record.size()) {
- switch ((pch::DesignatorTypes)Record[Idx++]) {
- case pch::DESIG_FIELD_DECL: {
+ switch ((DesignatorTypes)Record[Idx++]) {
+ case DESIG_FIELD_DECL: {
FieldDecl *Field = cast<FieldDecl>(Reader.GetDecl(Record[Idx++]));
SourceLocation DotLoc
= SourceLocation::getFromRawEncoding(Record[Idx++]);
@@ -657,7 +667,7 @@ void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
break;
}
- case pch::DESIG_FIELD_NAME: {
+ case DESIG_FIELD_NAME: {
const IdentifierInfo *Name = Reader.GetIdentifierInfo(Record, Idx);
SourceLocation DotLoc
= SourceLocation::getFromRawEncoding(Record[Idx++]);
@@ -667,7 +677,7 @@ void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
break;
}
- case pch::DESIG_ARRAY: {
+ case DESIG_ARRAY: {
unsigned Index = Record[Idx++];
SourceLocation LBracketLoc
= SourceLocation::getFromRawEncoding(Record[Idx++]);
@@ -677,7 +687,7 @@ void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
break;
}
- case pch::DESIG_ARRAY_RANGE: {
+ case DESIG_ARRAY_RANGE: {
unsigned Index = Record[Idx++];
SourceLocation LBracketLoc
= SourceLocation::getFromRawEncoding(Record[Idx++]);
@@ -695,40 +705,41 @@ void PCHStmtReader::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
Designators.data(), Designators.size());
}
-void PCHStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+void ASTStmtReader::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
VisitExpr(E);
}
-void PCHStmtReader::VisitVAArgExpr(VAArgExpr *E) {
+void ASTStmtReader::VisitVAArgExpr(VAArgExpr *E) {
VisitExpr(E);
E->setSubExpr(Reader.ReadSubExpr());
+ E->setWrittenTypeInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
+void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
VisitExpr(E);
E->setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setLabelLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
Reader.SetLabelOf(E, Record[Idx++]);
}
-void PCHStmtReader::VisitStmtExpr(StmtExpr *E) {
+void ASTStmtReader::VisitStmtExpr(StmtExpr *E) {
VisitExpr(E);
E->setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setSubStmt(cast_or_null<CompoundStmt>(Reader.ReadSubStmt()));
}
-void PCHStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
+void ASTStmtReader::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
VisitExpr(E);
- E->setArgType1(Reader.GetType(Record[Idx++]));
- E->setArgType2(Reader.GetType(Record[Idx++]));
+ E->setArgTInfo1(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
+ E->setArgTInfo2(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
E->setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitChooseExpr(ChooseExpr *E) {
+void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) {
VisitExpr(E);
E->setCond(Reader.ReadSubExpr());
E->setLHS(Reader.ReadSubExpr());
@@ -737,12 +748,12 @@ void PCHStmtReader::VisitChooseExpr(ChooseExpr *E) {
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
+void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) {
VisitExpr(E);
E->setTokenLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
VisitExpr(E);
llvm::SmallVector<Expr *, 16> Exprs;
unsigned NumExprs = Record[Idx++];
@@ -753,13 +764,13 @@ void PCHStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitBlockExpr(BlockExpr *E) {
+void ASTStmtReader::VisitBlockExpr(BlockExpr *E) {
VisitExpr(E);
E->setBlockDecl(cast_or_null<BlockDecl>(Reader.GetDecl(Record[Idx++])));
E->setHasBlockDeclRefExprs(Record[Idx++]);
}
-void PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+void ASTStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
VisitExpr(E);
E->setDecl(cast<ValueDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -771,34 +782,34 @@ void PCHStmtReader::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
//===----------------------------------------------------------------------===//
// Objective-C Expressions and Statements
-void PCHStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) {
+void ASTStmtReader::VisitObjCStringLiteral(ObjCStringLiteral *E) {
VisitExpr(E);
E->setString(cast<StringLiteral>(Reader.ReadSubStmt()));
E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+void ASTStmtReader::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
VisitExpr(E);
- E->setEncodedTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setEncodedTypeSourceInfo(Reader.GetTypeSourceInfo(DeclsCursor,Record,Idx));
E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+void ASTStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
VisitExpr(E);
E->setSelector(Reader.GetSelector(Record, Idx));
E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+void ASTStmtReader::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
VisitExpr(E);
E->setProtocol(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+void ASTStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
VisitExpr(E);
E->setDecl(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -807,14 +818,14 @@ void PCHStmtReader::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
E->setIsFreeIvar(Record[Idx++]);
}
-void PCHStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+void ASTStmtReader::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
VisitExpr(E);
E->setProperty(cast<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setBase(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr(
+void ASTStmtReader::VisitObjCImplicitSetterGetterRefExpr(
ObjCImplicitSetterGetterRefExpr *E) {
VisitExpr(E);
E->setGetterMethod(
@@ -828,7 +839,7 @@ void PCHStmtReader::VisitObjCImplicitSetterGetterRefExpr(
E->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+void ASTStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
VisitExpr(E);
assert(Record[Idx] == E->getNumArgs());
++Idx;
@@ -840,7 +851,7 @@ void PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
break;
case ObjCMessageExpr::Class:
- E->setClassReceiver(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setClassReceiver(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
break;
case ObjCMessageExpr::SuperClass:
@@ -866,12 +877,12 @@ void PCHStmtReader::VisitObjCMessageExpr(ObjCMessageExpr *E) {
E->setArg(I, Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) {
+void ASTStmtReader::VisitObjCSuperExpr(ObjCSuperExpr *E) {
VisitExpr(E);
E->setLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+void ASTStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
VisitStmt(S);
S->setElement(Reader.ReadSubStmt());
S->setCollection(Reader.ReadSubExpr());
@@ -880,7 +891,7 @@ void PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+void ASTStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
VisitStmt(S);
S->setCatchBody(Reader.ReadSubStmt());
S->setCatchParamDecl(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
@@ -888,13 +899,13 @@ void PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+void ASTStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
VisitStmt(S);
S->setFinallyBody(Reader.ReadSubStmt());
S->setAtFinallyLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+void ASTStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
VisitStmt(S);
assert(Record[Idx] == S->getNumCatchStmts());
++Idx;
@@ -908,14 +919,14 @@ void PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+void ASTStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
VisitStmt(S);
S->setSynchExpr(Reader.ReadSubStmt());
S->setSynchBody(Reader.ReadSubStmt());
S->setAtSynchronizedLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+void ASTStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
VisitStmt(S);
S->setThrowExpr(Reader.ReadSubStmt());
S->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
@@ -923,13 +934,31 @@ void PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
//===----------------------------------------------------------------------===//
// C++ Expressions and Statements
+//===----------------------------------------------------------------------===//
+
+void ASTStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ VisitStmt(S);
+ S->CatchLoc = Reader.ReadSourceLocation(Record, Idx);
+ S->ExceptionDecl = cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]));
+ S->HandlerBlock = Reader.ReadSubStmt();
+}
+
+void ASTStmtReader::VisitCXXTryStmt(CXXTryStmt *S) {
+ VisitStmt(S);
+ assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?");
+ ++Idx;
+ S->TryLoc = Reader.ReadSourceLocation(Record, Idx);
+ S->getStmts()[0] = Reader.ReadSubStmt();
+ for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
+ S->getStmts()[i + 1] = Reader.ReadSubStmt();
+}
-void PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
E->setOperator((OverloadedOperatorKind)Record[Idx++]);
}
-void PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
+void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
VisitExpr(E);
E->NumArgs = Record[Idx++];
if (E->NumArgs)
@@ -943,55 +972,56 @@ void PCHStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) {
E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]);
}
-void PCHStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
+void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
VisitCXXConstructExpr(E);
E->TyBeginLoc = Reader.ReadSourceLocation(Record, Idx);
E->RParenLoc = Reader.ReadSourceLocation(Record, Idx);
}
-void PCHStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
VisitExplicitCastExpr(E);
E->setOperatorLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+void ASTStmtReader::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
-void PCHStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+void ASTStmtReader::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
-void PCHStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+void ASTStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
-void PCHStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
-void PCHStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
VisitExplicitCastExpr(E);
E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+void ASTStmtReader::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
VisitExpr(E);
E->setValue(Record[Idx++]);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+void ASTStmtReader::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
VisitExpr(E);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+void ASTStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
VisitExpr(E);
E->setSourceRange(Reader.ReadSourceRange(Record, Idx));
if (E->isTypeOperand()) { // typeid(int)
- E->setTypeOperandSourceInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setTypeOperandSourceInfo(
+ Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
return;
}
@@ -999,19 +1029,19 @@ void PCHStmtReader::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
E->setExprOperand(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitCXXThisExpr(CXXThisExpr *E) {
+void ASTStmtReader::VisitCXXThisExpr(CXXThisExpr *E) {
VisitExpr(E);
E->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setImplicit(Record[Idx++]);
}
-void PCHStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
+void ASTStmtReader::VisitCXXThrowExpr(CXXThrowExpr *E) {
VisitExpr(E);
E->setThrowLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setSubExpr(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+void ASTStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
assert(Record[Idx] == E->Param.getInt() && "We messed up at creation ?");
@@ -1020,26 +1050,19 @@ void PCHStmtReader::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
E->Loc = Reader.ReadSourceLocation(Record, Idx);
}
-void PCHStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+void ASTStmtReader::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
VisitExpr(E);
E->setTemporary(Reader.ReadCXXTemporary(Record, Idx));
E->setSubExpr(Reader.ReadSubExpr());
}
-void PCHStmtReader::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
- VisitExpr(E);
- E->SubExpr = Reader.ReadSubExpr();
- E->ExtendsLifetime = Record[Idx++];
- E->RequiresTemporaryCopy = Record[Idx++];
-}
-
-void PCHStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
VisitExpr(E);
E->setTypeBeginLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
+void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
VisitExpr(E);
E->setGlobalNew(Record[Idx++]);
E->setHasInitializer(Record[Idx++]);
@@ -1067,7 +1090,7 @@ void PCHStmtReader::VisitCXXNewExpr(CXXNewExpr *E) {
*I = Reader.ReadSubStmt();
}
-void PCHStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
VisitExpr(E);
E->setGlobalDelete(Record[Idx++]);
E->setArrayForm(Record[Idx++]);
@@ -1077,7 +1100,7 @@ void PCHStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
E->setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}
-void PCHStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+void ASTStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
VisitExpr(E);
E->setBase(Reader.ReadSubExpr());
@@ -1085,7 +1108,7 @@ void PCHStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx));
E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
- E->setScopeTypeInfo(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setScopeTypeInfo(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
E->setColonColonLoc(Reader.ReadSourceLocation(Record, Idx));
E->setTildeLoc(Reader.ReadSourceLocation(Record, Idx));
@@ -1093,10 +1116,10 @@ void PCHStmtReader::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
if (II)
E->setDestroyedType(II, Reader.ReadSourceLocation(Record, Idx));
else
- E->setDestroyedType(Reader.GetTypeSourceInfo(Record, Idx));
+ E->setDestroyedType(Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx));
}
-void PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
+void ASTStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
VisitExpr(E);
unsigned NumTemps = Record[Idx++];
if (NumTemps) {
@@ -1108,14 +1131,14 @@ void PCHStmtReader::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
}
void
-PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
+ASTStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
VisitExpr(E);
unsigned NumTemplateArgs = Record[Idx++];
assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Read wrong record during creation ?");
if (E->hasExplicitTemplateArgs())
- ReadExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList(),
+ ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
E->setBase(Reader.ReadSubExpr());
@@ -1126,12 +1149,13 @@ PCHStmtReader::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
E->setFirstQualifierFoundInScope(
cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+ // FIXME: read whole DeclarationNameInfo.
E->setMember(Reader.ReadDeclarationName(Record, Idx));
E->setMemberLoc(Reader.ReadSourceLocation(Record, Idx));
}
void
-PCHStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+ASTStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
VisitExpr(E);
unsigned NumTemplateArgs = Record[Idx++];
@@ -1141,6 +1165,7 @@ PCHStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
+ // FIXME: read whole DeclarationNameInfo.
E->setDeclName(Reader.ReadDeclarationName(Record, Idx));
E->setLocation(Reader.ReadSourceLocation(Record, Idx));
E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
@@ -1148,7 +1173,7 @@ PCHStmtReader::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
}
void
-PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
+ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
VisitExpr(E);
assert(Record[Idx] == E->arg_size() && "Read wrong record during creation ?");
++Idx; // NumArgs;
@@ -1160,7 +1185,7 @@ PCHStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
E->setRParenLoc(Reader.ReadSourceLocation(Record, Idx));
}
-void PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) {
+void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
unsigned NumTemplateArgs = Record[Idx++];
@@ -1179,13 +1204,14 @@ void PCHStmtReader::VisitOverloadExpr(OverloadExpr *E) {
}
E->initializeResults(*Reader.getContext(), Decls.begin(), Decls.end());
+ // FIXME: read whole DeclarationNameInfo.
E->setName(Reader.ReadDeclarationName(Record, Idx));
E->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
E->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
E->setNameLoc(Reader.ReadSourceLocation(Record, Idx));
}
-void PCHStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+void ASTStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
VisitOverloadExpr(E);
E->setArrow(Record[Idx++]);
E->setHasUnresolvedUsing(Record[Idx++]);
@@ -1194,14 +1220,14 @@ void PCHStmtReader::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
E->setOperatorLoc(Reader.ReadSourceLocation(Record, Idx));
}
-void PCHStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
E->setRequiresADL(Record[Idx++]);
E->setOverloaded(Record[Idx++]);
E->setNamingClass(cast_or_null<CXXRecordDecl>(Reader.GetDecl(Record[Idx++])));
}
-void PCHStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+void ASTStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
VisitExpr(E);
E->UTT = (UnaryTypeTrait)Record[Idx++];
SourceRange Range = Reader.ReadSourceRange(Record, Idx);
@@ -1210,12 +1236,11 @@ void PCHStmtReader::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
E->QueriedType = Reader.GetType(Record[Idx++]);
}
-Stmt *PCHReader::ReadStmt() {
+Stmt *ASTReader::ReadStmt(llvm::BitstreamCursor &Cursor) {
switch (ReadingKind) {
case Read_Decl:
case Read_Type:
- // Read a statement from the current DeclCursor.
- return ReadStmtFromStream(DeclsCursor);
+ return ReadStmtFromStream(Cursor);
case Read_Stmt:
return ReadSubStmt();
}
@@ -1224,11 +1249,11 @@ Stmt *PCHReader::ReadStmt() {
return 0;
}
-Expr *PCHReader::ReadExpr() {
- return cast_or_null<Expr>(ReadStmt());
+Expr *ASTReader::ReadExpr(llvm::BitstreamCursor &Cursor) {
+ return cast_or_null<Expr>(ReadStmt(Cursor));
}
-Expr *PCHReader::ReadSubExpr() {
+Expr *ASTReader::ReadSubExpr() {
return cast_or_null<Expr>(ReadSubStmt());
}
@@ -1239,7 +1264,7 @@ Expr *PCHReader::ReadSubExpr() {
// the stack, with expressions having operands removing those operands from the
// stack. Evaluation terminates when we see a STMT_STOP record, and
// the single remaining expression on the stack is our result.
-Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
+Stmt *ASTReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
ReadingKindTracker ReadingKind(Read_Stmt, *this);
@@ -1249,14 +1274,14 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
RecordData Record;
unsigned Idx;
- PCHStmtReader Reader(*this, Record, Idx);
+ ASTStmtReader Reader(*this, Cursor, Record, Idx);
Stmt::EmptyShell Empty;
while (true) {
unsigned Code = Cursor.ReadCode();
if (Code == llvm::bitc::END_BLOCK) {
if (Cursor.ReadBlockEnd()) {
- Error("error at end of block in PCH file");
+ Error("error at end of block in AST file");
return 0;
}
break;
@@ -1266,7 +1291,7 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
// No known subblocks, always skip them.
Cursor.ReadSubBlockID();
if (Cursor.SkipBlock()) {
- Error("malformed block record in PCH file");
+ Error("malformed block record in AST file");
return 0;
}
continue;
@@ -1281,145 +1306,145 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
Idx = 0;
Record.clear();
bool Finished = false;
- switch ((pch::StmtCode)Cursor.ReadRecord(Code, Record)) {
- case pch::STMT_STOP:
+ switch ((StmtCode)Cursor.ReadRecord(Code, Record)) {
+ case STMT_STOP:
Finished = true;
break;
- case pch::STMT_NULL_PTR:
+ case STMT_NULL_PTR:
S = 0;
break;
- case pch::STMT_NULL:
+ case STMT_NULL:
S = new (Context) NullStmt(Empty);
break;
- case pch::STMT_COMPOUND:
+ case STMT_COMPOUND:
S = new (Context) CompoundStmt(Empty);
break;
- case pch::STMT_CASE:
+ case STMT_CASE:
S = new (Context) CaseStmt(Empty);
break;
- case pch::STMT_DEFAULT:
+ case STMT_DEFAULT:
S = new (Context) DefaultStmt(Empty);
break;
- case pch::STMT_LABEL:
+ case STMT_LABEL:
S = new (Context) LabelStmt(Empty);
break;
- case pch::STMT_IF:
+ case STMT_IF:
S = new (Context) IfStmt(Empty);
break;
- case pch::STMT_SWITCH:
+ case STMT_SWITCH:
S = new (Context) SwitchStmt(Empty);
break;
- case pch::STMT_WHILE:
+ case STMT_WHILE:
S = new (Context) WhileStmt(Empty);
break;
- case pch::STMT_DO:
+ case STMT_DO:
S = new (Context) DoStmt(Empty);
break;
- case pch::STMT_FOR:
+ case STMT_FOR:
S = new (Context) ForStmt(Empty);
break;
- case pch::STMT_GOTO:
+ case STMT_GOTO:
S = new (Context) GotoStmt(Empty);
break;
- case pch::STMT_INDIRECT_GOTO:
+ case STMT_INDIRECT_GOTO:
S = new (Context) IndirectGotoStmt(Empty);
break;
- case pch::STMT_CONTINUE:
+ case STMT_CONTINUE:
S = new (Context) ContinueStmt(Empty);
break;
- case pch::STMT_BREAK:
+ case STMT_BREAK:
S = new (Context) BreakStmt(Empty);
break;
- case pch::STMT_RETURN:
+ case STMT_RETURN:
S = new (Context) ReturnStmt(Empty);
break;
- case pch::STMT_DECL:
+ case STMT_DECL:
S = new (Context) DeclStmt(Empty);
break;
- case pch::STMT_ASM:
+ case STMT_ASM:
S = new (Context) AsmStmt(Empty);
break;
- case pch::EXPR_PREDEFINED:
+ case EXPR_PREDEFINED:
S = new (Context) PredefinedExpr(Empty);
break;
- case pch::EXPR_DECL_REF:
+ case EXPR_DECL_REF:
S = DeclRefExpr::CreateEmpty(*Context,
- /*HasQualifier=*/Record[PCHStmtReader::NumExprFields],
- /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields + 1]);
+ /*HasQualifier=*/Record[ASTStmtReader::NumExprFields],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]);
break;
- case pch::EXPR_INTEGER_LITERAL:
- S = new (Context) IntegerLiteral(Empty);
+ case EXPR_INTEGER_LITERAL:
+ S = IntegerLiteral::Create(*Context, Empty);
break;
- case pch::EXPR_FLOATING_LITERAL:
- S = new (Context) FloatingLiteral(Empty);
+ case EXPR_FLOATING_LITERAL:
+ S = FloatingLiteral::Create(*Context, Empty);
break;
- case pch::EXPR_IMAGINARY_LITERAL:
+ case EXPR_IMAGINARY_LITERAL:
S = new (Context) ImaginaryLiteral(Empty);
break;
- case pch::EXPR_STRING_LITERAL:
+ case EXPR_STRING_LITERAL:
S = StringLiteral::CreateEmpty(*Context,
- Record[PCHStmtReader::NumExprFields + 1]);
+ Record[ASTStmtReader::NumExprFields + 1]);
break;
- case pch::EXPR_CHARACTER_LITERAL:
+ case EXPR_CHARACTER_LITERAL:
S = new (Context) CharacterLiteral(Empty);
break;
- case pch::EXPR_PAREN:
+ case EXPR_PAREN:
S = new (Context) ParenExpr(Empty);
break;
- case pch::EXPR_PAREN_LIST:
+ case EXPR_PAREN_LIST:
S = new (Context) ParenListExpr(Empty);
break;
- case pch::EXPR_UNARY_OPERATOR:
+ case EXPR_UNARY_OPERATOR:
S = new (Context) UnaryOperator(Empty);
break;
- case pch::EXPR_OFFSETOF:
+ case EXPR_OFFSETOF:
S = OffsetOfExpr::CreateEmpty(*Context,
- Record[PCHStmtReader::NumExprFields],
- Record[PCHStmtReader::NumExprFields + 1]);
+ Record[ASTStmtReader::NumExprFields],
+ Record[ASTStmtReader::NumExprFields + 1]);
break;
- case pch::EXPR_SIZEOF_ALIGN_OF:
+ case EXPR_SIZEOF_ALIGN_OF:
S = new (Context) SizeOfAlignOfExpr(Empty);
break;
- case pch::EXPR_ARRAY_SUBSCRIPT:
+ case EXPR_ARRAY_SUBSCRIPT:
S = new (Context) ArraySubscriptExpr(Empty);
break;
- case pch::EXPR_CALL:
+ case EXPR_CALL:
S = new (Context) CallExpr(*Context, Stmt::CallExprClass, Empty);
break;
- case pch::EXPR_MEMBER: {
+ case EXPR_MEMBER: {
// We load everything here and fully initialize it at creation.
// That way we can use MemberExpr::Create and don't have to duplicate its
// logic with a MemberExpr::CreateEmpty.
@@ -1438,7 +1463,7 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
ArgInfo.setLAngleLoc(ReadSourceLocation(Record, Idx));
ArgInfo.setRAngleLoc(ReadSourceLocation(Record, Idx));
for (unsigned i = 0; i != NumTemplateArgs; ++i)
- ArgInfo.addArgument(ReadTemplateArgumentLoc(Record, Idx));
+ ArgInfo.addArgument(ReadTemplateArgumentLoc(Cursor, Record, Idx));
}
NamedDecl *FoundD = cast_or_null<NamedDecl>(GetDecl(Record[Idx++]));
@@ -1448,202 +1473,219 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
QualType T = GetType(Record[Idx++]);
Expr *Base = ReadSubExpr();
ValueDecl *MemberD = cast<ValueDecl>(GetDecl(Record[Idx++]));
+ // FIXME: read DeclarationNameLoc.
SourceLocation MemberLoc = ReadSourceLocation(Record, Idx);
+ DeclarationNameInfo MemberNameInfo(MemberD->getDeclName(), MemberLoc);
bool IsArrow = Record[Idx++];
S = MemberExpr::Create(*Context, Base, IsArrow, NNS, QualifierRange,
- MemberD, FoundDecl, MemberLoc,
+ MemberD, FoundDecl, MemberNameInfo,
NumTemplateArgs ? &ArgInfo : 0, T);
break;
}
- case pch::EXPR_BINARY_OPERATOR:
+ case EXPR_BINARY_OPERATOR:
S = new (Context) BinaryOperator(Empty);
break;
- case pch::EXPR_COMPOUND_ASSIGN_OPERATOR:
+ case EXPR_COMPOUND_ASSIGN_OPERATOR:
S = new (Context) CompoundAssignOperator(Empty);
break;
- case pch::EXPR_CONDITIONAL_OPERATOR:
+ case EXPR_CONDITIONAL_OPERATOR:
S = new (Context) ConditionalOperator(Empty);
break;
- case pch::EXPR_IMPLICIT_CAST:
- S = new (Context) ImplicitCastExpr(Empty);
+ case EXPR_IMPLICIT_CAST:
+ S = ImplicitCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CSTYLE_CAST:
- S = new (Context) CStyleCastExpr(Empty);
+ case EXPR_CSTYLE_CAST:
+ S = CStyleCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_COMPOUND_LITERAL:
+ case EXPR_COMPOUND_LITERAL:
S = new (Context) CompoundLiteralExpr(Empty);
break;
- case pch::EXPR_EXT_VECTOR_ELEMENT:
+ case EXPR_EXT_VECTOR_ELEMENT:
S = new (Context) ExtVectorElementExpr(Empty);
break;
- case pch::EXPR_INIT_LIST:
+ case EXPR_INIT_LIST:
S = new (Context) InitListExpr(*getContext(), Empty);
break;
- case pch::EXPR_DESIGNATED_INIT:
+ case EXPR_DESIGNATED_INIT:
S = DesignatedInitExpr::CreateEmpty(*Context,
- Record[PCHStmtReader::NumExprFields] - 1);
+ Record[ASTStmtReader::NumExprFields] - 1);
break;
- case pch::EXPR_IMPLICIT_VALUE_INIT:
+ case EXPR_IMPLICIT_VALUE_INIT:
S = new (Context) ImplicitValueInitExpr(Empty);
break;
- case pch::EXPR_VA_ARG:
+ case EXPR_VA_ARG:
S = new (Context) VAArgExpr(Empty);
break;
- case pch::EXPR_ADDR_LABEL:
+ case EXPR_ADDR_LABEL:
S = new (Context) AddrLabelExpr(Empty);
break;
- case pch::EXPR_STMT:
+ case EXPR_STMT:
S = new (Context) StmtExpr(Empty);
break;
- case pch::EXPR_TYPES_COMPATIBLE:
+ case EXPR_TYPES_COMPATIBLE:
S = new (Context) TypesCompatibleExpr(Empty);
break;
- case pch::EXPR_CHOOSE:
+ case EXPR_CHOOSE:
S = new (Context) ChooseExpr(Empty);
break;
- case pch::EXPR_GNU_NULL:
+ case EXPR_GNU_NULL:
S = new (Context) GNUNullExpr(Empty);
break;
- case pch::EXPR_SHUFFLE_VECTOR:
+ case EXPR_SHUFFLE_VECTOR:
S = new (Context) ShuffleVectorExpr(Empty);
break;
- case pch::EXPR_BLOCK:
+ case EXPR_BLOCK:
S = new (Context) BlockExpr(Empty);
break;
- case pch::EXPR_BLOCK_DECL_REF:
+ case EXPR_BLOCK_DECL_REF:
S = new (Context) BlockDeclRefExpr(Empty);
break;
- case pch::EXPR_OBJC_STRING_LITERAL:
+ case EXPR_OBJC_STRING_LITERAL:
S = new (Context) ObjCStringLiteral(Empty);
break;
- case pch::EXPR_OBJC_ENCODE:
+ case EXPR_OBJC_ENCODE:
S = new (Context) ObjCEncodeExpr(Empty);
break;
- case pch::EXPR_OBJC_SELECTOR_EXPR:
+ case EXPR_OBJC_SELECTOR_EXPR:
S = new (Context) ObjCSelectorExpr(Empty);
break;
- case pch::EXPR_OBJC_PROTOCOL_EXPR:
+ case EXPR_OBJC_PROTOCOL_EXPR:
S = new (Context) ObjCProtocolExpr(Empty);
break;
- case pch::EXPR_OBJC_IVAR_REF_EXPR:
+ case EXPR_OBJC_IVAR_REF_EXPR:
S = new (Context) ObjCIvarRefExpr(Empty);
break;
- case pch::EXPR_OBJC_PROPERTY_REF_EXPR:
+ case EXPR_OBJC_PROPERTY_REF_EXPR:
S = new (Context) ObjCPropertyRefExpr(Empty);
break;
- case pch::EXPR_OBJC_KVC_REF_EXPR:
+ case EXPR_OBJC_KVC_REF_EXPR:
S = new (Context) ObjCImplicitSetterGetterRefExpr(Empty);
break;
- case pch::EXPR_OBJC_MESSAGE_EXPR:
+ case EXPR_OBJC_MESSAGE_EXPR:
S = ObjCMessageExpr::CreateEmpty(*Context,
- Record[PCHStmtReader::NumExprFields]);
+ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_OBJC_SUPER_EXPR:
+ case EXPR_OBJC_SUPER_EXPR:
S = new (Context) ObjCSuperExpr(Empty);
break;
- case pch::EXPR_OBJC_ISA:
+ case EXPR_OBJC_ISA:
S = new (Context) ObjCIsaExpr(Empty);
break;
- case pch::STMT_OBJC_FOR_COLLECTION:
+ case STMT_OBJC_FOR_COLLECTION:
S = new (Context) ObjCForCollectionStmt(Empty);
break;
- case pch::STMT_OBJC_CATCH:
+ case STMT_OBJC_CATCH:
S = new (Context) ObjCAtCatchStmt(Empty);
break;
- case pch::STMT_OBJC_FINALLY:
+ case STMT_OBJC_FINALLY:
S = new (Context) ObjCAtFinallyStmt(Empty);
break;
- case pch::STMT_OBJC_AT_TRY:
+ case STMT_OBJC_AT_TRY:
S = ObjCAtTryStmt::CreateEmpty(*Context,
- Record[PCHStmtReader::NumStmtFields],
- Record[PCHStmtReader::NumStmtFields + 1]);
+ Record[ASTStmtReader::NumStmtFields],
+ Record[ASTStmtReader::NumStmtFields + 1]);
break;
- case pch::STMT_OBJC_AT_SYNCHRONIZED:
+ case STMT_OBJC_AT_SYNCHRONIZED:
S = new (Context) ObjCAtSynchronizedStmt(Empty);
break;
- case pch::STMT_OBJC_AT_THROW:
+ case STMT_OBJC_AT_THROW:
S = new (Context) ObjCAtThrowStmt(Empty);
break;
- case pch::EXPR_CXX_OPERATOR_CALL:
+ case STMT_CXX_CATCH:
+ S = new (Context) CXXCatchStmt(Empty);
+ break;
+
+ case STMT_CXX_TRY:
+ S = CXXTryStmt::Create(*Context, Empty,
+ /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]);
+ break;
+
+ case EXPR_CXX_OPERATOR_CALL:
S = new (Context) CXXOperatorCallExpr(*Context, Empty);
break;
- case pch::EXPR_CXX_MEMBER_CALL:
+ case EXPR_CXX_MEMBER_CALL:
S = new (Context) CXXMemberCallExpr(*Context, Empty);
break;
- case pch::EXPR_CXX_CONSTRUCT:
+ case EXPR_CXX_CONSTRUCT:
S = new (Context) CXXConstructExpr(Empty);
break;
- case pch::EXPR_CXX_TEMPORARY_OBJECT:
+ case EXPR_CXX_TEMPORARY_OBJECT:
S = new (Context) CXXTemporaryObjectExpr(Empty);
break;
- case pch::EXPR_CXX_STATIC_CAST:
- S = new (Context) CXXStaticCastExpr(Empty);
+ case EXPR_CXX_STATIC_CAST:
+ S = CXXStaticCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_DYNAMIC_CAST:
- S = new (Context) CXXDynamicCastExpr(Empty);
+ case EXPR_CXX_DYNAMIC_CAST:
+ S = CXXDynamicCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_REINTERPRET_CAST:
- S = new (Context) CXXReinterpretCastExpr(Empty);
+ case EXPR_CXX_REINTERPRET_CAST:
+ S = CXXReinterpretCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_CONST_CAST:
- S = new (Context) CXXConstCastExpr(Empty);
+ case EXPR_CXX_CONST_CAST:
+ S = CXXConstCastExpr::CreateEmpty(*Context);
break;
- case pch::EXPR_CXX_FUNCTIONAL_CAST:
- S = new (Context) CXXFunctionalCastExpr(Empty);
+ case EXPR_CXX_FUNCTIONAL_CAST:
+ S = CXXFunctionalCastExpr::CreateEmpty(*Context,
+ /*PathSize*/ Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_BOOL_LITERAL:
+ case EXPR_CXX_BOOL_LITERAL:
S = new (Context) CXXBoolLiteralExpr(Empty);
break;
- case pch::EXPR_CXX_NULL_PTR_LITERAL:
+ case EXPR_CXX_NULL_PTR_LITERAL:
S = new (Context) CXXNullPtrLiteralExpr(Empty);
break;
- case pch::EXPR_CXX_TYPEID_EXPR:
+ case EXPR_CXX_TYPEID_EXPR:
S = new (Context) CXXTypeidExpr(Empty, true);
break;
- case pch::EXPR_CXX_TYPEID_TYPE:
+ case EXPR_CXX_TYPEID_TYPE:
S = new (Context) CXXTypeidExpr(Empty, false);
break;
- case pch::EXPR_CXX_THIS:
+ case EXPR_CXX_THIS:
S = new (Context) CXXThisExpr(Empty);
break;
- case pch::EXPR_CXX_THROW:
+ case EXPR_CXX_THROW:
S = new (Context) CXXThrowExpr(Empty);
break;
- case pch::EXPR_CXX_DEFAULT_ARG: {
- bool HasOtherExprStored = Record[PCHStmtReader::NumExprFields];
+ case EXPR_CXX_DEFAULT_ARG: {
+ bool HasOtherExprStored = Record[ASTStmtReader::NumExprFields];
if (HasOtherExprStored) {
Expr *SubExpr = ReadSubExpr();
S = CXXDefaultArgExpr::Create(*Context, SourceLocation(), 0, SubExpr);
@@ -1651,56 +1693,53 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) {
S = new (Context) CXXDefaultArgExpr(Empty);
break;
}
- case pch::EXPR_CXX_BIND_TEMPORARY:
+ case EXPR_CXX_BIND_TEMPORARY:
S = new (Context) CXXBindTemporaryExpr(Empty);
break;
- case pch::EXPR_CXX_BIND_REFERENCE:
- S = new (Context) CXXBindReferenceExpr(Empty);
- break;
-
- case pch::EXPR_CXX_SCALAR_VALUE_INIT:
+
+ case EXPR_CXX_SCALAR_VALUE_INIT:
S = new (Context) CXXScalarValueInitExpr(Empty);
break;
- case pch::EXPR_CXX_NEW:
+ case EXPR_CXX_NEW:
S = new (Context) CXXNewExpr(Empty);
break;
- case pch::EXPR_CXX_DELETE:
+ case EXPR_CXX_DELETE:
S = new (Context) CXXDeleteExpr(Empty);
break;
- case pch::EXPR_CXX_PSEUDO_DESTRUCTOR:
+ case EXPR_CXX_PSEUDO_DESTRUCTOR:
S = new (Context) CXXPseudoDestructorExpr(Empty);
break;
- case pch::EXPR_CXX_EXPR_WITH_TEMPORARIES:
+ case EXPR_CXX_EXPR_WITH_TEMPORARIES:
S = new (Context) CXXExprWithTemporaries(Empty);
break;
- case pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
+ case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:
S = CXXDependentScopeMemberExpr::CreateEmpty(*Context,
- /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
+ case EXPR_CXX_DEPENDENT_SCOPE_DECL_REF:
S = DependentScopeDeclRefExpr::CreateEmpty(*Context,
- /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_UNRESOLVED_CONSTRUCT:
+ case EXPR_CXX_UNRESOLVED_CONSTRUCT:
S = CXXUnresolvedConstructExpr::CreateEmpty(*Context,
- /*NumArgs=*/Record[PCHStmtReader::NumExprFields]);
+ /*NumArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_UNRESOLVED_MEMBER:
+ case EXPR_CXX_UNRESOLVED_MEMBER:
S = UnresolvedMemberExpr::CreateEmpty(*Context,
- /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_UNRESOLVED_LOOKUP:
+ case EXPR_CXX_UNRESOLVED_LOOKUP:
S = UnresolvedLookupExpr::CreateEmpty(*Context,
- /*NumTemplateArgs=*/Record[PCHStmtReader::NumExprFields]);
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields]);
break;
- case pch::EXPR_CXX_UNARY_TYPE_TRAIT:
+ case EXPR_CXX_UNARY_TYPE_TRAIT:
S = new (Context) UnaryTypeTraitExpr(Empty);
break;
}
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 093c1e334a3d..3b6b218e744c 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1,4 +1,4 @@
-//===--- PCHWriter.cpp - Precompiled Headers Writer -----------------------===//
+//===--- ASTWriter.cpp - AST File Writer ----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,20 +7,23 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the PCHWriter class, which writes a precompiled header.
+// This file defines the ASTWriter class, which writes AST files.
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHWriter.h"
-#include "../Sema/Sema.h" // FIXME: move header into include/clang/Sema
-#include "../Sema/IdentifierResolver.h" // FIXME: move header
+#include "clang/Serialization/ASTWriter.h"
+#include "ASTCommon.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/IdentifierResolver.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLocVisitor.h"
-#include "clang/Frontend/PCHReader.h"
+#include "clang/Serialization/ASTReader.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
@@ -39,22 +42,32 @@
#include "llvm/System/Path.h"
#include <cstdio>
using namespace clang;
+using namespace clang::serialization;
+
+template <typename T, typename Allocator>
+T *data(std::vector<T, Allocator> &v) {
+ return v.empty() ? 0 : &v.front();
+}
+template <typename T, typename Allocator>
+const T *data(const std::vector<T, Allocator> &v) {
+ return v.empty() ? 0 : &v.front();
+}
//===----------------------------------------------------------------------===//
// Type serialization
//===----------------------------------------------------------------------===//
namespace {
- class PCHTypeWriter {
- PCHWriter &Writer;
- PCHWriter::RecordData &Record;
+ class ASTTypeWriter {
+ ASTWriter &Writer;
+ ASTWriter::RecordData &Record;
public:
/// \brief Type code that corresponds to the record generated.
- pch::TypeCode Code;
+ TypeCode Code;
- PCHTypeWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
- : Writer(Writer), Record(Record), Code(pch::TYPE_EXT_QUAL) { }
+ ASTTypeWriter(ASTWriter &Writer, ASTWriter::RecordData &Record)
+ : Writer(Writer), Record(Record), Code(TYPE_EXT_QUAL) { }
void VisitArrayType(const ArrayType *T);
void VisitFunctionType(const FunctionType *T);
@@ -66,79 +79,79 @@ namespace {
};
}
-void PCHTypeWriter::VisitBuiltinType(const BuiltinType *T) {
+void ASTTypeWriter::VisitBuiltinType(const BuiltinType *T) {
assert(false && "Built-in types are never serialized");
}
-void PCHTypeWriter::VisitComplexType(const ComplexType *T) {
+void ASTTypeWriter::VisitComplexType(const ComplexType *T) {
Writer.AddTypeRef(T->getElementType(), Record);
- Code = pch::TYPE_COMPLEX;
+ Code = TYPE_COMPLEX;
}
-void PCHTypeWriter::VisitPointerType(const PointerType *T) {
+void ASTTypeWriter::VisitPointerType(const PointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
- Code = pch::TYPE_POINTER;
+ Code = TYPE_POINTER;
}
-void PCHTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
+void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
- Code = pch::TYPE_BLOCK_POINTER;
+ Code = TYPE_BLOCK_POINTER;
}
-void PCHTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
+void ASTTypeWriter::VisitLValueReferenceType(const LValueReferenceType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
- Code = pch::TYPE_LVALUE_REFERENCE;
+ Code = TYPE_LVALUE_REFERENCE;
}
-void PCHTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
+void ASTTypeWriter::VisitRValueReferenceType(const RValueReferenceType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
- Code = pch::TYPE_RVALUE_REFERENCE;
+ Code = TYPE_RVALUE_REFERENCE;
}
-void PCHTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
+void ASTTypeWriter::VisitMemberPointerType(const MemberPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
Writer.AddTypeRef(QualType(T->getClass(), 0), Record);
- Code = pch::TYPE_MEMBER_POINTER;
+ Code = TYPE_MEMBER_POINTER;
}
-void PCHTypeWriter::VisitArrayType(const ArrayType *T) {
+void ASTTypeWriter::VisitArrayType(const ArrayType *T) {
Writer.AddTypeRef(T->getElementType(), Record);
Record.push_back(T->getSizeModifier()); // FIXME: stable values
Record.push_back(T->getIndexTypeCVRQualifiers()); // FIXME: stable values
}
-void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
+void ASTTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {
VisitArrayType(T);
Writer.AddAPInt(T->getSize(), Record);
- Code = pch::TYPE_CONSTANT_ARRAY;
+ Code = TYPE_CONSTANT_ARRAY;
}
-void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
+void ASTTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {
VisitArrayType(T);
- Code = pch::TYPE_INCOMPLETE_ARRAY;
+ Code = TYPE_INCOMPLETE_ARRAY;
}
-void PCHTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
+void ASTTypeWriter::VisitVariableArrayType(const VariableArrayType *T) {
VisitArrayType(T);
Writer.AddSourceLocation(T->getLBracketLoc(), Record);
Writer.AddSourceLocation(T->getRBracketLoc(), Record);
Writer.AddStmt(T->getSizeExpr());
- Code = pch::TYPE_VARIABLE_ARRAY;
+ Code = TYPE_VARIABLE_ARRAY;
}
-void PCHTypeWriter::VisitVectorType(const VectorType *T) {
+void ASTTypeWriter::VisitVectorType(const VectorType *T) {
Writer.AddTypeRef(T->getElementType(), Record);
Record.push_back(T->getNumElements());
Record.push_back(T->getAltiVecSpecific());
- Code = pch::TYPE_VECTOR;
+ Code = TYPE_VECTOR;
}
-void PCHTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
+void ASTTypeWriter::VisitExtVectorType(const ExtVectorType *T) {
VisitVectorType(T);
- Code = pch::TYPE_EXT_VECTOR;
+ Code = TYPE_EXT_VECTOR;
}
-void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
+void ASTTypeWriter::VisitFunctionType(const FunctionType *T) {
Writer.AddTypeRef(T->getResultType(), Record);
FunctionType::ExtInfo C = T->getExtInfo();
Record.push_back(C.getNoReturn());
@@ -147,12 +160,12 @@ void PCHTypeWriter::VisitFunctionType(const FunctionType *T) {
Record.push_back(C.getCC());
}
-void PCHTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
+void ASTTypeWriter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
VisitFunctionType(T);
- Code = pch::TYPE_FUNCTION_NO_PROTO;
+ Code = TYPE_FUNCTION_NO_PROTO;
}
-void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
+void ASTTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
VisitFunctionType(T);
Record.push_back(T->getNumArgs());
for (unsigned I = 0, N = T->getNumArgs(); I != N; ++I)
@@ -164,63 +177,63 @@ void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) {
Record.push_back(T->getNumExceptions());
for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I)
Writer.AddTypeRef(T->getExceptionType(I), Record);
- Code = pch::TYPE_FUNCTION_PROTO;
+ Code = TYPE_FUNCTION_PROTO;
}
-void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+void ASTTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
- Code = pch::TYPE_UNRESOLVED_USING;
+ Code = TYPE_UNRESOLVED_USING;
}
-void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
+void ASTTypeWriter::VisitTypedefType(const TypedefType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
assert(!T->isCanonicalUnqualified() && "Invalid typedef ?");
Writer.AddTypeRef(T->getCanonicalTypeInternal(), Record);
- Code = pch::TYPE_TYPEDEF;
+ Code = TYPE_TYPEDEF;
}
-void PCHTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
+void ASTTypeWriter::VisitTypeOfExprType(const TypeOfExprType *T) {
Writer.AddStmt(T->getUnderlyingExpr());
- Code = pch::TYPE_TYPEOF_EXPR;
+ Code = TYPE_TYPEOF_EXPR;
}
-void PCHTypeWriter::VisitTypeOfType(const TypeOfType *T) {
+void ASTTypeWriter::VisitTypeOfType(const TypeOfType *T) {
Writer.AddTypeRef(T->getUnderlyingType(), Record);
- Code = pch::TYPE_TYPEOF;
+ Code = TYPE_TYPEOF;
}
-void PCHTypeWriter::VisitDecltypeType(const DecltypeType *T) {
+void ASTTypeWriter::VisitDecltypeType(const DecltypeType *T) {
Writer.AddStmt(T->getUnderlyingExpr());
- Code = pch::TYPE_DECLTYPE;
+ Code = TYPE_DECLTYPE;
}
-void PCHTypeWriter::VisitTagType(const TagType *T) {
+void ASTTypeWriter::VisitTagType(const TagType *T) {
Record.push_back(T->isDependentType());
Writer.AddDeclRef(T->getDecl(), Record);
assert(!T->isBeingDefined() &&
"Cannot serialize in the middle of a type definition");
}
-void PCHTypeWriter::VisitRecordType(const RecordType *T) {
+void ASTTypeWriter::VisitRecordType(const RecordType *T) {
VisitTagType(T);
- Code = pch::TYPE_RECORD;
+ Code = TYPE_RECORD;
}
-void PCHTypeWriter::VisitEnumType(const EnumType *T) {
+void ASTTypeWriter::VisitEnumType(const EnumType *T) {
VisitTagType(T);
- Code = pch::TYPE_ENUM;
+ Code = TYPE_ENUM;
}
void
-PCHTypeWriter::VisitSubstTemplateTypeParmType(
+ASTTypeWriter::VisitSubstTemplateTypeParmType(
const SubstTemplateTypeParmType *T) {
Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record);
Writer.AddTypeRef(T->getReplacementType(), Record);
- Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM;
+ Code = TYPE_SUBST_TEMPLATE_TYPE_PARM;
}
void
-PCHTypeWriter::VisitTemplateSpecializationType(
+ASTTypeWriter::VisitTemplateSpecializationType(
const TemplateSpecializationType *T) {
Record.push_back(T->isDependentType());
Writer.AddTemplateName(T->getTemplateName(), Record);
@@ -231,46 +244,46 @@ PCHTypeWriter::VisitTemplateSpecializationType(
Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType()
: T->getCanonicalTypeInternal(),
Record);
- Code = pch::TYPE_TEMPLATE_SPECIALIZATION;
+ Code = TYPE_TEMPLATE_SPECIALIZATION;
}
void
-PCHTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
+ASTTypeWriter::VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
VisitArrayType(T);
Writer.AddStmt(T->getSizeExpr());
Writer.AddSourceRange(T->getBracketsRange(), Record);
- Code = pch::TYPE_DEPENDENT_SIZED_ARRAY;
+ Code = TYPE_DEPENDENT_SIZED_ARRAY;
}
void
-PCHTypeWriter::VisitDependentSizedExtVectorType(
+ASTTypeWriter::VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType *T) {
// FIXME: Serialize this type (C++ only)
assert(false && "Cannot serialize dependent sized extended vector types");
}
void
-PCHTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
+ASTTypeWriter::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
Record.push_back(T->getDepth());
Record.push_back(T->getIndex());
Record.push_back(T->isParameterPack());
Writer.AddIdentifierRef(T->getName(), Record);
- Code = pch::TYPE_TEMPLATE_TYPE_PARM;
+ Code = TYPE_TEMPLATE_TYPE_PARM;
}
void
-PCHTypeWriter::VisitDependentNameType(const DependentNameType *T) {
+ASTTypeWriter::VisitDependentNameType(const DependentNameType *T) {
Record.push_back(T->getKeyword());
Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
Writer.AddIdentifierRef(T->getIdentifier(), Record);
Writer.AddTypeRef(T->isCanonicalUnqualified() ? QualType()
: T->getCanonicalTypeInternal(),
Record);
- Code = pch::TYPE_DEPENDENT_NAME;
+ Code = TYPE_DEPENDENT_NAME;
}
void
-PCHTypeWriter::VisitDependentTemplateSpecializationType(
+ASTTypeWriter::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType *T) {
Record.push_back(T->getKeyword());
Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
@@ -279,50 +292,50 @@ PCHTypeWriter::VisitDependentTemplateSpecializationType(
for (DependentTemplateSpecializationType::iterator
I = T->begin(), E = T->end(); I != E; ++I)
Writer.AddTemplateArgument(*I, Record);
- Code = pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
+ Code = TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION;
}
-void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
+void ASTTypeWriter::VisitElaboratedType(const ElaboratedType *T) {
Record.push_back(T->getKeyword());
Writer.AddNestedNameSpecifier(T->getQualifier(), Record);
Writer.AddTypeRef(T->getNamedType(), Record);
- Code = pch::TYPE_ELABORATED;
+ Code = TYPE_ELABORATED;
}
-void PCHTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
+void ASTTypeWriter::VisitInjectedClassNameType(const InjectedClassNameType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
Writer.AddTypeRef(T->getInjectedSpecializationType(), Record);
- Code = pch::TYPE_INJECTED_CLASS_NAME;
+ Code = TYPE_INJECTED_CLASS_NAME;
}
-void PCHTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
+void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
Writer.AddDeclRef(T->getDecl(), Record);
- Code = pch::TYPE_OBJC_INTERFACE;
+ Code = TYPE_OBJC_INTERFACE;
}
-void PCHTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
+void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) {
Writer.AddTypeRef(T->getBaseType(), Record);
Record.push_back(T->getNumProtocols());
for (ObjCObjectType::qual_iterator I = T->qual_begin(),
E = T->qual_end(); I != E; ++I)
Writer.AddDeclRef(*I, Record);
- Code = pch::TYPE_OBJC_OBJECT;
+ Code = TYPE_OBJC_OBJECT;
}
void
-PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
+ASTTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
- Code = pch::TYPE_OBJC_OBJECT_POINTER;
+ Code = TYPE_OBJC_OBJECT_POINTER;
}
namespace {
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
- PCHWriter &Writer;
- PCHWriter::RecordData &Record;
+ ASTWriter &Writer;
+ ASTWriter::RecordData &Record;
public:
- TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+ TypeLocWriter(ASTWriter &Writer, ASTWriter::RecordData &Record)
: Writer(Writer), Record(Record) { }
#define ABSTRACT_TYPELOC(CLASS, PARENT)
@@ -488,12 +501,12 @@ void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
}
//===----------------------------------------------------------------------===//
-// PCHWriter Implementation
+// ASTWriter Implementation
//===----------------------------------------------------------------------===//
static void EmitBlockID(unsigned ID, const char *Name,
llvm::BitstreamWriter &Stream,
- PCHWriter::RecordData &Record) {
+ ASTWriter::RecordData &Record) {
Record.clear();
Record.push_back(ID);
Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
@@ -508,7 +521,7 @@ static void EmitBlockID(unsigned ID, const char *Name,
static void EmitRecordID(unsigned ID, const char *Name,
llvm::BitstreamWriter &Stream,
- PCHWriter::RecordData &Record) {
+ ASTWriter::RecordData &Record) {
Record.clear();
Record.push_back(ID);
while (*Name)
@@ -517,8 +530,8 @@ static void EmitRecordID(unsigned ID, const char *Name,
}
static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
- PCHWriter::RecordData &Record) {
-#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
+ ASTWriter::RecordData &Record) {
+#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
RECORD(STMT_STOP);
RECORD(STMT_NULL_PTR);
RECORD(STMT_NULL);
@@ -597,15 +610,15 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
#undef RECORD
}
-void PCHWriter::WriteBlockInfoBlock() {
+void ASTWriter::WriteBlockInfoBlock() {
RecordData Record;
Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3);
-#define BLOCK(X) EmitBlockID(pch::X ## _ID, #X, Stream, Record)
-#define RECORD(X) EmitRecordID(pch::X, #X, Stream, Record)
+#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record)
+#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
- // PCH Top-Level Block.
- BLOCK(PCH_BLOCK);
+ // AST Top-Level Block.
+ BLOCK(AST_BLOCK);
RECORD(ORIGINAL_FILE_NAME);
RECORD(TYPE_OFFSET);
RECORD(DECL_OFFSET);
@@ -617,7 +630,7 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(SPECIAL_TYPES);
RECORD(STATISTICS);
RECORD(TENTATIVE_DEFINITIONS);
- RECORD(UNUSED_STATIC_FUNCS);
+ RECORD(UNUSED_FILESCOPED_DECLS);
RECORD(LOCALLY_SCOPED_EXTERNAL_DECLS);
RECORD(SELECTOR_OFFSETS);
RECORD(METHOD_POOL);
@@ -627,9 +640,9 @@ void PCHWriter::WriteBlockInfoBlock() {
RECORD(STAT_CACHE);
RECORD(EXT_VECTOR_DECLS);
RECORD(VERSION_CONTROL_BRANCH_REVISION);
- RECORD(UNUSED_STATIC_FUNCS);
RECORD(MACRO_DEFINITION_OFFSETS);
RECORD(CHAINED_METADATA);
+ RECORD(REFERENCED_SELECTOR_POOL);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -742,17 +755,17 @@ adjustFilenameForRelocatablePCH(const char *Filename, const char *isysroot) {
return Filename + Pos;
}
-/// \brief Write the PCH metadata (e.g., i686-apple-darwin9).
-void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
+/// \brief Write the AST metadata (e.g., i686-apple-darwin9).
+void ASTWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
using namespace llvm;
// Metadata
const TargetInfo &Target = Context.Target;
BitCodeAbbrev *MetaAbbrev = new BitCodeAbbrev();
MetaAbbrev->Add(BitCodeAbbrevOp(
- Chain ? pch::CHAINED_METADATA : pch::METADATA));
- MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH major
- MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // PCH minor
+ Chain ? CHAINED_METADATA : METADATA));
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST major
+ MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // AST minor
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang major
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang minor
MetaAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
@@ -761,9 +774,9 @@ void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
unsigned MetaAbbrevCode = Stream.EmitAbbrev(MetaAbbrev);
RecordData Record;
- Record.push_back(Chain ? pch::CHAINED_METADATA : pch::METADATA);
- Record.push_back(pch::VERSION_MAJOR);
- Record.push_back(pch::VERSION_MINOR);
+ Record.push_back(Chain ? CHAINED_METADATA : METADATA);
+ Record.push_back(VERSION_MAJOR);
+ Record.push_back(VERSION_MINOR);
Record.push_back(CLANG_VERSION_MAJOR);
Record.push_back(CLANG_VERSION_MINOR);
Record.push_back(isysroot != 0);
@@ -775,7 +788,7 @@ void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
SourceManager &SM = Context.getSourceManager();
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
BitCodeAbbrev *FileAbbrev = new BitCodeAbbrev();
- FileAbbrev->Add(BitCodeAbbrevOp(pch::ORIGINAL_FILE_NAME));
+ FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE_NAME));
FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
unsigned FileAbbrevCode = Stream.EmitAbbrev(FileAbbrev);
@@ -787,23 +800,23 @@ void PCHWriter::WriteMetadata(ASTContext &Context, const char *isysroot) {
MainFileNameStr = adjustFilenameForRelocatablePCH(MainFileNameStr,
isysroot);
RecordData Record;
- Record.push_back(pch::ORIGINAL_FILE_NAME);
+ Record.push_back(ORIGINAL_FILE_NAME);
Stream.EmitRecordWithBlob(FileAbbrevCode, Record, MainFileNameStr);
}
// Repository branch/version information.
BitCodeAbbrev *RepoAbbrev = new BitCodeAbbrev();
- RepoAbbrev->Add(BitCodeAbbrevOp(pch::VERSION_CONTROL_BRANCH_REVISION));
+ RepoAbbrev->Add(BitCodeAbbrevOp(VERSION_CONTROL_BRANCH_REVISION));
RepoAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned RepoAbbrevCode = Stream.EmitAbbrev(RepoAbbrev);
Record.clear();
- Record.push_back(pch::VERSION_CONTROL_BRANCH_REVISION);
+ Record.push_back(VERSION_CONTROL_BRANCH_REVISION);
Stream.EmitRecordWithBlob(RepoAbbrevCode, Record,
getClangFullRepositoryVersion());
}
/// \brief Write the LangOptions structure.
-void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
+void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
RecordData Record;
Record.push_back(LangOpts.Trigraphs);
Record.push_back(LangOpts.BCPLComment); // BCPL-style '//' comments.
@@ -874,7 +887,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
Record.push_back(LangOpts.CatchUndefined);
Record.push_back(LangOpts.ElideConstructors);
Record.push_back(LangOpts.SpellChecking);
- Stream.EmitRecord(pch::LANGUAGE_OPTIONS, Record);
+ Stream.EmitRecord(LANGUAGE_OPTIONS, Record);
}
//===----------------------------------------------------------------------===//
@@ -883,7 +896,7 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
namespace {
// Trait used for the on-disk hash table of stat cache results.
-class PCHStatCacheTrait {
+class ASTStatCacheTrait {
public:
typedef const char * key_type;
typedef key_type key_type_ref;
@@ -932,11 +945,11 @@ public:
};
} // end anonymous namespace
-/// \brief Write the stat() system call cache to the PCH file.
-void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
+/// \brief Write the stat() system call cache to the AST file.
+void ASTWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
// Build the on-disk hash table containing information about every
// stat() call.
- OnDiskChainedHashTableGenerator<PCHStatCacheTrait> Generator;
+ OnDiskChainedHashTableGenerator<ASTStatCacheTrait> Generator;
unsigned NumStatEntries = 0;
for (MemorizeStatCalls::iterator Stat = StatCalls.begin(),
StatEnd = StatCalls.end();
@@ -958,7 +971,7 @@ void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
// Create a blob abbreviation
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::STAT_CACHE));
+ Abbrev->Add(BitCodeAbbrevOp(STAT_CACHE));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
@@ -966,7 +979,7 @@ void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
// Write the stat cache
RecordData Record;
- Record.push_back(pch::STAT_CACHE);
+ Record.push_back(STAT_CACHE);
Record.push_back(BucketOffset);
Record.push_back(NumStatEntries);
Stream.EmitRecordWithBlob(StatCacheAbbrev, Record, StatCacheData.str());
@@ -981,7 +994,7 @@ void PCHWriter::WriteStatCache(MemorizeStatCalls &StatCalls) {
static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_FILE_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
@@ -1003,7 +1016,7 @@ static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Characteristic
@@ -1017,7 +1030,7 @@ static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_BUFFER_BLOB));
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_BLOB));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
return Stream.EmitAbbrev(Abbrev);
}
@@ -1027,7 +1040,7 @@ static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream) {
static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::SM_SLOC_INSTANTIATION_ENTRY));
+ Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_INSTANTIATION_ENTRY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Start location
@@ -1044,13 +1057,13 @@ static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) {
/// entries for files that we actually need. In the common case (no
/// errors), we probably won't have to create file entries for any of
/// the files in the AST.
-void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
+void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
const Preprocessor &PP,
const char *isysroot) {
RecordData Record;
// Enter the source manager block.
- Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3);
+ Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 3);
// Abbreviations for the various kinds of source-location entries.
unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
@@ -1092,15 +1105,17 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Record.push_back(LE->IncludeOffset);
}
}
- Stream.EmitRecord(pch::SM_LINE_TABLE, Record);
+ Stream.EmitRecord(SM_LINE_TABLE, Record);
}
// Write out the source location entry table. We skip the first
// entry, which is always the same dummy entry.
std::vector<uint32_t> SLocEntryOffsets;
RecordData PreloadSLocs;
- SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1);
- for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) {
+ unsigned BaseSLocID = Chain ? Chain->getTotalNumSLocs() : 0;
+ SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1 - BaseSLocID);
+ for (unsigned I = BaseSLocID + 1, N = SourceMgr.sloc_entry_size();
+ I != N; ++I) {
// Get this source location entry.
const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I);
@@ -1111,11 +1126,11 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
unsigned Code;
if (SLoc->isFile()) {
if (SLoc->getFile().getContentCache()->Entry)
- Code = pch::SM_SLOC_FILE_ENTRY;
+ Code = SM_SLOC_FILE_ENTRY;
else
- Code = pch::SM_SLOC_BUFFER_ENTRY;
+ Code = SM_SLOC_BUFFER_ENTRY;
} else
- Code = pch::SM_SLOC_INSTANTIATION_ENTRY;
+ Code = SM_SLOC_INSTANTIATION_ENTRY;
Record.clear();
Record.push_back(Code);
@@ -1157,7 +1172,7 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
// FIXME: For now, preload all file source locations, so that
// we get the appropriate File entries in the reader. This is
// a temporary measure.
- PreloadSLocs.push_back(SLocEntryOffsets.size());
+ PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size());
} else {
// The source location entry is a buffer. The blob associated
// with this entry contains the contents of the buffer.
@@ -1171,13 +1186,13 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
llvm::StringRef(Name, strlen(Name) + 1));
Record.clear();
- Record.push_back(pch::SM_SLOC_BUFFER_BLOB);
+ Record.push_back(SM_SLOC_BUFFER_BLOB);
Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record,
llvm::StringRef(Buffer->getBufferStart(),
Buffer->getBufferSize() + 1));
if (strcmp(Name, "<built-in>") == 0)
- PreloadSLocs.push_back(SLocEntryOffsets.size());
+ PreloadSLocs.push_back(BaseSLocID + SLocEntryOffsets.size());
}
} else {
// The source location entry is an instantiation.
@@ -1200,27 +1215,27 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
if (SLocEntryOffsets.empty())
return;
- // Write the source-location offsets table into the PCH block. This
+ // Write the source-location offsets table into the AST block. This
// table is used for lazily loading source-location information.
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::SOURCE_LOCATION_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // next offset
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(Abbrev);
Record.clear();
- Record.push_back(pch::SOURCE_LOCATION_OFFSETS);
+ Record.push_back(SOURCE_LOCATION_OFFSETS);
Record.push_back(SLocEntryOffsets.size());
Record.push_back(SourceMgr.getNextOffset());
Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
- (const char *)&SLocEntryOffsets.front(),
+ (const char *)data(SLocEntryOffsets),
SLocEntryOffsets.size()*sizeof(SLocEntryOffsets[0]));
- // Write the source location entry preloads array, telling the PCH
+ // Write the source location entry preloads array, telling the AST
// reader which source locations entries it should load eagerly.
- Stream.EmitRecord(pch::SOURCE_LOCATION_PRELOADS, PreloadSLocs);
+ Stream.EmitRecord(SOURCE_LOCATION_PRELOADS, PreloadSLocs);
}
//===----------------------------------------------------------------------===//
@@ -1230,20 +1245,20 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
/// \brief Writes the block containing the serialized form of the
/// preprocessor.
///
-void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
+void ASTWriter::WritePreprocessor(const Preprocessor &PP) {
RecordData Record;
// If the preprocessor __COUNTER__ value has been bumped, remember it.
if (PP.getCounterValue() != 0) {
Record.push_back(PP.getCounterValue());
- Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record);
+ Stream.EmitRecord(PP_COUNTER_VALUE, Record);
Record.clear();
}
// Enter the preprocessor block.
- Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2);
+ Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 2);
- // If the PCH file contains __DATE__ or __TIME__ emit a warning about this.
+ // If the AST file contains __DATE__ or __TIME__ emit a warning about this.
// FIXME: use diagnostics subsystem for localization etc.
if (PP.SawDateOrTime())
fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n");
@@ -1257,9 +1272,10 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
// order so that output is reproducible.
MacroInfo *MI = I->second;
- // Don't emit builtin macros like __LINE__ to the PCH file unless they have
+ // Don't emit builtin macros like __LINE__ to the AST file unless they have
// been redefined by the header (in which case they are not isBuiltinMacro).
- if (MI->isBuiltinMacro())
+ // Also skip macros from a AST file if we're chaining.
+ if (MI->isBuiltinMacro() || (Chain && MI->isFromAST()))
continue;
AddIdentifierRef(I->first, Record);
@@ -1269,9 +1285,9 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
unsigned Code;
if (MI->isObjectLike()) {
- Code = pch::PP_MACRO_OBJECT_LIKE;
+ Code = PP_MACRO_OBJECT_LIKE;
} else {
- Code = pch::PP_MACRO_FUNCTION_LIKE;
+ Code = PP_MACRO_FUNCTION_LIKE;
Record.push_back(MI->isC99Varargs());
Record.push_back(MI->isGNUVarargs());
@@ -1308,7 +1324,7 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
// FIXME: Should translate token flags to a stable encoding.
Record.push_back(Tok.getFlags());
- Stream.EmitRecord(pch::PP_TOKEN, Record);
+ Stream.EmitRecord(PP_TOKEN, Record);
Record.clear();
}
++NumMacros;
@@ -1327,13 +1343,13 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
AddSourceLocation(MI->getSourceRange().getEnd(), Record);
AddIdentifierRef(MI->getName(), Record);
Record.push_back(getMacroDefinitionID(MI->getDefinition()));
- Stream.EmitRecord(pch::PP_MACRO_INSTANTIATION, Record);
+ Stream.EmitRecord(PP_MACRO_INSTANTIATION, Record);
continue;
}
if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
// Record this macro definition's location.
- pch::IdentID ID = getMacroDefinitionID(MD);
+ IdentID ID = getMacroDefinitionID(MD);
if (ID != MacroDefinitionOffsets.size()) {
if (ID > MacroDefinitionOffsets.size())
MacroDefinitionOffsets.resize(ID + 1);
@@ -1348,7 +1364,7 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
AddSourceLocation(MD->getSourceRange().getEnd(), Record);
AddIdentifierRef(MD->getName(), Record);
AddSourceLocation(MD->getLocation(), Record);
- Stream.EmitRecord(pch::PP_MACRO_DEFINITION, Record);
+ Stream.EmitRecord(PP_MACRO_DEFINITION, Record);
continue;
}
}
@@ -1361,18 +1377,18 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
// Write the offsets table for identifier IDs.
using namespace llvm;
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::MACRO_DEFINITION_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(MACRO_DEFINITION_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of records
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macro defs
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned MacroDefOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
Record.clear();
- Record.push_back(pch::MACRO_DEFINITION_OFFSETS);
+ Record.push_back(MACRO_DEFINITION_OFFSETS);
Record.push_back(NumPreprocessingRecords);
Record.push_back(MacroDefinitionOffsets.size());
Stream.EmitRecordWithBlob(MacroDefOffsetAbbrev, Record,
- (const char *)&MacroDefinitionOffsets.front(),
+ (const char *)data(MacroDefinitionOffsets),
MacroDefinitionOffsets.size() * sizeof(uint32_t));
}
}
@@ -1381,30 +1397,31 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {
// Type Serialization
//===----------------------------------------------------------------------===//
-/// \brief Write the representation of a type to the PCH stream.
-void PCHWriter::WriteType(QualType T) {
- pch::TypeID &ID = TypeIDs[T];
- if (ID == 0) // we haven't seen this type before.
- ID = NextTypeID++;
+/// \brief Write the representation of a type to the AST stream.
+void ASTWriter::WriteType(QualType T) {
+ TypeIdx &Idx = TypeIdxs[T];
+ if (Idx.getIndex() == 0) // we haven't seen this type before.
+ Idx = TypeIdx(NextTypeID++);
// Record the offset for this type.
- if (TypeOffsets.size() == ID - pch::NUM_PREDEF_TYPE_IDS)
+ unsigned Index = Idx.getIndex() - FirstTypeID;
+ if (TypeOffsets.size() == Index)
TypeOffsets.push_back(Stream.GetCurrentBitNo());
- else if (TypeOffsets.size() < ID - pch::NUM_PREDEF_TYPE_IDS) {
- TypeOffsets.resize(ID + 1 - pch::NUM_PREDEF_TYPE_IDS);
- TypeOffsets[ID - pch::NUM_PREDEF_TYPE_IDS] = Stream.GetCurrentBitNo();
+ else if (TypeOffsets.size() < Index) {
+ TypeOffsets.resize(Index + 1);
+ TypeOffsets[Index] = Stream.GetCurrentBitNo();
}
RecordData Record;
// Emit the type's representation.
- PCHTypeWriter W(*this, Record);
+ ASTTypeWriter W(*this, Record);
if (T.hasLocalNonFastQualifiers()) {
Qualifiers Qs = T.getLocalQualifiers();
AddTypeRef(T.getLocalUnqualifiedType(), Record);
Record.push_back(Qs.getAsOpaqueValue());
- W.Code = pch::TYPE_EXT_QUAL;
+ W.Code = TYPE_EXT_QUAL;
} else {
switch (T->getTypeClass()) {
// For all of the concrete, non-dependent types, call the
@@ -1432,73 +1449,54 @@ void PCHWriter::WriteType(QualType T) {
///
/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
/// bistream, or 0 if no block was written.
-uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
+uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
DeclContext *DC) {
if (DC->decls_empty())
return 0;
uint64_t Offset = Stream.GetCurrentBitNo();
RecordData Record;
+ Record.push_back(DECL_CONTEXT_LEXICAL);
+ llvm::SmallVector<DeclID, 64> Decls;
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
D != DEnd; ++D)
- AddDeclRef(*D, Record);
+ Decls.push_back(GetDeclRef(*D));
++NumLexicalDeclContexts;
- Stream.EmitRecord(pch::DECL_CONTEXT_LEXICAL, Record);
+ Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,
+ reinterpret_cast<char*>(Decls.data()), Decls.size() * sizeof(DeclID));
return Offset;
}
-/// \brief Write the block containing all of the declaration IDs
-/// visible from the given DeclContext.
-///
-/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
-/// bistream, or 0 if no block was written.
-uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
- DeclContext *DC) {
- if (DC->getPrimaryContext() != DC)
- return 0;
-
- // Since there is no name lookup into functions or methods, don't bother to
- // build a visible-declarations table for these entities.
- if (DC->isFunctionOrMethod())
- return 0;
-
- // If not in C++, we perform name lookup for the translation unit via the
- // IdentifierInfo chains, don't bother to build a visible-declarations table.
- // FIXME: In C++ we need the visible declarations in order to "see" the
- // friend declarations, is there a way to do this without writing the table ?
- if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus)
- return 0;
-
- // Force the DeclContext to build a its name-lookup table.
- DC->lookup(DeclarationName());
-
- // Serialize the contents of the mapping used for lookup. Note that,
- // although we have two very different code paths, the serialized
- // representation is the same for both cases: a declaration name,
- // followed by a size, followed by references to the visible
- // declarations that have that name.
- uint64_t Offset = Stream.GetCurrentBitNo();
+void ASTWriter::WriteTypeDeclOffsets() {
+ using namespace llvm;
RecordData Record;
- StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
- if (!Map)
- return 0;
- for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
- D != DEnd; ++D) {
- AddDeclarationName(D->first, Record);
- DeclContext::lookup_result Result = D->second.getLookupResult(Context);
- Record.push_back(Result.second - Result.first);
- for (; Result.first != Result.second; ++Result.first)
- AddDeclRef(*Result.first, Record);
- }
-
- if (Record.size() == 0)
- return 0;
+ // Write the type offsets array
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
+ unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+ Record.clear();
+ Record.push_back(TYPE_OFFSET);
+ Record.push_back(TypeOffsets.size());
+ Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
+ (const char *)data(TypeOffsets),
+ TypeOffsets.size() * sizeof(TypeOffsets[0]));
- Stream.EmitRecord(pch::DECL_CONTEXT_VISIBLE, Record);
- ++NumVisibleDeclContexts;
- return Offset;
+ // Write the declaration offsets array
+ Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
+ unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+ Record.clear();
+ Record.push_back(DECL_OFFSET);
+ Record.push_back(DeclOffsets.size());
+ Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
+ (const char *)data(DeclOffsets),
+ DeclOffsets.size() * sizeof(DeclOffsets[0]));
}
//===----------------------------------------------------------------------===//
@@ -1507,27 +1505,23 @@ uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
namespace {
// Trait used for the on-disk hash table used in the method pool.
-class PCHMethodPoolTrait {
- PCHWriter &Writer;
+class ASTMethodPoolTrait {
+ ASTWriter &Writer;
public:
typedef Selector key_type;
typedef key_type key_type_ref;
- typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
+ struct data_type {
+ SelectorID ID;
+ ObjCMethodList Instance, Factory;
+ };
typedef const data_type& data_type_ref;
- explicit PCHMethodPoolTrait(PCHWriter &Writer) : Writer(Writer) { }
+ explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) { }
static unsigned ComputeHash(Selector Sel) {
- unsigned N = Sel.getNumArgs();
- if (N == 0)
- ++N;
- unsigned R = 5381;
- for (unsigned I = 0; I != N; ++I)
- if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
- R = llvm::HashString(II->getName(), R);
- return R;
+ return serialization::ComputeHash(Sel);
}
std::pair<unsigned,unsigned>
@@ -1535,12 +1529,12 @@ public:
data_type_ref Methods) {
unsigned KeyLen = 2 + (Sel.getNumArgs()? Sel.getNumArgs() * 4 : 4);
clang::io::Emit16(Out, KeyLen);
- unsigned DataLen = 2 + 2; // 2 bytes for each of the method counts
- for (const ObjCMethodList *Method = &Methods.first; Method;
+ unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->Next)
if (Method->Method)
DataLen += 4;
- for (const ObjCMethodList *Method = &Methods.second; Method;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->Next)
if (Method->Method)
DataLen += 4;
@@ -1564,25 +1558,26 @@ public:
void EmitData(llvm::raw_ostream& Out, key_type_ref,
data_type_ref Methods, unsigned DataLen) {
uint64_t Start = Out.tell(); (void)Start;
+ clang::io::Emit32(Out, Methods.ID);
unsigned NumInstanceMethods = 0;
- for (const ObjCMethodList *Method = &Methods.first; Method;
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->Next)
if (Method->Method)
++NumInstanceMethods;
unsigned NumFactoryMethods = 0;
- for (const ObjCMethodList *Method = &Methods.second; Method;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->Next)
if (Method->Method)
++NumFactoryMethods;
clang::io::Emit16(Out, NumInstanceMethods);
clang::io::Emit16(Out, NumFactoryMethods);
- for (const ObjCMethodList *Method = &Methods.first; Method;
+ for (const ObjCMethodList *Method = &Methods.Instance; Method;
Method = Method->Next)
if (Method->Method)
clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
- for (const ObjCMethodList *Method = &Methods.second; Method;
+ for (const ObjCMethodList *Method = &Methods.Factory; Method;
Method = Method->Next)
if (Method->Method)
clang::io::Emit32(Out, Writer.getDeclID(Method->Method));
@@ -1592,89 +1587,78 @@ public:
};
} // end anonymous namespace
-/// \brief Write the method pool into the PCH file.
+/// \brief Write ObjC data: selectors and the method pool.
///
/// The method pool contains both instance and factory methods, stored
-/// in an on-disk hash table indexed by the selector.
-void PCHWriter::WriteMethodPool(Sema &SemaRef) {
+/// in an on-disk hash table indexed by the selector. The hash table also
+/// contains an empty entry for every other selector known to Sema.
+void ASTWriter::WriteSelectors(Sema &SemaRef) {
using namespace llvm;
- // Create and write out the blob that contains the instance and
- // factor method pools.
- bool Empty = true;
+ // Do we have to do anything at all?
+ if (SemaRef.MethodPool.empty() && SelectorIDs.empty())
+ return;
+ unsigned NumTableEntries = 0;
+ // Create and write out the blob that contains selectors and the method pool.
{
- OnDiskChainedHashTableGenerator<PCHMethodPoolTrait> Generator;
-
- // Create the on-disk hash table representation. Start by
- // iterating through the instance method pool.
- PCHMethodPoolTrait::key_type Key;
- unsigned NumSelectorsInMethodPool = 0;
- for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
- Instance = SemaRef.InstanceMethodPool.begin(),
- InstanceEnd = SemaRef.InstanceMethodPool.end();
- Instance != InstanceEnd; ++Instance) {
- // Check whether there is a factory method with the same
- // selector.
- llvm::DenseMap<Selector, ObjCMethodList>::iterator Factory
- = SemaRef.FactoryMethodPool.find(Instance->first);
-
- if (Factory == SemaRef.FactoryMethodPool.end())
- Generator.insert(Instance->first,
- std::make_pair(Instance->second,
- ObjCMethodList()));
- else
- Generator.insert(Instance->first,
- std::make_pair(Instance->second, Factory->second));
-
- ++NumSelectorsInMethodPool;
- Empty = false;
- }
-
- // Now iterate through the factory method pool, to pick up any
- // selectors that weren't already in the instance method pool.
- for (llvm::DenseMap<Selector, ObjCMethodList>::iterator
- Factory = SemaRef.FactoryMethodPool.begin(),
- FactoryEnd = SemaRef.FactoryMethodPool.end();
- Factory != FactoryEnd; ++Factory) {
- // Check whether there is an instance method with the same
- // selector. If so, there is no work to do here.
- llvm::DenseMap<Selector, ObjCMethodList>::iterator Instance
- = SemaRef.InstanceMethodPool.find(Factory->first);
-
- if (Instance == SemaRef.InstanceMethodPool.end()) {
- Generator.insert(Factory->first,
- std::make_pair(ObjCMethodList(), Factory->second));
- ++NumSelectorsInMethodPool;
+ OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
+ ASTMethodPoolTrait Trait(*this);
+
+ // Create the on-disk hash table representation. We walk through every
+ // selector we've seen and look it up in the method pool.
+ SelectorOffsets.resize(NextSelectorID - FirstSelectorID);
+ for (llvm::DenseMap<Selector, SelectorID>::iterator
+ I = SelectorIDs.begin(), E = SelectorIDs.end();
+ I != E; ++I) {
+ Selector S = I->first;
+ Sema::GlobalMethodPool::iterator F = SemaRef.MethodPool.find(S);
+ ASTMethodPoolTrait::data_type Data = {
+ I->second,
+ ObjCMethodList(),
+ ObjCMethodList()
+ };
+ if (F != SemaRef.MethodPool.end()) {
+ Data.Instance = F->second.first;
+ Data.Factory = F->second.second;
}
-
- Empty = false;
+ // Only write this selector if it's not in an existing AST or something
+ // changed.
+ if (Chain && I->second < FirstSelectorID) {
+ // Selector already exists. Did it change?
+ bool changed = false;
+ for (ObjCMethodList *M = &Data.Instance; !changed && M && M->Method;
+ M = M->Next) {
+ if (M->Method->getPCHLevel() == 0)
+ changed = true;
+ }
+ for (ObjCMethodList *M = &Data.Factory; !changed && M && M->Method;
+ M = M->Next) {
+ if (M->Method->getPCHLevel() == 0)
+ changed = true;
+ }
+ if (!changed)
+ continue;
+ } else if (Data.Instance.Method || Data.Factory.Method) {
+ // A new method pool entry.
+ ++NumTableEntries;
+ }
+ Generator.insert(S, Data, Trait);
}
- if (Empty && SelectorOffsets.empty())
- return;
-
// Create the on-disk hash table in a buffer.
llvm::SmallString<4096> MethodPool;
uint32_t BucketOffset;
- SelectorOffsets.resize(SelVector.size());
{
- PCHMethodPoolTrait Trait(*this);
+ ASTMethodPoolTrait Trait(*this);
llvm::raw_svector_ostream Out(MethodPool);
// Make sure that no bucket is at offset 0
clang::io::Emit32(Out, 0);
BucketOffset = Generator.Emit(Out, Trait);
-
- // For every selector that we have seen but which was not
- // written into the hash table, write the selector itself and
- // record it's offset.
- for (unsigned I = 0, N = SelVector.size(); I != N; ++I)
- if (SelectorOffsets[I] == 0)
- Trait.EmitKey(Out, SelVector[I], 0);
}
// Create a blob abbreviation
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::METHOD_POOL));
+ Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
@@ -1682,35 +1666,57 @@ void PCHWriter::WriteMethodPool(Sema &SemaRef) {
// Write the method pool
RecordData Record;
- Record.push_back(pch::METHOD_POOL);
+ Record.push_back(METHOD_POOL);
Record.push_back(BucketOffset);
- Record.push_back(NumSelectorsInMethodPool);
+ Record.push_back(NumTableEntries);
Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool.str());
// Create a blob abbreviation for the selector table offsets.
Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::SELECTOR_OFFSETS));
+ Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // index
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the selector offsets table.
Record.clear();
- Record.push_back(pch::SELECTOR_OFFSETS);
+ Record.push_back(SELECTOR_OFFSETS);
Record.push_back(SelectorOffsets.size());
Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
- (const char *)&SelectorOffsets.front(),
+ (const char *)data(SelectorOffsets),
SelectorOffsets.size() * 4);
}
}
+/// \brief Write the selectors referenced in @selector expression into AST file.
+void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
+ using namespace llvm;
+ if (SemaRef.ReferencedSelectors.empty())
+ return;
+
+ RecordData Record;
+
+ // Note: this writes out all references even for a dependent AST. But it is
+ // very tricky to fix, and given that @selector shouldn't really appear in
+ // headers, probably not worth it. It's not a correctness issue.
+ for (DenseMap<Selector, SourceLocation>::iterator S =
+ SemaRef.ReferencedSelectors.begin(),
+ E = SemaRef.ReferencedSelectors.end(); S != E; ++S) {
+ Selector Sel = (*S).first;
+ SourceLocation Loc = (*S).second;
+ AddSelectorRef(Sel, Record);
+ AddSourceLocation(Loc, Record);
+ }
+ Stream.EmitRecord(REFERENCED_SELECTOR_POOL, Record);
+}
+
//===----------------------------------------------------------------------===//
// Identifier Table Serialization
//===----------------------------------------------------------------------===//
namespace {
-class PCHIdentifierTableTrait {
- PCHWriter &Writer;
+class ASTIdentifierTableTrait {
+ ASTWriter &Writer;
Preprocessor &PP;
/// \brief Determines whether this is an "interesting" identifier
@@ -1728,10 +1734,10 @@ public:
typedef const IdentifierInfo* key_type;
typedef key_type key_type_ref;
- typedef pch::IdentID data_type;
+ typedef IdentID data_type;
typedef data_type data_type_ref;
- PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP)
+ ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP)
: Writer(Writer), PP(PP) { }
static unsigned ComputeHash(const IdentifierInfo* II) {
@@ -1740,7 +1746,7 @@ public:
std::pair<unsigned,unsigned>
EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,
- pch::IdentID ID) {
+ IdentID ID) {
unsigned KeyLen = II->getLength() + 1;
unsigned DataLen = 4; // 4 bytes for the persistent ID << 1
if (isInterestingIdentifier(II)) {
@@ -1751,7 +1757,7 @@ public:
for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
DEnd = IdentifierResolver::end();
D != DEnd; ++D)
- DataLen += sizeof(pch::DeclID);
+ DataLen += sizeof(DeclID);
}
clang::io::Emit16(Out, DataLen);
// We emit the key length after the data length so that every
@@ -1770,7 +1776,7 @@ public:
}
void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II,
- pch::IdentID ID, unsigned) {
+ IdentID ID, unsigned) {
if (!isInterestingIdentifier(II)) {
clang::io::Emit32(Out, ID << 1);
return;
@@ -1785,6 +1791,7 @@ public:
Bits = (Bits << 1) | unsigned(hasMacroDefinition);
Bits = (Bits << 1) | unsigned(II->isExtensionToken());
Bits = (Bits << 1) | unsigned(II->isPoisoned());
+ Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
clang::io::Emit16(Out, Bits);
@@ -1797,6 +1804,7 @@ public:
// "stat"), but IdentifierResolver::AddDeclToIdentifierChain()
// adds declarations to the end of the list (so we need to see the
// struct "status" before the function "status").
+ // Only emit declarations that aren't from a chained PCH, though.
llvm::SmallVector<Decl *, 16> Decls(IdentifierResolver::begin(II),
IdentifierResolver::end());
for (llvm::SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
@@ -1807,43 +1815,46 @@ public:
};
} // end anonymous namespace
-/// \brief Write the identifier table into the PCH file.
+/// \brief Write the identifier table into the AST file.
///
/// The identifier table consists of a blob containing string data
/// (the actual identifiers themselves) and a separate "offsets" index
/// that maps identifier IDs to locations within the blob.
-void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
+void ASTWriter::WriteIdentifierTable(Preprocessor &PP) {
using namespace llvm;
// Create and write out the blob that contains the identifier
// strings.
{
- OnDiskChainedHashTableGenerator<PCHIdentifierTableTrait> Generator;
+ OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
+ ASTIdentifierTableTrait Trait(*this, PP);
// Look for any identifiers that were named while processing the
// headers, but are otherwise not needed. We add these to the hash
// table to enable checking of the predefines buffer in the case
- // where the user adds new macro definitions when building the PCH
+ // where the user adds new macro definitions when building the AST
// file.
for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
IDEnd = PP.getIdentifierTable().end();
ID != IDEnd; ++ID)
getIdentifierRef(ID->second);
- // Create the on-disk hash table representation.
- IdentifierOffsets.resize(IdentifierIDs.size());
- for (llvm::DenseMap<const IdentifierInfo *, pch::IdentID>::iterator
+ // Create the on-disk hash table representation. We only store offsets
+ // for identifiers that appear here for the first time.
+ IdentifierOffsets.resize(NextIdentID - FirstIdentID);
+ for (llvm::DenseMap<const IdentifierInfo *, IdentID>::iterator
ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end();
ID != IDEnd; ++ID) {
assert(ID->first && "NULL identifier in identifier table");
- Generator.insert(ID->first, ID->second);
+ if (!Chain || !ID->first->isFromAST())
+ Generator.insert(ID->first, ID->second, Trait);
}
// Create the on-disk hash table in a buffer.
llvm::SmallString<4096> IdentifierTable;
uint32_t BucketOffset;
{
- PCHIdentifierTableTrait Trait(*this, PP);
+ ASTIdentifierTableTrait Trait(*this, PP);
llvm::raw_svector_ostream Out(IdentifierTable);
// Make sure that no bucket is at offset 0
clang::io::Emit32(Out, 0);
@@ -1852,236 +1863,345 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
// Create a blob abbreviation
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_TABLE));
+ Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);
// Write the identifier table
RecordData Record;
- Record.push_back(pch::IDENTIFIER_TABLE);
+ Record.push_back(IDENTIFIER_TABLE);
Record.push_back(BucketOffset);
Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
}
// Write the offsets table for identifier IDs.
BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::IDENTIFIER_OFFSET));
+ Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
RecordData Record;
- Record.push_back(pch::IDENTIFIER_OFFSET);
+ Record.push_back(IDENTIFIER_OFFSET);
Record.push_back(IdentifierOffsets.size());
Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
- (const char *)&IdentifierOffsets.front(),
+ (const char *)data(IdentifierOffsets),
IdentifierOffsets.size() * sizeof(uint32_t));
}
//===----------------------------------------------------------------------===//
-// General Serialization Routines
+// DeclContext's Name Lookup Table Serialization
//===----------------------------------------------------------------------===//
-/// \brief Write a record containing the given attributes.
-void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
- RecordData Record;
- for (; Attr; Attr = Attr->getNext()) {
- Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
- Record.push_back(Attr->isInherited());
- switch (Attr->getKind()) {
- default:
- assert(0 && "Does not support PCH writing for this attribute yet!");
+namespace {
+// Trait used for the on-disk hash table used in the method pool.
+class ASTDeclContextNameLookupTrait {
+ ASTWriter &Writer;
+
+public:
+ typedef DeclarationName key_type;
+ typedef key_type key_type_ref;
+
+ typedef DeclContext::lookup_result data_type;
+ typedef const data_type& data_type_ref;
+
+ explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) { }
+
+ unsigned ComputeHash(DeclarationName Name) {
+ llvm::FoldingSetNodeID ID;
+ ID.AddInteger(Name.getNameKind());
+
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ ID.AddString(Name.getAsIdentifierInfo()->getName());
break;
- case attr::Alias:
- AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ ID.AddInteger(serialization::ComputeHash(Name.getObjCSelector()));
break;
-
- case attr::AlignMac68k:
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ ID.AddInteger(Writer.GetOrCreateTypeID(Name.getCXXNameType()));
break;
-
- case attr::Aligned:
- Record.push_back(cast<AlignedAttr>(Attr)->getAlignment());
+ case DeclarationName::CXXOperatorName:
+ ID.AddInteger(Name.getCXXOverloadedOperator());
break;
-
- case attr::AlwaysInline:
+ case DeclarationName::CXXLiteralOperatorName:
+ ID.AddString(Name.getCXXLiteralIdentifier()->getName());
+ case DeclarationName::CXXUsingDirective:
break;
+ }
- case attr::AnalyzerNoReturn:
- break;
+ return ID.ComputeHash();
+ }
- case attr::Annotate:
- AddString(cast<AnnotateAttr>(Attr)->getAnnotation(), Record);
+ std::pair<unsigned,unsigned>
+ EmitKeyDataLength(llvm::raw_ostream& Out, DeclarationName Name,
+ data_type_ref Lookup) {
+ unsigned KeyLen = 1;
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ case DeclarationName::CXXLiteralOperatorName:
+ KeyLen += 4;
break;
-
- case attr::AsmLabel:
- AddString(cast<AsmLabelAttr>(Attr)->getLabel(), Record);
+ case DeclarationName::CXXOperatorName:
+ KeyLen += 1;
break;
-
- case attr::BaseCheck:
+ case DeclarationName::CXXUsingDirective:
break;
+ }
+ clang::io::Emit16(Out, KeyLen);
- case attr::Blocks:
- Record.push_back(cast<BlocksAttr>(Attr)->getType()); // FIXME: stable
- break;
+ // 2 bytes for num of decls and 4 for each DeclID.
+ unsigned DataLen = 2 + 4 * (Lookup.second - Lookup.first);
+ clang::io::Emit16(Out, DataLen);
- case attr::CDecl:
- break;
+ return std::make_pair(KeyLen, DataLen);
+ }
- case attr::Cleanup:
- AddDeclRef(cast<CleanupAttr>(Attr)->getFunctionDecl(), Record);
- break;
+ void EmitKey(llvm::raw_ostream& Out, DeclarationName Name, unsigned) {
+ using namespace clang::io;
- case attr::Const:
+ assert(Name.getNameKind() < 0x100 && "Invalid name kind ?");
+ Emit8(Out, Name.getNameKind());
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier:
+ Emit32(Out, Writer.getIdentifierRef(Name.getAsIdentifierInfo()));
break;
-
- case attr::Constructor:
- Record.push_back(cast<ConstructorAttr>(Attr)->getPriority());
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ Emit32(Out, Writer.getSelectorRef(Name.getObjCSelector()));
break;
-
- case attr::DLLExport:
- case attr::DLLImport:
- case attr::Deprecated:
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ Emit32(Out, Writer.getTypeID(Name.getCXXNameType()));
break;
-
- case attr::Destructor:
- Record.push_back(cast<DestructorAttr>(Attr)->getPriority());
+ case DeclarationName::CXXOperatorName:
+ assert(Name.getCXXOverloadedOperator() < 0x100 && "Invalid operator ?");
+ Emit8(Out, Name.getCXXOverloadedOperator());
break;
-
- case attr::FastCall:
- case attr::Final:
+ case DeclarationName::CXXLiteralOperatorName:
+ Emit32(Out, Writer.getIdentifierRef(Name.getCXXLiteralIdentifier()));
break;
-
- case attr::Format: {
- const FormatAttr *Format = cast<FormatAttr>(Attr);
- AddString(Format->getType(), Record);
- Record.push_back(Format->getFormatIdx());
- Record.push_back(Format->getFirstArg());
+ case DeclarationName::CXXUsingDirective:
break;
}
+ }
- case attr::FormatArg: {
- const FormatArgAttr *Format = cast<FormatArgAttr>(Attr);
- Record.push_back(Format->getFormatIdx());
- break;
- }
+ void EmitData(llvm::raw_ostream& Out, key_type_ref,
+ data_type Lookup, unsigned DataLen) {
+ uint64_t Start = Out.tell(); (void)Start;
+ clang::io::Emit16(Out, Lookup.second - Lookup.first);
+ for (; Lookup.first != Lookup.second; ++Lookup.first)
+ clang::io::Emit32(Out, Writer.GetDeclRef(*Lookup.first));
- case attr::Sentinel : {
- const SentinelAttr *Sentinel = cast<SentinelAttr>(Attr);
- Record.push_back(Sentinel->getSentinel());
- Record.push_back(Sentinel->getNullPos());
- break;
- }
+ assert(Out.tell() - Start == DataLen && "Data length is wrong");
+ }
+};
+} // end anonymous namespace
- case attr::GNUInline:
- case attr::Hiding:
- case attr::IBAction:
- case attr::IBOutlet:
- case attr::Malloc:
- case attr::NoDebug:
- case attr::NoInline:
- case attr::NoReturn:
- case attr::NoThrow:
- break;
+/// \brief Write the block containing all of the declaration IDs
+/// visible from the given DeclContext.
+///
+/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
+/// bitstream, or 0 if no block was written.
+uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,
+ DeclContext *DC) {
+ if (DC->getPrimaryContext() != DC)
+ return 0;
- case attr::IBOutletCollection: {
- const IBOutletCollectionAttr *ICA = cast<IBOutletCollectionAttr>(Attr);
- AddDeclRef(ICA->getClass(), Record);
- break;
- }
+ // Since there is no name lookup into functions or methods, don't bother to
+ // build a visible-declarations table for these entities.
+ if (DC->isFunctionOrMethod())
+ return 0;
- case attr::NonNull: {
- const NonNullAttr *NonNull = cast<NonNullAttr>(Attr);
- Record.push_back(NonNull->size());
- Record.insert(Record.end(), NonNull->begin(), NonNull->end());
- break;
- }
+ // If not in C++, we perform name lookup for the translation unit via the
+ // IdentifierInfo chains, don't bother to build a visible-declarations table.
+ // FIXME: In C++ we need the visible declarations in order to "see" the
+ // friend declarations, is there a way to do this without writing the table ?
+ if (DC->isTranslationUnit() && !Context.getLangOptions().CPlusPlus)
+ return 0;
- case attr::CFReturnsNotRetained:
- case attr::CFReturnsRetained:
- case attr::NSReturnsNotRetained:
- case attr::NSReturnsRetained:
- case attr::ObjCException:
- case attr::ObjCNSObject:
- case attr::Overloadable:
- case attr::Override:
- break;
+ // Force the DeclContext to build a its name-lookup table.
+ if (DC->hasExternalVisibleStorage())
+ DC->MaterializeVisibleDeclsFromExternalStorage();
+ else
+ DC->lookup(DeclarationName());
- case attr::MaxFieldAlignment:
- Record.push_back(cast<MaxFieldAlignmentAttr>(Attr)->getAlignment());
- break;
+ // Serialize the contents of the mapping used for lookup. Note that,
+ // although we have two very different code paths, the serialized
+ // representation is the same for both cases: a declaration name,
+ // followed by a size, followed by references to the visible
+ // declarations that have that name.
+ uint64_t Offset = Stream.GetCurrentBitNo();
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ if (!Map || Map->empty())
+ return 0;
- case attr::Packed:
- break;
+ OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
- case attr::Pure:
- break;
+ // Create the on-disk hash table representation.
+ for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+ D != DEnd; ++D) {
+ DeclarationName Name = D->first;
+ DeclContext::lookup_result Result = D->second.getLookupResult();
+ Generator.insert(Name, Result, Trait);
+ }
- case attr::Regparm:
- Record.push_back(cast<RegparmAttr>(Attr)->getNumParams());
- break;
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> LookupTable;
+ uint32_t BucketOffset;
+ {
+ llvm::raw_svector_ostream Out(LookupTable);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, Trait);
+ }
- case attr::ReqdWorkGroupSize:
- Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getXDim());
- Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getYDim());
- Record.push_back(cast<ReqdWorkGroupSizeAttr>(Attr)->getZDim());
- break;
+ // Write the lookup table
+ RecordData Record;
+ Record.push_back(DECL_CONTEXT_VISIBLE);
+ Record.push_back(BucketOffset);
+ Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,
+ LookupTable.str());
- case attr::Section:
- AddString(cast<SectionAttr>(Attr)->getName(), Record);
- break;
+ Stream.EmitRecord(DECL_CONTEXT_VISIBLE, Record);
+ ++NumVisibleDeclContexts;
+ return Offset;
+}
- case attr::StdCall:
- case attr::TransparentUnion:
- case attr::Unavailable:
- case attr::Unused:
- case attr::Used:
- break;
+/// \brief Write an UPDATE_VISIBLE block for the given context.
+///
+/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing
+/// DeclContext in a dependent AST file. As such, they only exist for the TU
+/// (in C++) and for namespaces.
+void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {
+ assert((DC->isTranslationUnit() || DC->isNamespace()) &&
+ "Only TU and namespaces should have visible decl updates.");
+
+ // Make the context build its lookup table, but don't make it load external
+ // decls.
+ DC->lookup(DeclarationName());
- case attr::Visibility:
- // FIXME: stable encoding
- Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
- break;
+ StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(DC->getLookupPtr());
+ if (!Map || Map->empty())
+ return;
- case attr::WarnUnusedResult:
- case attr::Weak:
- case attr::WeakRef:
- case attr::WeakImport:
- break;
- }
+ OnDiskChainedHashTableGenerator<ASTDeclContextNameLookupTrait> Generator;
+ ASTDeclContextNameLookupTrait Trait(*this);
+
+ // Create the hash table.
+ for (StoredDeclsMap::iterator D = Map->begin(), DEnd = Map->end();
+ D != DEnd; ++D) {
+ DeclarationName Name = D->first;
+ DeclContext::lookup_result Result = D->second.getLookupResult();
+ // For any name that appears in this table, the results are complete, i.e.
+ // they overwrite results from previous PCHs. Merging is always a mess.
+ Generator.insert(Name, Result, Trait);
+ }
+
+ // Create the on-disk hash table in a buffer.
+ llvm::SmallString<4096> LookupTable;
+ uint32_t BucketOffset;
+ {
+ llvm::raw_svector_ostream Out(LookupTable);
+ // Make sure that no bucket is at offset 0
+ clang::io::Emit32(Out, 0);
+ BucketOffset = Generator.Emit(Out, Trait);
}
- Stream.EmitRecord(pch::DECL_ATTR, Record);
+ // Write the lookup table
+ RecordData Record;
+ Record.push_back(UPDATE_VISIBLE);
+ Record.push_back(getDeclID(cast<Decl>(DC)));
+ Record.push_back(BucketOffset);
+ Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable.str());
+}
+
+/// \brief Write ADDITIONAL_TEMPLATE_SPECIALIZATIONS blocks for all templates
+/// that have new specializations in the current AST file.
+void ASTWriter::WriteAdditionalTemplateSpecializations() {
+ RecordData Record;
+ for (AdditionalTemplateSpecializationsMap::iterator
+ I = AdditionalTemplateSpecializations.begin(),
+ E = AdditionalTemplateSpecializations.end();
+ I != E; ++I) {
+ Record.clear();
+ Record.push_back(I->first);
+ Record.insert(Record.end(), I->second.begin(), I->second.end());
+ Stream.EmitRecord(ADDITIONAL_TEMPLATE_SPECIALIZATIONS, Record);
+ }
}
-void PCHWriter::AddString(const std::string &Str, RecordData &Record) {
+//===----------------------------------------------------------------------===//
+// General Serialization Routines
+//===----------------------------------------------------------------------===//
+
+/// \brief Write a record containing the given attributes.
+void ASTWriter::WriteAttributeRecord(const AttrVec &Attrs) {
+ RecordData Record;
+ for (AttrVec::const_iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i){
+ const Attr * A = *i;
+ Record.push_back(A->getKind()); // FIXME: stable encoding, target attrs
+ AddSourceLocation(A->getLocation(), Record);
+ Record.push_back(A->isInherited());
+
+#include "clang/Serialization/AttrPCHWrite.inc"
+
+ }
+
+ Stream.EmitRecord(DECL_ATTR, Record);
+}
+
+void ASTWriter::AddString(llvm::StringRef Str, RecordData &Record) {
Record.push_back(Str.size());
Record.insert(Record.end(), Str.begin(), Str.end());
}
/// \brief Note that the identifier II occurs at the given offset
/// within the identifier table.
-void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
- IdentifierOffsets[IdentifierIDs[II] - 1] = Offset;
+void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
+ IdentID ID = IdentifierIDs[II];
+ // Only store offsets new to this AST file. Other identifier names are looked
+ // up earlier in the chain and thus don't need an offset.
+ if (ID >= FirstIdentID)
+ IdentifierOffsets[ID - FirstIdentID] = Offset;
}
/// \brief Note that the selector Sel occurs at the given offset
/// within the method pool/selector table.
-void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
+void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
unsigned ID = SelectorIDs[Sel];
assert(ID && "Unknown selector");
- SelectorOffsets[ID - 1] = Offset;
+ // Don't record offsets for selectors that are also available in a different
+ // file.
+ if (ID < FirstSelectorID)
+ return;
+ SelectorOffsets[ID - FirstSelectorID] = Offset;
}
-PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain)
- : Stream(Stream), Chain(Chain), NextTypeID(pch::NUM_PREDEF_TYPE_IDS),
- CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0),
- NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) {
- if (Chain)
- Chain->setDeserializationListener(this);
+ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream)
+ : Stream(Stream), Chain(0), FirstDeclID(1), NextDeclID(FirstDeclID),
+ FirstTypeID(NUM_PREDEF_TYPE_IDS), NextTypeID(FirstTypeID),
+ FirstIdentID(1), NextIdentID(FirstIdentID), FirstSelectorID(1),
+ NextSelectorID(FirstSelectorID), CollectedStmts(&StmtsToEmit),
+ NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0),
+ NumVisibleDeclContexts(0) {
}
-void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+void ASTWriter::WriteAST(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char *isysroot) {
// Emit the file header.
Stream.Emit((unsigned)'C', 8);
@@ -2092,12 +2212,12 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,
WriteBlockInfoBlock();
if (Chain)
- WritePCHChain(SemaRef, StatCalls, isysroot);
+ WriteASTChain(SemaRef, StatCalls, isysroot);
else
- WritePCHCore(SemaRef, StatCalls, isysroot);
+ WriteASTCore(SemaRef, StatCalls, isysroot);
}
-void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+void ASTWriter::WriteASTCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char *isysroot) {
using namespace llvm;
@@ -2106,6 +2226,7 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
// The translation unit is the first declaration we'll emit.
DeclIDs[Context.getTranslationUnitDecl()] = 1;
+ ++NextDeclID;
DeclTypesToEmit.push(Context.getTranslationUnitDecl());
// Make sure that we emit IdentifierInfos (and any attached
@@ -2127,16 +2248,30 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
}
- // Build a record containing all of the static unused functions in this file.
- RecordData UnusedStaticFuncs;
- for (unsigned i=0, e = SemaRef.UnusedStaticFuncs.size(); i !=e; ++i)
- AddDeclRef(SemaRef.UnusedStaticFuncs[i], UnusedStaticFuncs);
+ // Build a record containing all of the file scoped decls in this file.
+ RecordData UnusedFileScopedDecls;
+ for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i)
+ AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
+
+ RecordData WeakUndeclaredIdentifiers;
+ if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
+ WeakUndeclaredIdentifiers.push_back(
+ SemaRef.WeakUndeclaredIdentifiers.size());
+ for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator
+ I = SemaRef.WeakUndeclaredIdentifiers.begin(),
+ E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+ AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
+ AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
+ AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
+ WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
+ }
+ }
// Build a record containing all of the locally-scoped external
// declarations in this header file. Generally, this record will be
// empty.
RecordData LocallyScopedExternalDecls;
- // FIXME: This is filling in the PCH file in densemap order which is
+ // FIXME: This is filling in the AST file in densemap order which is
// nondeterminstic!
for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
TD = SemaRef.LocallyScopedExternalDecls.begin(),
@@ -2151,11 +2286,13 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
// Build a record containing all of the VTable uses information.
RecordData VTableUses;
- VTableUses.push_back(SemaRef.VTableUses.size());
- for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
- AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
- AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
- VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
+ if (!SemaRef.VTableUses.empty()) {
+ VTableUses.push_back(SemaRef.VTableUses.size());
+ for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
+ AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
+ AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
+ VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
+ }
}
// Build a record containing all of dynamic classes declarations.
@@ -2163,9 +2300,27 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
- // Write the remaining PCH contents.
+ // Build a record containing all of pending implicit instantiations.
+ RecordData PendingInstantiations;
+ for (std::deque<Sema::PendingImplicitInstantiation>::iterator
+ I = SemaRef.PendingInstantiations.begin(),
+ N = SemaRef.PendingInstantiations.end(); I != N; ++I) {
+ AddDeclRef(I->first, PendingInstantiations);
+ AddSourceLocation(I->second, PendingInstantiations);
+ }
+ assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
+ "There are local ones at end of translation unit!");
+
+ // Build a record containing some declaration references.
+ RecordData SemaDeclRefs;
+ if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
+ AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
+ AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
+ }
+
+ // Write the remaining AST contents.
RecordData Record;
- Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5);
+ Stream.EnterSubblock(AST_BLOCK_ID, 5);
WriteMetadata(Context, isysroot);
WriteLanguageOptions(Context.getLangOptions());
if (StatCalls && !isysroot)
@@ -2191,11 +2346,11 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
AddTypeRef(Context.ObjCSelRedefinitionType, Record);
AddTypeRef(Context.getRawNSConstantStringType(), Record);
Record.push_back(Context.isInt128Installed());
- Stream.EmitRecord(pch::SPECIAL_TYPES, Record);
+ Stream.EmitRecord(SPECIAL_TYPES, Record);
// Keep writing types and declarations until all types and
// declarations have been written.
- Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, 3);
WriteDeclsBlockAbbrevs();
while (!DeclTypesToEmit.empty()) {
DeclOrType DOT = DeclTypesToEmit.front();
@@ -2208,63 +2363,53 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
Stream.ExitBlock();
WritePreprocessor(PP);
- WriteMethodPool(SemaRef);
+ WriteSelectors(SemaRef);
+ WriteReferencedSelectorsPool(SemaRef);
WriteIdentifierTable(PP);
- // Write the type offsets array
- BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
- unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
- Record.clear();
- Record.push_back(pch::TYPE_OFFSET);
- Record.push_back(TypeOffsets.size());
- Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
- (const char *)&TypeOffsets.front(),
- TypeOffsets.size() * sizeof(TypeOffsets[0]));
-
- // Write the declaration offsets array
- Abbrev = new BitCodeAbbrev();
- Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
- unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
- Record.clear();
- Record.push_back(pch::DECL_OFFSET);
- Record.push_back(DeclOffsets.size());
- Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
- (const char *)&DeclOffsets.front(),
- DeclOffsets.size() * sizeof(DeclOffsets[0]));
+ WriteTypeDeclOffsets();
// Write the record containing external, unnamed definitions.
if (!ExternalDefinitions.empty())
- Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions);
+ Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
// Write the record containing tentative definitions.
if (!TentativeDefinitions.empty())
- Stream.EmitRecord(pch::TENTATIVE_DEFINITIONS, TentativeDefinitions);
+ Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);
+
+ // Write the record containing unused file scoped decls.
+ if (!UnusedFileScopedDecls.empty())
+ Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);
- // Write the record containing unused static functions.
- if (!UnusedStaticFuncs.empty())
- Stream.EmitRecord(pch::UNUSED_STATIC_FUNCS, UnusedStaticFuncs);
+ // Write the record containing weak undeclared identifiers.
+ if (!WeakUndeclaredIdentifiers.empty())
+ Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
+ WeakUndeclaredIdentifiers);
// Write the record containing locally-scoped external definitions.
if (!LocallyScopedExternalDecls.empty())
- Stream.EmitRecord(pch::LOCALLY_SCOPED_EXTERNAL_DECLS,
+ Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS,
LocallyScopedExternalDecls);
// Write the record containing ext_vector type names.
if (!ExtVectorDecls.empty())
- Stream.EmitRecord(pch::EXT_VECTOR_DECLS, ExtVectorDecls);
+ Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);
// Write the record containing VTable uses information.
if (!VTableUses.empty())
- Stream.EmitRecord(pch::VTABLE_USES, VTableUses);
+ Stream.EmitRecord(VTABLE_USES, VTableUses);
// Write the record containing dynamic classes declarations.
if (!DynamicClasses.empty())
- Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses);
+ Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses);
+
+ // Write the record containing pending implicit instantiations.
+ if (!PendingInstantiations.empty())
+ Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
+
+ // Write the record containing declaration references of Sema.
+ if (!SemaDeclRefs.empty())
+ Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
// Some simple statistics
Record.clear();
@@ -2272,42 +2417,162 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls,
Record.push_back(NumMacros);
Record.push_back(NumLexicalDeclContexts);
Record.push_back(NumVisibleDeclContexts);
- Stream.EmitRecord(pch::STATISTICS, Record);
+ Stream.EmitRecord(STATISTICS, Record);
Stream.ExitBlock();
}
-void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
+void ASTWriter::WriteASTChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
const char *isysroot) {
using namespace llvm;
+ FirstDeclID += Chain->getTotalNumDecls();
+ FirstTypeID += Chain->getTotalNumTypes();
+ FirstIdentID += Chain->getTotalNumIdentifiers();
+ FirstSelectorID += Chain->getTotalNumSelectors();
+ NextDeclID = FirstDeclID;
+ NextTypeID = FirstTypeID;
+ NextIdentID = FirstIdentID;
+ NextSelectorID = FirstSelectorID;
+
ASTContext &Context = SemaRef.Context;
Preprocessor &PP = SemaRef.PP;
- (void)PP;
-
+
RecordData Record;
- Stream.EnterSubblock(pch::PCH_BLOCK_ID, 5);
+ Stream.EnterSubblock(AST_BLOCK_ID, 5);
WriteMetadata(Context, isysroot);
- // FIXME: StatCache
- // FIXME: Source manager block
+ if (StatCalls && !isysroot)
+ WriteStatCache(*StatCalls);
+ // FIXME: Source manager block should only write new stuff, which could be
+ // done by tracking the largest ID in the chain
+ WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot);
// The special types are in the chained PCH.
// We don't start with the translation unit, but with its decls that
- // don't come from the other PCH.
+ // don't come from the chained PCH.
const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
- // FIXME: We don't want to iterate over everything here, because it needlessly
- // deserializes the entire original PCH. Instead we only want to iterate over
- // the stuff that's already there.
- // All in good time, though.
- for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end();
+ llvm::SmallVector<DeclID, 64> NewGlobalDecls;
+ for (DeclContext::decl_iterator I = TU->noload_decls_begin(),
+ E = TU->noload_decls_end();
I != E; ++I) {
- if ((*I)->getPCHLevel() == 0) {
- (*I)->dump();
- DeclTypesToEmit.push(*I);
+ if ((*I)->getPCHLevel() == 0)
+ NewGlobalDecls.push_back(GetDeclRef(*I));
+ else if ((*I)->isChangedSinceDeserialization())
+ (void)GetDeclRef(*I); // Make sure it's written, but don't record it.
+ }
+ // We also need to write a lexical updates block for the TU.
+ llvm::BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev();
+ Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(Abv);
+ Record.clear();
+ Record.push_back(TU_UPDATE_LEXICAL);
+ Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
+ reinterpret_cast<const char*>(NewGlobalDecls.data()),
+ NewGlobalDecls.size() * sizeof(DeclID));
+ // And in C++, a visible updates block for the TU.
+ if (Context.getLangOptions().CPlusPlus) {
+ Abv = new llvm::BitCodeAbbrev();
+ Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, 32));
+ Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+ UpdateVisibleAbbrev = Stream.EmitAbbrev(Abv);
+ WriteDeclContextVisibleUpdate(TU);
+ }
+
+ // Build a record containing all of the new tentative definitions in this
+ // file, in TentativeDefinitions order.
+ RecordData TentativeDefinitions;
+ for (unsigned i = 0, e = SemaRef.TentativeDefinitions.size(); i != e; ++i) {
+ if (SemaRef.TentativeDefinitions[i]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.TentativeDefinitions[i], TentativeDefinitions);
+ }
+
+ // Build a record containing all of the file scoped decls in this file.
+ RecordData UnusedFileScopedDecls;
+ for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i) {
+ if (SemaRef.UnusedFileScopedDecls[i]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
+ }
+
+ // We write the entire table, overwriting the tables from the chain.
+ RecordData WeakUndeclaredIdentifiers;
+ if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
+ WeakUndeclaredIdentifiers.push_back(
+ SemaRef.WeakUndeclaredIdentifiers.size());
+ for (llvm::DenseMap<IdentifierInfo*,Sema::WeakInfo>::iterator
+ I = SemaRef.WeakUndeclaredIdentifiers.begin(),
+ E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+ AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
+ AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
+ AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
+ WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
+ }
+ }
+
+ // Build a record containing all of the locally-scoped external
+ // declarations in this header file. Generally, this record will be
+ // empty.
+ RecordData LocallyScopedExternalDecls;
+ // FIXME: This is filling in the AST file in densemap order which is
+ // nondeterminstic!
+ for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator
+ TD = SemaRef.LocallyScopedExternalDecls.begin(),
+ TDEnd = SemaRef.LocallyScopedExternalDecls.end();
+ TD != TDEnd; ++TD) {
+ if (TD->second->getPCHLevel() == 0)
+ AddDeclRef(TD->second, LocallyScopedExternalDecls);
+ }
+
+ // Build a record containing all of the ext_vector declarations.
+ RecordData ExtVectorDecls;
+ for (unsigned I = 0, N = SemaRef.ExtVectorDecls.size(); I != N; ++I) {
+ if (SemaRef.ExtVectorDecls[I]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.ExtVectorDecls[I], ExtVectorDecls);
+ }
+
+ // Build a record containing all of the VTable uses information.
+ // We write everything here, because it's too hard to determine whether
+ // a use is new to this part.
+ RecordData VTableUses;
+ if (!SemaRef.VTableUses.empty()) {
+ VTableUses.push_back(SemaRef.VTableUses.size());
+ for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
+ AddDeclRef(SemaRef.VTableUses[I].first, VTableUses);
+ AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
+ VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]);
+ }
+ }
+
+ // Build a record containing all of dynamic classes declarations.
+ RecordData DynamicClasses;
+ for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
+ if (SemaRef.DynamicClasses[I]->getPCHLevel() == 0)
+ AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
+
+ // Build a record containing all of pending implicit instantiations.
+ RecordData PendingInstantiations;
+ for (std::deque<Sema::PendingImplicitInstantiation>::iterator
+ I = SemaRef.PendingInstantiations.begin(),
+ N = SemaRef.PendingInstantiations.end(); I != N; ++I) {
+ if (I->first->getPCHLevel() == 0) {
+ AddDeclRef(I->first, PendingInstantiations);
+ AddSourceLocation(I->second, PendingInstantiations);
}
}
+ assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
+ "There are local ones at end of translation unit!");
+
+ // Build a record containing some declaration references.
+ // It's not worth the effort to avoid duplication here.
+ RecordData SemaDeclRefs;
+ if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
+ AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs);
+ AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs);
+ }
- Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
+ Stream.EnterSubblock(DECLTYPES_BLOCK_ID, 3);
WriteDeclsBlockAbbrevs();
while (!DeclTypesToEmit.empty()) {
DeclOrType DOT = DeclTypesToEmit.front();
@@ -2319,31 +2584,111 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls,
}
Stream.ExitBlock();
- // FIXME: Preprocessor
- // FIXME: Method pool
- // FIXME: Identifier table
- // FIXME: Type offsets
- // FIXME: Declaration offsets
- // FIXME: External unnamed definitions
- // FIXME: Tentative definitions
- // FIXME: Unused static functions
- // FIXME: Locally-scoped external definitions
- // FIXME: ext_vector type names
- // FIXME: Dynamic classes declarations
- // FIXME: Statistics
+ WritePreprocessor(PP);
+ WriteSelectors(SemaRef);
+ WriteReferencedSelectorsPool(SemaRef);
+ WriteIdentifierTable(PP);
+ WriteTypeDeclOffsets();
+
+ /// Build a record containing first declarations from a chained PCH and the
+ /// most recent declarations in this AST that they point to.
+ RecordData FirstLatestDeclIDs;
+ for (FirstLatestDeclMap::iterator
+ I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; ++I) {
+ assert(I->first->getPCHLevel() > I->second->getPCHLevel() &&
+ "Expected first & second to be in different PCHs");
+ AddDeclRef(I->first, FirstLatestDeclIDs);
+ AddDeclRef(I->second, FirstLatestDeclIDs);
+ }
+ if (!FirstLatestDeclIDs.empty())
+ Stream.EmitRecord(REDECLS_UPDATE_LATEST, FirstLatestDeclIDs);
+
+ // Write the record containing external, unnamed definitions.
+ if (!ExternalDefinitions.empty())
+ Stream.EmitRecord(EXTERNAL_DEFINITIONS, ExternalDefinitions);
+
+ // Write the record containing tentative definitions.
+ if (!TentativeDefinitions.empty())
+ Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);
+
+ // Write the record containing unused file scoped decls.
+ if (!UnusedFileScopedDecls.empty())
+ Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);
+
+ // Write the record containing weak undeclared identifiers.
+ if (!WeakUndeclaredIdentifiers.empty())
+ Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
+ WeakUndeclaredIdentifiers);
+
+ // Write the record containing locally-scoped external definitions.
+ if (!LocallyScopedExternalDecls.empty())
+ Stream.EmitRecord(LOCALLY_SCOPED_EXTERNAL_DECLS,
+ LocallyScopedExternalDecls);
+
+ // Write the record containing ext_vector type names.
+ if (!ExtVectorDecls.empty())
+ Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);
+
+ // Write the record containing VTable uses information.
+ if (!VTableUses.empty())
+ Stream.EmitRecord(VTABLE_USES, VTableUses);
+
+ // Write the record containing dynamic classes declarations.
+ if (!DynamicClasses.empty())
+ Stream.EmitRecord(DYNAMIC_CLASSES, DynamicClasses);
+
+ // Write the record containing pending implicit instantiations.
+ if (!PendingInstantiations.empty())
+ Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
+
+ // Write the record containing declaration references of Sema.
+ if (!SemaDeclRefs.empty())
+ Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
+
+ // Write the updates to C++ namespaces.
+ for (llvm::SmallPtrSet<const NamespaceDecl *, 16>::iterator
+ I = UpdatedNamespaces.begin(),
+ E = UpdatedNamespaces.end();
+ I != E; ++I)
+ WriteDeclContextVisibleUpdate(*I);
+
+ // Write the updates to C++ template specialization lists.
+ if (!AdditionalTemplateSpecializations.empty())
+ WriteAdditionalTemplateSpecializations();
+
+ Record.clear();
+ Record.push_back(NumStatements);
+ Record.push_back(NumMacros);
+ Record.push_back(NumLexicalDeclContexts);
+ Record.push_back(NumVisibleDeclContexts);
+ WriteDeclUpdateBlock();
+ Stream.EmitRecord(STATISTICS, Record);
Stream.ExitBlock();
}
-void PCHWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
+void ASTWriter::WriteDeclUpdateBlock() {
+ if (ReplacedDecls.empty())
+ return;
+
+ RecordData Record;
+ for (llvm::SmallVector<std::pair<DeclID, uint64_t>, 16>::iterator
+ I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) {
+ Record.push_back(I->first);
+ Record.push_back(I->second);
+ }
+ Stream.EmitRecord(DECL_REPLACEMENTS, Record);
+}
+
+void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordData &Record) {
Record.push_back(Loc.getRawEncoding());
}
-void PCHWriter::AddSourceRange(SourceRange Range, RecordData &Record) {
+void ASTWriter::AddSourceRange(SourceRange Range, RecordData &Record) {
AddSourceLocation(Range.getBegin(), Record);
AddSourceLocation(Range.getEnd(), Record);
}
-void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
+void ASTWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
Record.push_back(Value.getBitWidth());
unsigned N = Value.getNumWords();
const uint64_t* Words = Value.getRawData();
@@ -2351,58 +2696,65 @@ void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
Record.push_back(Words[I]);
}
-void PCHWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
+void ASTWriter::AddAPSInt(const llvm::APSInt &Value, RecordData &Record) {
Record.push_back(Value.isUnsigned());
AddAPInt(Value, Record);
}
-void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
+void ASTWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
AddAPInt(Value.bitcastToAPInt(), Record);
}
-void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
+void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
Record.push_back(getIdentifierRef(II));
}
-pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) {
+IdentID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {
if (II == 0)
return 0;
- pch::IdentID &ID = IdentifierIDs[II];
+ IdentID &ID = IdentifierIDs[II];
if (ID == 0)
- ID = IdentifierIDs.size();
+ ID = NextIdentID++;
return ID;
}
-pch::IdentID PCHWriter::getMacroDefinitionID(MacroDefinition *MD) {
+IdentID ASTWriter::getMacroDefinitionID(MacroDefinition *MD) {
if (MD == 0)
return 0;
- pch::IdentID &ID = MacroDefinitions[MD];
+ IdentID &ID = MacroDefinitions[MD];
if (ID == 0)
ID = MacroDefinitions.size();
return ID;
}
-void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
- if (SelRef.getAsOpaquePtr() == 0) {
- Record.push_back(0);
- return;
+void ASTWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
+ Record.push_back(getSelectorRef(SelRef));
+}
+
+SelectorID ASTWriter::getSelectorRef(Selector Sel) {
+ if (Sel.getAsOpaquePtr() == 0) {
+ return 0;
}
- pch::SelectorID &SID = SelectorIDs[SelRef];
+ SelectorID &SID = SelectorIDs[Sel];
+ if (SID == 0 && Chain) {
+ // This might trigger a ReadSelector callback, which will set the ID for
+ // this selector.
+ Chain->LoadSelector(Sel);
+ }
if (SID == 0) {
- SID = SelectorIDs.size();
- SelVector.push_back(SelRef);
+ SID = NextSelectorID++;
}
- Record.push_back(SID);
+ return SID;
}
-void PCHWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) {
+void ASTWriter::AddCXXTemporary(const CXXTemporary *Temp, RecordData &Record) {
AddDeclRef(Temp->getDestructor(), Record);
}
-void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
+void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
const TemplateArgumentLocInfo &Arg,
RecordData &Record) {
switch (Kind) {
@@ -2424,7 +2776,7 @@ void PCHWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
}
}
-void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
+void ASTWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
RecordData &Record) {
AddTemplateArgument(Arg.getArgument(), Record);
@@ -2439,7 +2791,7 @@ void PCHWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg,
Record);
}
-void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
+void ASTWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
if (TInfo == 0) {
AddTypeRef(QualType(), Record);
return;
@@ -2451,102 +2803,72 @@ void PCHWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record) {
TLW.Visit(TL);
}
-void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
- if (T.isNull()) {
- Record.push_back(pch::PREDEF_TYPE_NULL_ID);
- return;
- }
-
- unsigned FastQuals = T.getLocalFastQualifiers();
- T.removeFastQualifiers();
-
- if (T.hasLocalNonFastQualifiers()) {
- pch::TypeID &ID = TypeIDs[T];
- if (ID == 0) {
- // We haven't seen these qualifiers applied to this type before.
- // Assign it a new ID. This is the only time we enqueue a
- // qualified type, and it has no CV qualifiers.
- ID = NextTypeID++;
- DeclTypesToEmit.push(T);
- }
+void ASTWriter::AddTypeRef(QualType T, RecordData &Record) {
+ Record.push_back(GetOrCreateTypeID(T));
+}
- // Encode the type qualifiers in the type reference.
- Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
- return;
- }
+TypeID ASTWriter::GetOrCreateTypeID(QualType T) {
+ return MakeTypeID(T,
+ std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
+}
- assert(!T.hasLocalQualifiers());
-
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) {
- pch::TypeID ID = 0;
- switch (BT->getKind()) {
- case BuiltinType::Void: ID = pch::PREDEF_TYPE_VOID_ID; break;
- case BuiltinType::Bool: ID = pch::PREDEF_TYPE_BOOL_ID; break;
- case BuiltinType::Char_U: ID = pch::PREDEF_TYPE_CHAR_U_ID; break;
- case BuiltinType::UChar: ID = pch::PREDEF_TYPE_UCHAR_ID; break;
- case BuiltinType::UShort: ID = pch::PREDEF_TYPE_USHORT_ID; break;
- case BuiltinType::UInt: ID = pch::PREDEF_TYPE_UINT_ID; break;
- case BuiltinType::ULong: ID = pch::PREDEF_TYPE_ULONG_ID; break;
- case BuiltinType::ULongLong: ID = pch::PREDEF_TYPE_ULONGLONG_ID; break;
- case BuiltinType::UInt128: ID = pch::PREDEF_TYPE_UINT128_ID; break;
- case BuiltinType::Char_S: ID = pch::PREDEF_TYPE_CHAR_S_ID; break;
- case BuiltinType::SChar: ID = pch::PREDEF_TYPE_SCHAR_ID; break;
- case BuiltinType::WChar: ID = pch::PREDEF_TYPE_WCHAR_ID; break;
- case BuiltinType::Short: ID = pch::PREDEF_TYPE_SHORT_ID; break;
- case BuiltinType::Int: ID = pch::PREDEF_TYPE_INT_ID; break;
- case BuiltinType::Long: ID = pch::PREDEF_TYPE_LONG_ID; break;
- case BuiltinType::LongLong: ID = pch::PREDEF_TYPE_LONGLONG_ID; break;
- case BuiltinType::Int128: ID = pch::PREDEF_TYPE_INT128_ID; break;
- case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
- case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
- case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
- case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break;
- case BuiltinType::Char16: ID = pch::PREDEF_TYPE_CHAR16_ID; break;
- case BuiltinType::Char32: ID = pch::PREDEF_TYPE_CHAR32_ID; break;
- case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
- case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
- case BuiltinType::ObjCId: ID = pch::PREDEF_TYPE_OBJC_ID; break;
- case BuiltinType::ObjCClass: ID = pch::PREDEF_TYPE_OBJC_CLASS; break;
- case BuiltinType::ObjCSel: ID = pch::PREDEF_TYPE_OBJC_SEL; break;
- case BuiltinType::UndeducedAuto:
- assert(0 && "Should not see undeduced auto here");
- break;
- }
+TypeID ASTWriter::getTypeID(QualType T) const {
+ return MakeTypeID(T,
+ std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
+}
- Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
- return;
- }
+TypeIdx ASTWriter::GetOrCreateTypeIdx(QualType T) {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
- pch::TypeID &ID = TypeIDs[T];
- if (ID == 0) {
+ TypeIdx &Idx = TypeIdxs[T];
+ if (Idx.getIndex() == 0) {
// We haven't seen this type before. Assign it a new ID and put it
// into the queue of types to emit.
- ID = NextTypeID++;
+ Idx = TypeIdx(NextTypeID++);
DeclTypesToEmit.push(T);
}
+ return Idx;
+}
+
+TypeIdx ASTWriter::getTypeIdx(QualType T) const {
+ if (T.isNull())
+ return TypeIdx();
+ assert(!T.getLocalFastQualifiers());
- // Encode the type qualifiers in the type reference.
- Record.push_back((ID << Qualifiers::FastWidth) | FastQuals);
+ TypeIdxMap::const_iterator I = TypeIdxs.find(T);
+ assert(I != TypeIdxs.end() && "Type not emitted!");
+ return I->second;
}
-void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {
+void ASTWriter::AddDeclRef(const Decl *D, RecordData &Record) {
+ Record.push_back(GetDeclRef(D));
+}
+
+DeclID ASTWriter::GetDeclRef(const Decl *D) {
if (D == 0) {
- Record.push_back(0);
- return;
+ return 0;
}
- pch::DeclID &ID = DeclIDs[D];
+ DeclID &ID = DeclIDs[D];
if (ID == 0) {
// We haven't seen this declaration before. Give it a new ID and
// enqueue it in the list of declarations to emit.
- ID = DeclIDs.size();
+ ID = NextDeclID++;
+ DeclTypesToEmit.push(const_cast<Decl *>(D));
+ } else if (ID < FirstDeclID && D->isChangedSinceDeserialization()) {
+ // We don't add it to the replacement collection here, because we don't
+ // have the offset yet.
DeclTypesToEmit.push(const_cast<Decl *>(D));
+ // Reset the flag, so that we don't add this decl multiple times.
+ const_cast<Decl *>(D)->setChangedSinceDeserialization(false);
}
- Record.push_back(ID);
+ return ID;
}
-pch::DeclID PCHWriter::getDeclID(const Decl *D) {
+DeclID ASTWriter::getDeclID(const Decl *D) {
if (D == 0)
return 0;
@@ -2554,7 +2876,7 @@ pch::DeclID PCHWriter::getDeclID(const Decl *D) {
return DeclIDs[D];
}
-void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
+void ASTWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
// FIXME: Emit a stable enum for NameKind. 0 = Identifier etc.
Record.push_back(Name.getNameKind());
switch (Name.getNameKind()) {
@@ -2588,7 +2910,7 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) {
}
}
-void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
+void ASTWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
RecordData &Record) {
// Nested name specifiers usually aren't too long. I think that 8 would
// typically accomodate the vast majority.
@@ -2627,7 +2949,7 @@ void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
}
}
-void PCHWriter::AddTemplateName(TemplateName Name, RecordData &Record) {
+void ASTWriter::AddTemplateName(TemplateName Name, RecordData &Record) {
TemplateName::NameKind Kind = Name.getKind();
Record.push_back(Kind);
switch (Kind) {
@@ -2665,7 +2987,7 @@ void PCHWriter::AddTemplateName(TemplateName Name, RecordData &Record) {
}
}
-void PCHWriter::AddTemplateArgument(const TemplateArgument &Arg,
+void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg,
RecordData &Record) {
Record.push_back(Arg.getKind());
switch (Arg.getKind()) {
@@ -2697,7 +3019,7 @@ void PCHWriter::AddTemplateArgument(const TemplateArgument &Arg,
}
void
-PCHWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams,
+ASTWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams,
RecordData &Record) {
assert(TemplateParams && "No TemplateParams!");
AddSourceLocation(TemplateParams->getTemplateLoc(), Record);
@@ -2712,7 +3034,7 @@ PCHWriter::AddTemplateParameterList(const TemplateParameterList *TemplateParams,
/// \brief Emit a template argument list.
void
-PCHWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
+ASTWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
RecordData &Record) {
assert(TemplateArgs && "No TemplateArgs!");
Record.push_back(TemplateArgs->flat_size());
@@ -2722,7 +3044,7 @@ PCHWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
void
-PCHWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) {
+ASTWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) {
Record.push_back(Set.size());
for (UnresolvedSetImpl::const_iterator
I = Set.begin(), E = Set.end(); I != E; ++I) {
@@ -2731,18 +3053,67 @@ PCHWriter::AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record) {
}
}
-void PCHWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
+void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
RecordData &Record) {
Record.push_back(Base.isVirtual());
Record.push_back(Base.isBaseOfClass());
Record.push_back(Base.getAccessSpecifierAsWritten());
- AddTypeRef(Base.getType(), Record);
+ AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
AddSourceRange(Base.getSourceRange(), Record);
}
-void PCHWriter::TypeRead(pch::TypeID ID, QualType T) {
+void ASTWriter::AddCXXBaseOrMemberInitializers(
+ const CXXBaseOrMemberInitializer * const *BaseOrMembers,
+ unsigned NumBaseOrMembers, RecordData &Record) {
+ Record.push_back(NumBaseOrMembers);
+ for (unsigned i=0; i != NumBaseOrMembers; ++i) {
+ const CXXBaseOrMemberInitializer *Init = BaseOrMembers[i];
+
+ Record.push_back(Init->isBaseInitializer());
+ if (Init->isBaseInitializer()) {
+ AddTypeSourceInfo(Init->getBaseClassInfo(), Record);
+ Record.push_back(Init->isBaseVirtual());
+ } else {
+ AddDeclRef(Init->getMember(), Record);
+ }
+ AddSourceLocation(Init->getMemberLocation(), Record);
+ AddStmt(Init->getInit());
+ AddDeclRef(Init->getAnonUnionMember(), Record);
+ AddSourceLocation(Init->getLParenLoc(), Record);
+ AddSourceLocation(Init->getRParenLoc(), Record);
+ Record.push_back(Init->isWritten());
+ if (Init->isWritten()) {
+ Record.push_back(Init->getSourceOrder());
+ } else {
+ Record.push_back(Init->getNumArrayIndices());
+ for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i)
+ AddDeclRef(Init->getArrayIndex(i), Record);
+ }
+ }
+}
+
+void ASTWriter::SetReader(ASTReader *Reader) {
+ assert(Reader && "Cannot remove chain");
+ assert(FirstDeclID == NextDeclID &&
+ FirstTypeID == NextTypeID &&
+ FirstIdentID == NextIdentID &&
+ FirstSelectorID == NextSelectorID &&
+ "Setting chain after writing has started.");
+ Chain = Reader;
}
-void PCHWriter::DeclRead(pch::DeclID ID, const Decl *D) {
+void ASTWriter::IdentifierRead(IdentID ID, IdentifierInfo *II) {
+ IdentifierIDs[II] = ID;
}
+void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {
+ TypeIdxs[T] = Idx;
+}
+
+void ASTWriter::DeclRead(DeclID ID, const Decl *D) {
+ DeclIDs[D] = ID;
+}
+
+void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
+ SelectorIDs[S] = ID;
+}
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index bc4452ed7f4d..ce39a1076b8e 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -1,4 +1,4 @@
-//===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===//
+//===--- ASTWriterDecl.cpp - Declaration Serialization --------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHWriter.h"
+#include "clang/Serialization/ASTWriter.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
@@ -26,18 +26,18 @@ using namespace clang;
//===----------------------------------------------------------------------===//
namespace clang {
- class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
+ class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> {
- PCHWriter &Writer;
+ ASTWriter &Writer;
ASTContext &Context;
- PCHWriter::RecordData &Record;
+ ASTWriter::RecordData &Record;
public:
- pch::DeclCode Code;
+ serialization::DeclCode Code;
unsigned AbbrevToUse;
- PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
- PCHWriter::RecordData &Record)
+ ASTDeclWriter(ASTWriter &Writer, ASTContext &Context,
+ ASTWriter::RecordData &Record)
: Writer(Writer), Context(Context), Record(Record) {
}
@@ -76,6 +76,7 @@ namespace clang {
void VisitParmVarDecl(ParmVarDecl *D);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
void VisitTemplateDecl(TemplateDecl *D);
+ void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@@ -91,6 +92,7 @@ namespace clang {
void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
uint64_t VisibleOffset);
+ template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
// FIXME: Put in the same order is DeclNodes.td?
@@ -112,12 +114,12 @@ namespace clang {
};
}
-void PCHDeclWriter::Visit(Decl *D) {
- DeclVisitor<PCHDeclWriter>::Visit(D);
+void ASTDeclWriter::Visit(Decl *D) {
+ DeclVisitor<ASTDeclWriter>::Visit(D);
// Handle FunctionDecl's body here and write it after all other Stmts/Exprs
// have been written. We want it last because we will not read it back when
- // retrieving it from the PCH, we'll just lazily set the offset.
+ // retrieving it from the AST, we'll just lazily set the offset.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
Record.push_back(FD->isThisDeclarationADefinition());
if (FD->isThisDeclarationADefinition())
@@ -125,7 +127,7 @@ void PCHDeclWriter::Visit(Decl *D) {
}
}
-void PCHDeclWriter::VisitDecl(Decl *D) {
+void ASTDeclWriter::VisitDecl(Decl *D) {
Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
Writer.AddSourceLocation(D->getLocation(), Record);
@@ -137,32 +139,32 @@ void PCHDeclWriter::VisitDecl(Decl *D) {
Record.push_back(D->getPCHLevel());
}
-void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
VisitDecl(D);
Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
- Code = pch::DECL_TRANSLATION_UNIT;
+ Code = serialization::DECL_TRANSLATION_UNIT;
}
-void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
+void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
VisitDecl(D);
Writer.AddDeclarationName(D->getDeclName(), Record);
}
-void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
+void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
VisitNamedDecl(D);
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
}
-void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
+void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
VisitTypeDecl(D);
Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
- Code = pch::DECL_TYPEDEF;
+ Code = serialization::DECL_TYPEDEF;
}
-void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
+void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
VisitTypeDecl(D);
Record.push_back(D->getIdentifierNamespace());
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ VisitRedeclarable(D);
Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
Record.push_back(D->isDefinition());
Record.push_back(D->isEmbeddedInDeclarator());
@@ -172,46 +174,47 @@ void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
}
-void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
+void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
VisitTagDecl(D);
Writer.AddTypeRef(D->getIntegerType(), Record);
Writer.AddTypeRef(D->getPromotionType(), Record);
Record.push_back(D->getNumPositiveBits());
Record.push_back(D->getNumNegativeBits());
Writer.AddDeclRef(D->getInstantiatedFromMemberEnum(), Record);
- Code = pch::DECL_ENUM;
+ Code = serialization::DECL_ENUM;
}
-void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
+void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
VisitTagDecl(D);
Record.push_back(D->hasFlexibleArrayMember());
Record.push_back(D->isAnonymousStructOrUnion());
Record.push_back(D->hasObjectMember());
- Code = pch::DECL_RECORD;
+ Code = serialization::DECL_RECORD;
}
-void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
+void ASTDeclWriter::VisitValueDecl(ValueDecl *D) {
VisitNamedDecl(D);
Writer.AddTypeRef(D->getType(), Record);
}
-void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
+void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
VisitValueDecl(D);
Record.push_back(D->getInitExpr()? 1 : 0);
if (D->getInitExpr())
Writer.AddStmt(D->getInitExpr());
Writer.AddAPSInt(D->getInitVal(), Record);
- Code = pch::DECL_ENUM_CONSTANT;
+ Code = serialization::DECL_ENUM_CONSTANT;
}
-void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
+void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
VisitValueDecl(D);
Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
// FIXME: write optional qualifier and its range.
}
-void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
+void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
VisitDeclaratorDecl(D);
+ // FIXME: write DeclarationNameLoc.
Record.push_back(D->getIdentifierNamespace());
Record.push_back(D->getTemplatedKind());
@@ -275,10 +278,10 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
}
}
- // FunctionDecl's body is handled last at PCHWriterDecl::Visit,
+ // FunctionDecl's body is handled last at ASTWriterDecl::Visit,
// after everything else is written.
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ VisitRedeclarable(D);
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->isInlineSpecified());
@@ -296,15 +299,17 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
- Code = pch::DECL_FUNCTION;
+ Code = serialization::DECL_FUNCTION;
}
-void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
VisitNamedDecl(D);
// FIXME: convert to LazyStmtPtr?
// Unlike C/C++, method bodies will never be in header files.
- Record.push_back(D->getBody() != 0);
- if (D->getBody() != 0) {
+ bool HasBodyStuff = D->getBody() != 0 ||
+ D->getSelfDecl() != 0 || D->getCmdDecl() != 0;
+ Record.push_back(HasBodyStuff);
+ if (HasBodyStuff) {
Writer.AddStmt(D->getBody());
Writer.AddDeclRef(D->getSelfDecl(), Record);
Writer.AddDeclRef(D->getCmdDecl(), Record);
@@ -312,6 +317,7 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Record.push_back(D->isInstanceMethod());
Record.push_back(D->isVariadic());
Record.push_back(D->isSynthesized());
+ Record.push_back(D->isDefined());
// FIXME: stable encoding for @required/@optional
Record.push_back(D->getImplementationControl());
// FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
@@ -324,20 +330,22 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
for (ObjCMethodDecl::param_iterator P = D->param_begin(),
PEnd = D->param_end(); P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
- Code = pch::DECL_OBJC_METHOD;
+ Code = serialization::DECL_OBJC_METHOD;
}
-void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceRange(D->getAtEndRange(), Record);
- // Abstract class (no need to define a stable pch::DECL code).
+ // Abstract class (no need to define a stable serialization::DECL code).
}
-void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
VisitObjCContainerDecl(D);
Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
Writer.AddDeclRef(D->getSuperClass(), Record);
- Record.push_back(D->protocol_size());
+
+ // Write out the protocols that are directly referenced by the @interface.
+ Record.push_back(D->ReferencedProtocols.size());
for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
PEnd = D->protocol_end();
P != PEnd; ++P)
@@ -346,6 +354,16 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
+
+ // Write out the protocols that are transitively referenced.
+ Record.push_back(D->AllReferencedProtocols.size());
+ for (ObjCList<ObjCProtocolDecl>::iterator
+ P = D->AllReferencedProtocols.begin(),
+ PEnd = D->AllReferencedProtocols.end();
+ P != PEnd; ++P)
+ Writer.AddDeclRef(*P, Record);
+
+ // Write out the ivars.
Record.push_back(D->ivar_size());
for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
IEnd = D->ivar_end(); I != IEnd; ++I)
@@ -356,17 +374,18 @@ void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
Writer.AddSourceLocation(D->getClassLoc(), Record);
Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
Writer.AddSourceLocation(D->getLocEnd(), Record);
- Code = pch::DECL_OBJC_INTERFACE;
+ Code = serialization::DECL_OBJC_INTERFACE;
}
-void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
+void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
VisitFieldDecl(D);
// FIXME: stable encoding for @public/@private/@protected/@package
Record.push_back(D->getAccessControl());
- Code = pch::DECL_OBJC_IVAR;
+ Record.push_back(D->getSynthesize());
+ Code = serialization::DECL_OBJC_IVAR;
}
-void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
VisitObjCContainerDecl(D);
Record.push_back(D->isForwardDecl());
Writer.AddSourceLocation(D->getLocEnd(), Record);
@@ -378,25 +397,25 @@ void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
- Code = pch::DECL_OBJC_PROTOCOL;
+ Code = serialization::DECL_OBJC_PROTOCOL;
}
-void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
+void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
VisitFieldDecl(D);
- Code = pch::DECL_OBJC_AT_DEFS_FIELD;
+ Code = serialization::DECL_OBJC_AT_DEFS_FIELD;
}
-void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
+void ASTDeclWriter::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->getInterface(), Record);
for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
Writer.AddSourceLocation(I->getLocation(), Record);
- Code = pch::DECL_OBJC_CLASS;
+ Code = serialization::DECL_OBJC_CLASS;
}
-void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+void ASTDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
VisitDecl(D);
Record.push_back(D->protocol_size());
for (ObjCForwardProtocolDecl::protocol_iterator
@@ -406,10 +425,10 @@ void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
- Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
+ Code = serialization::DECL_OBJC_FORWARD_PROTOCOL;
}
-void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
+void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
VisitObjCContainerDecl(D);
Writer.AddDeclRef(D->getClassInterface(), Record);
Record.push_back(D->protocol_size());
@@ -421,18 +440,19 @@ void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
PL != PLEnd; ++PL)
Writer.AddSourceLocation(*PL, Record);
Writer.AddDeclRef(D->getNextClassCategory(), Record);
+ Record.push_back(D->hasSynthBitfield());
Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
- Code = pch::DECL_OBJC_CATEGORY;
+ Code = serialization::DECL_OBJC_CATEGORY;
}
-void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
+void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
VisitNamedDecl(D);
Writer.AddDeclRef(D->getClassInterface(), Record);
- Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
+ Code = serialization::DECL_OBJC_COMPATIBLE_ALIAS;
}
-void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getAtLoc(), Record);
Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
@@ -446,38 +466,41 @@ void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
- Code = pch::DECL_OBJC_PROPERTY;
+ Code = serialization::DECL_OBJC_PROPERTY;
}
-void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
+void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
VisitObjCContainerDecl(D);
Writer.AddDeclRef(D->getClassInterface(), Record);
- // Abstract class (no need to define a stable pch::DECL code).
+ // Abstract class (no need to define a stable serialization::DECL code).
}
-void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
VisitObjCImplDecl(D);
Writer.AddIdentifierRef(D->getIdentifier(), Record);
- Code = pch::DECL_OBJC_CATEGORY_IMPL;
+ Code = serialization::DECL_OBJC_CATEGORY_IMPL;
}
-void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
VisitObjCImplDecl(D);
Writer.AddDeclRef(D->getSuperClass(), Record);
- // FIXME add writing of IvarInitializers and NumIvarInitializers.
- Code = pch::DECL_OBJC_IMPLEMENTATION;
+ Writer.AddCXXBaseOrMemberInitializers(D->IvarInitializers,
+ D->NumIvarInitializers, Record);
+ Record.push_back(D->hasSynthBitfield());
+ Code = serialization::DECL_OBJC_IMPLEMENTATION;
}
-void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
VisitDecl(D);
Writer.AddSourceLocation(D->getLocStart(), Record);
Writer.AddDeclRef(D->getPropertyDecl(), Record);
Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
- // FIXME. write GetterCXXConstructor and SetterCXXAssignment.
- Code = pch::DECL_OBJC_PROPERTY_IMPL;
+ Writer.AddStmt(D->getGetterCXXConstructor());
+ Writer.AddStmt(D->getSetterCXXAssignment());
+ Code = serialization::DECL_OBJC_PROPERTY_IMPL;
}
-void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
+void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
VisitDeclaratorDecl(D);
Record.push_back(D->isMutable());
Record.push_back(D->getBitWidth()? 1 : 0);
@@ -485,19 +508,18 @@ void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
Writer.AddStmt(D->getBitWidth());
if (!D->getDeclName())
Writer.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D), Record);
- Code = pch::DECL_FIELD;
+ Code = serialization::DECL_FIELD;
}
-void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
+void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VisitDeclaratorDecl(D);
Record.push_back(D->getStorageClass()); // FIXME: stable encoding
Record.push_back(D->getStorageClassAsWritten());
Record.push_back(D->isThreadSpecified());
Record.push_back(D->hasCXXDirectInitializer());
- Record.push_back(D->isDeclaredInCondition());
Record.push_back(D->isExceptionVariable());
Record.push_back(D->isNRVOVariable());
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+ VisitRedeclarable(D);
Record.push_back(D->getInit() ? 1 : 0);
if (D->getInit())
Writer.AddStmt(D->getInit());
@@ -511,22 +533,22 @@ void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record);
}
- Code = pch::DECL_VAR;
+ Code = serialization::DECL_VAR;
}
-void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
+void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
VisitVarDecl(D);
- Code = pch::DECL_IMPLICIT_PARAM;
+ Code = serialization::DECL_IMPLICIT_PARAM;
}
-void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
+void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
VisitVarDecl(D);
Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
Record.push_back(D->hasInheritedDefaultArg());
Record.push_back(D->hasUninstantiatedDefaultArg());
if (D->hasUninstantiatedDefaultArg())
Writer.AddStmt(D->getUninstantiatedDefaultArg());
- Code = pch::DECL_PARM_VAR;
+ Code = serialization::DECL_PARM_VAR;
// If the assumptions about the DECL_PARM_VAR abbrev are true, use it. Here
// we dynamically check for the properties that we optimize for, but don't
@@ -550,20 +572,19 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
- assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition");
assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
assert(!D->isStaticDataMember() &&
"PARM_VAR_DECL can't be static data member");
}
-void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
+void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getAsmString());
- Code = pch::DECL_FILE_SCOPE_ASM;
+ Code = serialization::DECL_FILE_SCOPE_ASM;
}
-void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
+void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getBody());
Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record);
@@ -571,19 +592,19 @@ void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P)
Writer.AddDeclRef(*P, Record);
- Code = pch::DECL_BLOCK;
+ Code = serialization::DECL_BLOCK;
}
-void PCHDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
VisitDecl(D);
// FIXME: It might be nice to serialize the brace locations for this
// declaration, which don't seem to be readily available in the AST.
Record.push_back(D->getLanguage());
Record.push_back(D->hasBraces());
- Code = pch::DECL_LINKAGE_SPEC;
+ Code = serialization::DECL_LINKAGE_SPEC;
}
-void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
+void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceLocation(D->getLBracLoc(), Record);
Writer.AddSourceLocation(D->getRBracLoc(), Record);
@@ -595,20 +616,25 @@ void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
else
Writer.AddDeclRef(D->getOriginalNamespace(), Record);
- Code = pch::DECL_NAMESPACE;
+ Code = serialization::DECL_NAMESPACE;
+
+ if (Writer.hasChain() && !D->isOriginalNamespace() &&
+ D->getOriginalNamespace()->getPCHLevel() > 0) {
+ Writer.AddUpdatedNamespace(D->getOriginalNamespace());
+ }
}
-void PCHDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
VisitNamedDecl(D);
- Writer.AddSourceLocation(D->getAliasLoc(), Record);
+ Writer.AddSourceLocation(D->getNamespaceLoc(), Record);
Writer.AddSourceRange(D->getQualifierRange(), Record);
Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
Writer.AddDeclRef(D->getNamespace(), Record);
- Code = pch::DECL_NAMESPACE_ALIAS;
+ Code = serialization::DECL_NAMESPACE_ALIAS;
}
-void PCHDeclWriter::VisitUsingDecl(UsingDecl *D) {
+void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
VisitNamedDecl(D);
Writer.AddSourceRange(D->getNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLocation(), Record);
@@ -619,48 +645,48 @@ void PCHDeclWriter::VisitUsingDecl(UsingDecl *D) {
Writer.AddDeclRef(*P, Record);
Record.push_back(D->isTypeName());
Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record);
- Code = pch::DECL_USING;
+ Code = serialization::DECL_USING;
}
-void PCHDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
VisitNamedDecl(D);
Writer.AddDeclRef(D->getTargetDecl(), Record);
Writer.AddDeclRef(D->getUsingDecl(), Record);
Writer.AddDeclRef(Context.getInstantiatedFromUsingShadowDecl(D), Record);
- Code = pch::DECL_USING_SHADOW;
+ Code = serialization::DECL_USING_SHADOW;
}
-void PCHDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
VisitNamedDecl(D);
+ Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
Writer.AddSourceRange(D->getQualifierRange(), Record);
Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
- Writer.AddSourceLocation(D->getIdentLocation(), Record);
Writer.AddDeclRef(D->getNominatedNamespace(), Record);
Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
- Code = pch::DECL_USING_DIRECTIVE;
+ Code = serialization::DECL_USING_DIRECTIVE;
}
-void PCHDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
VisitValueDecl(D);
Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
- Code = pch::DECL_UNRESOLVED_USING_VALUE;
+ Code = serialization::DECL_UNRESOLVED_USING_VALUE;
}
-void PCHDeclWriter::VisitUnresolvedUsingTypenameDecl(
+void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
UnresolvedUsingTypenameDecl *D) {
VisitTypeDecl(D);
Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
Writer.AddSourceLocation(D->getUsingLoc(), Record);
Writer.AddSourceLocation(D->getTypenameLoc(), Record);
Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
- Code = pch::DECL_UNRESOLVED_USING_TYPENAME;
+ Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
}
-void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
- // See comments at PCHDeclReader::VisitCXXRecordDecl about why this happens
+void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ // See comments at ASTDeclReader::VisitCXXRecordDecl about why this happens
// before VisitRecordDecl.
enum { Data_NoDefData, Data_Owner, Data_NotOwner };
bool OwnsDefinitionData = false;
@@ -735,76 +761,52 @@ void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
Record.push_back(CXXRecNotTemplate);
}
- Code = pch::DECL_CXX_RECORD;
+ Code = serialization::DECL_CXX_RECORD;
}
-void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
+void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
VisitFunctionDecl(D);
Record.push_back(D->size_overridden_methods());
for (CXXMethodDecl::method_iterator
I = D->begin_overridden_methods(), E = D->end_overridden_methods();
I != E; ++I)
Writer.AddDeclRef(*I, Record);
- Code = pch::DECL_CXX_METHOD;
+ Code = serialization::DECL_CXX_METHOD;
}
-void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
VisitCXXMethodDecl(D);
Record.push_back(D->IsExplicitSpecified);
Record.push_back(D->ImplicitlyDefined);
-
- Record.push_back(D->NumBaseOrMemberInitializers);
- for (unsigned i=0; i != D->NumBaseOrMemberInitializers; ++i) {
- CXXBaseOrMemberInitializer *Init = D->BaseOrMemberInitializers[i];
-
- Record.push_back(Init->isBaseInitializer());
- if (Init->isBaseInitializer()) {
- Writer.AddTypeSourceInfo(Init->getBaseClassInfo(), Record);
- Record.push_back(Init->isBaseVirtual());
- } else {
- Writer.AddDeclRef(Init->getMember(), Record);
- }
- Writer.AddSourceLocation(Init->getMemberLocation(), Record);
- Writer.AddStmt(Init->getInit());
- Writer.AddDeclRef(Init->getAnonUnionMember(), Record);
- Writer.AddSourceLocation(Init->getLParenLoc(), Record);
- Writer.AddSourceLocation(Init->getRParenLoc(), Record);
- Record.push_back(Init->isWritten());
- if (Init->isWritten()) {
- Record.push_back(Init->getSourceOrder());
- } else {
- Record.push_back(Init->getNumArrayIndices());
- for (unsigned i=0, e=Init->getNumArrayIndices(); i != e; ++i)
- Writer.AddDeclRef(Init->getArrayIndex(i), Record);
- }
- }
+ Writer.AddCXXBaseOrMemberInitializers(D->BaseOrMemberInitializers,
+ D->NumBaseOrMemberInitializers, Record);
- Code = pch::DECL_CXX_CONSTRUCTOR;
+ Code = serialization::DECL_CXX_CONSTRUCTOR;
}
-void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
VisitCXXMethodDecl(D);
Record.push_back(D->ImplicitlyDefined);
Writer.AddDeclRef(D->OperatorDelete, Record);
- Code = pch::DECL_CXX_DESTRUCTOR;
+ Code = serialization::DECL_CXX_DESTRUCTOR;
}
-void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
+void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
VisitCXXMethodDecl(D);
Record.push_back(D->IsExplicitSpecified);
- Code = pch::DECL_CXX_CONVERSION;
+ Code = serialization::DECL_CXX_CONVERSION;
}
-void PCHDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
+void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
VisitDecl(D);
Writer.AddSourceLocation(D->getColonLoc(), Record);
- Code = pch::DECL_ACCESS_SPEC;
+ Code = serialization::DECL_ACCESS_SPEC;
}
-void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) {
+void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) {
VisitDecl(D);
Record.push_back(D->Friend.is<TypeSourceInfo*>());
if (D->Friend.is<TypeSourceInfo*>())
@@ -813,38 +815,68 @@ void PCHDeclWriter::VisitFriendDecl(FriendDecl *D) {
Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record);
Writer.AddDeclRef(D->NextFriend, Record);
Writer.AddSourceLocation(D->FriendLoc, Record);
- Code = pch::DECL_FRIEND;
+ Code = serialization::DECL_FRIEND;
}
-void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
- assert(false && "cannot write FriendTemplateDecl");
+void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+ VisitDecl(D);
+ Record.push_back(D->getNumTemplateParameters());
+ for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i)
+ Writer.AddTemplateParameterList(D->getTemplateParameterList(i), Record);
+ Record.push_back(D->getFriendDecl() != 0);
+ if (D->getFriendDecl())
+ Writer.AddDeclRef(D->getFriendDecl(), Record);
+ else
+ Writer.AddTypeSourceInfo(D->getFriendType(), Record);
+ Writer.AddSourceLocation(D->getFriendLoc(), Record);
+ Code = serialization::DECL_FRIEND_TEMPLATE;
}
-void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
+void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
VisitNamedDecl(D);
Writer.AddDeclRef(D->getTemplatedDecl(), Record);
Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
}
-static bool IsKeptInFoldingSet(ClassTemplateSpecializationDecl *D) {
- return D->getTypeForDecl()->getAsCXXRecordDecl() == D;
-}
-
-void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace());
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
if (D->getPreviousDeclaration() == 0) {
- // This ClassTemplateDecl owns the CommonPtr; write it.
+ // This TemplateDecl owns the CommonPtr; write it.
assert(D->isCanonicalDecl());
+ Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
+ if (D->getInstantiatedFromMemberTemplate())
+ Record.push_back(D->isMemberSpecialization());
+
+ Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
+ } else {
+ RedeclarableTemplateDecl *First = D->getFirstDeclaration();
+ assert(First != D);
+ // If this is a most recent redeclaration that is pointed to by a first decl
+ // in a chained PCH, keep track of the association with the map so we can
+ // update the first decl during AST reading.
+ if (First->getMostRecentDeclaration() == D &&
+ First->getPCHLevel() > D->getPCHLevel()) {
+ assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
+ && "The latest is already set");
+ Writer.FirstLatestDecls[First] = D;
+ }
+ }
+}
+
+void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
+
+ if (D->getPreviousDeclaration() == 0) {
typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
CTSDSetTy &CTSDSet = D->getSpecializations();
Record.push_back(CTSDSet.size());
for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) {
- assert(IsKeptInFoldingSet(&*I));
+ assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
Writer.AddDeclRef(&*I, Record);
}
@@ -852,33 +884,37 @@ void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
CTPSDSetTy &CTPSDSet = D->getPartialSpecializations();
Record.push_back(CTPSDSet.size());
for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) {
- assert(IsKeptInFoldingSet(&*I));
+ assert(I->isCanonicalDecl() && "Expected only canonical decls in set");
Writer.AddDeclRef(&*I, Record);
}
// InjectedClassNameType is computed, no need to write it.
-
- Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
- if (D->getInstantiatedFromMemberTemplate())
- Record.push_back(D->isMemberSpecialization());
}
- Code = pch::DECL_CLASS_TEMPLATE;
+ Code = serialization::DECL_CLASS_TEMPLATE;
}
-void PCHDeclWriter::VisitClassTemplateSpecializationDecl(
+void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
ClassTemplateSpecializationDecl *D) {
VisitCXXRecordDecl(D);
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *> InstFrom
= D->getSpecializedTemplateOrPartial();
+ Decl *InstFromD;
if (InstFrom.is<ClassTemplateDecl *>()) {
- Writer.AddDeclRef(InstFrom.get<ClassTemplateDecl *>(), Record);
+ InstFromD = InstFrom.get<ClassTemplateDecl *>();
+ Writer.AddDeclRef(InstFromD, Record);
} else {
- Writer.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>(),
- Record);
+ InstFromD = InstFrom.get<ClassTemplatePartialSpecializationDecl *>();
+ Writer.AddDeclRef(InstFromD, Record);
Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record);
+ InstFromD = cast<ClassTemplatePartialSpecializationDecl>(InstFromD)->
+ getSpecializedTemplate();
}
+ // Is this a specialization of an already-serialized template?
+ if (InstFromD->getCanonicalDecl()->getPCHLevel() != 0)
+ Writer.AddAdditionalTemplateSpecialization(Writer.getDeclID(InstFromD),
+ Writer.getDeclID(D));
// Explicit info.
Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record);
@@ -891,17 +927,15 @@ void PCHDeclWriter::VisitClassTemplateSpecializationDecl(
Writer.AddSourceLocation(D->getPointOfInstantiation(), Record);
Record.push_back(D->getSpecializationKind());
- bool IsInInFoldingSet = IsKeptInFoldingSet(D);
- Record.push_back(IsInInFoldingSet);
- if (IsInInFoldingSet) {
- // When reading, we'll add it to the folding set of this one.
+ if (D->isCanonicalDecl()) {
+ // When reading, we'll add it to the folding set of the following template.
Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record);
}
- Code = pch::DECL_CLASS_TEMPLATE_SPECIALIZATION;
+ Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION;
}
-void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl(
+void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) {
VisitClassTemplateSpecializationDecl(D);
@@ -919,14 +953,12 @@ void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl(
Record.push_back(D->isMemberSpecialization());
}
- Code = pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
+ Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
}
-void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
- VisitTemplateDecl(D);
+void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitRedeclarableTemplateDecl(D);
- Record.push_back(D->getIdentifierNamespace());
- Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
if (D->getPreviousDeclaration() == 0) {
// This FunctionTemplateDecl owns the CommonPtr; write it.
@@ -934,17 +966,16 @@ void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
Record.push_back(D->getSpecializations().size());
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
I = D->getSpecializations().begin(),
- E = D->getSpecializations().end() ; I != E; ++I)
+ E = D->getSpecializations().end() ; I != E; ++I) {
+ assert(I->Function->isCanonicalDecl() &&
+ "Expected only canonical decls in set");
Writer.AddDeclRef(I->Function, Record);
-
- Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
- if (D->getInstantiatedFromMemberTemplate())
- Record.push_back(D->isMemberSpecialization());
+ }
}
- Code = pch::DECL_FUNCTION_TEMPLATE;
+ Code = serialization::DECL_FUNCTION_TEMPLATE;
}
-void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
VisitTypeDecl(D);
Record.push_back(D->wasDeclaredWithTypename());
@@ -952,10 +983,10 @@ void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
Record.push_back(D->defaultArgumentWasInherited());
Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
- Code = pch::DECL_TEMPLATE_TYPE_PARM;
+ Code = serialization::DECL_TEMPLATE_TYPE_PARM;
}
-void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
VisitVarDecl(D);
// TemplateParmPosition.
Record.push_back(D->getDepth());
@@ -966,10 +997,10 @@ void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
Writer.AddStmt(D->getDefaultArgument());
Record.push_back(D->defaultArgumentWasInherited());
}
- Code = pch::DECL_NON_TYPE_TEMPLATE_PARM;
+ Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
}
-void PCHDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
VisitTemplateDecl(D);
// TemplateParmPosition.
Record.push_back(D->getDepth());
@@ -977,11 +1008,14 @@ void PCHDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
// Rest of TemplateTemplateParmDecl.
Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record);
Record.push_back(D->defaultArgumentWasInherited());
- Code = pch::DECL_TEMPLATE_TEMPLATE_PARM;
+ Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM;
}
-void PCHDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
- assert(false && "cannot write StaticAssertDecl");
+void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+ VisitDecl(D);
+ Writer.AddStmt(D->getAssertExpr());
+ Writer.AddStmt(D->getMessage());
+ Code = serialization::DECL_STATIC_ASSERT;
}
/// \brief Emit the DeclContext part of a declaration context decl.
@@ -995,22 +1029,45 @@ void PCHDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
/// that there are no declarations visible from this context. Note
/// that this value will not be emitted for non-primary declaration
/// contexts.
-void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
+void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
uint64_t VisibleOffset) {
Record.push_back(LexicalOffset);
Record.push_back(VisibleOffset);
}
+template <typename T>
+void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
+ enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+ if (D->RedeclLink.getNext() == D) {
+ Record.push_back(NoRedeclaration);
+ } else {
+ Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious
+ : PointsToLatest);
+ Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
+ }
+
+ T *First = D->getFirstDeclaration();
+ T *ThisDecl = static_cast<T*>(D);
+ // If this is a most recent redeclaration that is pointed to by a first decl
+ // in a chained PCH, keep track of the association with the map so we can
+ // update the first decl during AST reading.
+ if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
+ First->getPCHLevel() > ThisDecl->getPCHLevel()) {
+ assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
+ && "The latest is already set");
+ Writer.FirstLatestDecls[First] = ThisDecl;
+ }
+}
//===----------------------------------------------------------------------===//
-// PCHWriter Implementation
+// ASTWriter Implementation
//===----------------------------------------------------------------------===//
-void PCHWriter::WriteDeclsBlockAbbrevs() {
+void ASTWriter::WriteDeclsBlockAbbrevs() {
using namespace llvm;
// Abbreviation for DECL_PARM_VAR.
BitCodeAbbrev *Abv = new BitCodeAbbrev();
- Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR));
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR));
// Decl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
@@ -1029,13 +1086,12 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
// ValueDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
// DeclaratorDecl
- Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType
+ Abv->Add(BitCodeAbbrevOp(serialization::PREDEF_TYPE_NULL_ID)); // InfoType
// VarDecl
Abv->Add(BitCodeAbbrevOp(0)); // StorageClass
Abv->Add(BitCodeAbbrevOp(0)); // StorageClassAsWritten
Abv->Add(BitCodeAbbrevOp(0)); // isThreadSpecified
Abv->Add(BitCodeAbbrevOp(0)); // hasCXXDirectInitializer
- Abv->Add(BitCodeAbbrevOp(0)); // isDeclaredInCondition
Abv->Add(BitCodeAbbrevOp(0)); // isExceptionVariable
Abv->Add(BitCodeAbbrevOp(0)); // isNRVOVariable
Abv->Add(BitCodeAbbrevOp(0)); // PrevDecl
@@ -1047,12 +1103,23 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg
ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
+
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ DeclContextLexicalAbbrev = Stream.EmitAbbrev(Abv);
+
+ Abv = new BitCodeAbbrev();
+ Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
+ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(Abv);
}
/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
/// consumers of the AST.
///
-/// Such decls will always be deserialized from the PCH file, so we would like
+/// Such decls will always be deserialized from the AST file, so we would like
/// this to be as restrictive as possible. Currently the predicate is driven by
/// code generation requirements, if other clients have a different notion of
/// what is "required" then we may have to consider an alternate scheme where
@@ -1061,60 +1128,17 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {
/// clients to use a separate API call to "realize" the decl. This should be
/// relatively painless since they would presumably only do it for top-level
/// decls.
-//
-// FIXME: This predicate is essentially IRgen's predicate to determine whether a
-// declaration can be deferred. Merge them somehow.
static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
- // File scoped assembly must be seen.
- if (isa<FileScopeAsmDecl>(D))
+ // File scoped assembly or obj-c implementation must be seen.
+ if (isa<FileScopeAsmDecl>(D) || isa<ObjCImplementationDecl>(D))
return true;
- // Otherwise if this isn't a function or a file scoped variable it doesn't
- // need to be seen.
- if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- if (!VD->isFileVarDecl())
- return false;
- } else if (!isa<FunctionDecl>(D))
- return false;
-
- // Aliases and used decls must be seen.
- if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
- return true;
-
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // Forward declarations don't need to be seen.
- if (!FD->isThisDeclarationADefinition())
- return false;
-
- // Constructors and destructors must be seen.
- if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
- return true;
-
- // Otherwise, this is required unless it is static.
- //
- // FIXME: Inlines.
- return FD->getStorageClass() != FunctionDecl::Static;
- } else {
- const VarDecl *VD = cast<VarDecl>(D);
-
- // In C++, this doesn't need to be seen if it is marked "extern".
- if (Context.getLangOptions().CPlusPlus && !VD->getInit() &&
- (VD->getStorageClass() == VarDecl::Extern ||
- VD->isExternC()))
- return false;
-
- // In C, this doesn't need to be seen unless it is a definition.
- if (!Context.getLangOptions().CPlusPlus && !VD->getInit())
- return false;
-
- // Otherwise, this is required unless it is static.
- return VD->getStorageClass() != VarDecl::Static;
- }
+ return Context.DeclMustBeEmitted(D);
}
-void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
+void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
RecordData Record;
- PCHDeclWriter W(*this, Context, Record);
+ ASTDeclWriter W(*this, Context, Record);
// If this declaration is also a DeclContext, write blocks for the
// declarations that lexically stored inside its context and those
@@ -1130,23 +1154,29 @@ void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
}
// Determine the ID for this declaration
- pch::DeclID &ID = DeclIDs[D];
- if (ID == 0)
- ID = DeclIDs.size();
-
- unsigned Index = ID - 1;
-
- // Record the offset for this declaration
- if (DeclOffsets.size() == Index)
- DeclOffsets.push_back(Stream.GetCurrentBitNo());
- else if (DeclOffsets.size() < Index) {
- DeclOffsets.resize(Index+1);
- DeclOffsets[Index] = Stream.GetCurrentBitNo();
+ serialization::DeclID &IDR = DeclIDs[D];
+ if (IDR == 0)
+ IDR = NextDeclID++;
+ serialization::DeclID ID = IDR;
+
+ if (ID < FirstDeclID) {
+ // We're replacing a decl in a previous file.
+ ReplacedDecls.push_back(std::make_pair(ID, Stream.GetCurrentBitNo()));
+ } else {
+ unsigned Index = ID - FirstDeclID;
+
+ // Record the offset for this declaration
+ if (DeclOffsets.size() == Index)
+ DeclOffsets.push_back(Stream.GetCurrentBitNo());
+ else if (DeclOffsets.size() < Index) {
+ DeclOffsets.resize(Index+1);
+ DeclOffsets[Index] = Stream.GetCurrentBitNo();
+ }
}
// Build and emit a record for this declaration
Record.clear();
- W.Code = (pch::DeclCode)0;
+ W.Code = (serialization::DeclCode)0;
W.AbbrevToUse = 0;
W.Visit(D);
if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
@@ -1164,9 +1194,9 @@ void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
FlushStmts();
// Note "external" declarations so that we can add them to a record in the
- // PCH file later.
+ // AST file later.
//
// FIXME: This should be renamed, the predicate is much more complicated.
if (isRequiredDecl(D, Context))
- ExternalDefinitions.push_back(Index + 1);
+ ExternalDefinitions.push_back(ID);
}
diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 75377286e5aa..7f2da6c225a3 100644
--- a/lib/Frontend/PCHWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -1,4 +1,4 @@
-//===--- PCHWriterStmt.cpp - Statement and Expression Serialization -------===//
+//===--- ASTWriterStmt.cpp - Statement and Expression Serialization -------===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Frontend/PCHWriter.h"
+#include "clang/Serialization/ASTWriter.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtVisitor.h"
@@ -23,14 +23,14 @@ using namespace clang;
//===----------------------------------------------------------------------===//
namespace clang {
- class PCHStmtWriter : public StmtVisitor<PCHStmtWriter, void> {
- PCHWriter &Writer;
- PCHWriter::RecordData &Record;
+ class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> {
+ ASTWriter &Writer;
+ ASTWriter::RecordData &Record;
public:
- pch::StmtCode Code;
+ serialization::StmtCode Code;
- PCHStmtWriter(PCHWriter &Writer, PCHWriter::RecordData &Record)
+ ASTStmtWriter(ASTWriter &Writer, ASTWriter::RecordData &Record)
: Writer(Writer), Record(Record) { }
void
@@ -115,6 +115,9 @@ namespace clang {
void VisitObjCAtThrowStmt(ObjCAtThrowStmt *);
// C++ Statements
+ void VisitCXXCatchStmt(CXXCatchStmt *S);
+ void VisitCXXTryStmt(CXXTryStmt *S);
+
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
void VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
void VisitCXXConstructExpr(CXXConstructExpr *E);
@@ -132,7 +135,6 @@ namespace clang {
void VisitCXXThrowExpr(CXXThrowExpr *E);
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E);
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);
- void VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E);
void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E);
void VisitCXXNewExpr(CXXNewExpr *E);
@@ -152,7 +154,7 @@ namespace clang {
};
}
-void PCHStmtWriter::
+void ASTStmtWriter::
AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) {
Writer.AddSourceLocation(Args.LAngleLoc, Record);
Writer.AddSourceLocation(Args.RAngleLoc, Record);
@@ -160,16 +162,16 @@ AddExplicitTemplateArgumentList(const ExplicitTemplateArgumentList &Args) {
Writer.AddTemplateArgumentLoc(Args.getTemplateArgs()[i], Record);
}
-void PCHStmtWriter::VisitStmt(Stmt *S) {
+void ASTStmtWriter::VisitStmt(Stmt *S) {
}
-void PCHStmtWriter::VisitNullStmt(NullStmt *S) {
+void ASTStmtWriter::VisitNullStmt(NullStmt *S) {
VisitStmt(S);
Writer.AddSourceLocation(S->getSemiLoc(), Record);
- Code = pch::STMT_NULL;
+ Code = serialization::STMT_NULL;
}
-void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
+void ASTStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
VisitStmt(S);
Record.push_back(S->size());
for (CompoundStmt::body_iterator CS = S->body_begin(), CSEnd = S->body_end();
@@ -177,15 +179,15 @@ void PCHStmtWriter::VisitCompoundStmt(CompoundStmt *S) {
Writer.AddStmt(*CS);
Writer.AddSourceLocation(S->getLBracLoc(), Record);
Writer.AddSourceLocation(S->getRBracLoc(), Record);
- Code = pch::STMT_COMPOUND;
+ Code = serialization::STMT_COMPOUND;
}
-void PCHStmtWriter::VisitSwitchCase(SwitchCase *S) {
+void ASTStmtWriter::VisitSwitchCase(SwitchCase *S) {
VisitStmt(S);
Record.push_back(Writer.getSwitchCaseID(S));
}
-void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
+void ASTStmtWriter::VisitCaseStmt(CaseStmt *S) {
VisitSwitchCase(S);
Writer.AddStmt(S->getLHS());
Writer.AddStmt(S->getRHS());
@@ -193,27 +195,27 @@ void PCHStmtWriter::VisitCaseStmt(CaseStmt *S) {
Writer.AddSourceLocation(S->getCaseLoc(), Record);
Writer.AddSourceLocation(S->getEllipsisLoc(), Record);
Writer.AddSourceLocation(S->getColonLoc(), Record);
- Code = pch::STMT_CASE;
+ Code = serialization::STMT_CASE;
}
-void PCHStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
+void ASTStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
VisitSwitchCase(S);
Writer.AddStmt(S->getSubStmt());
Writer.AddSourceLocation(S->getDefaultLoc(), Record);
Writer.AddSourceLocation(S->getColonLoc(), Record);
- Code = pch::STMT_DEFAULT;
+ Code = serialization::STMT_DEFAULT;
}
-void PCHStmtWriter::VisitLabelStmt(LabelStmt *S) {
+void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
VisitStmt(S);
Writer.AddIdentifierRef(S->getID(), Record);
Writer.AddStmt(S->getSubStmt());
Writer.AddSourceLocation(S->getIdentLoc(), Record);
Record.push_back(Writer.GetLabelID(S));
- Code = pch::STMT_LABEL;
+ Code = serialization::STMT_LABEL;
}
-void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
+void ASTStmtWriter::VisitIfStmt(IfStmt *S) {
VisitStmt(S);
Writer.AddDeclRef(S->getConditionVariable(), Record);
Writer.AddStmt(S->getCond());
@@ -221,10 +223,10 @@ void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
Writer.AddStmt(S->getElse());
Writer.AddSourceLocation(S->getIfLoc(), Record);
Writer.AddSourceLocation(S->getElseLoc(), Record);
- Code = pch::STMT_IF;
+ Code = serialization::STMT_IF;
}
-void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
+void ASTStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
Writer.AddDeclRef(S->getConditionVariable(), Record);
Writer.AddStmt(S->getCond());
@@ -233,29 +235,29 @@ void PCHStmtWriter::VisitSwitchStmt(SwitchStmt *S) {
for (SwitchCase *SC = S->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase())
Record.push_back(Writer.RecordSwitchCaseID(SC));
- Code = pch::STMT_SWITCH;
+ Code = serialization::STMT_SWITCH;
}
-void PCHStmtWriter::VisitWhileStmt(WhileStmt *S) {
+void ASTStmtWriter::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S);
Writer.AddDeclRef(S->getConditionVariable(), Record);
Writer.AddStmt(S->getCond());
Writer.AddStmt(S->getBody());
Writer.AddSourceLocation(S->getWhileLoc(), Record);
- Code = pch::STMT_WHILE;
+ Code = serialization::STMT_WHILE;
}
-void PCHStmtWriter::VisitDoStmt(DoStmt *S) {
+void ASTStmtWriter::VisitDoStmt(DoStmt *S) {
VisitStmt(S);
Writer.AddStmt(S->getCond());
Writer.AddStmt(S->getBody());
Writer.AddSourceLocation(S->getDoLoc(), Record);
Writer.AddSourceLocation(S->getWhileLoc(), Record);
Writer.AddSourceLocation(S->getRParenLoc(), Record);
- Code = pch::STMT_DO;
+ Code = serialization::STMT_DO;
}
-void PCHStmtWriter::VisitForStmt(ForStmt *S) {
+void ASTStmtWriter::VisitForStmt(ForStmt *S) {
VisitStmt(S);
Writer.AddStmt(S->getInit());
Writer.AddStmt(S->getCond());
@@ -265,56 +267,56 @@ void PCHStmtWriter::VisitForStmt(ForStmt *S) {
Writer.AddSourceLocation(S->getForLoc(), Record);
Writer.AddSourceLocation(S->getLParenLoc(), Record);
Writer.AddSourceLocation(S->getRParenLoc(), Record);
- Code = pch::STMT_FOR;
+ Code = serialization::STMT_FOR;
}
-void PCHStmtWriter::VisitGotoStmt(GotoStmt *S) {
+void ASTStmtWriter::VisitGotoStmt(GotoStmt *S) {
VisitStmt(S);
Record.push_back(Writer.GetLabelID(S->getLabel()));
Writer.AddSourceLocation(S->getGotoLoc(), Record);
Writer.AddSourceLocation(S->getLabelLoc(), Record);
- Code = pch::STMT_GOTO;
+ Code = serialization::STMT_GOTO;
}
-void PCHStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
+void ASTStmtWriter::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
VisitStmt(S);
Writer.AddSourceLocation(S->getGotoLoc(), Record);
Writer.AddSourceLocation(S->getStarLoc(), Record);
Writer.AddStmt(S->getTarget());
- Code = pch::STMT_INDIRECT_GOTO;
+ Code = serialization::STMT_INDIRECT_GOTO;
}
-void PCHStmtWriter::VisitContinueStmt(ContinueStmt *S) {
+void ASTStmtWriter::VisitContinueStmt(ContinueStmt *S) {
VisitStmt(S);
Writer.AddSourceLocation(S->getContinueLoc(), Record);
- Code = pch::STMT_CONTINUE;
+ Code = serialization::STMT_CONTINUE;
}
-void PCHStmtWriter::VisitBreakStmt(BreakStmt *S) {
+void ASTStmtWriter::VisitBreakStmt(BreakStmt *S) {
VisitStmt(S);
Writer.AddSourceLocation(S->getBreakLoc(), Record);
- Code = pch::STMT_BREAK;
+ Code = serialization::STMT_BREAK;
}
-void PCHStmtWriter::VisitReturnStmt(ReturnStmt *S) {
+void ASTStmtWriter::VisitReturnStmt(ReturnStmt *S) {
VisitStmt(S);
Writer.AddStmt(S->getRetValue());
Writer.AddSourceLocation(S->getReturnLoc(), Record);
Writer.AddDeclRef(S->getNRVOCandidate(), Record);
- Code = pch::STMT_RETURN;
+ Code = serialization::STMT_RETURN;
}
-void PCHStmtWriter::VisitDeclStmt(DeclStmt *S) {
+void ASTStmtWriter::VisitDeclStmt(DeclStmt *S) {
VisitStmt(S);
Writer.AddSourceLocation(S->getStartLoc(), Record);
Writer.AddSourceLocation(S->getEndLoc(), Record);
DeclGroupRef DG = S->getDeclGroup();
for (DeclGroupRef::iterator D = DG.begin(), DEnd = DG.end(); D != DEnd; ++D)
Writer.AddDeclRef(*D, Record);
- Code = pch::STMT_DECL;
+ Code = serialization::STMT_DECL;
}
-void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) {
+void ASTStmtWriter::VisitAsmStmt(AsmStmt *S) {
VisitStmt(S);
Record.push_back(S->getNumOutputs());
Record.push_back(S->getNumInputs());
@@ -344,29 +346,29 @@ void PCHStmtWriter::VisitAsmStmt(AsmStmt *S) {
for (unsigned I = 0, N = S->getNumClobbers(); I != N; ++I)
Writer.AddStmt(S->getClobber(I));
- Code = pch::STMT_ASM;
+ Code = serialization::STMT_ASM;
}
-void PCHStmtWriter::VisitExpr(Expr *E) {
+void ASTStmtWriter::VisitExpr(Expr *E) {
VisitStmt(E);
Writer.AddTypeRef(E->getType(), Record);
Record.push_back(E->isTypeDependent());
Record.push_back(E->isValueDependent());
}
-void PCHStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
+void ASTStmtWriter::VisitPredefinedExpr(PredefinedExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->getIdentType()); // FIXME: stable encoding
- Code = pch::EXPR_PREDEFINED;
+ Code = serialization::EXPR_PREDEFINED;
}
-void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
+void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
Record.push_back(E->hasQualifier());
unsigned NumTemplateArgs = E->getNumTemplateArgs();
- assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() &&
+ assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Template args list with no args ?");
Record.push_back(NumTemplateArgs);
@@ -376,35 +378,36 @@ void PCHStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
}
if (NumTemplateArgs)
- AddExplicitTemplateArgumentList(*E->getExplicitTemplateArgumentList());
+ AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs());
Writer.AddDeclRef(E->getDecl(), Record);
+ // FIXME: write DeclarationNameLoc.
Writer.AddSourceLocation(E->getLocation(), Record);
- Code = pch::EXPR_DECL_REF;
+ Code = serialization::EXPR_DECL_REF;
}
-void PCHStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
+void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLocation(), Record);
Writer.AddAPInt(E->getValue(), Record);
- Code = pch::EXPR_INTEGER_LITERAL;
+ Code = serialization::EXPR_INTEGER_LITERAL;
}
-void PCHStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
+void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
Writer.AddAPFloat(E->getValue(), Record);
Record.push_back(E->isExact());
Writer.AddSourceLocation(E->getLocation(), Record);
- Code = pch::EXPR_FLOATING_LITERAL;
+ Code = serialization::EXPR_FLOATING_LITERAL;
}
-void PCHStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
+void ASTStmtWriter::VisitImaginaryLiteral(ImaginaryLiteral *E) {
VisitExpr(E);
Writer.AddStmt(E->getSubExpr());
- Code = pch::EXPR_IMAGINARY_LITERAL;
+ Code = serialization::EXPR_IMAGINARY_LITERAL;
}
-void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) {
+void ASTStmtWriter::VisitStringLiteral(StringLiteral *E) {
VisitExpr(E);
Record.push_back(E->getByteLength());
Record.push_back(E->getNumConcatenated());
@@ -412,49 +415,48 @@ void PCHStmtWriter::VisitStringLiteral(StringLiteral *E) {
// FIXME: String data should be stored as a blob at the end of the
// StringLiteral. However, we can't do so now because we have no
// provision for coping with abbreviations when we're jumping around
- // the PCH file during deserialization.
- Record.insert(Record.end(),
- E->getStrData(), E->getStrData() + E->getByteLength());
+ // the AST file during deserialization.
+ Record.append(E->getString().begin(), E->getString().end());
for (unsigned I = 0, N = E->getNumConcatenated(); I != N; ++I)
Writer.AddSourceLocation(E->getStrTokenLoc(I), Record);
- Code = pch::EXPR_STRING_LITERAL;
+ Code = serialization::EXPR_STRING_LITERAL;
}
-void PCHStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
+void ASTStmtWriter::VisitCharacterLiteral(CharacterLiteral *E) {
VisitExpr(E);
Record.push_back(E->getValue());
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->isWide());
- Code = pch::EXPR_CHARACTER_LITERAL;
+ Code = serialization::EXPR_CHARACTER_LITERAL;
}
-void PCHStmtWriter::VisitParenExpr(ParenExpr *E) {
+void ASTStmtWriter::VisitParenExpr(ParenExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLParen(), Record);
Writer.AddSourceLocation(E->getRParen(), Record);
Writer.AddStmt(E->getSubExpr());
- Code = pch::EXPR_PAREN;
+ Code = serialization::EXPR_PAREN;
}
-void PCHStmtWriter::VisitParenListExpr(ParenListExpr *E) {
+void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) {
VisitExpr(E);
Record.push_back(E->NumExprs);
for (unsigned i=0; i != E->NumExprs; ++i)
Writer.AddStmt(E->Exprs[i]);
Writer.AddSourceLocation(E->LParenLoc, Record);
Writer.AddSourceLocation(E->RParenLoc, Record);
- Code = pch::EXPR_PAREN_LIST;
+ Code = serialization::EXPR_PAREN_LIST;
}
-void PCHStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
+void ASTStmtWriter::VisitUnaryOperator(UnaryOperator *E) {
VisitExpr(E);
Writer.AddStmt(E->getSubExpr());
Record.push_back(E->getOpcode()); // FIXME: stable encoding
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
- Code = pch::EXPR_UNARY_OPERATOR;
+ Code = serialization::EXPR_UNARY_OPERATOR;
}
-void PCHStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
+void ASTStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumComponents());
Record.push_back(E->getNumExpressions());
@@ -480,17 +482,16 @@ void PCHStmtWriter::VisitOffsetOfExpr(OffsetOfExpr *E) {
break;
case OffsetOfExpr::OffsetOfNode::Base:
- // FIXME: Implement this!
- llvm_unreachable("PCH for offsetof(base-specifier) not implemented");
+ Writer.AddCXXBaseSpecifier(*ON.getBase(), Record);
break;
}
}
for (unsigned I = 0, N = E->getNumExpressions(); I != N; ++I)
Writer.AddStmt(E->getIndexExpr(I));
- Code = pch::EXPR_OFFSETOF;
+ Code = serialization::EXPR_OFFSETOF;
}
-void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+void ASTStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
VisitExpr(E);
Record.push_back(E->isSizeOf());
if (E->isArgumentType())
@@ -501,18 +502,18 @@ void PCHStmtWriter::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
}
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_SIZEOF_ALIGN_OF;
+ Code = serialization::EXPR_SIZEOF_ALIGN_OF;
}
-void PCHStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+void ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getLHS());
Writer.AddStmt(E->getRHS());
Writer.AddSourceLocation(E->getRBracketLoc(), Record);
- Code = pch::EXPR_ARRAY_SUBSCRIPT;
+ Code = serialization::EXPR_ARRAY_SUBSCRIPT;
}
-void PCHStmtWriter::VisitCallExpr(CallExpr *E) {
+void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
Writer.AddSourceLocation(E->getRParenLoc(), Record);
@@ -520,10 +521,10 @@ void PCHStmtWriter::VisitCallExpr(CallExpr *E) {
for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg)
Writer.AddStmt(*Arg);
- Code = pch::EXPR_CALL;
+ Code = serialization::EXPR_CALL;
}
-void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
+void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) {
// Don't call VisitExpr, we'll write everything here.
Record.push_back(E->hasQualifier());
@@ -533,7 +534,7 @@ void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
}
unsigned NumTemplateArgs = E->getNumTemplateArgs();
- assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgumentList() &&
+ assert((NumTemplateArgs != 0) == E->hasExplicitTemplateArgs() &&
"Template args list with no args ?");
Record.push_back(NumTemplateArgs);
if (NumTemplateArgs) {
@@ -550,92 +551,94 @@ void PCHStmtWriter::VisitMemberExpr(MemberExpr *E) {
Writer.AddTypeRef(E->getType(), Record);
Writer.AddStmt(E->getBase());
Writer.AddDeclRef(E->getMemberDecl(), Record);
+ // FIXME: write DeclarationNameLoc.
Writer.AddSourceLocation(E->getMemberLoc(), Record);
Record.push_back(E->isArrow());
- Code = pch::EXPR_MEMBER;
+ Code = serialization::EXPR_MEMBER;
}
-void PCHStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) {
+void ASTStmtWriter::VisitObjCIsaExpr(ObjCIsaExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getBase());
Writer.AddSourceLocation(E->getIsaMemberLoc(), Record);
Record.push_back(E->isArrow());
- Code = pch::EXPR_OBJC_ISA;
+ Code = serialization::EXPR_OBJC_ISA;
}
-void PCHStmtWriter::VisitCastExpr(CastExpr *E) {
+void ASTStmtWriter::VisitCastExpr(CastExpr *E) {
VisitExpr(E);
+ Record.push_back(E->path_size());
Writer.AddStmt(E->getSubExpr());
Record.push_back(E->getCastKind()); // FIXME: stable encoding
- CXXBaseSpecifierArray &BasePath = E->getBasePath();
- Record.push_back(BasePath.size());
- for (CXXBaseSpecifierArray::iterator I = BasePath.begin(), E = BasePath.end();
- I != E; ++I)
- Writer.AddCXXBaseSpecifier(**I, Record);
+
+ for (CastExpr::path_iterator
+ PI = E->path_begin(), PE = E->path_end(); PI != PE; ++PI)
+ Writer.AddCXXBaseSpecifier(**PI, Record);
}
-void PCHStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
+void ASTStmtWriter::VisitBinaryOperator(BinaryOperator *E) {
VisitExpr(E);
Writer.AddStmt(E->getLHS());
Writer.AddStmt(E->getRHS());
Record.push_back(E->getOpcode()); // FIXME: stable encoding
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
- Code = pch::EXPR_BINARY_OPERATOR;
+ Code = serialization::EXPR_BINARY_OPERATOR;
}
-void PCHStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
+void ASTStmtWriter::VisitCompoundAssignOperator(CompoundAssignOperator *E) {
VisitBinaryOperator(E);
Writer.AddTypeRef(E->getComputationLHSType(), Record);
Writer.AddTypeRef(E->getComputationResultType(), Record);
- Code = pch::EXPR_COMPOUND_ASSIGN_OPERATOR;
+ Code = serialization::EXPR_COMPOUND_ASSIGN_OPERATOR;
}
-void PCHStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
+void ASTStmtWriter::VisitConditionalOperator(ConditionalOperator *E) {
VisitExpr(E);
Writer.AddStmt(E->getCond());
Writer.AddStmt(E->getLHS());
Writer.AddStmt(E->getRHS());
+ Writer.AddStmt(E->getSAVE());
Writer.AddSourceLocation(E->getQuestionLoc(), Record);
Writer.AddSourceLocation(E->getColonLoc(), Record);
- Code = pch::EXPR_CONDITIONAL_OPERATOR;
+ Code = serialization::EXPR_CONDITIONAL_OPERATOR;
}
-void PCHStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
+void ASTStmtWriter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
VisitCastExpr(E);
- Record.push_back(E->isLvalueCast());
- Code = pch::EXPR_IMPLICIT_CAST;
+ Record.push_back(E->getValueKind());
+ Code = serialization::EXPR_IMPLICIT_CAST;
}
-void PCHStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+void ASTStmtWriter::VisitExplicitCastExpr(ExplicitCastExpr *E) {
VisitCastExpr(E);
Writer.AddTypeSourceInfo(E->getTypeInfoAsWritten(), Record);
}
-void PCHStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
+void ASTStmtWriter::VisitCStyleCastExpr(CStyleCastExpr *E) {
VisitExplicitCastExpr(E);
Writer.AddSourceLocation(E->getLParenLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_CSTYLE_CAST;
+ Code = serialization::EXPR_CSTYLE_CAST;
}
-void PCHStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+void ASTStmtWriter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLParenLoc(), Record);
Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record);
Writer.AddStmt(E->getInitializer());
Record.push_back(E->isFileScope());
- Code = pch::EXPR_COMPOUND_LITERAL;
+ Code = serialization::EXPR_COMPOUND_LITERAL;
}
-void PCHStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
+void ASTStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getBase());
Writer.AddIdentifierRef(&E->getAccessor(), Record);
Writer.AddSourceLocation(E->getAccessorLoc(), Record);
- Code = pch::EXPR_EXT_VECTOR_ELEMENT;
+ Code = serialization::EXPR_EXT_VECTOR_ELEMENT;
}
-void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) {
+void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumInits());
for (unsigned I = 0, N = E->getNumInits(); I != N; ++I)
@@ -645,10 +648,10 @@ void PCHStmtWriter::VisitInitListExpr(InitListExpr *E) {
Writer.AddSourceLocation(E->getRBraceLoc(), Record);
Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record);
Record.push_back(E->hadArrayRangeDesignator());
- Code = pch::EXPR_INIT_LIST;
+ Code = serialization::EXPR_INIT_LIST;
}
-void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
+void ASTStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumSubExprs());
for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
@@ -660,166 +663,167 @@ void PCHStmtWriter::VisitDesignatedInitExpr(DesignatedInitExpr *E) {
D != DEnd; ++D) {
if (D->isFieldDesignator()) {
if (FieldDecl *Field = D->getField()) {
- Record.push_back(pch::DESIG_FIELD_DECL);
+ Record.push_back(serialization::DESIG_FIELD_DECL);
Writer.AddDeclRef(Field, Record);
} else {
- Record.push_back(pch::DESIG_FIELD_NAME);
+ Record.push_back(serialization::DESIG_FIELD_NAME);
Writer.AddIdentifierRef(D->getFieldName(), Record);
}
Writer.AddSourceLocation(D->getDotLoc(), Record);
Writer.AddSourceLocation(D->getFieldLoc(), Record);
} else if (D->isArrayDesignator()) {
- Record.push_back(pch::DESIG_ARRAY);
+ Record.push_back(serialization::DESIG_ARRAY);
Record.push_back(D->getFirstExprIndex());
Writer.AddSourceLocation(D->getLBracketLoc(), Record);
Writer.AddSourceLocation(D->getRBracketLoc(), Record);
} else {
assert(D->isArrayRangeDesignator() && "Unknown designator");
- Record.push_back(pch::DESIG_ARRAY_RANGE);
+ Record.push_back(serialization::DESIG_ARRAY_RANGE);
Record.push_back(D->getFirstExprIndex());
Writer.AddSourceLocation(D->getLBracketLoc(), Record);
Writer.AddSourceLocation(D->getEllipsisLoc(), Record);
Writer.AddSourceLocation(D->getRBracketLoc(), Record);
}
}
- Code = pch::EXPR_DESIGNATED_INIT;
+ Code = serialization::EXPR_DESIGNATED_INIT;
}
-void PCHStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
+void ASTStmtWriter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) {
VisitExpr(E);
- Code = pch::EXPR_IMPLICIT_VALUE_INIT;
+ Code = serialization::EXPR_IMPLICIT_VALUE_INIT;
}
-void PCHStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
+void ASTStmtWriter::VisitVAArgExpr(VAArgExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getSubExpr());
+ Writer.AddTypeSourceInfo(E->getWrittenTypeInfo(), Record);
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_VA_ARG;
+ Code = serialization::EXPR_VA_ARG;
}
-void PCHStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
+void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
Writer.AddSourceLocation(E->getLabelLoc(), Record);
Record.push_back(Writer.GetLabelID(E->getLabel()));
- Code = pch::EXPR_ADDR_LABEL;
+ Code = serialization::EXPR_ADDR_LABEL;
}
-void PCHStmtWriter::VisitStmtExpr(StmtExpr *E) {
+void ASTStmtWriter::VisitStmtExpr(StmtExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getSubStmt());
Writer.AddSourceLocation(E->getLParenLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_STMT;
+ Code = serialization::EXPR_STMT;
}
-void PCHStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
+void ASTStmtWriter::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
VisitExpr(E);
- Writer.AddTypeRef(E->getArgType1(), Record);
- Writer.AddTypeRef(E->getArgType2(), Record);
+ Writer.AddTypeSourceInfo(E->getArgTInfo1(), Record);
+ Writer.AddTypeSourceInfo(E->getArgTInfo2(), Record);
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_TYPES_COMPATIBLE;
+ Code = serialization::EXPR_TYPES_COMPATIBLE;
}
-void PCHStmtWriter::VisitChooseExpr(ChooseExpr *E) {
+void ASTStmtWriter::VisitChooseExpr(ChooseExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getCond());
Writer.AddStmt(E->getLHS());
Writer.AddStmt(E->getRHS());
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_CHOOSE;
+ Code = serialization::EXPR_CHOOSE;
}
-void PCHStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) {
+void ASTStmtWriter::VisitGNUNullExpr(GNUNullExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getTokenLocation(), Record);
- Code = pch::EXPR_GNU_NULL;
+ Code = serialization::EXPR_GNU_NULL;
}
-void PCHStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
+void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumSubExprs());
for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I)
Writer.AddStmt(E->getExpr(I));
Writer.AddSourceLocation(E->getBuiltinLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_SHUFFLE_VECTOR;
+ Code = serialization::EXPR_SHUFFLE_VECTOR;
}
-void PCHStmtWriter::VisitBlockExpr(BlockExpr *E) {
+void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getBlockDecl(), Record);
Record.push_back(E->hasBlockDeclRefExprs());
- Code = pch::EXPR_BLOCK;
+ Code = serialization::EXPR_BLOCK;
}
-void PCHStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+void ASTStmtWriter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->isByRef());
Record.push_back(E->isConstQualAdded());
Writer.AddStmt(E->getCopyConstructorExpr());
- Code = pch::EXPR_BLOCK_DECL_REF;
+ Code = serialization::EXPR_BLOCK_DECL_REF;
}
//===----------------------------------------------------------------------===//
// Objective-C Expressions and Statements.
//===----------------------------------------------------------------------===//
-void PCHStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) {
+void ASTStmtWriter::VisitObjCStringLiteral(ObjCStringLiteral *E) {
VisitExpr(E);
Writer.AddStmt(E->getString());
Writer.AddSourceLocation(E->getAtLoc(), Record);
- Code = pch::EXPR_OBJC_STRING_LITERAL;
+ Code = serialization::EXPR_OBJC_STRING_LITERAL;
}
-void PCHStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+void ASTStmtWriter::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
VisitExpr(E);
Writer.AddTypeSourceInfo(E->getEncodedTypeSourceInfo(), Record);
Writer.AddSourceLocation(E->getAtLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_OBJC_ENCODE;
+ Code = serialization::EXPR_OBJC_ENCODE;
}
-void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
+void ASTStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
VisitExpr(E);
Writer.AddSelectorRef(E->getSelector(), Record);
Writer.AddSourceLocation(E->getAtLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_OBJC_SELECTOR_EXPR;
+ Code = serialization::EXPR_OBJC_SELECTOR_EXPR;
}
-void PCHStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+void ASTStmtWriter::VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getProtocol(), Record);
Writer.AddSourceLocation(E->getAtLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_OBJC_PROTOCOL_EXPR;
+ Code = serialization::EXPR_OBJC_PROTOCOL_EXPR;
}
-void PCHStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
+void ASTStmtWriter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getDecl(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Writer.AddStmt(E->getBase());
Record.push_back(E->isArrow());
Record.push_back(E->isFreeIvar());
- Code = pch::EXPR_OBJC_IVAR_REF_EXPR;
+ Code = serialization::EXPR_OBJC_IVAR_REF_EXPR;
}
-void PCHStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
+void ASTStmtWriter::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getProperty(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Writer.AddStmt(E->getBase());
- Code = pch::EXPR_OBJC_PROPERTY_REF_EXPR;
+ Code = serialization::EXPR_OBJC_PROPERTY_REF_EXPR;
}
-void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr(
+void ASTStmtWriter::VisitObjCImplicitSetterGetterRefExpr(
ObjCImplicitSetterGetterRefExpr *E) {
VisitExpr(E);
Writer.AddDeclRef(E->getGetterMethod(), Record);
@@ -830,10 +834,10 @@ void PCHStmtWriter::VisitObjCImplicitSetterGetterRefExpr(
Writer.AddStmt(E->getBase());
Writer.AddSourceLocation(E->getLocation(), Record);
Writer.AddSourceLocation(E->getClassLoc(), Record);
- Code = pch::EXPR_OBJC_KVC_REF_EXPR;
+ Code = serialization::EXPR_OBJC_KVC_REF_EXPR;
}
-void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+void ASTStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
Record.push_back((unsigned)E->getReceiverKind()); // FIXME: stable encoding
@@ -867,40 +871,40 @@ void PCHStmtWriter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end();
Arg != ArgEnd; ++Arg)
Writer.AddStmt(*Arg);
- Code = pch::EXPR_OBJC_MESSAGE_EXPR;
+ Code = serialization::EXPR_OBJC_MESSAGE_EXPR;
}
-void PCHStmtWriter::VisitObjCSuperExpr(ObjCSuperExpr *E) {
+void ASTStmtWriter::VisitObjCSuperExpr(ObjCSuperExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLoc(), Record);
- Code = pch::EXPR_OBJC_SUPER_EXPR;
+ Code = serialization::EXPR_OBJC_SUPER_EXPR;
}
-void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
+void ASTStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) {
VisitStmt(S);
Writer.AddStmt(S->getElement());
Writer.AddStmt(S->getCollection());
Writer.AddStmt(S->getBody());
Writer.AddSourceLocation(S->getForLoc(), Record);
Writer.AddSourceLocation(S->getRParenLoc(), Record);
- Code = pch::STMT_OBJC_FOR_COLLECTION;
+ Code = serialization::STMT_OBJC_FOR_COLLECTION;
}
-void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
+void ASTStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) {
Writer.AddStmt(S->getCatchBody());
Writer.AddDeclRef(S->getCatchParamDecl(), Record);
Writer.AddSourceLocation(S->getAtCatchLoc(), Record);
Writer.AddSourceLocation(S->getRParenLoc(), Record);
- Code = pch::STMT_OBJC_CATCH;
+ Code = serialization::STMT_OBJC_CATCH;
}
-void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
+void ASTStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) {
Writer.AddStmt(S->getFinallyBody());
Writer.AddSourceLocation(S->getAtFinallyLoc(), Record);
- Code = pch::STMT_OBJC_FINALLY;
+ Code = serialization::STMT_OBJC_FINALLY;
}
-void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
+void ASTStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
Record.push_back(S->getNumCatchStmts());
Record.push_back(S->getFinallyStmt() != 0);
Writer.AddStmt(S->getTryBody());
@@ -909,38 +913,56 @@ void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) {
if (S->getFinallyStmt())
Writer.AddStmt(S->getFinallyStmt());
Writer.AddSourceLocation(S->getAtTryLoc(), Record);
- Code = pch::STMT_OBJC_AT_TRY;
+ Code = serialization::STMT_OBJC_AT_TRY;
}
-void PCHStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
+void ASTStmtWriter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
Writer.AddStmt(S->getSynchExpr());
Writer.AddStmt(S->getSynchBody());
Writer.AddSourceLocation(S->getAtSynchronizedLoc(), Record);
- Code = pch::STMT_OBJC_AT_SYNCHRONIZED;
+ Code = serialization::STMT_OBJC_AT_SYNCHRONIZED;
}
-void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
+void ASTStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
Writer.AddStmt(S->getThrowExpr());
Writer.AddSourceLocation(S->getThrowLoc(), Record);
- Code = pch::STMT_OBJC_AT_THROW;
+ Code = serialization::STMT_OBJC_AT_THROW;
}
//===----------------------------------------------------------------------===//
// C++ Expressions and Statements.
//===----------------------------------------------------------------------===//
-void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+void ASTStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) {
+ VisitStmt(S);
+ Writer.AddSourceLocation(S->getCatchLoc(), Record);
+ Writer.AddDeclRef(S->getExceptionDecl(), Record);
+ Writer.AddStmt(S->getHandlerBlock());
+ Code = serialization::STMT_CXX_CATCH;
+}
+
+void ASTStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) {
+ VisitStmt(S);
+ Record.push_back(S->getNumHandlers());
+ Writer.AddSourceLocation(S->getTryLoc(), Record);
+ Writer.AddStmt(S->getTryBlock());
+ for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i)
+ Writer.AddStmt(S->getHandler(i));
+ Code = serialization::STMT_CXX_TRY;
+}
+
+void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
VisitCallExpr(E);
Record.push_back(E->getOperator());
- Code = pch::EXPR_CXX_OPERATOR_CALL;
+ Code = serialization::EXPR_CXX_OPERATOR_CALL;
}
-void PCHStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
+void ASTStmtWriter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
VisitCallExpr(E);
- Code = pch::EXPR_CXX_MEMBER_CALL;
+ Code = serialization::EXPR_CXX_MEMBER_CALL;
}
-void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
+void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
@@ -950,88 +972,88 @@ void PCHStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) {
Record.push_back(E->isElidable());
Record.push_back(E->requiresZeroInitialization());
Record.push_back(E->getConstructionKind()); // FIXME: stable encoding
- Code = pch::EXPR_CXX_CONSTRUCT;
+ Code = serialization::EXPR_CXX_CONSTRUCT;
}
-void PCHStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
+void ASTStmtWriter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) {
VisitCXXConstructExpr(E);
Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_CXX_TEMPORARY_OBJECT;
+ Code = serialization::EXPR_CXX_TEMPORARY_OBJECT;
}
-void PCHStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
+void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
VisitExplicitCastExpr(E);
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
}
-void PCHStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
+void ASTStmtWriter::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
VisitCXXNamedCastExpr(E);
- Code = pch::EXPR_CXX_STATIC_CAST;
+ Code = serialization::EXPR_CXX_STATIC_CAST;
}
-void PCHStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
+void ASTStmtWriter::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
VisitCXXNamedCastExpr(E);
- Code = pch::EXPR_CXX_DYNAMIC_CAST;
+ Code = serialization::EXPR_CXX_DYNAMIC_CAST;
}
-void PCHStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
+void ASTStmtWriter::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
VisitCXXNamedCastExpr(E);
- Code = pch::EXPR_CXX_REINTERPRET_CAST;
+ Code = serialization::EXPR_CXX_REINTERPRET_CAST;
}
-void PCHStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
+void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
VisitCXXNamedCastExpr(E);
- Code = pch::EXPR_CXX_CONST_CAST;
+ Code = serialization::EXPR_CXX_CONST_CAST;
}
-void PCHStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
+void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
VisitExplicitCastExpr(E);
Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_CXX_FUNCTIONAL_CAST;
+ Code = serialization::EXPR_CXX_FUNCTIONAL_CAST;
}
-void PCHStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
+void ASTStmtWriter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) {
VisitExpr(E);
Record.push_back(E->getValue());
Writer.AddSourceLocation(E->getLocation(), Record);
- Code = pch::EXPR_CXX_BOOL_LITERAL;
+ Code = serialization::EXPR_CXX_BOOL_LITERAL;
}
-void PCHStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
+void ASTStmtWriter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLocation(), Record);
- Code = pch::EXPR_CXX_NULL_PTR_LITERAL;
+ Code = serialization::EXPR_CXX_NULL_PTR_LITERAL;
}
-void PCHStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+void ASTStmtWriter::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
VisitExpr(E);
Writer.AddSourceRange(E->getSourceRange(), Record);
if (E->isTypeOperand()) {
Writer.AddTypeSourceInfo(E->getTypeOperandSourceInfo(), Record);
- Code = pch::EXPR_CXX_TYPEID_TYPE;
+ Code = serialization::EXPR_CXX_TYPEID_TYPE;
} else {
Writer.AddStmt(E->getExprOperand());
- Code = pch::EXPR_CXX_TYPEID_EXPR;
+ Code = serialization::EXPR_CXX_TYPEID_EXPR;
}
}
-void PCHStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) {
+void ASTStmtWriter::VisitCXXThisExpr(CXXThisExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getLocation(), Record);
Record.push_back(E->isImplicit());
- Code = pch::EXPR_CXX_THIS;
+ Code = serialization::EXPR_CXX_THIS;
}
-void PCHStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) {
+void ASTStmtWriter::VisitCXXThrowExpr(CXXThrowExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getThrowLoc(), Record);
Writer.AddStmt(E->getSubExpr());
- Code = pch::EXPR_CXX_THROW;
+ Code = serialization::EXPR_CXX_THROW;
}
-void PCHStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
+void ASTStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
VisitExpr(E);
bool HasOtherExprStored = E->Param.getInt();
@@ -1042,32 +1064,24 @@ void PCHStmtWriter::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
Writer.AddDeclRef(E->getParam(), Record);
Writer.AddSourceLocation(E->getUsedLocation(), Record);
- Code = pch::EXPR_CXX_DEFAULT_ARG;
+ Code = serialization::EXPR_CXX_DEFAULT_ARG;
}
-void PCHStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+void ASTStmtWriter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
VisitExpr(E);
Writer.AddCXXTemporary(E->getTemporary(), Record);
Writer.AddStmt(E->getSubExpr());
- Code = pch::EXPR_CXX_BIND_TEMPORARY;
-}
-
-void PCHStmtWriter::VisitCXXBindReferenceExpr(CXXBindReferenceExpr *E) {
- VisitExpr(E);
- Writer.AddStmt(E->getSubExpr());
- Record.push_back(E->extendsLifetime());
- Record.push_back(E->requiresTemporaryCopy());
- Code = pch::EXPR_CXX_BIND_REFERENCE;
+ Code = serialization::EXPR_CXX_BIND_TEMPORARY;
}
-void PCHStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
+void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) {
VisitExpr(E);
Writer.AddSourceLocation(E->getTypeBeginLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_CXX_SCALAR_VALUE_INIT;
+ Code = serialization::EXPR_CXX_SCALAR_VALUE_INIT;
}
-void PCHStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
+void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
VisitExpr(E);
Record.push_back(E->isGlobalNew());
Record.push_back(E->hasInitializer());
@@ -1084,10 +1098,10 @@ void PCHStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) {
I != e; ++I)
Writer.AddStmt(*I);
- Code = pch::EXPR_CXX_NEW;
+ Code = serialization::EXPR_CXX_NEW;
}
-void PCHStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
+void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
VisitExpr(E);
Record.push_back(E->isGlobalDelete());
Record.push_back(E->isArrayForm());
@@ -1095,10 +1109,10 @@ void PCHStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) {
Writer.AddStmt(E->getArgument());
Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record);
- Code = pch::EXPR_CXX_DELETE;
+ Code = serialization::EXPR_CXX_DELETE;
}
-void PCHStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+void ASTStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
VisitExpr(E);
Writer.AddStmt(E->getBase());
@@ -1117,30 +1131,29 @@ void PCHStmtWriter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
else
Writer.AddTypeSourceInfo(E->getDestroyedTypeInfo(), Record);
- Code = pch::EXPR_CXX_PSEUDO_DESTRUCTOR;
+ Code = serialization::EXPR_CXX_PSEUDO_DESTRUCTOR;
}
-void PCHStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
+void ASTStmtWriter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {
VisitExpr(E);
Record.push_back(E->getNumTemporaries());
for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i)
Writer.AddCXXTemporary(E->getTemporary(i), Record);
Writer.AddStmt(E->getSubExpr());
- Code = pch::EXPR_CXX_EXPR_WITH_TEMPORARIES;
+ Code = serialization::EXPR_CXX_EXPR_WITH_TEMPORARIES;
}
void
-PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
+ASTStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
VisitExpr(E);
// Don't emit anything here, NumTemplateArgs must be emitted first.
if (E->hasExplicitTemplateArgs()) {
- const ExplicitTemplateArgumentList &Args
- = *E->getExplicitTemplateArgumentList();
+ const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
assert(Args.NumTemplateArgs &&
- "Num of template args was zero! PCH reading will mess up!");
+ "Num of template args was zero! AST reading will mess up!");
Record.push_back(Args.NumTemplateArgs);
AddExplicitTemplateArgumentList(Args);
} else {
@@ -1157,13 +1170,14 @@ PCHStmtWriter::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E){
Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
Writer.AddSourceRange(E->getQualifierRange(), Record);
Writer.AddDeclRef(E->getFirstQualifierFoundInScope(), Record);
+ // FIXME: write whole DeclarationNameInfo.
Writer.AddDeclarationName(E->getMember(), Record);
Writer.AddSourceLocation(E->getMemberLoc(), Record);
- Code = pch::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
+ Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
}
void
-PCHStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+ASTStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
VisitExpr(E);
// Don't emit anything here, NumTemplateArgs must be emitted first.
@@ -1171,22 +1185,23 @@ PCHStmtWriter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
if (E->hasExplicitTemplateArgs()) {
const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
assert(Args.NumTemplateArgs &&
- "Num of template args was zero! PCH reading will mess up!");
+ "Num of template args was zero! AST reading will mess up!");
Record.push_back(Args.NumTemplateArgs);
AddExplicitTemplateArgumentList(Args);
} else {
Record.push_back(0);
}
+ // FIXME: write whole DeclarationNameInfo.
Writer.AddDeclarationName(E->getDeclName(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Writer.AddSourceRange(E->getQualifierRange(), Record);
Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
- Code = pch::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF;
+ Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_DECL_REF;
}
void
-PCHStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
+ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
VisitExpr(E);
Record.push_back(E->arg_size());
for (CXXUnresolvedConstructExpr::arg_iterator
@@ -1196,10 +1211,10 @@ PCHStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
Writer.AddTypeRef(E->getTypeAsWritten(), Record);
Writer.AddSourceLocation(E->getLParenLoc(), Record);
Writer.AddSourceLocation(E->getRParenLoc(), Record);
- Code = pch::EXPR_CXX_UNRESOLVED_CONSTRUCT;
+ Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT;
}
-void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
+void ASTStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
VisitExpr(E);
// Don't emit anything here, NumTemplateArgs must be emitted first.
@@ -1207,7 +1222,7 @@ void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
if (E->hasExplicitTemplateArgs()) {
const ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
assert(Args.NumTemplateArgs &&
- "Num of template args was zero! PCH reading will mess up!");
+ "Num of template args was zero! AST reading will mess up!");
Record.push_back(Args.NumTemplateArgs);
AddExplicitTemplateArgumentList(Args);
} else {
@@ -1221,43 +1236,44 @@ void PCHStmtWriter::VisitOverloadExpr(OverloadExpr *E) {
Record.push_back(OvI.getAccess());
}
+ // FIXME: write whole DeclarationNameInfo.
Writer.AddDeclarationName(E->getName(), Record);
Writer.AddNestedNameSpecifier(E->getQualifier(), Record);
Writer.AddSourceRange(E->getQualifierRange(), Record);
Writer.AddSourceLocation(E->getNameLoc(), Record);
}
-void PCHStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+void ASTStmtWriter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
VisitOverloadExpr(E);
Record.push_back(E->isArrow());
Record.push_back(E->hasUnresolvedUsing());
Writer.AddStmt(!E->isImplicitAccess() ? E->getBase() : 0);
Writer.AddTypeRef(E->getBaseType(), Record);
Writer.AddSourceLocation(E->getOperatorLoc(), Record);
- Code = pch::EXPR_CXX_UNRESOLVED_MEMBER;
+ Code = serialization::EXPR_CXX_UNRESOLVED_MEMBER;
}
-void PCHStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
+void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
VisitOverloadExpr(E);
Record.push_back(E->requiresADL());
Record.push_back(E->isOverloaded());
Writer.AddDeclRef(E->getNamingClass(), Record);
- Code = pch::EXPR_CXX_UNRESOLVED_LOOKUP;
+ Code = serialization::EXPR_CXX_UNRESOLVED_LOOKUP;
}
-void PCHStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+void ASTStmtWriter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
VisitExpr(E);
Record.push_back(E->getTrait());
Writer.AddSourceRange(E->getSourceRange(), Record);
Writer.AddTypeRef(E->getQueriedType(), Record);
- Code = pch::EXPR_CXX_UNARY_TYPE_TRAIT;
+ Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT;
}
//===----------------------------------------------------------------------===//
-// PCHWriter Implementation
+// ASTWriter Implementation
//===----------------------------------------------------------------------===//
-unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
+unsigned ASTWriter::RecordSwitchCaseID(SwitchCase *S) {
assert(SwitchCaseIDs.find(S) == SwitchCaseIDs.end() &&
"SwitchCase recorded twice");
unsigned NextID = SwitchCaseIDs.size();
@@ -1265,7 +1281,7 @@ unsigned PCHWriter::RecordSwitchCaseID(SwitchCase *S) {
return NextID;
}
-unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
+unsigned ASTWriter::getSwitchCaseID(SwitchCase *S) {
assert(SwitchCaseIDs.find(S) != SwitchCaseIDs.end() &&
"SwitchCase hasn't been seen yet");
return SwitchCaseIDs[S];
@@ -1273,7 +1289,7 @@ unsigned PCHWriter::getSwitchCaseID(SwitchCase *S) {
/// \brief Retrieve the ID for the given label statement, which may
/// or may not have been emitted yet.
-unsigned PCHWriter::GetLabelID(LabelStmt *S) {
+unsigned ASTWriter::GetLabelID(LabelStmt *S) {
std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S);
if (Pos != LabelIDs.end())
return Pos->second;
@@ -1285,33 +1301,33 @@ unsigned PCHWriter::GetLabelID(LabelStmt *S) {
/// \brief Write the given substatement or subexpression to the
/// bitstream.
-void PCHWriter::WriteSubStmt(Stmt *S) {
+void ASTWriter::WriteSubStmt(Stmt *S) {
RecordData Record;
- PCHStmtWriter Writer(*this, Record);
+ ASTStmtWriter Writer(*this, Record);
++NumStatements;
if (!S) {
- Stream.EmitRecord(pch::STMT_NULL_PTR, Record);
+ Stream.EmitRecord(serialization::STMT_NULL_PTR, Record);
return;
}
- // Redirect PCHWriter::AddStmt to collect sub stmts.
+ // Redirect ASTWriter::AddStmt to collect sub stmts.
llvm::SmallVector<Stmt *, 16> SubStmts;
CollectedStmts = &SubStmts;
- Writer.Code = pch::STMT_NULL_PTR;
+ Writer.Code = serialization::STMT_NULL_PTR;
Writer.Visit(S);
#ifndef NDEBUG
- if (Writer.Code == pch::STMT_NULL_PTR) {
+ if (Writer.Code == serialization::STMT_NULL_PTR) {
SourceManager &SrcMgr
= DeclIDs.begin()->first->getASTContext().getSourceManager();
S->dump(SrcMgr);
- assert(0 && "Unhandled sub statement writing PCH file");
+ assert(0 && "Unhandled sub statement writing AST file");
}
#endif
- // Revert PCHWriter::AddStmt.
+ // Revert ASTWriter::AddStmt.
CollectedStmts = &StmtsToEmit;
// Write the sub stmts in reverse order, last to first. When reading them back
@@ -1326,7 +1342,7 @@ void PCHWriter::WriteSubStmt(Stmt *S) {
/// \brief Flush all of the statements that have been added to the
/// queue via AddStmt().
-void PCHWriter::FlushStmts() {
+void ASTWriter::FlushStmts() {
RecordData Record;
for (unsigned I = 0, N = StmtsToEmit.size(); I != N; ++I) {
@@ -1338,7 +1354,7 @@ void PCHWriter::FlushStmts() {
// Note that we are at the end of a full expression. Any
// expression records that follow this one are part of a different
// expression.
- Stream.EmitRecord(pch::STMT_STOP, Record);
+ Stream.EmitRecord(serialization::STMT_STOP, Record);
}
StmtsToEmit.clear();
diff --git a/lib/Serialization/CMakeLists.txt b/lib/Serialization/CMakeLists.txt
new file mode 100644
index 000000000000..d863c179bed2
--- /dev/null
+++ b/lib/Serialization/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(LLVM_NO_RTTI 1)
+
+add_clang_library(clangSerialization
+ GeneratePCH.cpp
+ ASTCommon.cpp
+ ASTReader.cpp
+ ASTReaderDecl.cpp
+ ASTReaderStmt.cpp
+ ASTWriter.cpp
+ ASTWriterDecl.cpp
+ ASTWriterStmt.cpp
+ )
+
+add_dependencies(clangSerialization
+ ClangAttrClasses
+ ClangAttrList
+ ClangAttrPCHRead
+ ClangAttrPCHWrite
+ ClangDiagnosticFrontend
+ ClangDiagnosticLex
+ ClangDiagnosticSema
+ ClangDeclNodes
+ ClangStmtNodes)
diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp
index 2f3df9479d93..5329b6cbd4d0 100644
--- a/lib/Frontend/GeneratePCH.cpp
+++ b/lib/Serialization/GeneratePCH.cpp
@@ -8,12 +8,12 @@
//===----------------------------------------------------------------------===//
//
// This file defines the CreatePCHGenerate function, which creates an
-// ASTConsume that generates a PCH file.
+// ASTConsumer that generates a PCH file.
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/ASTConsumers.h"
-#include "clang/Frontend/PCHWriter.h"
+#include "clang/Serialization/ASTWriter.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
@@ -25,36 +25,20 @@
using namespace clang;
-namespace {
- class PCHGenerator : public SemaConsumer {
- const Preprocessor &PP;
- const char *isysroot;
- llvm::raw_ostream *Out;
- Sema *SemaPtr;
- MemorizeStatCalls *StatCalls; // owned by the FileManager
- std::vector<unsigned char> Buffer;
- llvm::BitstreamWriter Stream;
- PCHWriter Writer;
-
- public:
- PCHGenerator(const Preprocessor &PP, PCHReader *Chain,
- const char *isysroot, llvm::raw_ostream *Out);
- virtual void InitializeSema(Sema &S) { SemaPtr = &S; }
- virtual void HandleTranslationUnit(ASTContext &Ctx);
- };
-}
-
PCHGenerator::PCHGenerator(const Preprocessor &PP,
- PCHReader *Chain,
+ bool Chaining,
const char *isysroot,
llvm::raw_ostream *OS)
- : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0), StatCalls(0),
- Stream(Buffer), Writer(Stream, Chain) {
+ : PP(PP), isysroot(isysroot), Out(OS), SemaPtr(0),
+ StatCalls(0), Stream(Buffer), Writer(Stream) {
// Install a stat() listener to keep track of all of the stat()
// calls.
StatCalls = new MemorizeStatCalls;
- PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true);
+ // If we have a chain, we want new stat calls only, so install the memorizer
+ // *after* the already installed ASTReader's stat cache.
+ PP.getFileManager().addStatCache(StatCalls,
+ /*AtBeginning=*/!Chaining);
}
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
@@ -63,7 +47,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
// Emit the PCH file
assert(SemaPtr && "No Sema?");
- Writer.WritePCH(*SemaPtr, StatCalls, isysroot);
+ Writer.WriteAST(*SemaPtr, StatCalls, isysroot);
// Write the generated bitstream to "Out".
Out->write((char *)&Buffer.front(), Buffer.size());
@@ -75,9 +59,6 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
Buffer.clear();
}
-ASTConsumer *clang::CreatePCHGenerator(const Preprocessor &PP,
- llvm::raw_ostream *OS,
- PCHReader *Chain,
- const char *isysroot) {
- return new PCHGenerator(PP, Chain, isysroot, OS);
+ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
+ return &Writer;
}
diff --git a/lib/Serialization/Makefile b/lib/Serialization/Makefile
new file mode 100644
index 000000000000..e89ddc38ec94
--- /dev/null
+++ b/lib/Serialization/Makefile
@@ -0,0 +1,19 @@
+##===- clang/lib/Serialization/Makefile --------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This implements the semantic analyzer and AST builder library for the
+# C-Language front-end.
+#
+##===----------------------------------------------------------------------===##
+
+CLANG_LEVEL := ../..
+LIBRARYNAME := clangSerialization
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/test/Analysis/additive-folding.c b/test/Analysis/additive-folding.c
index 15d758800adc..e4a565133968 100644
--- a/test/Analysis/additive-folding.c
+++ b/test/Analysis/additive-folding.c
@@ -18,7 +18,7 @@ void separateExpressions (int a) {
char* buf = malloc(1);
if (a != 0 && b == 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(buf);
}
@@ -29,7 +29,7 @@ void oneLongExpression (int a) {
char* buf = malloc(1);
if (a != 0 && b == 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(buf);
}
@@ -40,11 +40,11 @@ void mixedTypes (int a) {
// This is part of PR7406.
int b = a + 1LL;
if (a != 0 && (b-1) == 0) // not crash
- return; // no warning
+ return; // expected-warning{{never executed}}
int c = a + 1U;
if (a != 0 && (c-1) == 0) // not crash
- return; // no warning
+ return; // expected-warning{{never executed}}
free(buf);
}
@@ -85,7 +85,7 @@ void mixed_eq_ne (int a) {
if (a+1U != 2)
return; // no-warning
if (a-1U != 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -96,7 +96,7 @@ void mixed_ne_eq (int a) {
if (a+1U == 2)
return; // no-warning
if (a-1U == 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
@@ -191,7 +191,7 @@ void tautologyGE (unsigned a) {
void tautologyLT (unsigned a) {
char* b = malloc(1);
if (a < 0)
- return; // no-warning
+ return; // expected-warning{{never executed}}
free(b);
}
diff --git a/test/Analysis/array-struct-region.c b/test/Analysis/array-struct-region.c
new file mode 100644
index 000000000000..dabd25bb1f50
--- /dev/null
+++ b/test/Analysis/array-struct-region.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -verify %s
+
+int string_literal_init() {
+ char a[] = "abc";
+ char b[2] = "abc"; // expected-warning{{too long}}
+ char c[5] = "abc";
+
+ if (a[1] != 'b')
+ return 0; // expected-warning{{never executed}}
+ if (b[1] != 'b')
+ return 0; // expected-warning{{never executed}}
+ if (c[1] != 'b')
+ return 0; // expected-warning{{never executed}}
+
+ if (a[3] != 0)
+ return 0; // expected-warning{{never executed}}
+ if (c[3] != 0)
+ return 0; // expected-warning{{never executed}}
+
+ if (c[4] != 0)
+ return 0; // expected-warning{{never executed}}
+
+ return 42;
+}
+
+void nested_compound_literals(int rad) {
+ int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ int a;
+
+ for (a = 0; a < 6; ++a) {
+ vec[a][0] *= rad; // no-warning
+ vec[a][1] *= rad; // no-warning
+ }
+}
+
+void nested_compound_literals_float(float rad) {
+ float vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
+ {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
+ int a;
+
+ for (a = 0; a < 6; ++a) {
+ vec[a][0] *= rad; // no-warning
+ vec[a][1] *= rad; // no-warning
+ }
+}
diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c
index f4ddb0a3d080..ffe420f72517 100644
--- a/test/Analysis/bstring.c
+++ b/test/Analysis/bstring.c
@@ -48,27 +48,30 @@ void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void memcpy0 () {
char src[] = {1, 2, 3, 4};
- char dst[4];
+ char dst[4] = {0};
memcpy(dst, src, 4); // no-warning
if (memcpy(dst, src, 4) != dst) {
- (void)*(char*)0; // no-warning -- should be unreachable
+ (void)*(char*)0; // no-warning
}
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
}
void memcpy1 () {
char src[] = {1, 2, 3, 4};
char dst[10];
- memcpy(dst, src, 5); // expected-warning{{out-of-bound}}
+ memcpy(dst, src, 5); // expected-warning{{Byte string function accesses out-of-bound array element}}
}
void memcpy2 () {
char src[] = {1, 2, 3, 4};
char dst[1];
- memcpy(dst, src, 4); // expected-warning{{out-of-bound}}
+ memcpy(dst, src, 4); // expected-warning{{Byte string function overflows destination buffer}}
}
void memcpy3 () {
@@ -82,14 +85,14 @@ void memcpy4 () {
char src[] = {1, 2, 3, 4};
char dst[10];
- memcpy(dst+2, src+2, 3); // expected-warning{{out-of-bound}}
+ memcpy(dst+2, src+2, 3); // expected-warning{{Byte string function accesses out-of-bound array element}}
}
void memcpy5() {
char src[] = {1, 2, 3, 4};
char dst[3];
- memcpy(dst+2, src+2, 2); // expected-warning{{out-of-bound}}
+ memcpy(dst+2, src+2, 2); // expected-warning{{Byte string function overflows destination buffer}}
}
void memcpy6() {
@@ -150,13 +153,16 @@ void *memmove(void *s1, const void *s2, size_t n);
void memmove0 () {
char src[] = {1, 2, 3, 4};
- char dst[4];
+ char dst[4] = {0};
memmove(dst, src, 4); // no-warning
if (memmove(dst, src, 4) != dst) {
- (void)*(char*)0; // no-warning -- should be unreachable
+ (void)*(char*)0; // no-warning
}
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
}
void memmove1 () {
@@ -170,7 +176,7 @@ void memmove2 () {
char src[] = {1, 2, 3, 4};
char dst[1];
- memmove(dst, src, 4); // expected-warning{{out-of-bound}}
+ memmove(dst, src, 4); // expected-warning{{overflow}}
}
//===----------------------------------------------------------------------===
@@ -246,6 +252,12 @@ void memcmp6 (char *a, char *b, size_t n) {
(void)*(char*)0; // expected-warning{{null}}
}
+int memcmp7 (char *a, size_t x, size_t y, size_t n) {
+ // We used to crash when either of the arguments was unknown.
+ return memcmp(a, &a[x*y], n) +
+ memcmp(&a[x*y], a, n);
+}
+
//===----------------------------------------------------------------------===
// bcopy()
//===----------------------------------------------------------------------===
@@ -257,9 +269,12 @@ void bcopy(/*const*/ void *s1, void *s2, size_t n);
void bcopy0 () {
char src[] = {1, 2, 3, 4};
- char dst[4];
+ char dst[4] = {0};
bcopy(src, dst, 4); // no-warning
+
+ if (dst[0] != 0)
+ (void)*(char*)0; // expected-warning{{null}}
}
void bcopy1 () {
@@ -273,5 +288,5 @@ void bcopy2 () {
char src[] = {1, 2, 3, 4};
char dst[1];
- bcopy(src, dst, 4); // expected-warning{{out-of-bound}}
+ bcopy(src, dst, 4); // expected-warning{{overflow}}
}
diff --git a/test/Analysis/constant-folding.c b/test/Analysis/constant-folding.c
index 6ed2b390cf7a..9191a9e0578e 100644
--- a/test/Analysis/constant-folding.c
+++ b/test/Analysis/constant-folding.c
@@ -9,51 +9,51 @@ void testComparisons (int a) {
// Sema can already catch the simple comparison a==a,
// since that's usually a logic error (and not path-dependent).
int b = a;
- if (!(b==a)) WARN;
- if (!(b>=a)) WARN;
- if (!(b<=a)) WARN;
- if (b!=a) WARN;
- if (b>a) WARN;
- if (b<a) WARN;
+ if (!(b==a)) WARN; // expected-warning{{never executed}}
+ if (!(b>=a)) WARN; // expected-warning{{never executed}}
+ if (!(b<=a)) WARN; // expected-warning{{never executed}}
+ if (b!=a) WARN; // expected-warning{{never executed}}
+ if (b>a) WARN; // expected-warning{{never executed}}
+ if (b<a) WARN; // expected-warning{{never executed}}
}
void testSelfOperations (int a) {
- if ((a|a) != a) WARN;
- if ((a&a) != a) WARN;
- if ((a^a) != 0) WARN;
- if ((a-a) != 0) WARN;
+ if ((a|a) != a) WARN; // expected-warning{{never executed}}
+ if ((a&a) != a) WARN; // expected-warning{{never executed}}
+ if ((a^a) != 0) WARN; // expected-warning{{never executed}}
+ if ((a-a) != 0) WARN; // expected-warning{{never executed}}
}
void testIdempotent (int a) {
- if ((a*1) != a) WARN;
- if ((a/1) != a) WARN;
- if ((a+0) != a) WARN;
- if ((a-0) != a) WARN;
- if ((a<<0) != a) WARN;
- if ((a>>0) != a) WARN;
- if ((a^0) != a) WARN;
- if ((a&(~0)) != a) WARN;
- if ((a|0) != a) WARN;
+ if ((a*1) != a) WARN; // expected-warning{{never executed}}
+ if ((a/1) != a) WARN; // expected-warning{{never executed}}
+ if ((a+0) != a) WARN; // expected-warning{{never executed}}
+ if ((a-0) != a) WARN; // expected-warning{{never executed}}
+ if ((a<<0) != a) WARN; // expected-warning{{never executed}}
+ if ((a>>0) != a) WARN; // expected-warning{{never executed}}
+ if ((a^0) != a) WARN; // expected-warning{{never executed}}
+ if ((a&(~0)) != a) WARN; // expected-warning{{never executed}}
+ if ((a|0) != a) WARN; // expected-warning{{never executed}}
}
void testReductionToConstant (int a) {
- if ((a*0) != 0) WARN;
- if ((a&0) != 0) WARN;
- if ((a|(~0)) != (~0)) WARN;
+ if ((a*0) != 0) WARN; // expected-warning{{never executed}}
+ if ((a&0) != 0) WARN; // expected-warning{{never executed}}
+ if ((a|(~0)) != (~0)) WARN; // expected-warning{{never executed}}
}
void testSymmetricIntSymOperations (int a) {
- if ((2+a) != (a+2)) WARN;
- if ((2*a) != (a*2)) WARN;
- if ((2&a) != (a&2)) WARN;
- if ((2^a) != (a^2)) WARN;
- if ((2|a) != (a|2)) WARN;
+ if ((2+a) != (a+2)) WARN; // expected-warning{{never executed}}
+ if ((2*a) != (a*2)) WARN; // expected-warning{{never executed}}
+ if ((2&a) != (a&2)) WARN; // expected-warning{{never executed}}
+ if ((2^a) != (a^2)) WARN; // expected-warning{{never executed}}
+ if ((2|a) != (a|2)) WARN; // expected-warning{{never executed}}
}
void testAsymmetricIntSymOperations (int a) {
- if (((~0) >> a) != (~0)) WARN;
- if ((0 >> a) != 0) WARN;
- if ((0 << a) != 0) WARN;
+ if (((~0) >> a) != (~0)) WARN; // expected-warning{{never executed}}
+ if ((0 >> a) != 0) WARN; // expected-warning{{never executed}}
+ if ((0 << a) != 0) WARN; // expected-warning{{never executed}}
// Unsigned right shift shifts in zeroes.
if ((((unsigned)(~0)) >> ((unsigned) a)) != ((unsigned)(~0)))
@@ -62,11 +62,11 @@ void testAsymmetricIntSymOperations (int a) {
void testLocations (char *a) {
char *b = a;
- if (!(b==a)) WARN;
- if (!(b>=a)) WARN;
- if (!(b<=a)) WARN;
- if (b!=a) WARN;
- if (b>a) WARN;
- if (b<a) WARN;
- if (b-a) WARN;
+ if (!(b==a)) WARN; // expected-warning{{never executed}}
+ if (!(b>=a)) WARN; // expected-warning{{never executed}}
+ if (!(b<=a)) WARN; // expected-warning{{never executed}}
+ if (b!=a) WARN; // expected-warning{{never executed}}
+ if (b>a) WARN; // expected-warning{{never executed}}
+ if (b<a) WARN; // expected-warning{{never executed}}
+ if (b-a) WARN; // expected-warning{{never executed}}
}
diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c
index defd7e0b7bdf..57d5d112d717 100644
--- a/test/Analysis/dead-stores.c
+++ b/test/Analysis/dead-stores.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
+// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
// RUN: %clang_cc1 -Wunused-variable -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s
@@ -150,7 +150,7 @@ void f15(unsigned x, unsigned y) {
int f16(int x) {
x = x * 2;
- x = sizeof(int [x = (x || x + 1) * 2]) // expected-warning{{Although the value stored to 'x' is used}}
+ x = sizeof(int [x = (x || x + 1) * 2]) // expected-warning{{Although the value stored to 'x' is used}} expected-warning{{The left operand to '*' is always 1}}
? 5 : 8;
return x;
}
@@ -158,7 +158,7 @@ int f16(int x) {
// Self-assignments should not be flagged as dead stores.
void f17() {
int x = 1;
- x = x; // no-warning
+ x = x;
}
// <rdar://problem/6506065>
@@ -458,7 +458,31 @@ void rdar8014335() {
// Note that the next value stored to 'i' is never executed
// because the next statement to be executed is the 'break'
// in the increment code of the first loop.
- i = i * 3; // expected-warning{{Value stored to 'i' is never read}}
+ i = i * 3; // expected-warning{{Value stored to 'i' is never read}} expected-warning{{The left operand to '*' is always 1}}
}
}
+// <rdar://problem/8320674> NullStmts followed by do...while() can lead to disconnected CFG
+//
+// This previously caused bogus dead-stores warnings because the body of the first do...while was
+// disconnected from the entry of the function.
+typedef struct { float r; float i; } s_rdar8320674;
+typedef struct { s_rdar8320674 x[1]; } s2_rdar8320674;
+
+void rdar8320674(s_rdar8320674 *z, unsigned y, s2_rdar8320674 *st, int m)
+{
+ s_rdar8320674 * z2;
+ s_rdar8320674 * tw1 = st->x;
+ s_rdar8320674 t;
+ z2 = z + m;
+ do{
+ ; ;
+ do{ (t).r = (*z2).r*(*tw1).r - (*z2).i*(*tw1).i; (t).i = (*z2).r*(*tw1).i + (*z2).i*(*tw1).r; }while(0);
+ tw1 += y;
+ do { (*z2).r=(*z).r-(t).r; (*z2).i=(*z).i-(t).i; }while(0);
+ do { (*z).r += (t).r; (*z).i += (t).i; }while(0);
+ ++z2;
+ ++z;
+ }while (--m);
+}
+
diff --git a/test/Analysis/flat-store.c b/test/Analysis/flat-store.c
new file mode 100644
index 000000000000..bb274b0d5dfa
--- /dev/null
+++ b/test/Analysis/flat-store.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=flat -verify %s
+#define FAIL ((void)*(char*)0)
+struct simple { int x; };
+
+void PR7297 () {
+ struct simple a;
+ struct simple *p = &a;
+ p->x = 5;
+ if (!p[0].x) FAIL; // no-warning
+ if (p[0].x) FAIL; // expected-warning {{null}}
+}
diff --git a/test/Analysis/idempotent-operations.c b/test/Analysis/idempotent-operations.c
index 9cef08edc43f..5c9a59d73616 100644
--- a/test/Analysis/idempotent-operations.c
+++ b/test/Analysis/idempotent-operations.c
@@ -1,52 +1,189 @@
-// RUN: %clang_cc1 -analyze -analyzer-idempotent-operation -analyzer-store=region -analyzer-constraints=range -fblocks -verify -analyzer-opt-analyze-nested-blocks -analyzer-check-objc-mem -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-check-objc-mem -analyzer-check-idempotent-operations -verify %s
// Basic tests
extern void test(int i);
+extern void test_f(float f);
-void basic() {
+unsigned basic() {
int x = 10, zero = 0, one = 1;
// x op x
- x = x; // expected-warning {{idempotent operation; both operands are always equal in value}}
- test(x - x); // expected-warning {{idempotent operation; both operands are always equal in value}}
- x -= x; // expected-warning {{idempotent operation; both operands are always equal in value}}
+ x = x; // expected-warning {{Assigned value is always the same as the existing value}}
+ test(x - x); // expected-warning {{Both operands to '-' always have the same value}}
+ x -= x; // expected-warning {{Both operands to '-=' always have the same value}}
x = 10; // no-warning
- test(x / x); // expected-warning {{idempotent operation; both operands are always equal in value}}
- x /= x; // expected-warning {{idempotent operation; both operands are always equal in value}}
+ test(x / x); // expected-warning {{Both operands to '/' always have the same value}}
+ x /= x; // expected-warning {{Both operands to '/=' always have the same value}}
x = 10; // no-warning
- test(x & x); // expected-warning {{idempotent operation; both operands are always equal in value}}
- x &= x; // expected-warning {{idempotent operation; both operands are always equal in value}}
- test(x | x); // expected-warning {{idempotent operation; both operands are always equal in value}}
- x |= x; // expected-warning {{idempotent operation; both operands are always equal in value}}
+ test(x & x); // expected-warning {{Both operands to '&' always have the same value}}
+ x &= x; // expected-warning {{Both operands to '&=' always have the same value}}
+ test(x | x); // expected-warning {{Both operands to '|' always have the same value}}
+ x |= x; // expected-warning {{Both operands to '|=' always have the same value}}
// x op 1
- test(x * one); // expected-warning {{idempotent operation; the right operand is always 1}}
- x *= one; // expected-warning {{idempotent operation; the right operand is always 1}}
- test(x / one); // expected-warning {{idempotent operation; the right operand is always 1}}
- x /= one; // expected-warning {{idempotent operation; the right operand is always 1}}
+ test(x * one); // expected-warning {{The right operand to '*' is always 1}}
+ x *= one; // expected-warning {{The right operand to '*=' is always 1}}
+ test(x / one); // expected-warning {{The right operand to '/' is always 1}}
+ x /= one; // expected-warning {{The right operand to '/=' is always 1}}
// 1 op x
- test(one * x); // expected-warning {{idempotent operation; the left operand is always 1}}
+ test(one * x); // expected-warning {{The left operand to '*' is always 1}}
// x op 0
- test(x + zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x - zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x * zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x & zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x | zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x ^ zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x << zero); // expected-warning {{idempotent operation; the right operand is always 0}}
- test(x >> zero); // expected-warning {{idempotent operation; the right operand is always 0}}
+ test(x + zero); // expected-warning {{The right operand to '+' is always 0}}
+ test(x - zero); // expected-warning {{The right operand to '-' is always 0}}
+ test(x * zero); // expected-warning {{The right operand to '*' is always 0}}
+ test(x & zero); // expected-warning {{The right operand to '&' is always 0}}
+ test(x | zero); // expected-warning {{The right operand to '|' is always 0}}
+ test(x ^ zero); // expected-warning {{The right operand to '^' is always 0}}
+ test(x << zero); // expected-warning {{The right operand to '<<' is always 0}}
+ test(x >> zero); // expected-warning {{The right operand to '>>' is always 0}}
// 0 op x
- test(zero + x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero - x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero / x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero * x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero & x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero | x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero ^ x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero << x); // expected-warning {{idempotent operation; the left operand is always 0}}
- test(zero >> x); // expected-warning {{idempotent operation; the left operand is always 0}}
+ test(zero + x); // expected-warning {{The left operand to '+' is always 0}}
+ test(zero - x); // expected-warning {{The left operand to '-' is always 0}}
+ test(zero / x); // expected-warning {{The left operand to '/' is always 0}}
+ test(zero * x); // expected-warning {{The left operand to '*' is always 0}}
+ test(zero & x); // expected-warning {{The left operand to '&' is always 0}}
+ test(zero | x); // expected-warning {{The left operand to '|' is always 0}}
+ test(zero ^ x); // expected-warning {{The left operand to '^' is always 0}}
+ test(zero << x); // expected-warning {{The left operand to '<<' is always 0}}
+ test(zero >> x); // expected-warning {{The left operand to '>>' is always 0}}
+
+ // Overwrite the values so these aren't marked as Pseudoconstants
+ x = 1;
+ zero = 2;
+ one = 3;
+
+ return x + zero + one;
+}
+
+void floats(float x) {
+ test_f(x * 1.0); // no-warning
+ test_f(x * 1.0F); // no-warning
+}
+
+// Ensure that we don't report false poitives in complex loops
+void bailout() {
+ int unused = 0, result = 4;
+ result = result; // expected-warning {{Assigned value is always the same as the existing value}}
+
+ for (unsigned bg = 0; bg < 1024; bg ++) {
+ result = bg * result; // no-warning
+
+ for (int i = 0; i < 256; i++) {
+ unused *= i; // no-warning
+ }
+ }
+}
+
+// Relaxed liveness - check that we don't kill liveness at assignments
+typedef unsigned uintptr_t;
+void kill_at_assign() {
+ short array[2];
+ uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion}}
+ short *p = x; // expected-warning{{incompatible integer to pointer conversion}}
+
+ // The following branch should be infeasible.
+ if (!(p = &array[0])) { // expected-warning{{Assigned value is always the same as the existing value}}
+ p = 0;
+ *p = 1; // no-warning
+ }
+}
+
+// False positive tests
+
+unsigned false1() {
+ int a = 10;
+ return a * (5 - 2 - 3); // no-warning
+}
+
+enum testenum { enum1 = 0, enum2 };
+unsigned false2() {
+ int a = 1234;
+ return enum1 + a; // no-warning
+}
+
+// Self assignments of unused variables are common false positives
+unsigned false3(int param, int param2) {
+ param = param; // no-warning
+
+ // if a self assigned variable is used later, then it should be reported still
+ param2 = param2; // expected-warning{{Assigned value is always the same as the existing value}}
+
+ unsigned nonparam = 5;
+
+ nonparam = nonparam; // expected-warning{{Assigned value is always the same as the existing value}}
+
+ return param2 + nonparam;
+}
+
+// Pseudo-constants (vars only read) and constants should not be reported
+unsigned false4() {
+ // Trivial constant
+ const int height = 1;
+ int c = 42;
+ test(height * c); // no-warning
+
+ // Pseudo-constant (never changes after decl)
+ int width = height;
+
+ return width * 10; // no-warning
+}
+
+// Block pseudoconstants
+void false4a() {
+ // Pseudo-constant
+ __block int a = 1;
+ int b = 10;
+ __block int c = 0;
+ b *= a; // no-warning
+
+ ^{
+ // Psuedoconstant block var
+ test(b * c); // no-warning
+
+ // Non-pseudoconstant block var
+ int d = 0;
+ test(b * d); // expected-warning{{The right operand to '*' is always 0}}
+ d = 5;
+ test(d);
+ }();
+
+ test(a + b);
+}
+
+// Static vars are common false positives
+int false5() {
+ static int test = 0;
+ int a = 56;
+ a *= test; // no-warning
+ test++;
+ return a;
+}
+
+// Non-local storage vars are considered false positives
+int globalInt = 1;
+int false6() {
+ int localInt = 23;
+
+ localInt /= globalInt;
+
+ return localInt;
+}
+
+// Check that assignments filter out false positives correctly
+int false7() {
+ int zero = 0; // psuedo-constant
+ int one = 1;
+
+ int a = 55;
+ a = a; // expected-warning{{Assigned value is always the same as the existing value}}
+ a = enum1 * a; // no-warning
+
+ int b = 123;
+ b = b; // no-warning
+
+ return a;
}
diff --git a/test/Analysis/idempotent-operations.cpp b/test/Analysis/idempotent-operations.cpp
new file mode 100644
index 000000000000..c5d1ceb8aff0
--- /dev/null
+++ b/test/Analysis/idempotent-operations.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-check-objc-mem -analyzer-check-idempotent-operations -verify %s
+
+// C++ specific false positives
+
+extern void test(int i);
+extern void test_ref(int &i);
+
+// Test references affecting pseudoconstants
+void false1() {
+ int a = 0;
+ int five = 5;
+ int &b = a;
+ test(five * a); // expected-warning {{The right operand to '*' is always 0}}
+ b = 4;
+}
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index b4c1314b34cf..e443150e1fbb 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -4,22 +4,136 @@ void *malloc(size_t);
void free(void *);
void *realloc(void *ptr, size_t size);
void *calloc(size_t nmemb, size_t size);
+void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
+void __attribute((ownership_takes(malloc, 1))) my_free(void *);
+void __attribute((ownership_returns(malloc, 1))) *my_malloc2(size_t);
+void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
+
+// Duplicate attributes are silly, but not an error.
+// Duplicate attribute has no extra effect.
+// If two are of different kinds, that is an error and reported as such.
+void __attribute((ownership_holds(malloc, 1)))
+__attribute((ownership_holds(malloc, 1)))
+__attribute((ownership_holds(malloc, 3))) my_hold2(void *, void *, void *);
+void *my_malloc3(size_t);
+void *myglobalpointer;
+struct stuff {
+ void *somefield;
+};
+struct stuff myglobalstuff;
void f1() {
int *p = malloc(12);
return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
}
-void f1_b() {
- int *p = malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
-}
-
void f2() {
int *p = malloc(12);
free(p);
free(p); // expected-warning{{Try to free a memory block that has been released}}
}
+// ownership attributes tests
+void naf1() {
+ int *p = my_malloc3(12);
+ return; // no-warning
+}
+
+void n2af1() {
+ int *p = my_malloc2(12);
+ return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void af1() {
+ int *p = my_malloc(12);
+ return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void af1_b() {
+ int *p = my_malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void af1_c() {
+ myglobalpointer = my_malloc(12); // no-warning
+}
+
+void af1_d() {
+ struct stuff mystuff;
+ mystuff.somefield = my_malloc(12); // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+// Test that we can pass out allocated memory via pointer-to-pointer.
+void af1_e(void **pp) {
+ *pp = my_malloc(42); // no-warning
+}
+
+void af1_f(struct stuff *somestuff) {
+ somestuff->somefield = my_malloc(12); // no-warning
+}
+
+// Allocating memory for a field via multiple indirections to our arguments is OK.
+void af1_g(struct stuff **pps) {
+ *pps = my_malloc(sizeof(struct stuff)); // no-warning
+ (*pps)->somefield = my_malloc(42); // no-warning
+}
+
+void af2() {
+ int *p = my_malloc(12);
+ my_free(p);
+ free(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void af2b() {
+ int *p = my_malloc(12);
+ free(p);
+ my_free(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void af2c() {
+ int *p = my_malloc(12);
+ free(p);
+ my_hold(p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void af2d() {
+ int *p = my_malloc(12);
+ free(p);
+ my_hold2(0, 0, p); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+// No leak if malloc returns null.
+void af2e() {
+ int *p = my_malloc(12);
+ if (!p)
+ return; // no-warning
+ free(p); // no-warning
+}
+
+// This case would inflict a double-free elsewhere.
+// However, this case is considered an analyzer bug since it causes false-positives.
+void af3() {
+ int *p = my_malloc(12);
+ my_hold(p);
+ free(p); // no-warning
+}
+
+// This case would inflict a double-free elsewhere.
+// However, this case is considered an analyzer bug since it causes false-positives.
+int * af4() {
+ int *p = my_malloc(12);
+ my_free(p);
+ return p; // no-warning
+}
+
+// This case is (possibly) ok, be conservative
+int * af5() {
+ int *p = my_malloc(12);
+ my_hold(p);
+ return p; // no-warning
+}
+
+
+
// 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.
@@ -117,7 +231,7 @@ char callocZeroesBad () {
char *buf = calloc(2,2);
char result = buf[3]; // no-warning
if (buf[1] != 0) {
- free(buf);
+ free(buf); // expected-warning{{never executed}}
}
return result; // expected-warning{{never released}}
}
diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp
index 6794d481d68b..bfa5e5cbb9b0 100644
--- a/test/Analysis/misc-ps-region-store.cpp
+++ b/test/Analysis/misc-ps-region-store.cpp
@@ -132,3 +132,30 @@ int TestHandleThis::null_deref_positive() {
return 0;
}
+// PR 7675 - passing literals by-reference
+void pr7675(const double &a);
+void pr7675(const int &a);
+void pr7675(const char &a);
+void pr7675_i(const _Complex double &a);
+
+void pr7675_test() {
+ pr7675(10.0);
+ pr7675(10);
+ pr7675('c');
+ pr7675_i(4.0i);
+ // Add null deref to ensure we are analyzing the code up to this point.
+ int *p = 0;
+ *p = 0xDEADBEEF; // expected-warning{{null pointer}}
+}
+
+// <rdar://problem/8375510> - CFGBuilder should handle temporaries.
+struct R8375510 {
+ R8375510();
+ ~R8375510();
+ R8375510 operator++(int);
+};
+
+int r8375510(R8375510 x, R8375510 y) {
+ for (; ; x++) { }
+}
+
diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m
index 6b4f658a3f85..a4e0d0bfa616 100644
--- a/test/Analysis/misc-ps-region-store.m
+++ b/test/Analysis/misc-ps-region-store.m
@@ -253,7 +253,7 @@ void rdar_7249327(unsigned int A[2*32]) {
a = A;
b = B;
- n = *a++;
+ n = *a++; // expected-warning{{Assigned value is always the same as the existing value}}
if (n)
x += *b++; // no-warning
}
@@ -1041,3 +1041,102 @@ void pr_7450() {
pr_7450_aux(p + 8);
}
+// <rdar://problem/8243408> - Symbolicate struct values returned by value.
+struct s_rdar_8243408 { int x; };
+extern struct s_rdar_8243408 rdar_8243408_aux(void);
+void rdar_8243408(void) {
+ struct s_rdar_8243408 a = { 1 }, *b = 0;
+ while (a.x && !b)
+ a = rdar_8243408_aux();
+
+ // Previously there was a false error here with 'b' being null.
+ (void) (a.x && b->x); // no-warning
+
+ // Introduce a null deref to ensure we are checking this path.
+ int *p = 0;
+ *p = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}}
+}
+
+// <rdar://problem/8258814>
+int r8258814()
+{
+ int foo;
+ int * a = &foo;
+ a[0] = 10;
+ // Do not warn that the value of 'foo' is uninitialized.
+ return foo; // no-warning
+}
+
+// PR 8052 - Don't crash when reasoning about loads from a function address.\n
+typedef unsigned int __uint32_t;
+typedef unsigned long vm_offset_t;
+typedef __uint32_t pd_entry_t;
+typedef unsigned char u_char;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+extern int bootMP_size;
+void bootMP(void);
+static void
+pr8052(u_int boot_addr)
+{
+ int x;
+ int size = *(int *) ((u_long) & bootMP_size);
+ u_char *src = (u_char *) ((u_long) bootMP);
+ u_char *dst = (u_char *) boot_addr + ((vm_offset_t) ((((((((1 <<
+12) / (sizeof(pd_entry_t))) - 1) - 1) - (260 - 2))) << 22) | ((0) << 12)));
+ for (x = 0;
+ x < size;
+ ++x)
+ *dst++ = *src++;
+}
+
+// PR 8015 - don't return undefined values for arrays when using a valid
+// symbolic index
+int pr8015_A();
+void pr8015_B(const char *);
+
+void pr8015_C() {
+ int number = pr8015_A();
+ const char *numbers[] = { "zero" };
+ if (number == 0) {
+ pr8015_B(numbers[number]); // no-warning
+ }
+}
+
+// FIXME: This is a false positive due to not reasoning about symbolic
+// array indices correctly. Discussion in PR 8015.
+void pr8015_D_FIXME() {
+ int number = pr8015_A();
+ const char *numbers[] = { "zero" };
+ if (number == 0) {
+ if (numbers[number] == numbers[0])
+ return;
+ int *p = 0;
+ *p = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}}
+ }
+}
+
+void pr8015_E() {
+ // Similar to pr8015_C, but number is allowed to be a valid range.
+ unsigned number = pr8015_A();
+ const char *numbers[] = { "zero", "one", "two" };
+ if (number < 3) {
+ pr8015_B(numbers[number]); // no-warning
+ }
+}
+
+void pr8015_F_FIXME() {
+ // Similar to pr8015_E, but like pr8015_D we check if the pointer
+ // is the same as one of the string literals. The null dereference
+ // here is not feasible in practice, so this is a false positive.
+ int number = pr8015_A();
+ const char *numbers[] = { "zero", "one", "two" };
+ if (number < 3) {
+ const char *p = numbers[number];
+ if (p == numbers[0] || p == numbers[1] || p == numbers[2])
+ return;
+ int *q = 0;
+ *q = 0xDEADBEEF; // expected-warning{{Dereference of null pointer}}
+ }
+}
+
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index b1d47e214ef7..4fbaa49c1168 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -86,11 +86,11 @@ unsigned r6268365Aux();
void r6268365() {
unsigned x = 0;
- x &= r6268365Aux();
+ x &= r6268365Aux(); // expected-warning{{The left operand to '&=' is always 0}}
unsigned j = 0;
if (x == 0) ++j;
- if (x == 0) x = x / j; // no-warning
+ if (x == 0) x = x / j; // expected-warning{{Assigned value is always the same as the existing value}} expected-warning{{The right operand to '/' is always 1}}
}
void divzeroassume(unsigned x, unsigned j) {
@@ -298,6 +298,7 @@ void rdar_6777209(char *p) {
typedef void *Opcode;
Opcode pr_4033_getOpcode();
void pr_4033(void) {
+ void *lbl = &&next_opcode;
next_opcode:
{
Opcode op = pr_4033_getOpcode();
@@ -406,14 +407,14 @@ void test_trivial_symbolic_comparison(int *x) {
int test_trivial_symbolic_comparison_aux();
int a = test_trivial_symbolic_comparison_aux();
int b = a;
- if (a != b) {
+ if (a != b) { // expected-warning{{Both operands to '!=' always have the same value}}
int *p = 0;
*p = 0xDEADBEEF; // no-warning
}
a = a == 1;
b = b == 1;
- if (a != b) {
+ if (a != b) { // expected-warning{{Both operands to '!=' always have the same value}}
int *p = 0;
*p = 0xDEADBEEF; // no-warning
}
@@ -457,7 +458,7 @@ void rdar_7062158_2() {
// ElementRegion is created.
unsigned char test_array_index_bitwidth(const unsigned char *p) {
unsigned short i = 0;
- for (i = 0; i < 2; i++) p = &p[i];
+ for (i = 0; i < 2; i++) p = &p[i];
return p[i+1];
}
@@ -1020,3 +1021,50 @@ void pr7475_warn() {
*someStatic = 0; // expected-warning{{null pointer}}
}
+// <rdar://problem/8202272> - __imag passed non-complex should not crash
+float f0(_Complex float x) {
+ float l0 = __real x;
+ return __real l0 + __imag l0;
+}
+
+
+//===----------------------------------------------------------------------===
+// Test that we can reduce symbols to constants whether they are on the left
+// or right side of an expression.
+//===----------------------------------------------------------------------===
+
+void reduce_to_constant(int x, int y) {
+ if (x != 20)
+ return;
+
+ int a = x + y;
+ int b = y + x;
+
+ if (y == -20 && a != 0)
+ (void)*(char*)0; // no-warning
+ if (y == -20 && b != 0)
+ (void)*(char*)0; // no-warning
+}
+
+// <rdar://problem/8360854> - Test that code after a switch statement with no
+// 'case:' labels is correctly evaluated.
+void r8360854(int n) {
+ switch (n) {
+ default: ;
+ }
+ int *p = 0;
+ *p = 0xDEADBEEF; // expected-warning{{null pointer}}
+}
+
+// PR 8050 - crash in CastSizeChecker when pointee is an incomplete type
+typedef long unsigned int __darwin_size_t;
+typedef __darwin_size_t size_t;
+void *malloc(size_t);
+
+struct PR8050;
+
+void pr8050(struct PR8050 **arg)
+{
+ *arg = malloc(1);
+}
+
diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c
index 7ca22ada7da7..8daa84506818 100644
--- a/test/Analysis/null-deref-ps.c
+++ b/test/Analysis/null-deref-ps.c
@@ -64,13 +64,13 @@ int f4_b() {
short array[2];
uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion}}
short *p = x; // expected-warning{{incompatible integer to pointer conversion}}
-
+
// The following branch should be infeasible.
- if (!(p = &array[0])) {
+ if (!(p == &array[0])) { // expected-warning{{Both operands to '==' always have the same value}}
p = 0;
*p = 1; // no-warning
}
-
+
if (p) {
*p = 5; // no-warning
p = 0;
@@ -81,7 +81,6 @@ int f4_b() {
return 0;
}
-
int f5() {
char *s = "hello world";
@@ -280,7 +279,7 @@ void f12(HF12ITEM i, char *q) {
// Test handling of translating between integer "pointers" and back.
void f13() {
int *x = 0;
- if (((((int) x) << 2) + 1) >> 1) *x = 1; // no-warning
+ if (((((int) x) << 2) + 1) >> 1) *x = 1;
}
// PR 4759 - Attribute non-null checking by the analyzer was not correctly
diff --git a/test/Analysis/outofbound.c b/test/Analysis/outofbound.c
index 9b487300c88a..ed51dc6ac06a 100644
--- a/test/Analysis/outofbound.c
+++ b/test/Analysis/outofbound.c
@@ -71,3 +71,27 @@ void sizeof_vla(int a) {
y[5] = 5; // expected-warning{{out-of-bound}}
}
}
+
+void alloca_region(int a) {
+ if (a == 5) {
+ char *x = __builtin_alloca(a);
+ x[4] = 4; // no-warning
+ x[5] = 5; // expected-warning{{out-of-bound}}
+ }
+}
+
+int symbolic_index(int a) {
+ int x[2] = {1, 2};
+ if (a == 2) {
+ return x[a]; // expected-warning{{out-of-bound}}
+ }
+ return 0;
+}
+
+int symbolic_index2(int a) {
+ int x[2] = {1, 2};
+ if (a < 0) {
+ return x[a]; // expected-warning{{out-of-bound}}
+ }
+ return 0;
+}
diff --git a/test/Analysis/plist-output.m b/test/Analysis/plist-output.m
index aa866de03c1f..95faa06a0633 100644
--- a/test/Analysis/plist-output.m
+++ b/test/Analysis/plist-output.m
@@ -205,7 +205,7 @@ void test_null_field(void) {
// CHECK: </dict>
// CHECK: <dict>
// CHECK: <key>line</key><integer>10</integer>
-// CHECK: <key>col</key><integer>3</integer>
+// CHECK: <key>col</key><integer>7</integer>
// CHECK: <key>file</key><integer>0</integer>
// CHECK: </dict>
// CHECK: </array>
diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m
index db49b91c27f5..7b9855473dce 100644
--- a/test/Analysis/retain-release-region-store.m
+++ b/test/Analysis/retain-release-region-store.m
@@ -50,6 +50,7 @@ typedef struct _NSZone NSZone;
@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
@end
@interface NSObject <NSObject> {}
+- (id)init;
+ (id)allocWithZone:(NSZone *)zone;
+ (id)alloc;
- (void)dealloc;
@@ -223,3 +224,29 @@ void pr6699(int x) {
}
}
+// <rdar://problem/8261992> Idempotent operation checker false positive with ObjC ivars
+@interface R8261992 : NSObject {
+ @package int myIvar;
+}
+@end
+
+static void R8261992_ChangeMyIvar(R8261992 *tc) {
+ tc->myIvar = 5;
+}
+
+void R8261992_test(R8261992 *tc) {
+ int temp = tc->myIvar;
+ // The ivar binding for tc->myIvar gets invalidated.
+ R8261992_ChangeMyIvar(tc);
+ tc->myIvar = temp; // no-warning
+ tc = [[R8261992 alloc] init];
+ temp = tc->myIvar; // no-warning
+ // The ivar binding for tc->myIvar gets invalidated.
+ R8261992_ChangeMyIvar(tc);
+ tc->myIvar = temp;
+ [tc release]; // no-warning
+ // did we analyze this?
+ int *p = 0x0;
+ *p = 0xDEADBEEF; // expected-warning{{null}}
+}
+
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index c9c7d271347b..064165aaf9e1 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1358,3 +1358,12 @@ void test_blocks_1_indirect_retain_via_call(void) {
}
@end
+// <rdar://problem/8272168> - Correcly handle Class<...> in Cocoa Conventions
+// detector.
+
+@protocol Prot_R8272168 @end
+Class <Prot_R8272168> GetAClassThatImplementsProt_R8272168();
+void r8272168() {
+ GetAClassThatImplementsProt_R8272168();
+}
+
diff --git a/test/Analysis/stack-addr-ps.cpp b/test/Analysis/stack-addr-ps.cpp
new file mode 100644
index 000000000000..593ba1df94d3
--- /dev/null
+++ b/test/Analysis/stack-addr-ps.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
+
+// FIXME: Only the stack-address checking in Sema catches this right now, and
+// the stack analyzer doesn't handle the ImplicitCastExpr (lvalue).
+const int& g() {
+ int s;
+ return s; // expected-warning{{reference to stack memory associated with local variable 's' returned}}
+}
diff --git a/test/Analysis/stream.c b/test/Analysis/stream.c
index 2b6a90353b9b..73bbc13cfbbc 100644
--- a/test/Analysis/stream.c
+++ b/test/Analysis/stream.c
@@ -6,6 +6,8 @@ typedef struct _IO_FILE FILE;
#define SEEK_CUR 1 /* Seek from current position. */
#define SEEK_END 2 /* Seek from end of file. */
extern FILE *fopen(const char *path, const char *mode);
+extern FILE *tmpfile(void);
+extern int fclose(FILE *fp);
extern size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
extern int fseek (FILE *__stream, long int __off, int __whence);
extern long int ftell (FILE *__stream);
@@ -15,21 +17,25 @@ void f1(void) {
FILE *p = fopen("foo", "r");
char buf[1024];
fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL.}}
+ fclose(p);
}
void f2(void) {
FILE *p = fopen("foo", "r");
fseek(p, 1, SEEK_SET); // expected-warning {{Stream pointer might be NULL.}}
+ fclose(p);
}
void f3(void) {
FILE *p = fopen("foo", "r");
ftell(p); // expected-warning {{Stream pointer might be NULL.}}
+ fclose(p);
}
void f4(void) {
FILE *p = fopen("foo", "r");
rewind(p); // expected-warning {{Stream pointer might be NULL.}}
+ fclose(p);
}
void f5(void) {
@@ -38,4 +44,36 @@ void f5(void) {
return;
fseek(p, 1, SEEK_SET); // no-warning
fseek(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR.}}
+ fclose(p);
+}
+
+void f6(void) {
+ FILE *p = fopen("foo", "r");
+ fclose(p);
+ fclose(p); // expected-warning {{Try to close a file Descriptor already closed. Cause undefined behaviour.}}
+}
+
+void f7(void) {
+ FILE *p = tmpfile();
+ ftell(p); // expected-warning {{Stream pointer might be NULL.}}
+ fclose(p);
+}
+
+void f8(int c) {
+ FILE *p = fopen("foo.c", "r");
+ if(c)
+ return; // expected-warning {{Opened File never closed. Potential Resource leak.}}
+ fclose(p);
+}
+
+FILE *f9(void) {
+ FILE *p = fopen("foo.c", "r");
+ if (p)
+ return p; // no-warning
+ else
+ return 0;
+}
+
+void pr7831(FILE *fp) {
+ fclose(fp); // no-warning
}
diff --git a/test/Analysis/string.c b/test/Analysis/string.c
new file mode 100644
index 000000000000..35ed7106f745
--- /dev/null
+++ b/test/Analysis/string.c
@@ -0,0 +1,240 @@
+// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
+// RUN: %clang_cc1 -analyze -DVARIANT -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
+// RUN: %clang_cc1 -analyze -DUSE_BUILTINS -DVARIANT -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-experimental-checks -verify %s
+
+//===----------------------------------------------------------------------===
+// Declarations
+//===----------------------------------------------------------------------===
+
+// Some functions are so similar to each other that they follow the same code
+// path, such as memcpy and __memcpy_chk, or memcmp and bcmp. If VARIANT is
+// defined, make sure to use the variants instead to make sure they are still
+// checked by the analyzer.
+
+// Some functions are implemented as builtins. These should be #defined as
+// BUILTIN(f), which will prepend "__builtin_" if USE_BUILTINS is defined.
+
+// Functions that have variants and are also availabe as builtins should be
+// declared carefully! See memcpy() for an example.
+
+#ifdef USE_BUILTINS
+# define BUILTIN(f) __builtin_ ## f
+#else /* USE_BUILTINS */
+# define BUILTIN(f) f
+#endif /* USE_BUILTINS */
+
+#define NULL 0
+typedef typeof(sizeof(int)) size_t;
+
+//===----------------------------------------------------------------------===
+// strlen()
+//===----------------------------------------------------------------------===
+
+#define strlen BUILTIN(strlen)
+size_t strlen(const char *s);
+
+void strlen_constant0() {
+ if (strlen("123") != 3)
+ (void)*(char*)0; // no-warning
+}
+
+void strlen_constant1() {
+ const char *a = "123";
+ if (strlen(a) != 3)
+ (void)*(char*)0; // no-warning
+}
+
+void strlen_constant2(char x) {
+ char a[] = "123";
+ if (strlen(a) != 3)
+ (void)*(char*)0; // no-warning
+ a[0] = x;
+ if (strlen(a) != 3)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+size_t strlen_null() {
+ return strlen(0); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+size_t strlen_fn() {
+ return strlen((char*)&strlen_fn); // expected-warning{{Argument to byte string function is the address of the function 'strlen_fn', which is not a null-terminated string}}
+}
+
+size_t strlen_nonloc() {
+label:
+ return strlen((char*)&&label); // expected-warning{{Argument to byte string function is the address of the label 'label', which is not a null-terminated string}}
+}
+
+void strlen_subregion() {
+ struct two_strings { char a[2], b[2] };
+ extern void use_two_strings(struct two_strings *);
+
+ struct two_strings z;
+ use_two_strings(&z);
+
+ size_t a = strlen(z.a);
+ z.b[0] = 5;
+ size_t b = strlen(z.a);
+ if (a == 0 && b != 0)
+ (void)*(char*)0; // expected-warning{{never executed}}
+
+ use_two_strings(&z);
+
+ size_t c = strlen(z.a);
+ if (a == 0 && c != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+extern void use_string(char *);
+void strlen_argument(char *x) {
+ size_t a = strlen(x);
+ size_t b = strlen(x);
+ if (a == 0 && b != 0)
+ (void)*(char*)0; // expected-warning{{never executed}}
+
+ use_string(x);
+
+ size_t c = strlen(x);
+ if (a == 0 && c != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+extern char global_str[];
+void strlen_global() {
+ size_t a = strlen(global_str);
+ size_t b = strlen(global_str);
+ if (a == 0 && b != 0)
+ (void)*(char*)0; // expected-warning{{never executed}}
+
+ // Call a function with unknown effects, which should invalidate globals.
+ use_string(0);
+
+ size_t c = strlen(global_str);
+ if (a == 0 && c != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strlen_indirect(char *x) {
+ size_t a = strlen(x);
+ char *p = x;
+ char **p2 = &p;
+ size_t b = strlen(x);
+ if (a == 0 && b != 0)
+ (void)*(char*)0; // expected-warning{{never executed}}
+
+ extern void use_string_ptr(char*const*);
+ use_string_ptr(p2);
+
+ size_t c = strlen(x);
+ if (a == 0 && c != 0)
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strlen_liveness(const char *x) {
+ if (strlen(x) < 5)
+ return;
+ if (strlen(x) < 5)
+ (void)*(char*)0; // no-warning
+}
+
+//===----------------------------------------------------------------------===
+// strcpy()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __strcpy_chk BUILTIN(__strcpy_chk)
+char *__strcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
+
+#define strcpy(a,b) __strcpy_chk(a,b,(size_t)-1)
+
+#else /* VARIANT */
+
+#define strcpy BUILTIN(strcpy)
+char *strcpy(char *restrict s1, const char *restrict s2);
+
+#endif /* VARIANT */
+
+
+void strcpy_null_dst(char *x) {
+ strcpy(NULL, x); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strcpy_null_src(char *x) {
+ strcpy(x, NULL); // expected-warning{{Null pointer argument in call to byte string function}}
+}
+
+void strcpy_fn(char *x) {
+ strcpy(x, (char*)&strcpy_fn); // expected-warning{{Argument to byte string function is the address of the function 'strcpy_fn', which is not a null-terminated string}}
+}
+
+void strcpy_effects(char *x, char *y) {
+ char a = x[0];
+
+ if (strcpy(x, y) != x)
+ (void)*(char*)0; // no-warning
+
+ if (strlen(x) != strlen(y))
+ (void)*(char*)0; // no-warning
+
+ if (a != x[0])
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void strcpy_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 4)
+ strcpy(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void strcpy_no_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 3)
+ strcpy(x, y); // no-warning
+}
+
+//===----------------------------------------------------------------------===
+// stpcpy()
+//===----------------------------------------------------------------------===
+
+#ifdef VARIANT
+
+#define __stpcpy_chk BUILTIN(__stpcpy_chk)
+char *__stpcpy_chk(char *restrict s1, const char *restrict s2, size_t destlen);
+
+#define stpcpy(a,b) __stpcpy_chk(a,b,(size_t)-1)
+
+#else /* VARIANT */
+
+#define stpcpy BUILTIN(stpcpy)
+char *stpcpy(char *restrict s1, const char *restrict s2);
+
+#endif /* VARIANT */
+
+
+void stpcpy_effect(char *x, char *y) {
+ char a = x[0];
+
+ if (stpcpy(x, y) != &x[strlen(y)])
+ (void)*(char*)0; // no-warning
+
+ if (strlen(x) != strlen(y))
+ (void)*(char*)0; // no-warning
+
+ if (a != x[0])
+ (void)*(char*)0; // expected-warning{{null}}
+}
+
+void stpcpy_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 4)
+ stpcpy(x, y); // expected-warning{{Byte string function overflows destination buffer}}
+}
+
+void stpcpy_no_overflow(char *y) {
+ char x[4];
+ if (strlen(y) == 3)
+ stpcpy(x, y); // no-warning
+}
diff --git a/test/Analysis/uninit-vals-ps-region.m b/test/Analysis/uninit-vals-ps-region.m
index 69c1ecd1e3a6..751e91ba8627 100644
--- a/test/Analysis/uninit-vals-ps-region.m
+++ b/test/Analysis/uninit-vals-ps-region.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-check-idempotent-operations -verify %s
struct s {
int data;
@@ -42,7 +42,7 @@ void test_uninit_pos_3() {
void test_uninit_neg() {
struct TestUninit v1 = { 0, 0 };
struct TestUninit v2 = test_uninit_aux();
- test_unit_aux2(v2.x + v1.y); // no-warning
+ test_unit_aux2(v2.x + v1.y); // expected-warning{{The right operand to '+' is always 0}}
}
extern void test_uninit_struct_arg_aux(struct TestUninit arg);
diff --git a/test/Analysis/unreachable-code-path.c b/test/Analysis/unreachable-code-path.c
new file mode 100644
index 000000000000..071532739cbe
--- /dev/null
+++ b/test/Analysis/unreachable-code-path.c
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-check-dead-stores -verify -analyzer-opt-analyze-nested-blocks %s
+
+extern void foo(int a);
+
+// The first few tests are non-path specific - we should be able to find them
+
+void test(unsigned a) {
+ switch (a) {
+ a += 5; // expected-warning{{never executed}}
+ case 2:
+ a *= 10;
+ case 3:
+ a %= 2;
+ }
+ foo(a);
+}
+
+void test2(unsigned a) {
+ help:
+ if (a > 0)
+ return;
+ if (a == 0)
+ return;
+ foo(a); // expected-warning{{never executed}}
+ goto help;
+}
+
+void test3(unsigned a) {
+ while(1);
+ if (a > 5) { // expected-warning{{never executed}}
+ return;
+ }
+}
+
+// These next tests are path-sensitive
+
+void test4() {
+ int a = 5;
+
+ while (a > 1)
+ a -= 2;
+
+ if (a > 1) {
+ a = a + 56; // expected-warning{{never executed}}
+ }
+
+ foo(a);
+}
+
+extern void bar(char c);
+
+void test5(const char *c) {
+ foo(c[0]);
+
+ if (!c) {
+ bar(1); // expected-warning{{never executed}}
+ }
+}
+
+// These next tests are false positives and should not generate warnings
+
+void test6(const char *c) {
+ if (c) return;
+ if (!c) return;
+ __builtin_unreachable(); // no-warning
+}
+
+// Compile-time constant false positives
+#define CONSTANT 0
+enum test_enum { Off, On };
+void test7() {
+ if (CONSTANT)
+ return; // no-warning
+
+ if (sizeof(int))
+ return; // no-warning
+
+ if (Off)
+ return; // no-warning
+}
+
+void test8() {
+ static unsigned a = 0;
+
+ if (a)
+ a = 123; // no-warning
+
+ a = 5;
+}
+
+// Check for bugs where multiple statements are reported
+void test9(unsigned a) {
+ switch (a) {
+ if (a) // expected-warning{{never executed}}
+ foo(a + 5); // no-warning
+ else // no-warning
+ foo(a); // no-warning
+ case 1:
+ case 2:
+ break;
+ default:
+ break;
+ }
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6bb5b6c3a0c2..611867f73ff2 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -54,7 +54,7 @@ if(PYTHONINTERP_FOUND)
--param build_config=${CMAKE_CFG_INTDIR}
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}/${testdir}
- DEPENDS clang c-index-test
+ DEPENDS clang c-index-test FileCheck not count
COMMENT "Running Clang regression tests in ${testdir}")
endforeach()
@@ -65,7 +65,7 @@ if(PYTHONINTERP_FOUND)
--param build_config=${CMAKE_CFG_INTDIR}
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_BINARY_DIR}
- DEPENDS clang c-index-test
+ DEPENDS clang c-index-test FileCheck not count
COMMENT "Running Clang regression tests")
add_custom_target(clang-c++tests
@@ -75,6 +75,6 @@ if(PYTHONINTERP_FOUND)
--param build_config=${CMAKE_CFG_INTDIR}
-sv ${CLANG_TEST_EXTRA_ARGS}
${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests
- DEPENDS clang c-index-test
+ DEPENDS clang c-index-test FileCheck not count
COMMENT "Running Clang regression tests")
endif()
diff --git a/test/CXX/class.access/class.protected/p1.cpp b/test/CXX/class.access/class.protected/p1.cpp
index 778e16aa3f53..8698fb1da8a5 100644
--- a/test/CXX/class.access/class.protected/p1.cpp
+++ b/test/CXX/class.access/class.protected/p1.cpp
@@ -68,7 +68,7 @@ namespace test1 {
namespace test2 {
class A {
- protected: int x; // expected-note 3 {{declared}}
+ protected: int x; // expected-note 3 {{object type must derive}}
static int sx;
static void test(A&);
};
@@ -103,7 +103,7 @@ namespace test2 {
namespace test3 {
class B;
class A {
- protected: int x; // expected-note {{declared}}
+ protected: int x; // expected-note {{object type must derive}}
static int sx;
static void test(B&);
};
@@ -138,7 +138,7 @@ namespace test3 {
namespace test4 {
class C;
class A {
- protected: int x; // expected-note 3 {{declared}}
+ protected: int x; // expected-note {{declared}} expected-note 2 {{object type must derive}}
static int sx; // expected-note 3{{member is declared here}}
static void test(C&);
};
@@ -215,7 +215,7 @@ namespace test6 {
class Static {};
class A {
protected:
- void foo(int); // expected-note 3 {{declared}}
+ void foo(int); // expected-note 3 {{object type must derive}}
void foo(long);
static void foo(Static);
@@ -253,7 +253,7 @@ namespace test7 {
class Static {};
class A {
protected:
- void foo(int); // expected-note 3 {{declared}}
+ void foo(int); // expected-note 3 {{object type must derive}}
void foo(long);
static void foo(Static);
@@ -291,7 +291,7 @@ namespace test8 {
class Static {};
class A {
protected:
- void foo(int); // expected-note 3 {{declared}}
+ void foo(int); // expected-note 3 {{object type must derive}}
void foo(long);
static void foo(Static);
@@ -329,8 +329,7 @@ namespace test8 {
namespace test9 {
class A { // expected-note {{member is declared here}}
- protected: int foo(); // expected-note 8 {{declared}} \
- // expected-note {{member is declared here}}
+ protected: int foo(); // expected-note 4 {{declared}} expected-note 2 {{object type must derive}} expected-note {{object type 'test9::A' must derive}}
};
class B : public A { // expected-note {{member is declared here}}
@@ -338,7 +337,7 @@ namespace test9 {
};
class C : protected B { // expected-note {{declared}} \
- // expected-note 6 {{constrained}}
+ // expected-note 9 {{constrained}}
};
class D : public A {
@@ -351,7 +350,7 @@ namespace test9 {
static void test(B &b) {
b.foo();
- b.A::foo(); // expected-error {{'foo' is a protected member}}
+ b.A::foo();
b.B::foo();
b.C::foo(); // expected-error {{'foo' is a protected member}}
}
@@ -359,8 +358,7 @@ namespace test9 {
static void test(C &c) {
c.foo(); // expected-error {{'foo' is a protected member}} \
// expected-error {{cannot cast}}
- c.A::foo(); // expected-error {{'foo' is a protected member}} \
- // expected-error {{'A' is a protected member}} \
+ c.A::foo(); // expected-error {{'A' is a protected member}} \
// expected-error {{cannot cast}}
c.B::foo(); // expected-error {{'B' is a protected member}} \
// expected-error {{cannot cast}}
@@ -388,3 +386,50 @@ namespace test10 {
template class A<int>;
}
+
+// rdar://problem/8360285: class.protected friendship
+namespace test11 {
+ class A {
+ protected:
+ int foo();
+ };
+
+ class B : public A {
+ friend class C;
+ };
+
+ class C {
+ void test() {
+ B b;
+ b.A::foo();
+ }
+ };
+}
+
+// This friendship is considered because a public member of A would be
+// a private member of C.
+namespace test12 {
+ class A { protected: int foo(); };
+ class B : public virtual A {};
+ class C : private B { friend void test(); };
+ class D : private C, public virtual A {};
+
+ void test() {
+ D d;
+ d.A::foo();
+ }
+}
+
+// This friendship is not considered because a public member of A is
+// inaccessible in C.
+namespace test13 {
+ class A { protected: int foo(); }; // expected-note {{declared protected here}}
+ class B : private virtual A {};
+ class C : private B { friend void test(); };
+ class D : public virtual A {};
+
+ void test() {
+ D d;
+ d.A::foo(); // expected-error {{protected member}}
+ }
+}
diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp
index 90a1449610f3..115a22ad4412 100644
--- a/test/CXX/class.access/p4.cpp
+++ b/test/CXX/class.access/p4.cpp
@@ -372,7 +372,7 @@ namespace test15 {
int private_foo; // expected-note {{declared private here}}
static int private_sfoo; // expected-note {{declared private here}}
protected:
- int protected_foo; // expected-note 4 {{declared protected here}}
+ int protected_foo; // expected-note 3 {{declared protected here}} // expected-note {{object type must derive from context type 'test15::B<int>'}}
static int protected_sfoo; // expected-note 3 {{declared protected here}}
int test1(A<int> &a) {
@@ -427,3 +427,26 @@ namespace test16 {
void b() { throw A(); } // expected-error{{temporary of type 'test16::A' has private destructor}} \
// expected-error{{exception object of type 'test16::A' has private destructor}}
}
+
+// rdar://problem/8146294
+namespace test17 {
+ class A {
+ template <typename T> class Inner { }; // expected-note {{declared private here}}
+ };
+
+ A::Inner<int> s; // expected-error {{'Inner' is a private member of 'test17::A'}}
+}
+
+namespace test18 {
+ template <class T> class A {};
+ class B : A<int> {
+ A<int> member;
+ };
+
+ // FIXME: this access to A should be forbidden (because C++ is dumb),
+ // but LookupResult can't express the necessary information to do
+ // the check, so we aggressively suppress access control.
+ class C : B {
+ A<int> member;
+ };
+}
diff --git a/test/CXX/class.access/p6.cpp b/test/CXX/class.access/p6.cpp
index 734a4d8c4869..87957084747a 100644
--- a/test/CXX/class.access/p6.cpp
+++ b/test/CXX/class.access/p6.cpp
@@ -119,3 +119,23 @@ namespace test4 {
foo(a, 0);
}
}
+
+// PR7644
+namespace test5 {
+ class A {
+ enum Enum { E0, E1, E2 }; // expected-note 4 {{declared private here}}
+ template <Enum> void foo();
+ template <Enum> class bar;
+ };
+
+ template <A::Enum en> void A::foo() {}
+ template <A::Enum en> class A::bar {};
+
+ template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}}
+ template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}}
+
+ class B {
+ template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}}
+ template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}}
+ };
+}
diff --git a/test/CXX/class/class.mem/p1.cpp b/test/CXX/class/class.mem/p1.cpp
new file mode 100644
index 000000000000..55507d4e9616
--- /dev/null
+++ b/test/CXX/class/class.mem/p1.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct S
+{
+ static int v1; // expected-note{{previous declaration is here}}
+ int v1; //expected-error{{duplicate member 'v1'}}
+ int v; //expected-note 2{{previous definition is here}} \
+ // expected-note{{previous declaration is here}}
+ static int v; //expected-error{{redefinition of 'v' as different kind of symbol}}
+ int v; //expected-error{{duplicate member 'v'}}
+ static int v; //expected-error{{redefinition of 'v' as different kind of symbol}}
+ enum EnumT { E = 10 };
+ friend struct M;
+ struct X; //expected-note{{forward declaration of 'S::X'}}
+ friend struct X;
+};
+
+S::EnumT Evar = S::E; // ok
+S::EnumT Evar2 = EnumT(); //expected-error{{use of undeclared identifier 'EnumT'}}
+S::M m; //expected-error{{no type named 'M' in 'S'}}
+S::X x; //expected-error{{variable has incomplete type 'S::X'}}
+
+
+struct S2
+{
+ static int v2; // expected-note{{previous declaration is here}}
+ static int v2; //expected-error{{duplicate member 'v2'}}
+};
+
+struct S3
+{
+ static int v3;
+ struct S4
+ {
+ static int v3;
+ };
+};
+
+struct S4
+{
+ static int v4;
+};
+
+int S4::v4; //expected-note{{previous definition is here}}
+int S4::v4; //expected-error{{redefinition of 'v4'}}
+
+struct S5
+{
+ static int v5; //expected-note{{previous definition is here}}
+ void v5() { } //expected-error{{redefinition of 'v5' as different kind of symbol}}
+
+ void v6() { } //expected-note{{previous definition is here}}
+ static int v6; //expected-error{{redefinition of 'v6' as different kind of symbol}}
+
+ void v7() { }
+ void v7(int) { } //expected-note{{previous definition is here}}
+ static int v7; //expected-error{{redefinition of 'v7' as different kind of symbol}}
+
+ void v8();
+ int v8(int); //expected-note{{previous declaration is here}}
+ int v8; //expected-error{{duplicate member 'v8'}}
+
+
+};
diff --git a/test/CXX/class/class.static/class.static.data/p4.cpp b/test/CXX/class/class.static/class.static.data/p4.cpp
new file mode 100644
index 000000000000..2b1eca741937
--- /dev/null
+++ b/test/CXX/class/class.static/class.static.data/p4.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+struct InClassInitializerOnly {
+ static const int i = 0;
+};
+int const InClassInitializerOnly::i;
+
+struct OutOfClassInitializerOnly {
+ static const int i;
+};
+int const OutOfClassInitializerOnly::i = 0;
+
+struct InClassInitializerAndOutOfClassCopyInitializer {
+ static const int i = 0; // expected-note{{previous definition is here}}
+};
+int const InClassInitializerAndOutOfClassCopyInitializer::i = 0; // expected-error{{redefinition of 'i'}}
+
+struct InClassInitializerAndOutOfClassDirectInitializer {
+ static const int i = 0; // expected-note{{previous definition is here}}
+};
+int const InClassInitializerAndOutOfClassDirectInitializer::i(0); // expected-error{{redefinition of 'i'}}
+
+
+
+int main() { }
+
diff --git a/test/CXX/conv/conv.ptr/p2.cpp b/test/CXX/conv/conv.ptr/p2.cpp
new file mode 100644
index 000000000000..8808d203fd91
--- /dev/null
+++ b/test/CXX/conv/conv.ptr/p2.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace pr7801 {
+ extern void* x[];
+ void* dummy[] = { &x };
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp
new file mode 100644
index 000000000000..6ffa873cd46b
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p1.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s
+
+// Intentionally compiled as C++03 to test the extension warning.
+
+namespace a {} // original
+namespace a {} // ext
+inline namespace b {} // inline original expected-warning {{inline namespaces are}}
+inline namespace b {} // inline ext expected-warning {{inline namespaces are}}
+inline namespace {} // inline unnamed expected-warning {{inline namespaces are}}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp
new file mode 100644
index 000000000000..198b0135187e
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p7.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+namespace NIL {} // expected-note {{previous definition}}
+inline namespace NIL {} // expected-error {{cannot be reopened as inline}}
+inline namespace IL {} // expected-note {{previous definition}}
+namespace IL {} // expected-error {{cannot be reopened as non-inline}}
+
+namespace {} // expected-note {{previous definition}}
+inline namespace {} // expected-error {{cannot be reopened as inline}}
+namespace X {
+ inline namespace {} // expected-note {{previous definition}}
+ namespace {} // expected-error {{cannot be reopened as non-inline}}
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp
new file mode 100644
index 000000000000..b9ad6e1c067f
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/p8.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+// Fun things you can do with inline namespaces:
+
+inline namespace X {
+ void f1();
+
+ inline namespace Y {
+ void f2();
+
+ template <typename T> class C {};
+ }
+
+ // Specialize and partially specialize somewhere else.
+ template <> class C<int> {};
+ template <typename T> class C<T*> {};
+}
+
+// Qualified and unqualified lookup as if member of enclosing NS.
+void foo1() {
+ f1();
+ ::f1();
+ X::f1();
+ Y::f1(); // expected-error {{no member named 'f1' in namespace 'X::Y'}}
+
+ f2();
+ ::f2();
+ X::f2();
+ Y::f2();
+}
+
+template <> class C<float> {};
+template <typename T> class C<T&> {};
+
+template class C<double>;
+
+
+// As well as all the fun with ADL.
+
+namespace ADL {
+ struct Outer {};
+
+ inline namespace IL {
+ struct Inner {};
+
+ void fo(Outer);
+ }
+
+ void fi(Inner);
+
+ inline namespace IL2 {
+ void fi2(Inner);
+ }
+}
+
+void foo2() {
+ ADL::Outer o;
+ ADL::Inner i;
+ fo(o);
+ fi(i);
+ fi2(i);
+}
+
+// Let's not forget overload sets.
+struct Distinct {};
+inline namespace Over {
+ void over(Distinct);
+}
+void over(int);
+
+void foo3() {
+ Distinct d;
+ ::over(d);
+}
+
+// Don't forget to do correct lookup for redeclarations.
+namespace redecl { inline namespace n1 {
+
+ template <class Tp> class allocator;
+
+ template <>
+ class allocator<void>
+ {
+ public:
+ typedef const void* const_pointer;
+ };
+
+ template <class Tp>
+ class allocator
+ {
+ public:
+ typedef Tp& reference;
+
+ void allocate(allocator<void>::const_pointer = 0);
+ };
+
+} }
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
index 27b41a755ed0..546c4a477f7b 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
@@ -31,3 +31,4 @@ namespace test1 {
using test1::foo;
}
}
+
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp
new file mode 100644
index 000000000000..4cb91cdf0021
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udir/p6.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/8296180>
+typedef int pid_t;
+namespace ns {
+ typedef int pid_t;
+}
+using namespace ns;
+pid_t x;
+
+struct A { };
+namespace ns {
+ typedef ::A A;
+}
+A a;
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
index 99a4f7aec4c8..d7b9eff10a80 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p3.cpp
@@ -1,11 +1,13 @@
// RUN: %clang_cc1 -verify %s
-// XFAIL: *
-void f0(void) {
- inline void f1(); // expected-error {{'inline' is not allowed on block scope function declaration}}
+void f0a(void) {
+ inline void f1(); // expected-error {{inline declaration of 'f1' not allowed in block scope}}
+}
+
+void f0b(void) {
+ void f1();
}
// FIXME: Add test for "If the inline specifier is used in a friend declaration,
// that declaration shall be a definition or the function shall have previously
// been declared inline.
-
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
index f507eecb4223..491ab17802e0 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
@@ -1,12 +1,11 @@
// RUN: %clang_cc1 -verify %s
-struct S; // expected-note {{forward declaration of 'S'}}
+struct S; // expected-note 2{{forward declaration of 'S'}}
extern S a;
extern S f(); // expected-note {{'f' declared here}}
-extern void g(S a); // expected-note {{candidate function}}
+extern void g(S a);
void h() {
- // FIXME: This diagnostic could be better.
- g(a); // expected-error {{no matching function for call to 'g'}}
+ g(a); // expected-error {{argument type 'S' is incomplete}}
f(); // expected-error {{calling 'f' with incomplete return type 'S'}}
}
diff --git a/test/CXX/dcl.decl/dcl.init/p5.cpp b/test/CXX/dcl.decl/dcl.init/p5.cpp
new file mode 100644
index 000000000000..b50e8d780ccd
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.init/p5.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// FIXME: Very incomplete!
+
+// A program that calls for default-initialization or value-initialization of
+// an entity of reference type is illformed. If T is a cv-qualified type, the
+// cv-unqualified version of T is used for these definitions of
+// zero-initialization, default-initialization, and value-initialization.
+//
+// FIXME: The diagnostics for these errors are terrible because they fall out
+// of the AST representation rather than being explicitly issued during the
+// respective initialization forms.
+struct S { // expected-error {{implicit default constructor for 'S' must explicitly initialize the reference member}} \
+ // expected-note {{candidate constructor (the implicit copy constructor) not viable}}
+ int& x; // expected-note {{declared here}}
+};
+S s; // expected-note {{implicit default constructor for 'S' first required here}}
+S f() {
+ return S(); // expected-error {{no matching constructor for initialization of 'S'}}
+}
diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
new file mode 100644
index 000000000000..170c734fd307
--- /dev/null
+++ b/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// rdar://problem/8347416
+namespace test0 {
+ struct A {
+ void foo(void (A::*)(int)); // expected-note {{passing argument to parameter here}}
+ template<typename T> void g(T);
+
+ void test() {
+ // FIXME: this diagnostic is terrible
+ foo(&g<int>); // expected-error {{cannot initialize a parameter of type 'void (test0::A::*)(int)' with an rvalue of type '<overloaded function type>'}}
+ }
+ };
+}
+
+// This should succeed.
+namespace test1 {
+ struct A {
+ static void f(void (A::*)());
+ static void f(void (*)(int));
+ void g();
+ static void g(int);
+
+ void test() {
+ f(&g);
+ }
+ };
+}
+
+// Also rdar://problem/8347416
+namespace test2 {
+ struct A {
+ static int foo(short);
+ static int foo(float);
+ int foo(int);
+ int foo(double);
+
+ void test();
+ };
+
+ void A::test() {
+ // FIXME: This diagnostic is terrible.
+ int (A::*ptr)(int) = &(A::foo); // expected-error {{cannot initialize a variable of type 'int (test2::A::*)(int)' with an rvalue of type '<overloaded function type>'}}
+ }
+}
diff --git a/test/CXX/special/class.dtor/p9.cpp b/test/CXX/special/class.dtor/p9.cpp
new file mode 100644
index 000000000000..8b76a15078b7
--- /dev/null
+++ b/test/CXX/special/class.dtor/p9.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef typeof(sizeof(int)) size_t;
+
+// PR7803
+namespace test0 {
+ class A {
+ public:
+ static void operator delete(void *p) {};
+ virtual ~A();
+ };
+
+ class B : protected A {
+ public:
+ ~B();
+ };
+
+ class C : protected B {
+ public:
+ using B::operator delete;
+ ~C();
+ };
+
+ // Shouldn't have an error.
+ C::~C() {}
+}
+
+namespace test1 {
+ class A {
+ public:
+ static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}}
+ virtual ~A();
+ };
+
+ class B : protected A {
+ public:
+ static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}}
+ ~B();
+ };
+
+ class C : protected B {
+ public:
+ using A::operator delete;
+ using B::operator delete;
+
+ ~C();
+ };
+
+ C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}}
+}
+
+// ...at the point of definition of a virtual destructor...
+namespace test2 {
+ struct A {
+ virtual ~A();
+ static void operator delete(void*, const int &);
+ };
+
+ struct B {
+ virtual ~B();
+ static void operator delete(void*, const int &); // expected-note {{declared here}}
+ };
+ B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}}
+
+ struct CBase { virtual ~CBase(); };
+ struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}}
+ static void operator delete(void*, const int &); // expected-note {{declared here}}
+ };
+ void test() {
+ C c; // expected-note {{first required here}}
+ }
+}
+
+// PR7346
+namespace test3 {
+ struct A {
+ virtual ~A();
+ static void operator delete(void*, const int &);
+ };
+
+ struct B : A {
+ virtual ~B() {}
+ static void operator delete(void*);
+ };
+}
diff --git a/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp b/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp
new file mode 100644
index 000000000000..6f6286f71078
--- /dev/null
+++ b/test/CXX/temp/temp.arg/temp.arg.type/p2-cxx0x.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s
+
+// C++03 imposed restrictions in this paragraph that were lifted with 0x, so we
+// just test that the example given now parses cleanly.
+
+template <class T> class X { };
+template <class T> void f(T t) { }
+struct { } unnamed_obj;
+void f() {
+ struct A { };
+ enum { e1 };
+ typedef struct { } B;
+ B b;
+ X<A> x1;
+ X<A*> x2;
+ X<B> x3;
+ f(e1);
+ f(unnamed_obj);
+ f(b);
+}
diff --git a/test/CXX/temp/temp.decls/temp.friend/p4.cpp b/test/CXX/temp/temp.decls/temp.friend/p4.cpp
index 226ac0fc622f..e036cef32b28 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p4.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p4.cpp
@@ -8,3 +8,21 @@ struct X1 {
X1<int> x1a;
X1<float> x1b; // expected-note {{in instantiation of}}
+
+template<typename T>
+struct X2 {
+ operator int();
+
+ friend void f(int x) { } // expected-error{{redefinition}} \
+ // expected-note{{previous definition}}
+};
+
+int array0[sizeof(X2<int>)];
+int array1[sizeof(X2<float>)]; // expected-note{{instantiation of}}
+
+void g() {
+ X2<int> xi;
+ f(xi);
+ X2<float> xf;
+ f(xf);
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp
index f6121b373e13..6481485b2a08 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s
+// RUN: %clang_cc1 -verify %s
typedef char one_byte;
struct two_bytes { char data[2]; };
@@ -15,3 +15,28 @@ struct X { };
int array0[is_class<X>::value? 1 : -1];
int array1[is_class<int>::value? -1 : 1];
int array2[is_class<char[3]>::value? -1 : 1];
+
+namespace instantiation_order1 {
+ template<typename T>
+ struct it_is_a_trap {
+ typedef typename T::trap type;
+ };
+
+ template<bool, typename T = void>
+ struct enable_if {
+ typedef T type;
+ };
+
+ template<typename T>
+ struct enable_if<false, T> { };
+
+ template<typename T>
+ typename enable_if<sizeof(T) == 17>::type
+ f(const T&, typename it_is_a_trap<T>::type* = 0);
+
+ void f(...);
+
+ void test_f() {
+ f('a');
+ }
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp
index 1b240cc98fc7..16b5cd297d8b 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp
@@ -93,3 +93,21 @@ namespace test1 {
invoke(&temp2<int, int>); // expected-error {{no matching function for call to 'invoke'}}
}
}
+
+namespace rdar8360106 {
+ template<typename R, typename T> void f0(R (*)(T), T);
+ template<typename R, typename T> void f1(R (&)(T) , T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}}
+ template<typename R, typename T> void f2(R (* const&)(T), T); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}}
+
+ int g(int);
+ int g(int, int);
+
+ void h() {
+ f0(g, 1);
+ f0(&g, 1);
+ f1(g, 1);
+ f1(&g, 1); // expected-error{{no matching function for call to 'f1'}}
+ f2(g, 1); // expected-error{{no matching function for call to 'f2'}}
+ f2(&g, 1);
+ }
+}
diff --git a/test/CXX/temp/temp.param/p4.cpp b/test/CXX/temp/temp.param/p4.cpp
index 5ec402a45bf5..809fb20b4a3a 100644
--- a/test/CXX/temp/temp.param/p4.cpp
+++ b/test/CXX/temp/temp.param/p4.cpp
@@ -17,4 +17,5 @@ template<typename T, T x> struct A10;
template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}}
-template<void *Ptr> struct A12; // expected-error{{a non-type template parameter cannot have type 'void *'}}
+template<void *Ptr> struct A12;
+template<int (*IncompleteArrayPtr)[]> struct A13;
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
index e9758bcdec2c..48c42c399a46 100644
--- a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
@@ -2,8 +2,9 @@
// A declaration of a function template shall be in scope at the point of the
// explicit instantiation of the function template.
-template<typename T> void f0(T) { }
+template<typename T> void f0(T);
template void f0(int); // okay
+template<typename T> void f0(T) { }
// A definition of the class or class template containing a member function
// template shall be in scope at the point of the explicit instantiation of
@@ -47,3 +48,27 @@ template X2<int>::X2(); // expected-error{{not an instantiation}}
template X2<int>::X2(const X2&); // expected-error{{not an instantiation}}
template X2<int>::~X2(); // expected-error{{not an instantiation}}
template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}}
+
+
+// A definition of a class template is sufficient to explicitly
+// instantiate a member of the class template which itself is not yet defined.
+namespace PR7979 {
+ template <typename T> struct S {
+ void f();
+ static void g();
+ static int i;
+ struct S2 {
+ void h();
+ };
+ };
+
+ template void S<int>::f();
+ template void S<int>::g();
+ template int S<int>::i;
+ template void S<int>::S2::h();
+
+ template <typename T> void S<T>::f() {}
+ template <typename T> void S<T>::g() {}
+ template <typename T> int S<T>::i;
+ template <typename T> void S<T>::S2::h() {}
+}
diff --git a/test/CodeCompletion/enum-switch-case.c b/test/CodeCompletion/enum-switch-case.c
index 082072600ffe..d5df37115222 100644
--- a/test/CodeCompletion/enum-switch-case.c
+++ b/test/CodeCompletion/enum-switch-case.c
@@ -18,11 +18,28 @@ void test(enum Color color) {
case Green:
break;
-
+ }
+
+ unsigned c2;
+ switch (c2) {
+ case
+ }
+
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:19:10 %s -o - | FileCheck -check-prefix=CC1 %s
// CHECK-CC1: Blue
// CHECK-CC1-NEXT: Green
// CHECK-CC1-NEXT: Indigo
// CHECK-CC1-NEXT: Orange
// CHECK-CC1-NEXT: Violet
-
+
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:25:10 %s -o - | FileCheck -check-prefix=CC2 %s
+ // CHECK-CC2: COMPLETION: Blue : [#enum Color#]Blue
+ // CHECK-CC2-NEXT: COMPLETION: c2 : [#unsigned int#]c2
+ // CHECK-CC2-NEXT: COMPLETION: color : [#enum Color#]color
+ // CHECK-CC2-NEXT: COMPLETION: Green : [#enum Color#]Green
+ // CHECK-CC2-NEXT: COMPLETION: Indigo : [#enum Color#]Indigo
+ // CHECK-CC2-NEXT: COMPLETION: Orange : [#enum Color#]Orange
+ // CHECK-CC2-NEXT: COMPLETION: Red : [#enum Color#]Red
+ // CHECK-CC2-NEXT: COMPLETION: Pattern : sizeof(<#expression-or-type#>)
+ // CHECK-CC2-NEXT: COMPLETION: Violet : [#enum Color#]Violet
+ // CHECK-CC2-NEXT: COMPLETION: Yellow : [#enum Color#]Yellow
diff --git a/test/CodeCompletion/functions.cpp b/test/CodeCompletion/functions.cpp
index 6838de36e846..fcab3dcbe120 100644
--- a/test/CodeCompletion/functions.cpp
+++ b/test/CodeCompletion/functions.cpp
@@ -5,4 +5,4 @@ void test() {
::
// RUN: %clang_cc1 -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#><#, ...#>)
+ // CHECK-CC1: f(<#float x#>, <#float y, ...#>)
diff --git a/test/CodeGen/2009-04-23-dbg.c b/test/CodeGen/2009-04-23-dbg.c
index 6a8bf01ba86f..704aba244fc1 100644
--- a/test/CodeGen/2009-04-23-dbg.c
+++ b/test/CodeGen/2009-04-23-dbg.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -g -o %t %s -emit-llvm-bc && llc %t -o %t.s
+// RUN: %clang_cc1 -S -g -o %t %s
# 1 "a.c"
# 1 "a.c" 1
# 1 "<built-in>" 1
diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c
index 1db37de4bb27..3c46bea37986 100644
--- a/test/CodeGen/2009-10-20-GlobalDebug.c
+++ b/test/CodeGen/2009-10-20-GlobalDebug.c
@@ -1,7 +1,7 @@
// RUN: %clang -ccc-host-triple i386-apple-darwin10 -S -g -dA %s -o - | FileCheck %s
int global;
+// CHECK: ascii "localstatic" ## DW_AT_name
// CHECK: asciz "global" ## External Name
-// CHECK: asciz "localstatic" ## External Name
int main() {
static int localstatic;
return 0;
diff --git a/test/CodeGen/2010-08-10-DbgConstant.c b/test/CodeGen/2010-08-10-DbgConstant.c
new file mode 100644
index 000000000000..5b8f06470c8f
--- /dev/null
+++ b/test/CodeGen/2010-08-10-DbgConstant.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -S -emit-llvm -g %s -o - | grep DW_TAG_variable
+
+static const unsigned int ro = 201;
+void bar(int);
+void foo() { bar(ro); }
diff --git a/test/CodeGen/_Bool-conversion.c b/test/CodeGen/_Bool-conversion.c
new file mode 100644
index 000000000000..9e5e89450314
--- /dev/null
+++ b/test/CodeGen/_Bool-conversion.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple i386 -emit-llvm -O2 -o - %s | FileCheck %s
+
+// CHECK: define i32 @f0()
+// CHECK: ret i32 1
+// CHECK: }
+
+static _Bool f0_0(void *a0) { return (_Bool) a0; }
+int f0() { return f0_0((void*) 0x2); }
+
+_Bool f1(void) {
+ return (_Bool) ({ void (*x)(); x = 0; });
+}
diff --git a/test/CodeGen/address-space-field1.c b/test/CodeGen/address-space-field1.c
index a81e08ebcaea..e9c18712f289 100644
--- a/test/CodeGen/address-space-field1.c
+++ b/test/CodeGen/address-space-field1.c
@@ -1,22 +1,22 @@
-// RUN: %clang_cc1 -emit-llvm < %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 < %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: [[p1addr:%.*]] = alloca %struct.S addrspace(1)*
// CHECK: [[p2addr:%.*]] = alloca %struct.S addrspace(2)*
// 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: [[t0:%.*]] = load %struct.S addrspace(2)** [[p2addr]], align 8
+// CHECK: [[t1:%.*]] = getelementptr inbounds %struct.S addrspace(2)* [[t0]], i32 0, i32 1
+// CHECK: [[t2:%.*]] = load i32 addrspace(2)* [[t1]], align 4
+// CHECK: [[t3:%.*]] = load %struct.S addrspace(1)** [[p1addr]], align 8
+// CHECK: [[t4:%.*]] = getelementptr inbounds %struct.S addrspace(1)* [[t3]], i32 0, i32 0
+// CHECK: store i32 [[t2]], i32 addrspace(1)* [[t4]], align 4
+// CHECK: [[t5:%.*]] = load %struct.S addrspace(2)** [[p2addr]], align 8
+// CHECK: [[t6:%.*]] = getelementptr inbounds %struct.S addrspace(2)* [[t5]], i32 0, i32 0
+// CHECK: [[t7:%.*]] = load i32 addrspace(2)* [[t6]], align 4
+// CHECK: [[t8:%.*]] = load %struct.S addrspace(1)** [[p1addr]], align 8
+// CHECK: [[t9:%.*]] = getelementptr inbounds %struct.S addrspace(1)* [[t8]], i32 0, i32 1
+// CHECK: store i32 [[t7]], i32 addrspace(1)* [[t9]], align 4
// CHECK: ret void
// CHECK:}
diff --git a/test/CodeGen/address-space-field2.c b/test/CodeGen/address-space-field2.c
deleted file mode 100644
index 9c21cab3a566..000000000000
--- a/test/CodeGen/address-space-field2.c
+++ /dev/null
@@ -1,46 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-
-// Check that we don't lose the address space when accessing an array element
-// inside a structure.
-
-#define __addr1 __attribute__((address_space(1)))
-#define __addr2 __attribute__((address_space(2)))
-
-typedef struct S {
- int arr[ 3 ];
-} S;
-
-void test_addrspace(__addr1 S* p1, __addr2 S*p2, int* val, int n) {
- for (int i=0; i < 3; ++i) {
- int t = val[i];
- p1->arr[i] = t;
- for (int j=0; j < n; ++j)
- p2[j].arr[i] = t;
- }
-}
diff --git a/test/CodeGen/address-space-field3.c b/test/CodeGen/address-space-field3.c
deleted file mode 100644
index c17085cdf48b..000000000000
--- a/test/CodeGen/address-space-field3.c
+++ /dev/null
@@ -1,42 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-
-// Check that we don't lose the address space when accessing an array element
-// inside a structure.
-
-#define __addr1 __attribute__((address_space(1)))
-#define __addr2 __attribute__((address_space(2)))
-
-typedef struct S {
- int arr[ 3 ];
-} S;
-
-void test_addrspace(__addr1 S* p1, __addr2 S*p2, int* val, int n) {
- for (int i=0; i < 3; ++i) {
- int t = val[i];
- p1->arr[i] = p2->arr[i];
- }
-}
diff --git a/test/CodeGen/address-space-field4.c b/test/CodeGen/address-space-field4.c
deleted file mode 100644
index a896ab652d98..000000000000
--- a/test/CodeGen/address-space-field4.c
+++ /dev/null
@@ -1,55 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
-// CHECK: addrspace(2)
-// CHECK: addrspace(3)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(3)
-// CHECK: addrspace(3)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(1)
-// CHECK: addrspace(2)
-// CHECK: addrspace(2)
-
-// Check the load and store are using the correct address space to access
-// the variables.
-
-#define __addr1 __attribute__((address_space(1)))
-#define __addr2 __attribute__((address_space(2)))
-#define __addr3 __attribute__((address_space(3)))
-
-typedef struct Pair {
- __addr2 int* a;
- __addr3 int* b;
-} Pair;
-
-typedef struct S {
- Pair arr[ 3 ];
-} S;
-
-void test_addrspace(__addr1 S* p1, __addr1 S* p2) {
- *p1->arr[0].a = *p2->arr[1].b;
-}
diff --git a/test/CodeGen/asm-errors.c b/test/CodeGen/asm-errors.c
index 7323e61b591a..aea5cb247fa8 100644
--- a/test/CodeGen/asm-errors.c
+++ b/test/CodeGen/asm-errors.c
@@ -1,4 +1,4 @@
-// RUN: not %clang_cc1 -triple i386-apple-darwin10 -emit-obj %s > %t 2>&1
+// RUN: not %clang_cc1 -triple i386-apple-darwin10 -emit-obj %s -o /dev/null > %t 2>&1
// RUN: FileCheck %s < %t
int test1(int X) {
diff --git a/test/CodeGen/asm-inout.c b/test/CodeGen/asm-inout.c
new file mode 100644
index 000000000000..f04276693e2c
--- /dev/null
+++ b/test/CodeGen/asm-inout.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+// PR3800
+int *foo(void);
+
+// CHECK: @test1
+void test1() {
+ // CHECK: [[REGCALLRESULT:%[a-zA-Z0-9\.]+]] = call i32* @foo()
+ // CHECK: call void asm "foobar", "=*m,*m,~{dirflag},~{fpsr},~{flags}"(i32* [[REGCALLRESULT]], i32* [[REGCALLRESULT]])
+ asm ("foobar" : "+m"(*foo()));
+}
+
+// CHECK: @test2
+void test2() {
+ // CHECK: [[REGCALLRESULT:%[a-zA-Z0-9\.]+]] = call i32* @foo()
+ // CHECK: load i32* [[REGCALLRESULT]]
+ // CHECK: call i32 asm
+ // CHECK: store i32 {{%[a-zA-Z0-9\.]+}}, i32* [[REGCALLRESULT]]
+ asm ("foobar" : "+r"(*foo()));
+}
diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c
index 507702887866..eb112858718c 100644
--- a/test/CodeGen/asm.c
+++ b/test/CodeGen/asm.c
@@ -168,3 +168,25 @@ float t21(long double x) {
// CHECK: call x86_fp80 asm sideeffect "frndint"
// CHECK-NEXT: fptrunc x86_fp80 {{.*}} to float
}
+
+// <rdar://problem/8348447> - accept 'l' constraint
+unsigned char t22(unsigned char a, unsigned char b) {
+ unsigned int la = a;
+ unsigned int lb = b;
+ unsigned int bigres;
+ unsigned char res;
+ __asm__ ("0:\n1:\n" : [bigres] "=la"(bigres) : [la] "0"(la), [lb] "c"(lb) :
+ "edx", "cc");
+ res = bigres;
+ return res;
+}
+
+// <rdar://problem/8348447> - accept 'l' constraint
+unsigned char t23(unsigned char a, unsigned char b) {
+ unsigned int la = a;
+ unsigned int lb = b;
+ unsigned char res;
+ __asm__ ("0:\n1:\n" : [res] "=la"(res) : [la] "0"(la), [lb] "c"(lb) :
+ "edx", "cc");
+ return res;
+}
diff --git a/test/CodeGen/asm_arm.c b/test/CodeGen/asm_arm.c
index aac47d57dc5a..633bf5569dd6 100644
--- a/test/CodeGen/asm_arm.c
+++ b/test/CodeGen/asm_arm.c
@@ -30,3 +30,25 @@ void test4(float *a, float *b) {
"vst1.32 {q4}, [%0,:128] \n\t"
:: "r"(a), "r"(b));
}
+
+// {sp, lr, pc} are the canonical names for {r13, r14, r15}.
+//
+// CHECK: @test5
+// CHECK: call void asm sideeffect "", "~{sp},~{lr},~{pc},~{sp},~{lr},~{pc}"()
+void test5() {
+ __asm__("" : : : "r13", "r14", "r15", "sp", "lr", "pc");
+}
+
+// CHECK: @test6
+// CHECK: call void asm sideeffect "", "
+// CHECK: ~{s0},~{s1},~{s2},~{s3},~{s4},~{s5},~{s6},~{s7},
+// CHECK: ~{s8},~{s9},~{s10},~{s11},~{s12},~{s13},~{s14},~{s15},
+// CHECK: ~{s16},~{s17},~{s18},~{s19},~{s20},~{s21},~{s22},~{s23},
+// CHECK: ~{s24},~{s25},~{s26},~{s27},~{s28},~{s29},~{s30},~{s31}"()
+void test6() {
+ __asm__("" : : :
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31");
+}
diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c
index aa5aa1507b03..d0a7e04eaa92 100644
--- a/test/CodeGen/atomic.c
+++ b/test/CodeGen/atomic.c
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 > %t1
-// RUN: grep @llvm.memory.barrier %t1 | count 38
+// RUN: grep @llvm.memory.barrier %t1 | count 42
// 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
@@ -7,7 +7,7 @@
// 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.cmp.swap.i32 %t1 | count 5
// RUN: grep @llvm.atomic.load.and.i32 %t1
// RUN: grep @llvm.atomic.load.or.i8 %t1
// RUN: grep @llvm.atomic.load.xor.i8 %t1
@@ -19,6 +19,7 @@ int atomic(void)
int old;
int val = 1;
char valc = 1;
+ _Bool valb = 0;
unsigned int uval = 1;
int cmp = 0;
@@ -43,10 +44,18 @@ int atomic(void)
__sync_val_compare_and_swap((void **)0, (void *)0, (void *)0);
-
+ if ( __sync_val_compare_and_swap(&valb, 0, 1)) {
+ old = 42;
+ }
+ __sync_bool_compare_and_swap((void **)0, (void *)0, (void *)0);
__sync_lock_release(&val);
__sync_synchronize ();
return old;
}
+
+void release_return(int *lock) {
+ // Ensure this is actually returning void all the way through.
+ return __sync_lock_release(lock);
+}
diff --git a/test/CodeGen/available-externally-suppress.c b/test/CodeGen/available-externally-suppress.c
index c3b7a213baf6..747d3cd35755 100644
--- a/test/CodeGen/available-externally-suppress.c
+++ b/test/CodeGen/available-externally-suppress.c
@@ -10,3 +10,18 @@ inline void f0(int y) { x = y; }
void test() {
f0(17);
}
+
+inline int __attribute__((always_inline)) f1(int x) {
+ int blarg = 0;
+ for (int i = 0; i < x; ++i)
+ blarg = blarg + x * i;
+ return blarg;
+}
+
+// CHECK: @test1
+int test1(int x) {
+ // CHECK: br i1
+ // CHECK-NOT: call
+ // CHECK: ret i32
+ return f1(x);
+}
diff --git a/test/CodeGen/bitfield-2.c b/test/CodeGen/bitfield-2.c
index e91859fb7287..8de432faa8ae 100644
--- a/test/CodeGen/bitfield-2.c
+++ b/test/CodeGen/bitfield-2.c
@@ -12,7 +12,7 @@
// CHECK-RECORD: Record: struct s0
// CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:<{ [3 x i8] }>
-// CHECK-RECORD: ContainsPointerToDataMember:0
+// CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:24 IsSigned:1
// CHECK-RECORD: NumComponents:2 Components: [
@@ -57,7 +57,7 @@ unsigned long long test_0() {
// CHECK-RECORD: Record: struct s1
// CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:<{ [2 x i8], i8 }>
-// CHECK-RECORD: ContainsPointerToDataMember:0
+// CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:10 IsSigned:1
// CHECK-RECORD: NumComponents:1 Components: [
@@ -114,7 +114,7 @@ unsigned long long test_1() {
// CHECK-RECORD: Record: union u2
// CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:<{ i8 }>
-// CHECK-RECORD: ContainsPointerToDataMember:0
+// CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:3 IsSigned:0
// CHECK-RECORD: NumComponents:1 Components: [
@@ -289,7 +289,7 @@ _Bool test_6() {
// CHECK-RECORD: Record: struct s7
// CHECK-RECORD: Layout: <CGRecordLayout
// CHECK-RECORD: LLVMType:{ i32, i32, i32, i8, [3 x i8], [4 x i8], [12 x i8] }
-// CHECK-RECORD: ContainsPointerToDataMember:0
+// CHECK-RECORD: IsZeroInitializable:1
// CHECK-RECORD: BitFields:[
// CHECK-RECORD: <CGBitFieldInfo Size:5 IsSigned:1
// CHECK-RECORD: NumComponents:1 Components: [
diff --git a/test/CodeGen/block-decl-merging.c b/test/CodeGen/block-decl-merging.c
new file mode 100644
index 000000000000..1e7a9f4e92cb
--- /dev/null
+++ b/test/CodeGen/block-decl-merging.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -fblocks -emit-llvm -o - %s | \
+// RUN: FileCheck %s
+
+// CHECK: @_NSConcreteGlobalBlock = extern_weak global
+extern void * _NSConcreteStackBlock[32] __attribute__((weak_import));
+// CHECK: @_NSConcreteStackBlock = extern_weak global
+extern void * _NSConcreteGlobalBlock[32] __attribute__((weak_import));
+extern void _Block_object_dispose(const void *, const int) __attribute__((weak_import));
+// CHECK: declare extern_weak void @_Block_object_assign
+extern void _Block_object_assign(void *, const void *, const int) __attribute__((weak_import));
+// CHECK: declare extern_weak void @_Block_object_dispose
+
+void *x = ^(){};
+
+void f1(void (^a0)(void));
+
+void f0() {
+ __block int x;
+ f1(^(void){ x = 1; });
+}
diff --git a/test/CodeGen/blockstret.c b/test/CodeGen/blockstret.c
index 09292b809f5a..f630f22b1676 100644
--- a/test/CodeGen/blockstret.c
+++ b/test/CodeGen/blockstret.c
@@ -98,8 +98,8 @@ int main(int argc, char *argv[]) {
/*
desired global flags: 1879048192
desired stack flags: 1610612736
-should be non-zero: 0
-should be non-zero: 0
+should be non-zero: 1
+should be non-zero: 1
should be non-zero: 1
should be zero: 0
diff --git a/test/CodeGen/builtin-expect.c b/test/CodeGen/builtin-expect.c
new file mode 100644
index 000000000000..8f02c4da78a4
--- /dev/null
+++ b/test/CodeGen/builtin-expect.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+int x;
+int y(void);
+void foo();
+void FUNC() {
+// CHECK: [[call:%.*]] = call i32 @y
+ if (__builtin_expect (x, y()))
+ foo ();
+}
+
diff --git a/test/CodeGen/builtins-arm.c b/test/CodeGen/builtins-arm.c
index 546f57a4a18a..09df1ef42c74 100644
--- a/test/CodeGen/builtins-arm.c
+++ b/test/CodeGen/builtins-arm.c
@@ -9,4 +9,4 @@ void f1(char *a, char *b) {
__clear_cache(a,b);
}
-// CHECK: call void @__clear_cache
+// CHECK: call {{.*}} @__clear_cache
diff --git a/test/CodeGen/builtins-ppc-altivec.c b/test/CodeGen/builtins-ppc-altivec.c
index 6f65866ae56a..8627499cdc77 100644
--- a/test/CodeGen/builtins-ppc-altivec.c
+++ b/test/CodeGen/builtins-ppc-altivec.c
@@ -1,31 +1,25 @@
// RUN: %clang_cc1 -faltivec -triple powerpc-unknown-unknown -emit-llvm %s -o - | FileCheck %s
-// TODO: uncomment
-/* vector bool char vbc = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }; */
+vector bool char vbc = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
vector signed char vsc = { 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16 };
vector unsigned char vuc = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
-// TODO: uncomment
-/* vector bool short vbs = { 1, 0, 1, 0, 1, 0, 1, 0 }; */
+vector bool short vbs = { 1, 0, 1, 0, 1, 0, 1, 0 };
vector short vs = { -1, 2, -3, 4, -5, 6, -7, 8 };
vector unsigned short vus = { 1, 2, 3, 4, 5, 6, 7, 8 };
-// TODO: uncomment
-/* vector bool int vbi = { 1, 0, 1, 0 }; */
+vector pixel vp = { 1, 2, 3, 4, 5, 6, 7, 8 };
+vector bool int vbi = { 1, 0, 1, 0 };
vector int vi = { -1, 2, -3, 4 };
vector unsigned int vui = { 1, 2, 3, 4 };
vector float vf = { -1.5, 2.5, -3.5, 4.5 };
-// TODO: uncomment
-/* vector bool char res_vbc; */
+vector bool char res_vbc;
vector signed char res_vsc;
vector unsigned char res_vuc;
-// TODO: uncomment
-/* vector bool short res_vbs; */
+vector bool short res_vbs;
vector short res_vs;
vector unsigned short res_vus;
-// TODO: uncomment
vector pixel res_vp;
-// TODO: uncomment
-/* vector bool int res_vbi; */
+vector bool int res_vbi;
vector int res_vi;
vector unsigned int res_vui;
vector float res_vf;
@@ -40,8 +34,8 @@ float param_f;
int res_i;
-int test1() {
-// CHECK: define i32 @test1
+// CHECK: define void @test1
+void test1() {
/* vec_abs */
vsc = vec_abs(vsc); // CHECK: sub nsw <16 x i8> zeroinitializer
@@ -67,18 +61,42 @@ int test1() {
/* vec_add */
res_vsc = vec_add(vsc, vsc); // CHECK: add nsw <16 x i8>
+ res_vsc = vec_add(vbc, vsc); // CHECK: add nsw <16 x i8>
+ res_vsc = vec_add(vsc, vbc); // CHECK: add nsw <16 x i8>
res_vuc = vec_add(vuc, vuc); // CHECK: add <16 x i8>
+ res_vuc = vec_add(vbc, vuc); // CHECK: add <16 x i8>
+ res_vuc = vec_add(vuc, vbc); // CHECK: add <16 x i8>
res_vs = vec_add(vs, vs); // CHECK: add nsw <8 x i16>
+ res_vs = vec_add(vbs, vs); // CHECK: add nsw <8 x i16>
+ res_vs = vec_add(vs, vbs); // CHECK: add nsw <8 x i16>
res_vus = vec_add(vus, vus); // CHECK: add <8 x i16>
+ res_vus = vec_add(vbs, vus); // CHECK: add <8 x i16>
+ res_vus = vec_add(vus, vbs); // CHECK: add <8 x i16>
res_vi = vec_add(vi, vi); // CHECK: add nsw <4 x i32>
+ res_vi = vec_add(vbi, vi); // CHECK: add nsw <4 x i32>
+ res_vi = vec_add(vi, vbi); // CHECK: add nsw <4 x i32>
res_vui = vec_add(vui, vui); // CHECK: add <4 x i32>
+ res_vui = vec_add(vbi, vui); // CHECK: add <4 x i32>
+ res_vui = vec_add(vui, vbi); // CHECK: add <4 x i32>
res_vf = vec_add(vf, vf); // CHECK: fadd <4 x float>
res_vsc = vec_vaddubm(vsc, vsc); // CHECK: add nsw <16 x i8>
+ res_vsc = vec_vaddubm(vbc, vsc); // CHECK: add nsw <16 x i8>
+ res_vsc = vec_vaddubm(vsc, vbc); // CHECK: add nsw <16 x i8>
res_vuc = vec_vaddubm(vuc, vuc); // CHECK: add <16 x i8>
+ res_vuc = vec_vaddubm(vbc, vuc); // CHECK: add <16 x i8>
+ res_vuc = vec_vaddubm(vuc, vbc); // CHECK: add <16 x i8>
res_vs = vec_vadduhm(vs, vs); // CHECK: add nsw <8 x i16>
+ res_vs = vec_vadduhm(vbs, vs); // CHECK: add nsw <8 x i16>
+ res_vs = vec_vadduhm(vs, vbs); // CHECK: add nsw <8 x i16>
res_vus = vec_vadduhm(vus, vus); // CHECK: add <8 x i16>
+ res_vus = vec_vadduhm(vbs, vus); // CHECK: add <8 x i16>
+ res_vus = vec_vadduhm(vus, vbs); // CHECK: add <8 x i16>
res_vi = vec_vadduwm(vi, vi); // CHECK: add nsw <4 x i32>
+ res_vi = vec_vadduwm(vbi, vi); // CHECK: add nsw <4 x i32>
+ res_vi = vec_vadduwm(vi, vbi); // CHECK: add nsw <4 x i32>
res_vui = vec_vadduwm(vui, vui); // CHECK: add <4 x i32>
+ res_vui = vec_vadduwm(vbi, vui); // CHECK: add <4 x i32>
+ res_vui = vec_vadduwm(vui, vbi); // CHECK: add <4 x i32>
res_vf = vec_vaddfp(vf, vf); // CHECK: fadd <4 x float>
/* vec_addc */
@@ -87,80 +105,231 @@ int test1() {
/* vec_adds */
res_vsc = vec_adds(vsc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs
+ res_vsc = vec_adds(vbc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs
+ res_vsc = vec_adds(vsc, vbc); // CHECK: @llvm.ppc.altivec.vaddsbs
res_vuc = vec_adds(vuc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs
+ res_vuc = vec_adds(vbc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs
+ res_vuc = vec_adds(vuc, vbc); // CHECK: @llvm.ppc.altivec.vaddubs
res_vs = vec_adds(vs, vs); // CHECK: @llvm.ppc.altivec.vaddshs
+ res_vs = vec_adds(vbs, vs); // CHECK: @llvm.ppc.altivec.vaddshs
+ res_vs = vec_adds(vs, vbs); // CHECK: @llvm.ppc.altivec.vaddshs
res_vus = vec_adds(vus, vus); // CHECK: @llvm.ppc.altivec.vadduhs
+ res_vus = vec_adds(vbs, vus); // CHECK: @llvm.ppc.altivec.vadduhs
+ res_vus = vec_adds(vus, vbs); // CHECK: @llvm.ppc.altivec.vadduhs
res_vi = vec_adds(vi, vi); // CHECK: @llvm.ppc.altivec.vaddsws
+ res_vi = vec_adds(vbi, vi); // CHECK: @llvm.ppc.altivec.vaddsws
+ res_vi = vec_adds(vi, vbi); // CHECK: @llvm.ppc.altivec.vaddsws
res_vui = vec_adds(vui, vui); // CHECK: @llvm.ppc.altivec.vadduws
+ res_vui = vec_adds(vbi, vui); // CHECK: @llvm.ppc.altivec.vadduws
+ res_vui = vec_adds(vui, vbi); // CHECK: @llvm.ppc.altivec.vadduws
res_vsc = vec_vaddsbs(vsc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs
+ res_vsc = vec_vaddsbs(vbc, vsc); // CHECK: @llvm.ppc.altivec.vaddsbs
+ res_vsc = vec_vaddsbs(vsc, vbc); // CHECK: @llvm.ppc.altivec.vaddsbs
res_vuc = vec_vaddubs(vuc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs
+ res_vuc = vec_vaddubs(vbc, vuc); // CHECK: @llvm.ppc.altivec.vaddubs
+ res_vuc = vec_vaddubs(vuc, vbc); // CHECK: @llvm.ppc.altivec.vaddubs
res_vs = vec_vaddshs(vs, vs); // CHECK: @llvm.ppc.altivec.vaddshs
+ res_vs = vec_vaddshs(vbs, vs); // CHECK: @llvm.ppc.altivec.vaddshs
+ res_vs = vec_vaddshs(vs, vbs); // CHECK: @llvm.ppc.altivec.vaddshs
res_vus = vec_vadduhs(vus, vus); // CHECK: @llvm.ppc.altivec.vadduhs
+ res_vus = vec_vadduhs(vbs, vus); // CHECK: @llvm.ppc.altivec.vadduhs
+ res_vus = vec_vadduhs(vus, vbs); // CHECK: @llvm.ppc.altivec.vadduhs
res_vi = vec_vaddsws(vi, vi); // CHECK: @llvm.ppc.altivec.vaddsws
+ res_vi = vec_vaddsws(vbi, vi); // CHECK: @llvm.ppc.altivec.vaddsws
+ res_vi = vec_vaddsws(vi, vbi); // CHECK: @llvm.ppc.altivec.vaddsws
res_vui = vec_vadduws(vui, vui); // CHECK: @llvm.ppc.altivec.vadduws
+ res_vui = vec_vadduws(vbi, vui); // CHECK: @llvm.ppc.altivec.vadduws
+ res_vui = vec_vadduws(vui, vbi); // CHECK: @llvm.ppc.altivec.vadduws
/* vec_and */
res_vsc = vec_and(vsc, vsc); // CHECK: and <16 x i8>
+ res_vsc = vec_and(vbc, vsc); // CHECK: and <16 x i8>
+ res_vsc = vec_and(vsc, vbc); // CHECK: and <16 x i8>
res_vuc = vec_and(vuc, vuc); // CHECK: and <16 x i8>
+ res_vuc = vec_and(vbc, vuc); // CHECK: and <16 x i8>
+ res_vuc = vec_and(vuc, vbc); // CHECK: and <16 x i8>
+ res_vbc = vec_and(vbc, vbc); // CHECK: and <16 x i8>
res_vs = vec_and(vs, vs); // CHECK: and <8 x i16>
+ res_vs = vec_and(vbs, vs); // CHECK: and <8 x i16>
+ res_vs = vec_and(vs, vbs); // CHECK: and <8 x i16>
res_vus = vec_and(vus, vus); // CHECK: and <8 x i16>
+ res_vus = vec_and(vbs, vus); // CHECK: and <8 x i16>
+ res_vus = vec_and(vus, vbs); // CHECK: and <8 x i16>
+ res_vbs = vec_and(vbs, vbs); // CHECK: and <8 x i16>
res_vi = vec_and(vi, vi); // CHECK: and <4 x i32>
+ res_vi = vec_and(vbi, vi); // CHECK: and <4 x i32>
+ res_vi = vec_and(vi, vbi); // CHECK: and <4 x i32>
res_vui = vec_and(vui, vui); // CHECK: and <4 x i32>
+ res_vui = vec_and(vbi, vui); // CHECK: and <4 x i32>
+ res_vui = vec_and(vui, vbi); // CHECK: and <4 x i32>
+ res_vbi = vec_and(vbi, vbi); // CHECK: and <4 x i32>
res_vsc = vec_vand(vsc, vsc); // CHECK: and <16 x i8>
+ res_vsc = vec_vand(vbc, vsc); // CHECK: and <16 x i8>
+ res_vsc = vec_vand(vsc, vbc); // CHECK: and <16 x i8>
res_vuc = vec_vand(vuc, vuc); // CHECK: and <16 x i8>
+ res_vuc = vec_vand(vbc, vuc); // CHECK: and <16 x i8>
+ res_vuc = vec_vand(vuc, vbc); // CHECK: and <16 x i8>
+ res_vbc = vec_vand(vbc, vbc); // CHECK: and <16 x i8>
res_vs = vec_vand(vs, vs); // CHECK: and <8 x i16>
+ res_vs = vec_vand(vbs, vs); // CHECK: and <8 x i16>
+ res_vs = vec_vand(vs, vbs); // CHECK: and <8 x i16>
res_vus = vec_vand(vus, vus); // CHECK: and <8 x i16>
+ res_vus = vec_vand(vbs, vus); // CHECK: and <8 x i16>
+ res_vus = vec_vand(vus, vbs); // CHECK: and <8 x i16>
+ res_vbs = vec_vand(vbs, vbs); // CHECK: and <8 x i16>
res_vi = vec_vand(vi, vi); // CHECK: and <4 x i32>
+ res_vi = vec_vand(vbi, vi); // CHECK: and <4 x i32>
+ res_vi = vec_vand(vi, vbi); // CHECK: and <4 x i32>
res_vui = vec_vand(vui, vui); // CHECK: and <4 x i32>
+ res_vui = vec_vand(vbi, vui); // CHECK: and <4 x i32>
+ res_vui = vec_vand(vui, vbi); // CHECK: and <4 x i32>
+ res_vbi = vec_vand(vbi, vbi); // CHECK: and <4 x i32>
/* vec_andc */
res_vsc = vec_andc(vsc, vsc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
+ res_vsc = vec_andc(vbc, vsc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
+ res_vsc = vec_andc(vsc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
res_vuc = vec_andc(vuc, vuc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
+ res_vuc = vec_andc(vbc, vuc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
+ res_vuc = vec_andc(vuc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
+ res_vbc = vec_andc(vbc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
res_vs = vec_andc(vs, vs); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
+ res_vs = vec_andc(vbs, vs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
+ res_vs = vec_andc(vs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
res_vus = vec_andc(vus, vus); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
+ res_vus = vec_andc(vbs, vus); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
+ res_vus = vec_andc(vus, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
+ res_vbs = vec_andc(vbs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
res_vi = vec_andc(vi, vi); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
+ res_vi = vec_andc(vbi, vi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
+ res_vi = vec_andc(vi, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
res_vui = vec_andc(vui, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
+ res_vui = vec_andc(vbi, vui); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
+ res_vui = vec_andc(vui, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
res_vf = vec_andc(vf, vf); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
+ res_vf = vec_andc(vbi, vf); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
+ res_vf = vec_andc(vf, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
res_vsc = vec_vandc(vsc, vsc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
+ res_vsc = vec_vandc(vbc, vsc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
+ res_vsc = vec_vandc(vsc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
res_vuc = vec_vandc(vuc, vuc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
+ res_vuc = vec_vandc(vbc, vuc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
+ res_vuc = vec_vandc(vuc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
+ res_vbc = vec_vandc(vbc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+
res_vs = vec_vandc(vs, vs); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
+ res_vs = vec_vandc(vbs, vs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
+ res_vs = vec_vandc(vs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
res_vus = vec_vandc(vus, vus); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
+ res_vus = vec_vandc(vbs, vus); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
+ res_vus = vec_vandc(vus, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
+ res_vbs = vec_vandc(vbs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+
res_vi = vec_vandc(vi, vi); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
+ res_vi = vec_vandc(vbi, vi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
+ res_vi = vec_vandc(vi, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
res_vui = vec_vandc(vui, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
+ res_vui = vec_vandc(vbi, vui); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
+ res_vui = vec_vandc(vui, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
res_vf = vec_vandc(vf, vf); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
+
+ res_vf = vec_vandc(vbi, vf); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
+ res_vf = vec_vandc(vf, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+
}
-// CHECK: i32 @test2
-int test2() {
+// CHECK: define void @test2
+void test2() {
/* vec_avg */
- res_vsc = vec_avg(vsc, vsc); // CHECK: call {{.*}}@llvm.ppc.altivec.vavgsb
+ res_vsc = vec_avg(vsc, vsc); // CHECK: @llvm.ppc.altivec.vavgsb
res_vuc = vec_avg(vuc, vuc); // CHECK: @llvm.ppc.altivec.vavgub
res_vs = vec_avg(vs, vs); // CHECK: @llvm.ppc.altivec.vavgsh
res_vus = vec_avg(vus, vus); // CHECK: @llvm.ppc.altivec.vavguh
@@ -182,53 +351,52 @@ int test2() {
res_vi = vec_vcmpbfp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp
/* vec_cmpeq */
- vsc = vec_cmpeq(vsc, vsc); // CHCK: call {{.*}}@llvm.ppc.altivec.vcmpequb
- vuc = vec_cmpeq(vuc, vuc); // CHCK: @llvm.ppc.altivec.vcmpequb
- vs = vec_cmpeq(vs, vs); // CHCK: @llvm.ppc.altivec.vcmpequh
- vs = vec_cmpeq(vus, vus); // CHCK: @llvm.ppc.altivec.vcmpequh
- vi = vec_cmpeq(vi, vi); // CHCK: @llvm.ppc.altivec.vcmpequw
- vui = vec_cmpeq(vui, vui); // CHCK: @llvm.ppc.altivec.vcmpequw
- vf = vec_cmpeq(vf, vf); // CHCK: @llvm.ppc.altivec.vcmpeqfp
+ res_vbc = vec_cmpeq(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb
+ res_vbc = vec_cmpeq(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb
+ res_vbs = vec_cmpeq(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh
+ res_vbs = vec_cmpeq(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh
+ res_vbi = vec_cmpeq(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw
+ res_vbi = vec_cmpeq(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw
+ res_vbi = vec_cmpeq(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp
/* vec_cmpge */
- vf = vec_cmpge(vf, vf); // CHCK: @llvm.ppc.altivec.vcmpgefp
- vf = vec_vcmpgefp(vf, vf); // CHCK: call {{.*}}@llvm.ppc.altivec.vcmpgefp
-
+ res_vbi = vec_cmpge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp
+ res_vbi = vec_vcmpgefp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp
}
-// CHECK: define i32 @test5
-int test5() {
+// CHECK: define void @test5
+void test5() {
/* vec_cmpgt */
- vsc = vec_cmpgt(vsc, vsc); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgtsb
- vuc = vec_cmpgt(vuc, vuc); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgtub
- vs = vec_cmpgt(vs, vs); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgtsh
- vus = vec_cmpgt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh
- vi = vec_cmpgt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw
- vui = vec_cmpgt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw
- vf = vec_cmpgt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp
- vsc = vec_vcmpgtsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb
- vuc = vec_vcmpgtub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub
- vs = vec_vcmpgtsh(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh
- vus = vec_vcmpgtuh(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh
- vi = vec_vcmpgtsw(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw
- vui = vec_vcmpgtuw(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw
- vf = vec_vcmpgtfp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp
+ res_vbc = vec_cmpgt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb
+ res_vbc = vec_cmpgt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub
+ res_vbs = vec_cmpgt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh
+ res_vbs = vec_cmpgt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh
+ res_vbi = vec_cmpgt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw
+ res_vbi = vec_cmpgt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw
+ res_vbi = vec_cmpgt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp
+ res_vbc = vec_vcmpgtsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb
+ res_vbc = vec_vcmpgtub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub
+ res_vbs = vec_vcmpgtsh(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh
+ res_vbs = vec_vcmpgtuh(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh
+ res_vbi = vec_vcmpgtsw(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw
+ res_vbi = vec_vcmpgtuw(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw
+ res_vbi = vec_vcmpgtfp(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp
/* vec_cmple */
- vf = vec_cmple(vf, vf); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgefp
+ res_vbi = vec_cmple(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp
}
-// CHECK: define i32 @test6
-int test6() {
+// CHECK: define void @test6
+void test6() {
/* vec_cmplt */
- vsc =vec_cmplt(vsc, vsc); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgtsb
- vsc =vec_cmplt(vuc, vuc); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgtub
- vs = vec_cmplt(vs, vs); // CHECK: call {{.*}}@llvm.ppc.altivec.vcmpgtsh
- vs = vec_cmplt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh
- vi = vec_cmplt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw
- vui = vec_cmplt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw
- vf = vec_cmplt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp
+ res_vbc = vec_cmplt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb
+ res_vbc = vec_cmplt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub
+ res_vbs = vec_cmplt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh
+ res_vbs = vec_cmplt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh
+ res_vbi = vec_cmplt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw
+ res_vbi = vec_cmplt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw
+ res_vbi = vec_cmplt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp
/* vec_ctf */
res_vf = vec_ctf(vi, param_i); // CHECK: @llvm.ppc.altivec.vcfsx
@@ -275,28 +443,36 @@ int test6() {
res_vsc = vec_ld(0, &param_sc); // CHECK: @llvm.ppc.altivec.lvx
res_vuc = vec_ld(0, &vuc); // CHECK: @llvm.ppc.altivec.lvx
res_vuc = vec_ld(0, &param_uc); // CHECK: @llvm.ppc.altivec.lvx
+ res_vbc = vec_ld(0, &vbc); // CHECK: @llvm.ppc.altivec.lvx
res_vs = vec_ld(0, &vs); // CHECK: @llvm.ppc.altivec.lvx
res_vs = vec_ld(0, &param_s); // CHECK: @llvm.ppc.altivec.lvx
res_vus = vec_ld(0, &vus); // CHECK: @llvm.ppc.altivec.lvx
res_vus = vec_ld(0, &param_us); // CHECK: @llvm.ppc.altivec.lvx
+ res_vbs = vec_ld(0, &vbs); // CHECK: @llvm.ppc.altivec.lvx
+ res_vp = vec_ld(0, &vp); // CHECK: @llvm.ppc.altivec.lvx
res_vi = vec_ld(0, &vi); // CHECK: @llvm.ppc.altivec.lvx
res_vi = vec_ld(0, &param_i); // CHECK: @llvm.ppc.altivec.lvx
res_vui = vec_ld(0, &vui); // CHECK: @llvm.ppc.altivec.lvx
res_vui = vec_ld(0, &param_ui); // CHECK: @llvm.ppc.altivec.lvx
+ res_vbi = vec_ld(0, &vbi); // CHECK: @llvm.ppc.altivec.lvx
res_vf = vec_ld(0, &vf); // CHECK: @llvm.ppc.altivec.lvx
res_vf = vec_ld(0, &param_f); // CHECK: @llvm.ppc.altivec.lvx
res_vsc = vec_lvx(0, &vsc); // CHECK: @llvm.ppc.altivec.lvx
res_vsc = vec_lvx(0, &param_sc); // CHECK: @llvm.ppc.altivec.lvx
res_vuc = vec_lvx(0, &vuc); // CHECK: @llvm.ppc.altivec.lvx
res_vuc = vec_lvx(0, &param_uc); // CHECK: @llvm.ppc.altivec.lvx
+ res_vbc = vec_lvx(0, &vbc); // CHECK: @llvm.ppc.altivec.lvx
res_vs = vec_lvx(0, &vs); // CHECK: @llvm.ppc.altivec.lvx
res_vs = vec_lvx(0, &param_s); // CHECK: @llvm.ppc.altivec.lvx
res_vus = vec_lvx(0, &vus); // CHECK: @llvm.ppc.altivec.lvx
res_vus = vec_lvx(0, &param_us); // CHECK: @llvm.ppc.altivec.lvx
+ res_vbs = vec_lvx(0, &vbs); // CHECK: @llvm.ppc.altivec.lvx
+ res_vp = vec_lvx(0, &vp); // CHECK: @llvm.ppc.altivec.lvx
res_vi = vec_lvx(0, &vi); // CHECK: @llvm.ppc.altivec.lvx
res_vi = vec_lvx(0, &param_i); // CHECK: @llvm.ppc.altivec.lvx
res_vui = vec_lvx(0, &vui); // CHECK: @llvm.ppc.altivec.lvx
res_vui = vec_lvx(0, &param_ui); // CHECK: @llvm.ppc.altivec.lvx
+ res_vbi = vec_lvx(0, &vbi); // CHECK: @llvm.ppc.altivec.lvx
res_vf = vec_lvx(0, &vf); // CHECK: @llvm.ppc.altivec.lvx
res_vf = vec_lvx(0, &param_f); // CHECK: @llvm.ppc.altivec.lvx
@@ -321,28 +497,36 @@ int test6() {
res_vsc = vec_ldl(0, &param_sc); // CHECK: @llvm.ppc.altivec.lvxl
res_vuc = vec_ldl(0, &vuc); // CHECK: @llvm.ppc.altivec.lvxl
res_vuc = vec_ldl(0, &param_uc); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vbc = vec_ldl(0, &vbc); // CHECK: @llvm.ppc.altivec.lvxl
res_vs = vec_ldl(0, &vs); // CHECK: @llvm.ppc.altivec.lvxl
res_vs = vec_ldl(0, &param_s); // CHECK: @llvm.ppc.altivec.lvxl
res_vus = vec_ldl(0, &vus); // CHECK: @llvm.ppc.altivec.lvxl
res_vus = vec_ldl(0, &param_us); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vbs = vec_ldl(0, &vbs); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vp = vec_ldl(0, &vp); // CHECK: @llvm.ppc.altivec.lvxl
res_vi = vec_ldl(0, &vi); // CHECK: @llvm.ppc.altivec.lvxl
res_vi = vec_ldl(0, &param_i); // CHECK: @llvm.ppc.altivec.lvxl
res_vui = vec_ldl(0, &vui); // CHECK: @llvm.ppc.altivec.lvxl
res_vui = vec_ldl(0, &param_ui); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vbi = vec_ldl(0, &vbi); // CHECK: @llvm.ppc.altivec.lvxl
res_vf = vec_ldl(0, &vf); // CHECK: @llvm.ppc.altivec.lvxl
res_vf = vec_ldl(0, &param_f); // CHECK: @llvm.ppc.altivec.lvxl
res_vsc = vec_lvxl(0, &vsc); // CHECK: @llvm.ppc.altivec.lvxl
res_vsc = vec_lvxl(0, &param_sc); // CHECK: @llvm.ppc.altivec.lvxl
res_vuc = vec_lvxl(0, &vuc); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vbc = vec_lvxl(0, &vbc); // CHECK: @llvm.ppc.altivec.lvxl
res_vuc = vec_lvxl(0, &param_uc); // CHECK: @llvm.ppc.altivec.lvxl
res_vs = vec_lvxl(0, &vs); // CHECK: @llvm.ppc.altivec.lvxl
res_vs = vec_lvxl(0, &param_s); // CHECK: @llvm.ppc.altivec.lvxl
res_vus = vec_lvxl(0, &vus); // CHECK: @llvm.ppc.altivec.lvxl
res_vus = vec_lvxl(0, &param_us); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vbs = vec_lvxl(0, &vbs); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vp = vec_lvxl(0, &vp); // CHECK: @llvm.ppc.altivec.lvxl
res_vi = vec_lvxl(0, &vi); // CHECK: @llvm.ppc.altivec.lvxl
res_vi = vec_lvxl(0, &param_i); // CHECK: @llvm.ppc.altivec.lvxl
res_vui = vec_lvxl(0, &vui); // CHECK: @llvm.ppc.altivec.lvxl
res_vui = vec_lvxl(0, &param_ui); // CHECK: @llvm.ppc.altivec.lvxl
+ res_vbi = vec_lvxl(0, &vbi); // CHECK: @llvm.ppc.altivec.lvxl
res_vf = vec_lvxl(0, &vf); // CHECK: @llvm.ppc.altivec.lvxl
res_vf = vec_lvxl(0, &param_f); // CHECK: @llvm.ppc.altivec.lvxl
@@ -366,50 +550,90 @@ int test6() {
/* vec_max */
res_vsc = vec_max(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb
+ res_vsc = vec_max(vbc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb
+ res_vsc = vec_max(vsc, vbc); // CHECK: @llvm.ppc.altivec.vmaxsb
res_vuc = vec_max(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub
+ res_vuc = vec_max(vbc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub
+ res_vuc = vec_max(vuc, vbc); // CHECK: @llvm.ppc.altivec.vmaxub
res_vs = vec_max(vs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh
+ res_vs = vec_max(vbs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh
+ res_vs = vec_max(vs, vbs); // CHECK: @llvm.ppc.altivec.vmaxsh
res_vus = vec_max(vus, vus); // CHECK: @llvm.ppc.altivec.vmaxuh
+ res_vus = vec_max(vbs, vus); // CHECK: @llvm.ppc.altivec.vmaxuh
+ res_vus = vec_max(vus, vbs); // CHECK: @llvm.ppc.altivec.vmaxuh
res_vi = vec_max(vi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw
+ res_vi = vec_max(vbi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw
+ res_vi = vec_max(vi, vbi); // CHECK: @llvm.ppc.altivec.vmaxsw
res_vui = vec_max(vui, vui); // CHECK: @llvm.ppc.altivec.vmaxuw
+ res_vui = vec_max(vbi, vui); // CHECK: @llvm.ppc.altivec.vmaxuw
+ res_vui = vec_max(vui, vbi); // CHECK: @llvm.ppc.altivec.vmaxuw
res_vf = vec_max(vf, vf); // CHECK: @llvm.ppc.altivec.vmaxfp
res_vsc = vec_vmaxsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb
+ res_vsc = vec_vmaxsb(vbc, vsc); // CHECK: @llvm.ppc.altivec.vmaxsb
+ res_vsc = vec_vmaxsb(vsc, vbc); // CHECK: @llvm.ppc.altivec.vmaxsb
res_vuc = vec_vmaxub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub
+ res_vuc = vec_vmaxub(vbc, vuc); // CHECK: @llvm.ppc.altivec.vmaxub
+ res_vuc = vec_vmaxub(vuc, vbc); // CHECK: @llvm.ppc.altivec.vmaxub
res_vs = vec_vmaxsh(vs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh
+ res_vs = vec_vmaxsh(vbs, vs); // CHECK: @llvm.ppc.altivec.vmaxsh
+ res_vs = vec_vmaxsh(vs, vbs); // CHECK: @llvm.ppc.altivec.vmaxsh
res_vus = vec_vmaxuh(vus, vus); // CHECK: @llvm.ppc.altivec.vmaxuh
+ res_vus = vec_vmaxuh(vbs, vus); // CHECK: @llvm.ppc.altivec.vmaxuh
+ res_vus = vec_vmaxuh(vus, vbs); // CHECK: @llvm.ppc.altivec.vmaxuh
res_vi = vec_vmaxsw(vi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw
+ res_vi = vec_vmaxsw(vbi, vi); // CHECK: @llvm.ppc.altivec.vmaxsw
+ res_vi = vec_vmaxsw(vi, vbi); // CHECK: @llvm.ppc.altivec.vmaxsw
res_vui = vec_vmaxuw(vui, vui); // CHECK: @llvm.ppc.altivec.vmaxuw
+ res_vui = vec_vmaxuw(vbi, vui); // CHECK: @llvm.ppc.altivec.vmaxuw
+ res_vui = vec_vmaxuw(vui, vbi); // CHECK: @llvm.ppc.altivec.vmaxuw
res_vf = vec_vmaxfp(vf, vf); // CHECK: @llvm.ppc.altivec.vmaxfp
/* vec_mergeh */
res_vsc = vec_mergeh(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_mergeh(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_mergeh(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_mergeh(vs, vs); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_mergeh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_mergeh(vus, vus); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_mergeh(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_mergeh(vi, vi); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_mergeh(vui, vui); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_mergeh(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_mergeh(vf, vf); // CHECK: @llvm.ppc.altivec.vperm
res_vsc = vec_vmrghb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_vmrghb(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_vmrghb(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_vmrghh(vs, vs); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_vmrghh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_vmrghh(vus, vus); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_vmrghh(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_vmrghw(vi, vi); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_vmrghw(vui, vui); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_vmrghw(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_vmrghw(vf, vf); // CHECK: @llvm.ppc.altivec.vperm
/* vec_mergel */
res_vsc = vec_mergel(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_mergel(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_mergel(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_mergel(vs, vs); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_mergeh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_mergel(vus, vus); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_mergel(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_mergel(vi, vi); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_mergel(vui, vui); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_mergel(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_mergel(vf, vf); // CHECK: @llvm.ppc.altivec.vperm
res_vsc = vec_vmrglb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_vmrglb(vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_vmrglb(vbc, vbc); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_vmrglh(vs, vs); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_vmrglh(vp, vp); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_vmrglh(vus, vus); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_vmrglh(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_vmrglw(vi, vi); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_vmrglw(vui, vui); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_vmrglw(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_vmrglw(vf, vf); // CHECK: @llvm.ppc.altivec.vperm
/* vec_mfvscr */
@@ -417,18 +641,42 @@ int test6() {
/* vec_min */
res_vsc = vec_min(vsc, vsc); // CHECK: @llvm.ppc.altivec.vminsb
+ res_vsc = vec_min(vbc, vsc); // CHECK: @llvm.ppc.altivec.vminsb
+ res_vsc = vec_min(vsc, vbc); // CHECK: @llvm.ppc.altivec.vminsb
res_vuc = vec_min(vuc, vuc); // CHECK: @llvm.ppc.altivec.vminub
+ res_vuc = vec_min(vbc, vuc); // CHECK: @llvm.ppc.altivec.vminub
+ res_vuc = vec_min(vuc, vbc); // CHECK: @llvm.ppc.altivec.vminub
res_vs = vec_min(vs, vs); // CHECK: @llvm.ppc.altivec.vminsh
+ res_vs = vec_min(vbs, vs); // CHECK: @llvm.ppc.altivec.vminsh
+ res_vs = vec_min(vs, vbs); // CHECK: @llvm.ppc.altivec.vminsh
res_vus = vec_min(vus, vus); // CHECK: @llvm.ppc.altivec.vminuh
+ res_vus = vec_min(vbs, vus); // CHECK: @llvm.ppc.altivec.vminuh
+ res_vus = vec_min(vus, vbs); // CHECK: @llvm.ppc.altivec.vminuh
res_vi = vec_min(vi, vi); // CHECK: @llvm.ppc.altivec.vminsw
+ res_vi = vec_min(vbi, vi); // CHECK: @llvm.ppc.altivec.vminsw
+ res_vi = vec_min(vi, vbi); // CHECK: @llvm.ppc.altivec.vminsw
res_vui = vec_min(vui, vui); // CHECK: @llvm.ppc.altivec.vminuw
+ res_vui = vec_min(vbi, vui); // CHECK: @llvm.ppc.altivec.vminuw
+ res_vui = vec_min(vui, vbi); // CHECK: @llvm.ppc.altivec.vminuw
res_vf = vec_min(vf, vf); // CHECK: @llvm.ppc.altivec.vminfp
res_vsc = vec_vminsb(vsc, vsc); // CHECK: @llvm.ppc.altivec.vminsb
+ res_vsc = vec_vminsb(vbc, vsc); // CHECK: @llvm.ppc.altivec.vminsb
+ res_vsc = vec_vminsb(vsc, vbc); // CHECK: @llvm.ppc.altivec.vminsb
res_vuc = vec_vminub(vuc, vuc); // CHECK: @llvm.ppc.altivec.vminub
+ res_vuc = vec_vminub(vbc, vuc); // CHECK: @llvm.ppc.altivec.vminub
+ res_vuc = vec_vminub(vuc, vbc); // CHECK: @llvm.ppc.altivec.vminub
res_vs = vec_vminsh(vs, vs); // CHECK: @llvm.ppc.altivec.vminsh
+ res_vs = vec_vminsh(vbs, vs); // CHECK: @llvm.ppc.altivec.vminsh
+ res_vs = vec_vminsh(vs, vbs); // CHECK: @llvm.ppc.altivec.vminsh
res_vus = vec_vminuh(vus, vus); // CHECK: @llvm.ppc.altivec.vminuh
+ res_vus = vec_vminuh(vbs, vus); // CHECK: @llvm.ppc.altivec.vminuh
+ res_vus = vec_vminuh(vus, vbs); // CHECK: @llvm.ppc.altivec.vminuh
res_vi = vec_vminsw(vi, vi); // CHECK: @llvm.ppc.altivec.vminsw
+ res_vi = vec_vminsw(vbi, vi); // CHECK: @llvm.ppc.altivec.vminsw
+ res_vi = vec_vminsw(vi, vbi); // CHECK: @llvm.ppc.altivec.vminsw
res_vui = vec_vminuw(vui, vui); // CHECK: @llvm.ppc.altivec.vminuw
+ res_vui = vec_vminuw(vbi, vui); // CHECK: @llvm.ppc.altivec.vminuw
+ res_vui = vec_vminuw(vui, vbi); // CHECK: @llvm.ppc.altivec.vminuw
res_vf = vec_vminfp(vf, vf); // CHECK: @llvm.ppc.altivec.vminfp
/* vec_mladd */
@@ -466,6 +714,15 @@ int test6() {
/* vec_mtvscr */
vec_mtvscr(vsc); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vuc); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vbc); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vs); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vus); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vbs); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vp); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vi); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vui); // CHECK: @llvm.ppc.altivec.mtvscr
+ vec_mtvscr(vbi); // CHECK: @llvm.ppc.altivec.mtvscr
/* vec_mule */
res_vs = vec_mule(vsc, vsc); // CHECK: @llvm.ppc.altivec.vmulesb
@@ -498,18 +755,27 @@ int test6() {
res_vuc = vec_nor(vuc, vuc); // CHECK: or <16 x i8>
// CHECK: xor <16 x i8>
+ res_vuc = vec_nor(vbc, vbc); // CHECK: or <16 x i8>
+ // CHECK: xor <16 x i8>
+
res_vs = vec_nor(vs, vs); // CHECK: or <8 x i16>
// CHECK: xor <8 x i16>
res_vus = vec_nor(vus, vus); // CHECK: or <8 x i16>
// CHECK: xor <8 x i16>
+ res_vus = vec_nor(vbs, vbs); // CHECK: or <8 x i16>
+ // CHECK: xor <8 x i16>
+
res_vi = vec_nor(vi, vi); // CHECK: or <4 x i32>
// CHECK: xor <4 x i32>
res_vui = vec_nor(vui, vui); // CHECK: or <4 x i32>
// CHECK: xor <4 x i32>
+ res_vui = vec_nor(vbi, vbi); // CHECK: or <4 x i32>
+ // CHECK: xor <4 x i32>
+
res_vf = vec_nor(vf, vf); // CHECK: or <4 x i32>
// CHECK: xor <4 x i32>
@@ -519,46 +785,93 @@ int test6() {
res_vuc = vec_vnor(vuc, vuc); // CHECK: or <16 x i8>
// CHECK: xor <16 x i8>
+ res_vuc = vec_vnor(vbc, vbc); // CHECK: or <16 x i8>
+ // CHECK: xor <16 x i8>
+
res_vs = vec_vnor(vs, vs); // CHECK: or <8 x i16>
// CHECK: xor <8 x i16>
res_vus = vec_vnor(vus, vus); // CHECK: or <8 x i16>
// CHECK: xor <8 x i16>
+ res_vus = vec_vnor(vbs, vbs); // CHECK: or <8 x i16>
+ // CHECK: xor <8 x i16>
+
res_vi = vec_vnor(vi, vi); // CHECK: or <4 x i32>
// CHECK: xor <4 x i32>
res_vui = vec_vnor(vui, vui); // CHECK: or <4 x i32>
// CHECK: xor <4 x i32>
+ res_vui = vec_vnor(vbi, vbi); // CHECK: or <4 x i32>
+ // CHECK: xor <4 x i32>
+
res_vf = vec_vnor(vf, vf); // CHECK: or <4 x i32>
// CHECK: xor <4 x i32>
/* vec_or */
res_vsc = vec_or(vsc, vsc); // CHECK: or <16 x i8>
+ res_vsc = vec_or(vbc, vsc); // CHECK: or <16 x i8>
+ res_vsc = vec_or(vsc, vbc); // CHECK: or <16 x i8>
res_vuc = vec_or(vuc, vuc); // CHECK: or <16 x i8>
+ res_vuc = vec_or(vbc, vuc); // CHECK: or <16 x i8>
+ res_vuc = vec_or(vuc, vbc); // CHECK: or <16 x i8>
+ res_vbc = vec_or(vbc, vbc); // CHECK: or <16 x i8>
res_vs = vec_or(vs, vs); // CHECK: or <8 x i16>
+ res_vs = vec_or(vbs, vs); // CHECK: or <8 x i16>
+ res_vs = vec_or(vs, vbs); // CHECK: or <8 x i16>
res_vus = vec_or(vus, vus); // CHECK: or <8 x i16>
+ res_vus = vec_or(vbs, vus); // CHECK: or <8 x i16>
+ res_vus = vec_or(vus, vbs); // CHECK: or <8 x i16>
+ res_vbs = vec_or(vbs, vbs); // CHECK: or <8 x i16>
res_vi = vec_or(vi, vi); // CHECK: or <4 x i32>
+ res_vi = vec_or(vbi, vi); // CHECK: or <4 x i32>
+ res_vi = vec_or(vi, vbi); // CHECK: or <4 x i32>
res_vui = vec_or(vui, vui); // CHECK: or <4 x i32>
+ res_vui = vec_or(vbi, vui); // CHECK: or <4 x i32>
+ res_vui = vec_or(vui, vbi); // CHECK: or <4 x i32>
+ res_vbi = vec_or(vbi, vbi); // CHECK: or <4 x i32>
res_vf = vec_or(vf, vf); // CHECK: or <4 x i32>
+ res_vf = vec_or(vbi, vf); // CHECK: or <4 x i32>
+ res_vf = vec_or(vf, vbi); // CHECK: or <4 x i32>
res_vsc = vec_vor(vsc, vsc); // CHECK: or <16 x i8>
+ res_vsc = vec_vor(vbc, vsc); // CHECK: or <16 x i8>
+ res_vsc = vec_vor(vsc, vbc); // CHECK: or <16 x i8>
res_vuc = vec_vor(vuc, vuc); // CHECK: or <16 x i8>
+ res_vuc = vec_vor(vbc, vuc); // CHECK: or <16 x i8>
+ res_vuc = vec_vor(vuc, vbc); // CHECK: or <16 x i8>
+ res_vbc = vec_vor(vbc, vbc); // CHECK: or <16 x i8>
res_vs = vec_vor(vs, vs); // CHECK: or <8 x i16>
+ res_vs = vec_vor(vbs, vs); // CHECK: or <8 x i16>
+ res_vs = vec_vor(vs, vbs); // CHECK: or <8 x i16>
res_vus = vec_vor(vus, vus); // CHECK: or <8 x i16>
+ res_vus = vec_vor(vbs, vus); // CHECK: or <8 x i16>
+ res_vus = vec_vor(vus, vbs); // CHECK: or <8 x i16>
+ res_vbs = vec_vor(vbs, vbs); // CHECK: or <8 x i16>
res_vi = vec_vor(vi, vi); // CHECK: or <4 x i32>
+ res_vi = vec_vor(vbi, vi); // CHECK: or <4 x i32>
+ res_vi = vec_vor(vi, vbi); // CHECK: or <4 x i32>
res_vui = vec_vor(vui, vui); // CHECK: or <4 x i32>
+ res_vui = vec_vor(vbi, vui); // CHECK: or <4 x i32>
+ res_vui = vec_vor(vui, vbi); // CHECK: or <4 x i32>
+ res_vbi = vec_vor(vbi, vbi); // CHECK: or <4 x i32>
res_vf = vec_vor(vf, vf); // CHECK: or <4 x i32>
+ res_vf = vec_vor(vbi, vf); // CHECK: or <4 x i32>
+ res_vf = vec_vor(vf, vbi); // CHECK: or <4 x i32>
/* vec_pack */
res_vsc = vec_pack(vs, vs); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_pack(vus, vus); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_pack(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_pack(vi, vi); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_pack(vui, vui); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_pack(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm
res_vsc = vec_vpkuhum(vs, vs); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_vpkuhum(vus, vus); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_vpkuhum(vbs, vbs); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_vpkuwum(vi, vi); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_vpkuwum(vui, vui); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_vpkuwum(vbi, vbi); // CHECK: @llvm.ppc.altivec.vperm
/* vec_packpx */
res_vp = vec_packpx(vui, vui); // CHECK: @llvm.ppc.altivec.vpkpx
@@ -587,17 +900,25 @@ int test6() {
/* vec_perm */
res_vsc = vec_perm(vsc, vsc, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_perm(vuc, vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_perm(vbc, vbc, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_perm(vs, vs, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_perm(vus, vus, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_perm(vbs, vbs, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_perm(vp, vp, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_perm(vi, vi, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_perm(vui, vui, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_perm(vbi, vbi, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_perm(vf, vf, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vsc = vec_vperm(vsc, vsc, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_vperm(vuc, vuc, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_vperm(vbc, vbc, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_vperm(vs, vs, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_vperm(vus, vus, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_vperm(vbs, vbs, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_vperm(vp, vp, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_vperm(vi, vi, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_vperm(vui, vui, vuc); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_vperm(vbi, vbi, vuc); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_vperm(vf, vf, vuc); // CHECK: @llvm.ppc.altivec.vperm
/* vec_re */
@@ -632,77 +953,200 @@ int test6() {
// CHECK: and <16 x i8>
// CHECK: or <16 x i8>
+ res_vsc = vec_sel(vsc, vsc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
res_vuc = vec_sel(vuc, vuc, vuc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
// CHECK: and <16 x i8>
// CHECK: or <16 x i8>
+ res_vuc = vec_sel(vuc, vuc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
+ res_vbc = vec_sel(vbc, vbc, vuc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
+ res_vbc = vec_sel(vbc, vbc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
res_vs = vec_sel(vs, vs, vus); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
// CHECK: and <8 x i16>
// CHECK: or <8 x i16>
+ res_vs = vec_sel(vs, vs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
res_vus = vec_sel(vus, vus, vus); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
// CHECK: and <8 x i16>
// CHECK: or <8 x i16>
+ res_vus = vec_sel(vus, vus, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
+
+ res_vbs = vec_sel(vbs, vbs, vus); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
+
+ res_vbs = vec_sel(vbs, vbs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
+
res_vi = vec_sel(vi, vi, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
// CHECK: and <4 x i32>
// CHECK: or <4 x i32>
+ res_vi = vec_sel(vi, vi, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
res_vui = vec_sel(vui, vui, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
// CHECK: and <4 x i32>
// CHECK: or <4 x i32>
+ res_vui = vec_sel(vui, vui, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
+
+ res_vbi = vec_sel(vbi, vbi, vui); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
+
+ res_vbi = vec_sel(vbi, vbi, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
res_vf = vec_sel(vf, vf, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
// CHECK: and <4 x i32>
// CHECK: or <4 x i32>
+ res_vf = vec_sel(vf, vf, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
+
res_vsc = vec_vsel(vsc, vsc, vuc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
// CHECK: and <16 x i8>
// CHECK: or <16 x i8>
+ res_vsc = vec_vsel(vsc, vsc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
res_vuc = vec_vsel(vuc, vuc, vuc); // CHECK: xor <16 x i8>
// CHECK: and <16 x i8>
// CHECK: and <16 x i8>
// CHECK: or <16 x i8>
+ res_vuc = vec_vsel(vuc, vuc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
+ res_vbc = vec_vsel(vbc, vbc, vuc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
+ res_vbc = vec_vsel(vbc, vbc, vbc); // CHECK: xor <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: and <16 x i8>
+ // CHECK: or <16 x i8>
+
res_vs = vec_vsel(vs, vs, vus); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
// CHECK: and <8 x i16>
// CHECK: or <8 x i16>
+ res_vs = vec_vsel(vs, vs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
res_vus = vec_vsel(vus, vus, vus); // CHECK: xor <8 x i16>
// CHECK: and <8 x i16>
// CHECK: and <8 x i16>
// CHECK: or <8 x i16>
+ res_vus = vec_vsel(vus, vus, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
+
+ res_vbs = vec_vsel(vbs, vbs, vus); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
+
+ res_vbs = vec_vsel(vbs, vbs, vbs); // CHECK: xor <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: and <8 x i16>
+ // CHECK: or <8 x i16>
+
res_vi = vec_vsel(vi, vi, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
// CHECK: and <4 x i32>
// CHECK: or <4 x i32>
+ res_vi = vec_vsel(vi, vi, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
res_vui = vec_vsel(vui, vui, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
// CHECK: and <4 x i32>
// CHECK: or <4 x i32>
+ res_vui = vec_vsel(vui, vui, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
+
+ res_vbi = vec_vsel(vbi, vbi, vui); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
+
+ res_vbi = vec_vsel(vbi, vbi, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
res_vf = vec_vsel(vf, vf, vui); // CHECK: xor <4 x i32>
// CHECK: and <4 x i32>
// CHECK: and <4 x i32>
// CHECK: or <4 x i32>
+ res_vf = vec_vsel(vf, vf, vbi); // CHECK: xor <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: and <4 x i32>
+ // CHECK: or <4 x i32>
/* vec_sl */
res_vsc = vec_sl(vsc, vuc); // CHECK: shl <16 x i8>
@@ -723,6 +1167,7 @@ int test6() {
res_vuc = vec_sld(vuc, vuc, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_sld(vs, vs, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_sld(vus, vus, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_sld(vp, vp, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_sld(vi, vi, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_sld(vui, vui, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_sld(vf, vf, 0); // CHECK: @llvm.ppc.altivec.vperm
@@ -730,6 +1175,7 @@ int test6() {
res_vuc = vec_vsldoi(vuc, vuc, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_vsldoi(vs, vs, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_vsldoi(vus, vus, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_vsldoi(vp, vp, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_vsldoi(vi, vi, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_vsldoi(vui, vui, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_vsldoi(vf, vf, 0); // CHECK: @llvm.ppc.altivec.vperm
@@ -741,36 +1187,60 @@ int test6() {
res_vuc = vec_sll(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vuc = vec_sll(vuc, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vuc = vec_sll(vuc, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbc = vec_sll(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbc = vec_sll(vbc, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbc = vec_sll(vbc, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vs = vec_sll(vs, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vs = vec_sll(vs, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vs = vec_sll(vs, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vus = vec_sll(vus, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vus = vec_sll(vus, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vus = vec_sll(vus, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbs = vec_sll(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbs = vec_sll(vbs, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbs = vec_sll(vbs, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vp = vec_sll(vp, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vp = vec_sll(vp, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vp = vec_sll(vp, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vi = vec_sll(vi, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vi = vec_sll(vi, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vi = vec_sll(vi, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vui = vec_sll(vui, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vui = vec_sll(vui, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vui = vec_sll(vui, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbi = vec_sll(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbi = vec_sll(vbi, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbi = vec_sll(vbi, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vsc = vec_vsl(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vsc = vec_vsl(vsc, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vsc = vec_vsl(vsc, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vuc = vec_vsl(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vuc = vec_vsl(vuc, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vuc = vec_vsl(vuc, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbc = vec_vsl(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbc = vec_vsl(vbc, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbc = vec_vsl(vbc, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vs = vec_vsl(vs, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vs = vec_vsl(vs, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vs = vec_vsl(vs, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vus = vec_vsl(vus, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vus = vec_vsl(vus, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vus = vec_vsl(vus, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbs = vec_vsl(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbs = vec_vsl(vbs, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbs = vec_vsl(vbs, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vp = vec_vsl(vp, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vp = vec_vsl(vp, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vp = vec_vsl(vp, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vi = vec_vsl(vi, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vi = vec_vsl(vi, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vi = vec_vsl(vi, vui); // CHECK: @llvm.ppc.altivec.vsl
res_vui = vec_vsl(vui, vuc); // CHECK: @llvm.ppc.altivec.vsl
res_vui = vec_vsl(vui, vus); // CHECK: @llvm.ppc.altivec.vsl
res_vui = vec_vsl(vui, vui); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbi = vec_vsl(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbi = vec_vsl(vbi, vus); // CHECK: @llvm.ppc.altivec.vsl
+ res_vbi = vec_vsl(vbi, vui); // CHECK: @llvm.ppc.altivec.vsl
/* vec_slo */
res_vsc = vec_slo(vsc, vsc); // CHECK: @llvm.ppc.altivec.vslo
@@ -781,6 +1251,8 @@ int test6() {
res_vs = vec_slo(vs, vuc); // CHECK: @llvm.ppc.altivec.vslo
res_vus = vec_slo(vus, vsc); // CHECK: @llvm.ppc.altivec.vslo
res_vus = vec_slo(vus, vuc); // CHECK: @llvm.ppc.altivec.vslo
+ res_vp = vec_slo(vp, vsc); // CHECK: @llvm.ppc.altivec.vslo
+ res_vp = vec_slo(vp, vuc); // CHECK: @llvm.ppc.altivec.vslo
res_vi = vec_slo(vi, vsc); // CHECK: @llvm.ppc.altivec.vslo
res_vi = vec_slo(vi, vuc); // CHECK: @llvm.ppc.altivec.vslo
res_vui = vec_slo(vui, vsc); // CHECK: @llvm.ppc.altivec.vslo
@@ -795,6 +1267,8 @@ int test6() {
res_vs = vec_vslo(vs, vuc); // CHECK: @llvm.ppc.altivec.vslo
res_vus = vec_vslo(vus, vsc); // CHECK: @llvm.ppc.altivec.vslo
res_vus = vec_vslo(vus, vuc); // CHECK: @llvm.ppc.altivec.vslo
+ res_vp = vec_vslo(vp, vsc); // CHECK: @llvm.ppc.altivec.vslo
+ res_vp = vec_vslo(vp, vuc); // CHECK: @llvm.ppc.altivec.vslo
res_vi = vec_vslo(vi, vsc); // CHECK: @llvm.ppc.altivec.vslo
res_vi = vec_vslo(vi, vuc); // CHECK: @llvm.ppc.altivec.vslo
res_vui = vec_vslo(vui, vsc); // CHECK: @llvm.ppc.altivec.vslo
@@ -805,17 +1279,25 @@ int test6() {
/* vec_splat */
res_vsc = vec_splat(vsc, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_splat(vuc, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_splat(vbc, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_splat(vs, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_splat(vus, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_splat(vbs, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_splat(vp, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_splat(vi, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_splat(vui, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_splat(vbi, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_splat(vf, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vsc = vec_vspltb(vsc, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vuc = vec_vspltb(vuc, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbc = vec_vspltb(vbc, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vs = vec_vsplth(vs, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vus = vec_vsplth(vus, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbs = vec_vsplth(vbs, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vp = vec_vsplth(vp, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vi = vec_vspltw(vi, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vui = vec_vspltw(vui, 0); // CHECK: @llvm.ppc.altivec.vperm
+ res_vbi = vec_vspltw(vbi, 0); // CHECK: @llvm.ppc.altivec.vperm
res_vf = vec_vspltw(vf, 0); // CHECK: @llvm.ppc.altivec.vperm
/* vec_splat_s8 */
@@ -874,36 +1356,60 @@ int test6() {
res_vuc = vec_srl(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vuc = vec_srl(vuc, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vuc = vec_srl(vuc, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbc = vec_srl(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbc = vec_srl(vbc, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbc = vec_srl(vbc, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vs = vec_srl(vs, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vs = vec_srl(vs, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vs = vec_srl(vs, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vus = vec_srl(vus, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vus = vec_srl(vus, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vus = vec_srl(vus, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbs = vec_srl(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbs = vec_srl(vbs, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbs = vec_srl(vbs, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vp = vec_srl(vp, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vp = vec_srl(vp, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vp = vec_srl(vp, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vi = vec_srl(vi, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vi = vec_srl(vi, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vi = vec_srl(vi, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vui = vec_srl(vui, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vui = vec_srl(vui, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vui = vec_srl(vui, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbi = vec_srl(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbi = vec_srl(vbi, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbi = vec_srl(vbi, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vsc = vec_vsr(vsc, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vsc = vec_vsr(vsc, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vsc = vec_vsr(vsc, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vuc = vec_vsr(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vuc = vec_vsr(vuc, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vuc = vec_vsr(vuc, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbc = vec_vsr(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbc = vec_vsr(vbc, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbc = vec_vsr(vbc, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vs = vec_vsr(vs, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vs = vec_vsr(vs, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vs = vec_vsr(vs, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vus = vec_vsr(vus, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vus = vec_vsr(vus, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vus = vec_vsr(vus, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbs = vec_vsr(vbs, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbs = vec_vsr(vbs, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbs = vec_vsr(vbs, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vp = vec_vsr(vp, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vp = vec_vsr(vp, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vp = vec_vsr(vp, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vi = vec_vsr(vi, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vi = vec_vsr(vi, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vi = vec_vsr(vi, vui); // CHECK: @llvm.ppc.altivec.vsr
res_vui = vec_vsr(vui, vuc); // CHECK: @llvm.ppc.altivec.vsr
res_vui = vec_vsr(vui, vus); // CHECK: @llvm.ppc.altivec.vsr
res_vui = vec_vsr(vui, vui); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbi = vec_vsr(vbi, vuc); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbi = vec_vsr(vbi, vus); // CHECK: @llvm.ppc.altivec.vsr
+ res_vbi = vec_vsr(vbi, vui); // CHECK: @llvm.ppc.altivec.vsr
/* vec_sro */
res_vsc = vec_sro(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsro
@@ -914,6 +1420,8 @@ int test6() {
res_vs = vec_sro(vs, vuc); // CHECK: @llvm.ppc.altivec.vsro
res_vus = vec_sro(vus, vsc); // CHECK: @llvm.ppc.altivec.vsro
res_vus = vec_sro(vus, vuc); // CHECK: @llvm.ppc.altivec.vsro
+ res_vp = vec_sro(vp, vsc); // CHECK: @llvm.ppc.altivec.vsro
+ res_vp = vec_sro(vp, vuc); // CHECK: @llvm.ppc.altivec.vsro
res_vi = vec_sro(vi, vsc); // CHECK: @llvm.ppc.altivec.vsro
res_vi = vec_sro(vi, vuc); // CHECK: @llvm.ppc.altivec.vsro
res_vui = vec_sro(vui, vsc); // CHECK: @llvm.ppc.altivec.vsro
@@ -928,6 +1436,8 @@ int test6() {
res_vs = vec_vsro(vs, vuc); // CHECK: @llvm.ppc.altivec.vsro
res_vus = vec_vsro(vus, vsc); // CHECK: @llvm.ppc.altivec.vsro
res_vus = vec_vsro(vus, vuc); // CHECK: @llvm.ppc.altivec.vsro
+ res_vp = vec_vsro(vp, vsc); // CHECK: @llvm.ppc.altivec.vsro
+ res_vp = vec_vsro(vp, vuc); // CHECK: @llvm.ppc.altivec.vsro
res_vi = vec_vsro(vi, vsc); // CHECK: @llvm.ppc.altivec.vsro
res_vi = vec_vsro(vi, vuc); // CHECK: @llvm.ppc.altivec.vsro
res_vui = vec_vsro(vui, vsc); // CHECK: @llvm.ppc.altivec.vsro
@@ -940,45 +1450,85 @@ int test6() {
vec_st(vsc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vuc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vus, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbs, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vp, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vp, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vui, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbi, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvx
+ vec_st(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvx
vec_st(vf, 0, &param_f); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vsc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vuc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vus, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbs, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vp, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vp, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vui, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbi, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvx
+ vec_stvx(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvx
vec_stvx(vf, 0, &param_f); // CHECK: @llvm.ppc.altivec.stvx
/* vec_ste */
vec_ste(vsc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvebx
vec_ste(vuc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvebx
+ vec_ste(vbc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvebx
+ vec_ste(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvebx
vec_ste(vs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvehx
vec_ste(vus, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_ste(vbs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_ste(vbs, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_ste(vp, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_ste(vp, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvehx
vec_ste(vi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvewx
vec_ste(vui, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvewx
+ vec_ste(vbi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvewx
+ vec_ste(vbi, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvewx
vec_ste(vf, 0, &param_f); // CHECK: @llvm.ppc.altivec.stvewx
vec_stvebx(vsc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvebx
vec_stvebx(vuc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvebx
+ vec_stvebx(vbc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvebx
+ vec_stvebx(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvebx
vec_stvehx(vs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvehx
vec_stvehx(vus, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_stvehx(vbs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_stvehx(vbs, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_stvehx(vp, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvehx
+ vec_stvehx(vp, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvehx
vec_stvewx(vi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvewx
vec_stvewx(vui, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvewx
+ vec_stvewx(vbi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvewx
+ vec_stvewx(vbi, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvewx
vec_stvewx(vf, 0, &param_f); // CHECK: @llvm.ppc.altivec.stvewx
/* vec_stl */
@@ -986,45 +1536,93 @@ int test6() {
vec_stl(vsc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vuc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vus, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbs, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vp, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vp, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vui, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbi, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stl(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvxl
vec_stl(vf, 0, &param_f); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vsc, 0, &vsc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vsc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vuc, 0, &vuc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vuc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbc, 0, &param_sc); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbc, 0, &param_uc); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbc, 0, &vbc); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vs, 0, &vs); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vus, 0, &vus); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vus, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbs, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbs, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbs, 0, &vbs); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vp, 0, &param_s); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vp, 0, &param_us); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vp, 0, &vp); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vi, 0, &vi); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vui, 0, &vui); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vui, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbi, 0, &param_i); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbi, 0, &param_ui); // CHECK: @llvm.ppc.altivec.stvxl
+ vec_stvxl(vbi, 0, &vbi); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vf, 0, &vf); // CHECK: @llvm.ppc.altivec.stvxl
vec_stvxl(vf, 0, &param_f); // CHECK: @llvm.ppc.altivec.stvxl
/* vec_sub */
res_vsc = vec_sub(vsc, vsc); // CHECK: sub nsw <16 x i8>
+ res_vsc = vec_sub(vbc, vsc); // CHECK: sub nsw <16 x i8>
+ res_vsc = vec_sub(vsc, vbc); // CHECK: sub nsw <16 x i8>
res_vuc = vec_sub(vuc, vuc); // CHECK: sub <16 x i8>
+ res_vuc = vec_sub(vbc, vuc); // CHECK: sub <16 x i8>
+ res_vuc = vec_sub(vuc, vbc); // CHECK: sub <16 x i8>
res_vs = vec_sub(vs, vs); // CHECK: sub nsw <8 x i16>
+ res_vs = vec_sub(vbs, vs); // CHECK: sub nsw <8 x i16>
+ res_vs = vec_sub(vs, vbs); // CHECK: sub nsw <8 x i16>
res_vus = vec_sub(vus, vus); // CHECK: sub <8 x i16>
+ res_vus = vec_sub(vbs, vus); // CHECK: sub <8 x i16>
+ res_vus = vec_sub(vus, vbs); // CHECK: sub <8 x i16>
res_vi = vec_sub(vi, vi); // CHECK: sub nsw <4 x i32>
+ res_vi = vec_sub(vbi, vi); // CHECK: sub nsw <4 x i32>
+ res_vi = vec_sub(vi, vbi); // CHECK: sub nsw <4 x i32>
res_vui = vec_sub(vui, vui); // CHECK: sub <4 x i32>
+ res_vui = vec_sub(vbi, vui); // CHECK: sub <4 x i32>
+ res_vui = vec_sub(vui, vbi); // CHECK: sub <4 x i32>
res_vf = vec_sub(vf, vf); // CHECK: fsub <4 x float>
res_vsc = vec_vsububm(vsc, vsc); // CHECK: sub nsw <16 x i8>
+ res_vsc = vec_vsububm(vbc, vsc); // CHECK: sub nsw <16 x i8>
+ res_vsc = vec_vsububm(vsc, vbc); // CHECK: sub nsw <16 x i8>
res_vuc = vec_vsububm(vuc, vuc); // CHECK: sub <16 x i8>
+ res_vuc = vec_vsububm(vbc, vuc); // CHECK: sub <16 x i8>
+ res_vuc = vec_vsububm(vuc, vbc); // CHECK: sub <16 x i8>
res_vs = vec_vsubuhm(vs, vs); // CHECK: sub nsw <8 x i16>
+ res_vs = vec_vsubuhm(vbs, vus); // CHECK: sub <8 x i16>
+ res_vs = vec_vsubuhm(vus, vbs); // CHECK: sub <8 x i16>
res_vus = vec_vsubuhm(vus, vus); // CHECK: sub <8 x i16>
+ res_vus = vec_vsubuhm(vbs, vus); // CHECK: sub <8 x i16>
+ res_vus = vec_vsubuhm(vus, vbs); // CHECK: sub <8 x i16>
res_vi = vec_vsubuwm(vi, vi); // CHECK: sub nsw <4 x i32>
+ res_vi = vec_vsubuwm(vbi, vi); // CHECK: sub nsw <4 x i32>
+ res_vi = vec_vsubuwm(vi, vbi); // CHECK: sub nsw <4 x i32>
res_vui = vec_vsubuwm(vui, vui); // CHECK: sub <4 x i32>
+ res_vui = vec_vsubuwm(vbi, vui); // CHECK: sub <4 x i32>
+ res_vui = vec_vsubuwm(vui, vbi); // CHECK: sub <4 x i32>
res_vf = vec_vsubfp(vf, vf); // CHECK: fsub <4 x float>
/* vec_subc */
@@ -1033,17 +1631,41 @@ int test6() {
/* vec_subs */
res_vsc = vec_subs(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs
+ res_vsc = vec_subs(vbc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs
+ res_vsc = vec_subs(vsc, vbc); // CHECK: @llvm.ppc.altivec.vsubsbs
res_vuc = vec_subs(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsububs
+ res_vuc = vec_subs(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsububs
+ res_vuc = vec_subs(vuc, vbc); // CHECK: @llvm.ppc.altivec.vsububs
res_vs = vec_subs(vs, vs); // CHECK: @llvm.ppc.altivec.vsubshs
+ res_vs = vec_subs(vbs, vs); // CHECK: @llvm.ppc.altivec.vsubshs
+ res_vs = vec_subs(vs, vbs); // CHECK: @llvm.ppc.altivec.vsubshs
res_vus = vec_subs(vus, vus); // CHECK: @llvm.ppc.altivec.vsubuhs
+ res_vus = vec_subs(vbs, vus); // CHECK: @llvm.ppc.altivec.vsubuhs
+ res_vus = vec_subs(vus, vbs); // CHECK: @llvm.ppc.altivec.vsubuhs
res_vi = vec_subs(vi, vi); // CHECK: @llvm.ppc.altivec.vsubsws
+ res_vi = vec_subs(vbi, vi); // CHECK: @llvm.ppc.altivec.vsubsws
+ res_vi = vec_subs(vi, vbi); // CHECK: @llvm.ppc.altivec.vsubsws
res_vui = vec_subs(vui, vui); // CHECK: @llvm.ppc.altivec.vsubuws
+ res_vui = vec_subs(vbi, vui); // CHECK: @llvm.ppc.altivec.vsubuws
+ res_vui = vec_subs(vui, vbi); // CHECK: @llvm.ppc.altivec.vsubuws
res_vsc = vec_vsubsbs(vsc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs
+ res_vsc = vec_vsubsbs(vbc, vsc); // CHECK: @llvm.ppc.altivec.vsubsbs
+ res_vsc = vec_vsubsbs(vsc, vbc); // CHECK: @llvm.ppc.altivec.vsubsbs
res_vuc = vec_vsububs(vuc, vuc); // CHECK: @llvm.ppc.altivec.vsububs
+ res_vuc = vec_vsububs(vbc, vuc); // CHECK: @llvm.ppc.altivec.vsububs
+ res_vuc = vec_vsububs(vuc, vbc); // CHECK: @llvm.ppc.altivec.vsububs
res_vs = vec_vsubshs(vs, vs); // CHECK: @llvm.ppc.altivec.vsubshs
+ res_vs = vec_vsubshs(vbs, vs); // CHECK: @llvm.ppc.altivec.vsubshs
+ res_vs = vec_vsubshs(vs, vbs); // CHECK: @llvm.ppc.altivec.vsubshs
res_vus = vec_vsubuhs(vus, vus); // CHECK: @llvm.ppc.altivec.vsubuhs
+ res_vus = vec_vsubuhs(vbs, vus); // CHECK: @llvm.ppc.altivec.vsubuhs
+ res_vus = vec_vsubuhs(vus, vbs); // CHECK: @llvm.ppc.altivec.vsubuhs
res_vi = vec_vsubsws(vi, vi); // CHECK: @llvm.ppc.altivec.vsubsws
+ res_vi = vec_vsubsws(vbi, vi); // CHECK: @llvm.ppc.altivec.vsubsws
+ res_vi = vec_vsubsws(vi, vbi); // CHECK: @llvm.ppc.altivec.vsubsws
res_vui = vec_vsubuws(vui, vui); // CHECK: @llvm.ppc.altivec.vsubuws
+ res_vui = vec_vsubuws(vbi, vui); // CHECK: @llvm.ppc.altivec.vsubuws
+ res_vui = vec_vsubuws(vui, vbi); // CHECK: @llvm.ppc.altivec.vsubuws
/* vec_sum4s */
res_vi = vec_sum4s(vsc, vi); // CHECK: @llvm.ppc.altivec.vsum4sbs
@@ -1066,60 +1688,152 @@ int test6() {
res_vf = vec_vrfiz(vf); // CHECK: @llvm.ppc.altivec.vrfiz
/* vec_unpackh */
- res_vs = vec_unpackh(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb
- res_vi = vec_unpackh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh
- res_vs = vec_vupkhsb(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb
- res_vi = vec_vupkhsh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh
+ res_vs = vec_unpackh(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb
+ res_vbs = vec_unpackh(vbc); // CHECK: @llvm.ppc.altivec.vupkhsb
+ res_vi = vec_unpackh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh
+ res_vbi = vec_unpackh(vbs); // CHECK: @llvm.ppc.altivec.vupkhsh
+ res_vui = vec_unpackh(vp); // CHECK: @llvm.ppc.altivec.vupkhsh
+ res_vs = vec_vupkhsb(vsc); // CHECK: @llvm.ppc.altivec.vupkhsb
+ res_vbs = vec_vupkhsb(vbc); // CHECK: @llvm.ppc.altivec.vupkhsb
+ res_vi = vec_vupkhsh(vs); // CHECK: @llvm.ppc.altivec.vupkhsh
+ res_vbi = vec_vupkhsh(vbs); // CHECK: @llvm.ppc.altivec.vupkhsh
+ res_vui = vec_vupkhsh(vp); // CHECK: @llvm.ppc.altivec.vupkhsh
/* vec_unpackl */
- res_vs = vec_unpackl(vsc); // CHECK: @llvm.ppc.altivec.vupklsb
- res_vi = vec_vupklsh(vs); // CHECK: @llvm.ppc.altivec.vupklsh
- res_vs = vec_vupklsb(vsc); // CHECK: @llvm.ppc.altivec.vupklsb
- res_vi = vec_vupklsh(vs); // CHECK: @llvm.ppc.altivec.vupklsh
+ res_vs = vec_unpackl(vsc); // CHECK: @llvm.ppc.altivec.vupklsb
+ res_vbs = vec_unpackl(vbc); // CHECK: @llvm.ppc.altivec.vupklsb
+ res_vi = vec_unpackl(vs); // CHECK: @llvm.ppc.altivec.vupklsh
+ res_vbi = vec_unpackl(vbs); // CHECK: @llvm.ppc.altivec.vupklsh
+ res_vui = vec_unpackl(vp); // CHECK: @llvm.ppc.altivec.vupklsh
+ res_vs = vec_vupklsb(vsc); // CHECK: @llvm.ppc.altivec.vupklsb
+ res_vbs = vec_vupklsb(vbc); // CHECK: @llvm.ppc.altivec.vupklsb
+ res_vi = vec_vupklsh(vs); // CHECK: @llvm.ppc.altivec.vupklsh
+ res_vbi = vec_vupklsh(vbs); // CHECK: @llvm.ppc.altivec.vupklsh
+ res_vui = vec_vupklsh(vp); // CHECK: @llvm.ppc.altivec.vupklsh
/* vec_xor */
res_vsc = vec_xor(vsc, vsc); // CHECK: xor <16 x i8>
+ res_vsc = vec_xor(vbc, vsc); // CHECK: xor <16 x i8>
+ res_vsc = vec_xor(vsc, vbc); // CHECK: xor <16 x i8>
res_vuc = vec_xor(vuc, vuc); // CHECK: xor <16 x i8>
+ res_vuc = vec_xor(vbc, vuc); // CHECK: xor <16 x i8>
+ res_vuc = vec_xor(vuc, vbc); // CHECK: xor <16 x i8>
+ res_vbc = vec_xor(vbc, vbc); // CHECK: xor <16 x i8>
res_vs = vec_xor(vs, vs); // CHECK: xor <8 x i16>
+ res_vs = vec_xor(vbs, vs); // CHECK: xor <8 x i16>
+ res_vs = vec_xor(vs, vbs); // CHECK: xor <8 x i16>
res_vus = vec_xor(vus, vus); // CHECK: xor <8 x i16>
+ res_vus = vec_xor(vbs, vus); // CHECK: xor <8 x i16>
+ res_vus = vec_xor(vus, vbs); // CHECK: xor <8 x i16>
+ res_vbs = vec_xor(vbs, vbs); // CHECK: xor <8 x i16>
res_vi = vec_xor(vi, vi); // CHECK: xor <4 x i32>
+ res_vi = vec_xor(vbi, vi); // CHECK: xor <4 x i32>
+ res_vi = vec_xor(vi, vbi); // CHECK: xor <4 x i32>
res_vui = vec_xor(vui, vui); // CHECK: xor <4 x i32>
+ res_vui = vec_xor(vbi, vui); // CHECK: xor <4 x i32>
+ res_vui = vec_xor(vui, vbi); // CHECK: xor <4 x i32>
+ res_vbi = vec_xor(vbi, vbi); // CHECK: xor <4 x i32>
res_vf = vec_xor(vf, vf); // CHECK: xor <4 x i32>
+ res_vf = vec_xor(vbi, vf); // CHECK: xor <4 x i32>
+ res_vf = vec_xor(vf, vbi); // CHECK: xor <4 x i32>
res_vsc = vec_vxor(vsc, vsc); // CHECK: xor <16 x i8>
+ res_vsc = vec_vxor(vbc, vsc); // CHECK: xor <16 x i8>
+ res_vsc = vec_vxor(vsc, vbc); // CHECK: xor <16 x i8>
res_vuc = vec_vxor(vuc, vuc); // CHECK: xor <16 x i8>
+ res_vuc = vec_vxor(vbc, vuc); // CHECK: xor <16 x i8>
+ res_vuc = vec_vxor(vuc, vbc); // CHECK: xor <16 x i8>
+ res_vbc = vec_vxor(vbc, vbc); // CHECK: xor <16 x i8>
res_vs = vec_vxor(vs, vs); // CHECK: xor <8 x i16>
+ res_vs = vec_vxor(vbs, vs); // CHECK: xor <8 x i16>
+ res_vs = vec_vxor(vs, vbs); // CHECK: xor <8 x i16>
res_vus = vec_vxor(vus, vus); // CHECK: xor <8 x i16>
+ res_vus = vec_vxor(vbs, vus); // CHECK: xor <8 x i16>
+ res_vus = vec_vxor(vus, vbs); // CHECK: xor <8 x i16>
+ res_vbs = vec_vxor(vbs, vbs); // CHECK: xor <8 x i16>
res_vi = vec_vxor(vi, vi); // CHECK: xor <4 x i32>
+ res_vi = vec_vxor(vbi, vi); // CHECK: xor <4 x i32>
+ res_vi = vec_vxor(vi, vbi); // CHECK: xor <4 x i32>
res_vui = vec_vxor(vui, vui); // CHECK: xor <4 x i32>
+ res_vui = vec_vxor(vbi, vui); // CHECK: xor <4 x i32>
+ res_vui = vec_vxor(vui, vbi); // CHECK: xor <4 x i32>
+ res_vbi = vec_vxor(vbi, vbi); // CHECK: xor <4 x i32>
res_vf = vec_vxor(vf, vf); // CHECK: xor <4 x i32>
+ res_vf = vec_vxor(vbi, vf); // CHECK: xor <4 x i32>
+ res_vf = vec_vxor(vf, vbi); // CHECK: xor <4 x i32>
/* ------------------------------ predicates -------------------------------------- */
/* vec_all_eq */
res_i = vec_all_eq(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_eq(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_all_eq(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_eq(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_eq(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_eq(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_eq(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_all_eq(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_eq(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_all_eq(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_eq(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_eq(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_eq(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_eq(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_eq(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_all_eq(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_eq(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_all_eq(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_eq(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_eq(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_eq(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_eq(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_all_eq(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p
/* vec_all_ge */
res_i = vec_all_ge(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_all_ge(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_all_ge(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_ge(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_ge(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_ge(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_ge(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_all_ge(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_all_ge(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_all_ge(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_ge(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_ge(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_ge(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_ge(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_all_ge(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_all_ge(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_all_ge(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_ge(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_ge(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_ge(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_ge(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_all_ge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p
/* vec_all_gt */
res_i = vec_all_gt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_all_gt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_all_gt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_gt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_gt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_gt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_gt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_all_gt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_all_gt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_all_gt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_gt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_gt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_gt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_gt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_all_gt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_all_gt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_all_gt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_gt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_gt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_gt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_gt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_all_gt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p
/* vec_all_in */
@@ -1127,23 +1841,78 @@ int test6() {
/* vec_all_le */
res_i = vec_all_le(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_all_le(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_all_le(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_le(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_le(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_le(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_le(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_all_le(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_all_le(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_all_le(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_le(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_le(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_le(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_le(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_all_le(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_all_le(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_all_le(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_le(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_le(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_le(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_le(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_all_le(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p
+ /* vec_all_lt */
+ res_i = vec_all_lt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_all_lt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_all_lt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_lt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_lt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_lt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_lt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_all_lt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_all_lt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_all_lt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_lt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_lt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_lt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_lt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_all_lt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_all_lt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_all_lt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_lt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_lt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_lt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_lt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_all_lt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p
+
/* vec_all_nan */
res_i = vec_all_nan(vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p
/* vec_all_ne */
res_i = vec_all_ne(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_ne(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_all_ne(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_ne(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_ne(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_ne(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_all_ne(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_all_ne(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_ne(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_all_ne(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_ne(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_ne(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_ne(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_ne(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_all_ne(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_all_ne(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_ne(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_all_ne(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_ne(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_ne(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_ne(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_all_ne(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_all_ne(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p
/* vec_all_nge */
@@ -1163,47 +1932,123 @@ int test6() {
/* vec_any_eq */
res_i = vec_any_eq(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_eq(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_any_eq(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_eq(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_eq(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_eq(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_eq(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_any_eq(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_eq(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_any_eq(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_eq(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_eq(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_eq(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_eq(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_eq(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_any_eq(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_eq(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_any_eq(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_eq(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_eq(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_eq(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_eq(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_any_eq(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p
/* vec_any_ge */
res_i = vec_any_ge(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_any_ge(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_any_ge(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_ge(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_ge(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_ge(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_ge(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_any_ge(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_any_ge(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_any_ge(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_ge(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_ge(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_ge(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_ge(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_any_ge(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_any_ge(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_any_ge(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_ge(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_ge(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_ge(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_ge(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_any_ge(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p
/* vec_any_gt */
res_i = vec_any_gt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_any_gt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_any_gt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_gt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_gt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_gt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_gt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_any_gt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_any_gt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_any_gt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_gt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_gt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_gt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_gt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_any_gt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_any_gt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_any_gt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_gt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_gt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_gt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_gt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_any_gt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p
/* vec_any_le */
res_i = vec_any_le(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_any_le(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_any_le(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_le(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_le(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_le(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_le(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_any_le(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_any_le(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_any_le(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_le(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_le(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_le(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_le(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_any_le(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_any_le(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_any_le(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_le(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_le(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_le(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_le(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_any_le(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgefp.p
/* vec_any_lt */
res_i = vec_any_lt(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
+ res_i = vec_any_lt(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtsb.p
res_i = vec_any_lt(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_lt(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_lt(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_lt(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
+ res_i = vec_any_lt(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpgtub.p
res_i = vec_any_lt(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
+ res_i = vec_any_lt(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtsh.p
res_i = vec_any_lt(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_lt(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_lt(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_lt(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
+ res_i = vec_any_lt(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpgtuh.p
res_i = vec_any_lt(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
+ res_i = vec_any_lt(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtsw.p
res_i = vec_any_lt(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_lt(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_lt(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_lt(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
+ res_i = vec_any_lt(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpgtuw.p
res_i = vec_any_lt(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpgtfp.p
/* vec_any_nan */
@@ -1211,11 +2056,27 @@ int test6() {
/* vec_any_ne */
res_i = vec_any_ne(vsc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_ne(vsc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_any_ne(vuc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_ne(vuc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_ne(vbc, vsc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_ne(vbc, vuc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
+ res_i = vec_any_ne(vbc, vbc); // CHECK: @llvm.ppc.altivec.vcmpequb.p
res_i = vec_any_ne(vs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_ne(vs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_any_ne(vus, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_ne(vus, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_ne(vbs, vs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_ne(vbs, vus); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_ne(vbs, vbs); // CHECK: @llvm.ppc.altivec.vcmpequh.p
+ res_i = vec_any_ne(vp, vp); // CHECK: @llvm.ppc.altivec.vcmpequh.p
res_i = vec_any_ne(vi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_ne(vi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_any_ne(vui, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_ne(vui, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_ne(vbi, vi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_ne(vbi, vui); // CHECK: @llvm.ppc.altivec.vcmpequw.p
+ res_i = vec_any_ne(vbi, vbi); // CHECK: @llvm.ppc.altivec.vcmpequw.p
res_i = vec_any_ne(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpeqfp.p
/* vec_any_nge */
@@ -1235,6 +2096,4 @@ int test6() {
/* vec_any_out */
res_i = vec_any_out(vf, vf); // CHECK: @llvm.ppc.altivec.vcmpbfp.p
-
- return 0;
}
diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c
index b5878144981f..1b4e68b01ede 100644
--- a/test/CodeGen/builtins-x86.c
+++ b/test/CodeGen/builtins-x86.c
@@ -24,6 +24,14 @@ typedef signed long long V2LLi __attribute__((vector_size(16)));
typedef float V4f __attribute__((vector_size(16)));
typedef double V2d __attribute__((vector_size(16)));
+// 256-bit
+typedef char V32c __attribute__((vector_size(32)));
+typedef signed int V8i __attribute__((vector_size(32)));
+typedef signed long long V4LLi __attribute__((vector_size(32)));
+
+typedef double V4d __attribute__((vector_size(32)));
+typedef float V8f __attribute__((vector_size(32)));
+
void f0() {
signed char tmp_c;
// unsigned char tmp_Uc;
@@ -76,6 +84,22 @@ void f0() {
V2LLi tmp_V2LLi;
V4f tmp_V4f;
V2d tmp_V2d;
+ V2d* tmp_V2dp;
+ V4f* tmp_V4fp;
+ const V2d* tmp_V2dCp;
+ const V4f* tmp_V4fCp;
+
+ // 256-bit
+ V32c tmp_V32c;
+ V4d tmp_V4d;
+ V8f tmp_V8f;
+ V4LLi tmp_V4LLi;
+ V8i tmp_V8i;
+ V4LLi* tmp_V4LLip;
+ V4d* tmp_V4dp;
+ V8f* tmp_V8fp;
+ const V4d* tmp_V4dCp;
+ const V8f* tmp_V8fCp;
tmp_i = __builtin_ia32_comieq(tmp_V4f, tmp_V4f);
tmp_i = __builtin_ia32_comilt(tmp_V4f, tmp_V4f);
@@ -365,6 +389,95 @@ void f0() {
tmp_V2d = __builtin_ia32_roundpd(tmp_V2d, imm_i_0_16);
tmp_V4f = __builtin_ia32_insertps128(tmp_V4f, tmp_V4f, tmp_i);
#endif
-}
-
+ tmp_V4d = __builtin_ia32_addsubpd256(tmp_V4d, tmp_V4d);
+ tmp_V8f = __builtin_ia32_addsubps256(tmp_V8f, tmp_V8f);
+ tmp_V4d = __builtin_ia32_haddpd256(tmp_V4d, tmp_V4d);
+ tmp_V8f = __builtin_ia32_hsubps256(tmp_V8f, tmp_V8f);
+ tmp_V4d = __builtin_ia32_hsubpd256(tmp_V4d, tmp_V4d);
+ tmp_V8f = __builtin_ia32_haddps256(tmp_V8f, tmp_V8f);
+ tmp_V4d = __builtin_ia32_maxpd256(tmp_V4d, tmp_V4d);
+ tmp_V8f = __builtin_ia32_maxps256(tmp_V8f, tmp_V8f);
+ tmp_V4d = __builtin_ia32_minpd256(tmp_V4d, tmp_V4d);
+ tmp_V8f = __builtin_ia32_minps256(tmp_V8f, tmp_V8f);
+ tmp_V2d = __builtin_ia32_vpermilvarpd(tmp_V2d, tmp_V2LLi);
+ tmp_V4f = __builtin_ia32_vpermilvarps(tmp_V4f, tmp_V4i);
+ tmp_V4d = __builtin_ia32_vpermilvarpd256(tmp_V4d, tmp_V4LLi);
+ tmp_V8f = __builtin_ia32_vpermilvarps256(tmp_V8f, tmp_V8i);
+ tmp_V4d = __builtin_ia32_blendpd256(tmp_V4d, tmp_V4d, 0x7);
+ tmp_V8f = __builtin_ia32_blendps256(tmp_V8f, tmp_V8f, 0x7);
+ tmp_V4d = __builtin_ia32_blendvpd256(tmp_V4d, tmp_V4d, tmp_V4d);
+ tmp_V8f = __builtin_ia32_blendvps256(tmp_V8f, tmp_V8f, tmp_V8f);
+ tmp_V8f = __builtin_ia32_dpps256(tmp_V8f, tmp_V8f, 0x7);
+ tmp_V4d = __builtin_ia32_cmppd256(tmp_V4d, tmp_V4d, 0);
+ tmp_V8f = __builtin_ia32_cmpps256(tmp_V8f, tmp_V8f, 0);
+ tmp_V2d = __builtin_ia32_vextractf128_pd256(tmp_V4d, 0x7);
+ tmp_V4f = __builtin_ia32_vextractf128_ps256(tmp_V8f, 0x7);
+ tmp_V4i = __builtin_ia32_vextractf128_si256(tmp_V8i, 0x7);
+ tmp_V4d = __builtin_ia32_cvtdq2pd256(tmp_V4i);
+ tmp_V8f = __builtin_ia32_cvtdq2ps256(tmp_V8i);
+ tmp_V4f = __builtin_ia32_cvtpd2ps256(tmp_V4d);
+ tmp_V8i = __builtin_ia32_cvtps2dq256(tmp_V8f);
+ tmp_V4d = __builtin_ia32_cvtps2pd256(tmp_V4f);
+ tmp_V4i = __builtin_ia32_cvttpd2dq256(tmp_V4d);
+ tmp_V4i = __builtin_ia32_cvtpd2dq256(tmp_V4d);
+ tmp_V8i = __builtin_ia32_cvttps2dq256(tmp_V8f);
+ tmp_V4d = __builtin_ia32_vperm2f128_pd256(tmp_V4d, tmp_V4d, 0x7);
+ tmp_V8f = __builtin_ia32_vperm2f128_ps256(tmp_V8f, tmp_V8f, 0x7);
+ tmp_V8i = __builtin_ia32_vperm2f128_si256(tmp_V8i, tmp_V8i, 0x7);
+ tmp_V2d = __builtin_ia32_vpermilpd(tmp_V2d, 0x7);
+ tmp_V4f = __builtin_ia32_vpermilps(tmp_V4f, 0x7);
+ tmp_V4d = __builtin_ia32_vpermilpd256(tmp_V4d, 0x7);
+ tmp_V8f = __builtin_ia32_vpermilps256(tmp_V8f, 0x7);
+ tmp_V4d = __builtin_ia32_vinsertf128_pd256(tmp_V4d, tmp_V2d, 0x7);
+ tmp_V8f = __builtin_ia32_vinsertf128_ps256(tmp_V8f, tmp_V4f, 0x7);
+ tmp_V8i = __builtin_ia32_vinsertf128_si256(tmp_V8i, tmp_V4i, 0x7);
+ tmp_V4d = __builtin_ia32_sqrtpd256(tmp_V4d);
+ tmp_V8f = __builtin_ia32_sqrtps256(tmp_V8f);
+ tmp_V8f = __builtin_ia32_rsqrtps256(tmp_V8f);
+ tmp_V8f = __builtin_ia32_rcpps256(tmp_V8f);
+ tmp_V4d = __builtin_ia32_roundpd256(tmp_V4d, tmp_i);
+ tmp_V8f = __builtin_ia32_roundps256(tmp_V8f, tmp_i);
+ tmp_i = __builtin_ia32_vtestzpd(tmp_V2d, tmp_V2d);
+ tmp_i = __builtin_ia32_vtestcpd(tmp_V2d, tmp_V2d);
+ tmp_i = __builtin_ia32_vtestnzcpd(tmp_V2d, tmp_V2d);
+ tmp_i = __builtin_ia32_vtestzps(tmp_V4f, tmp_V4f);
+ tmp_i = __builtin_ia32_vtestcps(tmp_V4f, tmp_V4f);
+ tmp_i = __builtin_ia32_vtestnzcps(tmp_V4f, tmp_V4f);
+ tmp_i = __builtin_ia32_vtestzpd256(tmp_V4d, tmp_V4d);
+ tmp_i = __builtin_ia32_vtestcpd256(tmp_V4d, tmp_V4d);
+ tmp_i = __builtin_ia32_vtestnzcpd256(tmp_V4d, tmp_V4d);
+ tmp_i = __builtin_ia32_vtestzps256(tmp_V8f, tmp_V8f);
+ tmp_i = __builtin_ia32_vtestcps256(tmp_V8f, tmp_V8f);
+ tmp_i = __builtin_ia32_vtestnzcps256(tmp_V8f, tmp_V8f);
+ tmp_i = __builtin_ia32_ptestz256(tmp_V4LLi, tmp_V4LLi);
+ tmp_i = __builtin_ia32_ptestc256(tmp_V4LLi, tmp_V4LLi);
+ tmp_i = __builtin_ia32_ptestnzc256(tmp_V4LLi, tmp_V4LLi);
+ tmp_i = __builtin_ia32_movmskpd256(tmp_V4d);
+ tmp_i = __builtin_ia32_movmskps256(tmp_V8f);
+ __builtin_ia32_vzeroall();
+ __builtin_ia32_vzeroupper();
+ tmp_V4f = __builtin_ia32_vbroadcastss(tmp_fCp);
+ tmp_V4d = __builtin_ia32_vbroadcastsd256(tmp_dCp);
+ tmp_V8f = __builtin_ia32_vbroadcastss256(tmp_fCp);
+ tmp_V4d = __builtin_ia32_vbroadcastf128_pd256(tmp_V2dCp);
+ tmp_V8f = __builtin_ia32_vbroadcastf128_ps256(tmp_V4fCp);
+ tmp_V4d = __builtin_ia32_loadupd256(tmp_dCp);
+ tmp_V8f = __builtin_ia32_loadups256(tmp_fCp);
+ __builtin_ia32_storeupd256(tmp_dp, tmp_V4d);
+ __builtin_ia32_storeups256(tmp_fp, tmp_V8f);
+ tmp_V32c = __builtin_ia32_loaddqu256(tmp_cCp);
+ __builtin_ia32_storedqu256(tmp_cp, tmp_V32c);
+ tmp_V32c = __builtin_ia32_lddqu256(tmp_cCp);
+ __builtin_ia32_movntdq256(tmp_V4LLip, tmp_V4LLi);
+ __builtin_ia32_movntpd256(tmp_dp, tmp_V4d);
+ __builtin_ia32_movntps256(tmp_fp, tmp_V8f);
+ tmp_V2d = __builtin_ia32_maskloadpd(tmp_V2dCp, tmp_V2d);
+ tmp_V4f = __builtin_ia32_maskloadps(tmp_V4fCp, tmp_V4f);
+ tmp_V4d = __builtin_ia32_maskloadpd256(tmp_V4dCp, tmp_V4d);
+ tmp_V8f = __builtin_ia32_maskloadps256(tmp_V8fCp, tmp_V8f);
+ __builtin_ia32_maskstorepd(tmp_V2dp, tmp_V2d, tmp_V2d);
+ __builtin_ia32_maskstoreps(tmp_V4fp, tmp_V4f, tmp_V4f);
+ __builtin_ia32_maskstorepd256(tmp_V4dp, tmp_V4d, tmp_V4d);
+ __builtin_ia32_maskstoreps256(tmp_V8fp, tmp_V8f, tmp_V8f);
+}
diff --git a/test/CodeGen/const-arithmetic.c b/test/CodeGen/const-arithmetic.c
index 92c02f0b3dfb..a28f73f004e4 100644
--- a/test/CodeGen/const-arithmetic.c
+++ b/test/CodeGen/const-arithmetic.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
-// CHECK: @g1 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 16 ; <[2 x i8*]*> [#uses=0]
-// CHECK: @g2 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 16 ; <[2 x i8*]*> [#uses=0]
+// CHECK: @g1 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 16
+// CHECK: @g2 = global [2 x i8*] [i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -2), i8* getelementptr (i8* getelementptr inbounds ([0 x %struct.anon]* @g0, i32 0, i32 0, i32 0), i64 -46)], align 16
extern struct { unsigned char a, b; } g0[];
void *g1[] = {g0 + -1, g0 + -23 };
diff --git a/test/CodeGen/const-init.c b/test/CodeGen/const-init.c
index c7a53be02c58..ac26b65e688d 100644
--- a/test/CodeGen/const-init.c
+++ b/test/CodeGen/const-init.c
@@ -117,9 +117,14 @@ 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)
+// CHECK: @__func__.g25 = private constant [4 x i8] c"g25\00"
int g25() {
static const char *g26 = __func__;
return *g26;
}
+
+// CHECK: @g27.x = internal global i8* bitcast (i8** @g27.x to i8*), align 4
+void g27() { // PR8073
+ static void *x = &x;
+}
diff --git a/test/CodeGen/debug-info-enum.c b/test/CodeGen/debug-info-enum.c
new file mode 100644
index 000000000000..b4a1ce0d3a22
--- /dev/null
+++ b/test/CodeGen/debug-info-enum.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -g %s -o %t
+// RUN: grep DW_TAG_enumeration_type %t
+// Radar 8195980
+
+enum vtag {
+ VT_ONE
+};
+
+int foo(int i) {
+ return i == VT_ONE;
+}
diff --git a/test/CodeGen/debug-info-scope.c b/test/CodeGen/debug-info-scope.c
new file mode 100644
index 000000000000..6051e6ed0fe1
--- /dev/null
+++ b/test/CodeGen/debug-info-scope.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -g -emit-llvm < %s | FileCheck %s
+// Two variables with same name in separate scope.
+// Radar 8330217.
+int main() {
+ int j = 0;
+ int k = 0;
+// CHECK: DW_TAG_auto_variable
+// CHECK-NEXT: DW_TAG_lexical_block
+ for (int i = 0; i < 10; i++)
+ j++;
+ for (int i = 0; i < 10; i++)
+ k++;
+ return 0;
+}
diff --git a/test/CodeGen/designated-initializers.c b/test/CodeGen/designated-initializers.c
index 49f57ad062c5..312d78565294 100644
--- a/test/CodeGen/designated-initializers.c
+++ b/test/CodeGen/designated-initializers.c
@@ -8,10 +8,10 @@ struct foo {
// CHECK: @u = global %union.anon zeroinitializer
union { int i; float f; } u = { };
-// CHECK: @u2 = global %0 { i32 0, [4 x i8] undef }
+// CHECK: @u2 = global %1 { i32 0, [4 x i8] undef }
union { int i; double f; } u2 = { };
-// CHECK: @u3 = global %1 zeroinitializer
+// CHECK: @u3 = global %2 zeroinitializer
union { double f; int i; } u3 = { };
// CHECK: @b = global [2 x i32] [i32 0, i32 22]
@@ -19,7 +19,7 @@ int b[2] = {
[1] = 22
};
-int main(int argc, char **argv)
+void test1(int argc, char **argv)
{
// CHECK: internal global %struct.foo { i8* null, i32 1024 }
static struct foo foo = {
@@ -33,5 +33,24 @@ int main(int argc, char **argv)
// CHECK-NOT: call void @llvm.memset
union { int i; float f; } u3;
- // CHECK: ret i32
+ // CHECK: ret void
+}
+
+
+// PR7151
+struct S {
+ int nkeys;
+ int *keys;
+ union {
+ void *data;
+ };
+};
+
+void test2() {
+ struct S *btkr;
+
+ *btkr = (struct S) {
+ .keys = 0,
+ { .data = 0 },
+ };
}
diff --git a/test/CodeGen/enum2.c b/test/CodeGen/enum2.c
new file mode 100644
index 000000000000..3203627b8983
--- /dev/null
+++ b/test/CodeGen/enum2.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -g -emit-llvm -o /dev/null
+int v;
+enum e { MAX };
+
+void foo (void)
+{
+ v = MAX;
+}
diff --git a/test/CodeGen/exprs.c b/test/CodeGen/exprs.c
index 7cc1134077ee..c9978b851642 100644
--- a/test/CodeGen/exprs.c
+++ b/test/CodeGen/exprs.c
@@ -145,3 +145,10 @@ double f13(double X) {
// CHECK: fsub double -0.0
return -X;
}
+
+// Check operations on incomplete types.
+struct s14;
+void f14(struct s13 *a) {
+ (void) &*a;
+}
+
diff --git a/test/CodeGen/fold-const-declref.c b/test/CodeGen/fold-const-declref.c
new file mode 100644
index 000000000000..5a7ba8e26a77
--- /dev/null
+++ b/test/CodeGen/fold-const-declref.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify -emit-llvm-only
+
+// PR7242: Check that this doesn't crash.
+int main(void)
+{
+ int __negative = 1;
+ const int __max = __negative && 0 ;
+ __max / 0;
+}
diff --git a/test/CodeGen/func-in-block.c b/test/CodeGen/func-in-block.c
index 27e0c0960997..7e65ff92df05 100644
--- a/test/CodeGen/func-in-block.c
+++ b/test/CodeGen/func-in-block.c
@@ -15,4 +15,5 @@ int main()
return 0; // not reached
}
+// CHECK: @__func__.__main_block_invoke_0 = private constant [22 x i8] c"__main_block_invoke_0\00"
// CHECK: call void @PRINTF({{.*}}@__func__.__main_block_invoke_
diff --git a/test/CodeGen/lineno-dbginfo.c b/test/CodeGen/lineno-dbginfo.c
index c5c350f7009e..176d4157f39d 100644
--- a/test/CodeGen/lineno-dbginfo.c
+++ b/test/CodeGen/lineno-dbginfo.c
@@ -1,6 +1,5 @@
// RUN: echo "#include <stdio.h>" > %t.h
-// RUN: %clang -S -save-temps -g -include %t.h %s -emit-llvm -o %t.ll
+// RUN: %clang -S -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/packed-structure.c b/test/CodeGen/packed-structure.c
new file mode 100644
index 000000000000..2934d01d6496
--- /dev/null
+++ b/test/CodeGen/packed-structure.c
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | opt -S -strip -o %t
+// RUX: llvm-gcc -flto -S -O3 -o %t %s
+// RUN: FileCheck --check-prefix=CHECK-GLOBAL < %t %s
+// RUN: FileCheck --check-prefix=CHECK-FUNCTIONS < %t %s
+
+struct s0 {
+ int x;
+ int y __attribute__((packed));
+};
+
+// CHECK-GLOBAL: @s0_align_x = global i32 4
+
+// FIXME: This should be 1 to match gcc. PR7951.
+// CHECK-GLOBAL: @s0_align_y = global i32 4
+
+// CHECK-GLOBAL: @s0_align = global i32 4
+int s0_align_x = __alignof(((struct s0*)0)->x);
+int s0_align_y = __alignof(((struct s0*)0)->y);
+int s0_align = __alignof(struct s0);
+
+// CHECK-FUNCTIONS: define i32 @s0_load_x
+// CHECK-FUNCTIONS: [[s0_load_x:%.*]] = load i32* {{.*}}, align 4
+// CHECK-FUNCTIONS: ret i32 [[s0_load_x]]
+int s0_load_x(struct s0 *a) { return a->x; }
+// FIXME: This seems like it should be align 1. This is actually something which
+// has changed in llvm-gcc recently, previously both x and y would be loaded
+// with align 1 (in 2363.1 at least).
+//
+// CHECK-FUNCTIONS: define i32 @s0_load_y
+// CHECK-FUNCTIONS: [[s0_load_y:%.*]] = load i32* {{.*}}, align 4
+// CHECK-FUNCTIONS: ret i32 [[s0_load_y]]
+int s0_load_y(struct s0 *a) { return a->y; }
+// CHECK-FUNCTIONS: define void @s0_copy
+// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 4, i1 false)
+void s0_copy(struct s0 *a, struct s0 *b) { *b = *a; }
+
+//
+
+struct s1 {
+ int x;
+ int y;
+} __attribute__((packed));
+
+// CHECK-GLOBAL: @s1_align_x = global i32 1
+// CHECK-GLOBAL: @s1_align_y = global i32 1
+// CHECK-GLOBAL: @s1_align = global i32 1
+int s1_align_x = __alignof(((struct s1*)0)->x);
+int s1_align_y = __alignof(((struct s1*)0)->y);
+int s1_align = __alignof(struct s1);
+
+// CHECK-FUNCTIONS: define i32 @s1_load_x
+// CHECK-FUNCTIONS: [[s1_load_x:%.*]] = load i32* {{.*}}, align 1
+// CHECK-FUNCTIONS: ret i32 [[s1_load_x]]
+int s1_load_x(struct s1 *a) { return a->x; }
+// CHECK-FUNCTIONS: define i32 @s1_load_y
+// CHECK-FUNCTIONS: [[s1_load_y:%.*]] = load i32* {{.*}}, align 1
+// CHECK-FUNCTIONS: ret i32 [[s1_load_y]]
+int s1_load_y(struct s1 *a) { return a->y; }
+// CHECK-FUNCTIONS: define void @s1_copy
+// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 1, i1 false)
+void s1_copy(struct s1 *a, struct s1 *b) { *b = *a; }
+
+//
+
+#pragma pack(push,2)
+struct s2 {
+ int x;
+ int y;
+};
+#pragma pack(pop)
+
+// CHECK-GLOBAL: @s2_align_x = global i32 2
+// CHECK-GLOBAL: @s2_align_y = global i32 2
+// CHECK-GLOBAL: @s2_align = global i32 2
+int s2_align_x = __alignof(((struct s2*)0)->x);
+int s2_align_y = __alignof(((struct s2*)0)->y);
+int s2_align = __alignof(struct s2);
+
+// CHECK-FUNCTIONS: define i32 @s2_load_x
+// CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32* {{.*}}, align 2
+// CHECK-FUNCTIONS: ret i32 [[s2_load_y]]
+int s2_load_x(struct s2 *a) { return a->x; }
+// CHECK-FUNCTIONS: define i32 @s2_load_y
+// CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32* {{.*}}, align 2
+// CHECK-FUNCTIONS: ret i32 [[s2_load_y]]
+int s2_load_y(struct s2 *a) { return a->y; }
+// CHECK-FUNCTIONS: define void @s2_copy
+// CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 2, i1 false)
+void s2_copy(struct s2 *a, struct s2 *b) { *b = *a; }
diff --git a/test/CodeGen/palignr.c b/test/CodeGen/palignr.c
index 6297b2e990f4..e9c1dbd012b5 100644
--- a/test/CodeGen/palignr.c
+++ b/test/CodeGen/palignr.c
@@ -27,4 +27,4 @@ int2 align6(int2 a, int2 b) { return _mm_alignr_pi8(a, b, 9); }
int2 align7(int2 a, int2 b) { return _mm_alignr_pi8(a, b, 16); }
// CHECK: palignr
-int2 align8(int2 a, int2 b) { return _mm_alignr_pi8(a, b, 7); } \ No newline at end of file
+int2 align8(int2 a, int2 b) { return _mm_alignr_pi8(a, b, 7); }
diff --git a/test/CodeGen/pragma-visibility.c b/test/CodeGen/pragma-visibility.c
new file mode 100644
index 000000000000..16460a28280e
--- /dev/null
+++ b/test/CodeGen/pragma-visibility.c
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+#pragma GCC visibility push(hidden)
+int x = 2;
+// CHECK: @x = hidden global
+
+extern int y;
+#pragma GCC visibility pop
+int y = 4;
+// CHECK: @y = hidden global
+
+#pragma GCC visibility push(hidden)
+extern __attribute((visibility("default"))) int z;
+int z = 0;
+// CHECK: @z = global
+#pragma GCC visibility pop
+
+#pragma GCC visibility push(hidden)
+void f() {}
+// CHECK: define hidden void @f
+
+__attribute((visibility("default"))) void g();
+void g() {}
+// CHECK: define void @g
diff --git a/test/CodeGen/statements.c b/test/CodeGen/statements.c
index 7ed82add69b0..0ea0597835cb 100644
--- a/test/CodeGen/statements.c
+++ b/test/CodeGen/statements.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wreturn-type < %s -emit-llvm
+// RUN: %clang_cc1 -Wreturn-type %s -emit-llvm -o /dev/null
void test1(int x) {
switch (x) {
@@ -31,5 +31,10 @@ static long y = &&baz;
}
// PR3869
-int test5(long long b) { goto *b; }
+int test5(long long b) {
+ static void *lbls[] = { &&lbl };
+ goto *b;
+ lbl:
+ return 0;
+}
diff --git a/test/CodeGen/struct-passing.c b/test/CodeGen/struct-passing.c
index 409d14e22d39..cbc14d5b7819 100644
--- a/test/CodeGen/struct-passing.c
+++ b/test/CodeGen/struct-passing.c
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -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(.* sret)$' %t
-// RUN: grep 'declare void @f3(.* sret)$' %t
-// RUN: grep 'declare void @f4(.* byval)$' %t
-// RUN: grep 'declare void @f5(.* byval)$' %t
+// RUN: grep 'declare i32 @f0() readnone' %t
+// RUN: grep 'declare i32 @f1() readonly' %t
+// RUN: grep 'declare void @f2(.* sret)' %t
+// RUN: grep 'declare void @f3(.* 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/thread-specifier.c b/test/CodeGen/thread-specifier.c
index b1e1ed84647f..a16103f08f6d 100644
--- a/test/CodeGen/thread-specifier.c
+++ b/test/CodeGen/thread-specifier.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -o - %s | grep thread_local | count 4
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -emit-llvm -o - %s | not grep common
__thread int a;
extern __thread int b;
diff --git a/test/CodeGen/trapv.c b/test/CodeGen/trapv.c
index d10d6176bf94..7f192c634c88 100644
--- a/test/CodeGen/trapv.c
+++ b/test/CodeGen/trapv.c
@@ -1,10 +1,51 @@
-// RUN: %clang_cc1 -ftrapv %s -emit-llvm -o %t
-// RUN: grep "__overflow_handler" %t | count 2
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -ftrapv %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: [[I32O:%.*]] = type { i32, i1 }
unsigned int ui, uj, uk;
int i, j, k;
-void foo() {
+// CHECK: define void @test0()
+void test0() {
+ // -ftrapv doesn't affect unsigned arithmetic.
+ // CHECK: [[T1:%.*]] = load i32* @uj
+ // CHECK-NEXT: [[T2:%.*]] = load i32* @uk
+ // CHECK-NEXT: [[T3:%.*]] = add i32 [[T1]], [[T2]]
+ // CHECK-NEXT: store i32 [[T3]], i32* @ui
ui = uj + uk;
+
+ // CHECK: [[T1:%.*]] = load i32* @j
+ // CHECK-NEXT: [[T2:%.*]] = load i32* @k
+ // CHECK-NEXT: [[T3:%.*]] = call [[I32O]] @llvm.sadd.with.overflow.i32(i32 [[T1]], i32 [[T2]])
+ // CHECK-NEXT: [[T4:%.*]] = extractvalue [[I32O]] [[T3]], 0
+ // CHECK-NEXT: [[T5:%.*]] = extractvalue [[I32O]] [[T3]], 1
+ // CHECK-NEXT: br i1 [[T5]]
+ // CHECK: call void @llvm.trap()
i = j + k;
}
+
+// CHECK: define void @test1()
+void test1() {
+ extern void opaque(int);
+ opaque(i++);
+
+ // CHECK: [[T1:%.*]] = load i32* @i
+ // CHECK-NEXT: [[T2:%.*]] = call [[I32O]] @llvm.sadd.with.overflow.i32(i32 [[T1]], i32 1)
+ // CHECK-NEXT: [[T3:%.*]] = extractvalue [[I32O]] [[T2]], 0
+ // CHECK-NEXT: [[T4:%.*]] = extractvalue [[I32O]] [[T2]], 1
+ // CHECK-NEXT: br i1 [[T4]]
+ // CHECK: call void @llvm.trap()
+}
+
+// CHECK: define void @test2()
+void test2() {
+ extern void opaque(int);
+ opaque(++i);
+
+ // CHECK: [[T1:%.*]] = load i32* @i
+ // CHECK-NEXT: [[T2:%.*]] = call [[I32O]] @llvm.sadd.with.overflow.i32(i32 [[T1]], i32 1)
+ // CHECK-NEXT: [[T3:%.*]] = extractvalue [[I32O]] [[T2]], 0
+ // CHECK-NEXT: [[T4:%.*]] = extractvalue [[I32O]] [[T2]], 1
+ // CHECK-NEXT: br i1 [[T4]]
+ // CHECK: call void @llvm.trap()
+}
diff --git a/test/CodeGen/unwind-attr.c b/test/CodeGen/unwind-attr.c
index ee3199d274dd..c588ca8e1b60 100644
--- a/test/CodeGen/unwind-attr.c
+++ b/test/CodeGen/unwind-attr.c
@@ -1,6 +1,24 @@
-// RUN: %clang_cc1 -fexceptions -emit-llvm -o - %s | grep "@foo()" | not grep nounwind
-// RUN: %clang_cc1 -emit-llvm -o - %s | grep "@foo()" | grep nounwind
+// RUN: %clang_cc1 -fexceptions -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix NOEXC %s
-int foo(void) {
+int opaque();
+
+// CHECK: define [[INT:i.*]] @test0() {
+// CHECK-NOEXC: define [[INT:i.*]] @test0() nounwind {
+int test0(void) {
+ return opaque();
+}
+
+// <rdar://problem/8087431>: locally infer nounwind at -O0
+// CHECK: define [[INT:i.*]] @test1() nounwind {
+// CHECK-NOEXC: define [[INT:i.*]] @test1() nounwind {
+int test1(void) {
+ return 0;
+}
+
+// <rdar://problem/8283071>: not for weak functions
+// CHECK: define weak [[INT:i.*]] @test2() {
+// CHECK-NOEXC: define weak [[INT:i.*]] @test2() nounwind {
+__attribute__((weak)) int test2(void) {
return 0;
}
diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c
index c16d65bebec2..3fa5f1441d2f 100644
--- a/test/CodeGen/vector.c
+++ b/test/CodeGen/vector.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-apple-darwin9 -target-cpu pentium4 -g -emit-llvm %s -o -
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -O1 -target-cpu pentium4 -target-feature +sse4.1 -g -emit-llvm %s -o - | FileCheck %s
typedef short __v4hi __attribute__ ((__vector_size__ (8)));
void test1() {
@@ -20,6 +20,8 @@ void test3 ( vec4* a, char b, float c ) {
+// Don't include mm_malloc.h, it's system specific.
+#define __MM_MALLOC_H
#include <mmintrin.h>
@@ -40,3 +42,16 @@ int test4(int argc, char *argv[]) {
return result;
}
+
+#include <smmintrin.h>
+
+unsigned long test_epi8(__m128i x) { return _mm_extract_epi8(x, 4); }
+// CHECK: @test_epi8
+// CHECK: extractelement <16 x i8> {{.*}}, i32 4
+// CHECK: zext i8 {{.*}} to i32
+
+unsigned long test_epi16(__m128i x) { return _mm_extract_epi16(x, 3); }
+
+// CHECK: @test_epi16
+// CHECK: extractelement <8 x i16> {{.*}}, i32 3
+// CHECK: zext i16 {{.*}} to i32
diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c
index 01c3e236f3bd..75dfb82b32ad 100644
--- a/test/CodeGen/x86_32-arguments.c
+++ b/test/CodeGen/x86_32-arguments.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fblocks -triple i386-apple-darwin9 -emit-llvm -o %t %s
+// RUN: %clang_cc1 -w -fblocks -triple i386-apple-darwin9 -emit-llvm -o %t %s
// RUN: FileCheck < %t %s
// CHECK: define signext i8 @f0()
@@ -214,3 +214,17 @@ struct __attribute__((aligned(32))) s53 {
int y;
};
void f53(struct s53 x) {}
+
+typedef unsigned short v2i16 __attribute__((__vector_size__(4)));
+
+// CHECK: define i32 @f54(i32 %arg.coerce)
+// rdar://8359483
+v2i16 f54(v2i16 arg) { return arg+arg; }
+
+
+typedef int v4i32 __attribute__((__vector_size__(16)));
+
+// CHECK: define <2 x i64> @f55(<4 x i32> %arg)
+// PR8029
+v4i32 f55(v4i32 arg) { return arg+arg; }
+
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index cc318dc749b3..51a234d993ca 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o %t %s
-// RUN: FileCheck < %t %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s| FileCheck %s
+#include <stdarg.h>
// CHECK: %0 = type { i64, double }
@@ -63,8 +63,8 @@ void f10(struct s10 a0) {}
// CHECK: define void @f11(%struct.s19* sret %agg.result)
union { long double a; float b; } f11() { while (1) {} }
-// CHECK: define i64 @f12_0()
-// CHECK: define void @f12_1(i64 %a0.coerce)
+// CHECK: define i32 @f12_0()
+// CHECK: define void @f12_1(i32 %a0.coerce)
struct s12 { int a __attribute__((aligned(16))); };
struct s12 f12_0(void) { while (1) {} }
void f12_1(struct s12 a0) {}
@@ -131,3 +131,117 @@ void f22(L x, L y) { }
// CHECK: %y = alloca{{.*}}, align 16
+
+// PR7714
+struct f23S {
+ short f0;
+ unsigned f1;
+ int f2;
+};
+
+
+void f23(int A, struct f23S B) {
+ // CHECK: define void @f23(i32 %A, i64 %B.coerce0, i32 %B.coerce1)
+}
+
+struct f24s { long a; int b; };
+
+struct f23S f24(struct f23S *X, struct f24s *P2) {
+ return *X;
+
+ // CHECK: define %struct.f24s @f24(%struct.f23S* %X, %struct.f24s* %P2)
+}
+
+// rdar://8248065
+typedef float v4f32 __attribute__((__vector_size__(16)));
+v4f32 f25(v4f32 X) {
+ // CHECK: define <4 x float> @f25(<4 x float> %X)
+ // CHECK-NOT: alloca
+ // CHECK: alloca <4 x float>
+ // CHECK-NOT: alloca
+ // CHECK: store <4 x float> %X, <4 x float>*
+ // CHECK-NOT: store
+ // CHECK: ret <4 x float>
+ return X+X;
+}
+
+struct foo26 {
+ int *X;
+ float *Y;
+};
+
+struct foo26 f26(struct foo26 *P) {
+ // CHECK: define %struct.foo26 @f26(%struct.foo26* %P)
+ return *P;
+}
+
+
+struct v4f32wrapper {
+ v4f32 v;
+};
+
+struct v4f32wrapper f27(struct v4f32wrapper X) {
+ // CHECK: define <4 x float> @f27(<4 x float> %X.coerce)
+ return X;
+}
+
+// rdar://5711709
+struct f28c {
+ double x;
+ int y;
+};
+void f28(struct f28c C) {
+ // CHECK: define void @f28(double %C.coerce0, i32 %C.coerce1)
+}
+
+struct f29a {
+ struct c {
+ double x;
+ int y;
+ } x[1];
+};
+
+void f29a(struct f29a A) {
+ // CHECK: define void @f29a(double %A.coerce0, i32 %A.coerce1)
+}
+
+// rdar://8249586
+struct S0 { char f0[8]; char f2; char f3; char f4; };
+void f30(struct S0 p_4) {
+ // CHECK: define void @f30(i64 %p_4.coerce0, i24 %p_4.coerce1)
+}
+
+// Pass the third element as a float when followed by tail padding.
+// rdar://8251384
+struct f31foo { float a, b, c; };
+float f31(struct f31foo X) {
+ // CHECK: define float @f31(<2 x float> %X.coerce0, float %X.coerce1)
+ return X.c;
+}
+
+_Complex float f32(_Complex float A, _Complex float B) {
+ // rdar://6379669
+ // CHECK: define <2 x float> @f32(<2 x float> %A.coerce, <2 x float> %B.coerce)
+ return A+B;
+}
+
+
+// rdar://8357396
+struct f33s { long x; float c,d; };
+
+void f33(va_list X) {
+ va_arg(X, struct f33s);
+}
+
+typedef unsigned long long v1i64 __attribute__((__vector_size__(8)));
+
+// rdar://8359248
+// CHECK: define i64 @f34(i64 %arg.coerce)
+v1i64 f34(v1i64 arg) { return arg; }
+
+
+// rdar://8358475
+// CHECK: define i64 @f35(i64 %arg.coerce)
+typedef unsigned long v1i64_2 __attribute__((__vector_size__(8)));
+v1i64_2 f35(v1i64_2 arg) { return arg+arg; }
+
diff --git a/test/CodeGenCXX/anonymous-namespaces.cpp b/test/CodeGenCXX/anonymous-namespaces.cpp
index fb3470ca9bee..3ec7032ee5f5 100644
--- a/test/CodeGenCXX/anonymous-namespaces.cpp
+++ b/test/CodeGenCXX/anonymous-namespaces.cpp
@@ -1,12 +1,14 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm %s -o - > %t
+// RUN: FileCheck %s -check-prefix=1 < %t
+// RUN: FileCheck %s -check-prefix=2 < %t
int f();
namespace {
- // CHECK: @_ZN12_GLOBAL__N_11bE = internal global i32 0
- // CHECK: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0
- // CHECK: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0
- // CHECK: @_ZN12_GLOBAL__N_11aE = internal global i32 0
+ // CHECK-1: @_ZN12_GLOBAL__N_11bE = internal global i32 0
+ // CHECK-1: @_ZN12_GLOBAL__N_1L1cE = internal global i32 0
+ // CHECK-1: @_ZN12_GLOBAL__N_11D1dE = internal global i32 0
+ // CHECK-1: @_ZN12_GLOBAL__N_11aE = internal global i32 0
int a = 0;
int b = f();
@@ -20,18 +22,18 @@ namespace {
int D::d = f();
// Check for generation of a VTT with internal linkage
- // CHECK: @_ZTSN12_GLOBAL__N_11X1EE = internal constant
+ // CHECK-1: @_ZTSN12_GLOBAL__N_11X1EE = internal constant
struct X {
struct EBase { };
struct E : public virtual EBase { virtual ~E() {} };
};
- // CHECK: define internal i32 @_ZN12_GLOBAL__N_13fooEv()
+ // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_13fooEv()
int foo() {
return 32;
}
- // CHECK: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv()
+ // CHECK-1: define internal i32 @_ZN12_GLOBAL__N_11A3fooEv()
namespace A {
int foo() {
return 45;
@@ -44,3 +46,23 @@ int concrete() {
}
void test_XE() { throw X::E(); }
+
+// Miscompile on llvmc plugins.
+namespace test2 {
+ struct A {
+ template <class T> struct B {
+ static void foo() {}
+ };
+ };
+ namespace {
+ struct C;
+ }
+
+ // CHECK-2: define void @_ZN5test24testEv()
+ // CHECK-2: call void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
+ void test() {
+ A::B<C>::foo();
+ }
+
+ // CHECK-2: define internal void @_ZN5test21A1BINS_12_GLOBAL__N_11CEE3fooEv()
+}
diff --git a/test/CodeGenCXX/anonymous-union-member-initializer.cpp b/test/CodeGenCXX/anonymous-union-member-initializer.cpp
index a4da2c04fd7b..9ba38052e172 100644
--- a/test/CodeGenCXX/anonymous-union-member-initializer.cpp
+++ b/test/CodeGenCXX/anonymous-union-member-initializer.cpp
@@ -78,3 +78,15 @@ namespace test3 {
// CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
// CHECK-NEXT: store i8* null, void i8** [[CVALUE]]
}
+
+struct S {
+ // CHECK: store i32 42
+ // CHECK: store i32 55
+ S() : x(42), y(55) {}
+ union {
+ struct {
+ int x;
+ union { int y; };
+ };
+ };
+} s;
diff --git a/test/CodeGenCXX/arm.cpp b/test/CodeGenCXX/arm.cpp
index 1d4085ca231d..44c0affa5a8f 100644
--- a/test/CodeGenCXX/arm.cpp
+++ b/test/CodeGenCXX/arm.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=thumbv7-apple-darwin3.0.0-iphoneos -fno-use-cxa-atexit -target-abi apcs-gnu -emit-llvm -o - -fexceptions | FileCheck %s
+
+typedef typeof(sizeof(int)) size_t;
class foo {
public:
@@ -13,7 +15,275 @@ public:
// The global dtor needs the right calling conv with -fno-use-cxa-atexit
// rdar://7817590
+// Checked at end of file.
bar baz;
+// Destructors and constructors must return this.
+namespace test1 {
+ void foo();
+
+ struct A {
+ A(int i) { foo(); }
+ ~A() { foo(); }
+ void bar() { foo(); }
+ };
+
+ // CHECK: define void @_ZN5test14testEv()
+ void test() {
+ // CHECK: [[AV:%.*]] = alloca [[A:%.*]], align 1
+ // CHECK: call [[A]]* @_ZN5test11AC1Ei([[A]]* [[AV]], i32 10)
+ // CHECK: invoke void @_ZN5test11A3barEv([[A]]* [[AV]])
+ // CHECK: call [[A]]* @_ZN5test11AD1Ev([[A]]* [[AV]])
+ // CHECK: ret void
+ A a = 10;
+ a.bar();
+ }
+
+ // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]*
+ // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4
+ // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
+ // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
+ // CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
+ // CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]]
+ // CHECK: call [[A]]* @_ZN5test11AC2Ei(
+ // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]]
+ // CHECK: ret [[A]]* [[THIS2]]
+
+ // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]*
+ // CHECK: [[RET:%.*]] = alloca [[A]]*, align 4
+ // CHECK: [[THIS:%.*]] = alloca [[A]]*, align 4
+ // CHECK: store [[A]]* {{.*}}, [[A]]** [[THIS]]
+ // CHECK: [[THIS1:%.*]] = load [[A]]** [[THIS]]
+ // CHECK: store [[A]]* [[THIS1]], [[A]]** [[RET]]
+ // CHECK: call [[A]]* @_ZN5test11AD2Ev(
+ // CHECK: [[THIS2:%.*]] = load [[A]]** [[RET]]
+ // CHECK: ret [[A]]* [[THIS2]]
+}
+
+// Awkward virtual cases.
+namespace test2 {
+ void foo();
+
+ struct A {
+ int x;
+
+ A(int);
+ virtual ~A() { foo(); }
+ };
+
+ struct B {
+ int y;
+ int z;
+
+ B(int);
+ virtual ~B() { foo(); }
+ };
+
+ struct C : A, virtual B {
+ int q;
+
+ C(int i) : A(i), B(i) { foo(); }
+ ~C() { foo(); }
+ };
+
+ void test() {
+ C c = 10;
+ }
+
+ // Tests at eof
+}
+
+namespace test3 {
+ struct A {
+ int x;
+ ~A();
+ };
+
+ void a() {
+ // CHECK: define void @_ZN5test31aEv()
+ // CHECK: call noalias i8* @_Znam(i32 48)
+ // CHECK: store i32 4
+ // CHECK: store i32 10
+ A *x = new A[10];
+ }
+
+ void b(int n) {
+ // CHECK: define void @_ZN5test31bEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[N]]
+ A *x = new A[n];
+ }
+
+ void c() {
+ // CHECK: define void @_ZN5test31cEv()
+ // CHECK: call noalias i8* @_Znam(i32 808)
+ // CHECK: store i32 4
+ // CHECK: store i32 200
+ A (*x)[20] = new A[10][20];
+ }
+
+ void d(int n) {
+ // CHECK: define void @_ZN5test31dEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[NE]]
+ A (*x)[20] = new A[n][20];
+ }
+
+ void e(A *x) {
+ // CHECK: define void @_ZN5test31eEPNS_1AE(
+ // CHECK: icmp eq {{.*}}, null
+ // CHECK: getelementptr {{.*}}, i64 -8
+ // CHECK: getelementptr {{.*}}, i64 4
+ // CHECK: bitcast {{.*}} to i32*
+ // CHECK: load
+ // CHECK: invoke {{.*}} @_ZN5test31AD1Ev
+ // CHECK: call void @_ZdaPv
+ delete [] x;
+ }
+
+ void f(A (*x)[20]) {
+ // CHECK: define void @_ZN5test31fEPA20_NS_1AE(
+ // CHECK: icmp eq {{.*}}, null
+ // CHECK: getelementptr {{.*}}, i64 -8
+ // CHECK: getelementptr {{.*}}, i64 4
+ // CHECK: bitcast {{.*}} to i32*
+ // CHECK: load
+ // CHECK: invoke {{.*}} @_ZN5test31AD1Ev
+ // CHECK: call void @_ZdaPv
+ delete [] x;
+ }
+}
+
+namespace test4 {
+ struct A {
+ int x;
+ void operator delete[](void *, size_t sz);
+ };
+
+ void a() {
+ // CHECK: define void @_ZN5test41aEv()
+ // CHECK: call noalias i8* @_Znam(i32 48)
+ // CHECK: store i32 4
+ // CHECK: store i32 10
+ A *x = new A[10];
+ }
+
+ void b(int n) {
+ // CHECK: define void @_ZN5test41bEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 4)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[N]]
+ A *x = new A[n];
+ }
+
+ void c() {
+ // CHECK: define void @_ZN5test41cEv()
+ // CHECK: call noalias i8* @_Znam(i32 808)
+ // CHECK: store i32 4
+ // CHECK: store i32 200
+ A (*x)[20] = new A[10][20];
+ }
+
+ void d(int n) {
+ // CHECK: define void @_ZN5test41dEi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK: [[NE:%.*]] = mul i32 [[N]], 20
+ // CHECK: @llvm.umul.with.overflow.i32(i32 [[N]], i32 80)
+ // CHECK: @llvm.uadd.with.overflow.i32(i32 {{.*}}, i32 8)
+ // CHECK: [[SZ:%.*]] = select
+ // CHECK: call noalias i8* @_Znam(i32 [[SZ]])
+ // CHECK: store i32 4
+ // CHECK: store i32 [[NE]]
+ A (*x)[20] = new A[n][20];
+ }
+
+ void e(A *x) {
+ // CHECK: define void @_ZN5test41eEPNS_1AE(
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
+ // CHECK: getelementptr inbounds {{.*}}, i64 4
+ // CHECK: bitcast
+ // CHECK: [[T0:%.*]] = load i32*
+ // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
+ // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
+ // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]])
+ delete [] x;
+ }
+
+ void f(A (*x)[20]) {
+ // CHECK: define void @_ZN5test41fEPA20_NS_1AE(
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
+ // CHECK: getelementptr inbounds {{.*}}, i64 4
+ // CHECK: bitcast
+ // CHECK: [[T0:%.*]] = load i32*
+ // CHECK: [[T1:%.*]] = mul i32 4, [[T0]]
+ // CHECK: [[T2:%.*]] = add i32 [[T1]], 8
+ // CHECK: call void @_ZN5test41AdaEPvm(i8* [[ALLOC]], i32 [[T2]])
+ delete [] x;
+ }
+}
+
+// <rdar://problem/8386802>: don't crash
+namespace test5 {
+ struct A {
+ ~A();
+ };
+
+ // CHECK: define void @_ZN5test54testEPNS_1AE
+ void test(A *a) {
+ // CHECK: [[PTR:%.*]] = alloca [[A:%.*]]*, align 4
+ // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[PTR]], align 4
+ // CHECK-NEXT: [[TMP:%.*]] = load [[A]]** [[PTR]], align 4
+ // CHECK-NEXT: call [[A]]* @_ZN5test51AD1Ev([[A]]* [[TMP]])
+ // CHECK-NEXT: ret void
+ a->~A();
+ }
+}
+
+namespace test6 {
+ struct A {
+ virtual ~A();
+ };
+
+ // CHECK: define void @_ZN5test64testEPNS_1AE
+ void test(A *a) {
+ // CHECK: [[AVAR:%.*]] = alloca [[A:%.*]]*, align 4
+ // CHECK-NEXT: store [[A]]* {{.*}}, [[A]]** [[AVAR]], align 4
+ // CHECK-NEXT: [[V:%.*]] = load [[A]]** [[AVAR]], align 4
+ // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq [[A]]* [[V]], null
+ // CHECK-NEXT: br i1 [[ISNULL]]
+ // CHECK: [[T0:%.*]] = bitcast [[A]]* [[V]] to [[A]]* ([[A]]*)***
+ // CHECK-NEXT: [[T1:%.*]] = load [[A]]* ([[A]]*)*** [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]]* ([[A]]*)** [[T1]], i64 1
+ // CHECK-NEXT: [[T3:%.*]] = load [[A]]* ([[A]]*)** [[T2]]
+ // CHECK-NEXT: call [[A]]* [[T3]]([[A]]* [[V]])
+ // CHECK-NEXT: br label
+ // CHECK: ret void
+ delete a;
+ }
+}
+
+ // CHECK: define linkonce_odr [[C:%.*]]* @_ZTv0_n12_N5test21CD1Ev(
+ // CHECK: call [[C]]* @_ZN5test21CD1Ev(
+ // CHECK: ret [[C]]* undef
+
+ // CHECK: define linkonce_odr void @_ZTv0_n12_N5test21CD0Ev(
+ // CHECK: call void @_ZN5test21CD0Ev(
+ // CHECK: ret void
+
// CHECK: @_GLOBAL__D_a()
-// CHECK: call void @_ZN3barD1Ev(%class.bar* @baz)
+// CHECK: call %class.bar* @_ZN3barD1Ev(%class.bar* @baz)
diff --git a/test/CodeGenCXX/condition.cpp b/test/CodeGenCXX/condition.cpp
index 652e7c89c157..cc2eaf5bd6a5 100644
--- a/test/CodeGenCXX/condition.cpp
+++ b/test/CodeGenCXX/condition.cpp
@@ -105,12 +105,12 @@ void while_destruct(int z) {
// CHECK-NEXT: br i1 [[COND]]
// Loop-exit staging block.
- // CHECK: store i32 1, i32* [[CLEANUPDEST]]
+ // CHECK: store i32 3, i32* [[CLEANUPDEST]]
// CHECK-NEXT: br
// While body.
// CHECK: store i32 21, i32* [[Z]]
- // CHECK: store i32 2, i32* [[CLEANUPDEST]]
+ // CHECK: store i32 0, i32* [[CLEANUPDEST]]
// CHECK-NEXT: br
z = 21;
@@ -138,7 +138,7 @@ void while_destruct(int z) {
// CHECK: define void @_Z12for_destructi(
void for_destruct(int z) {
// CHECK: [[Z:%.*]] = alloca i32
- // CHECK: [[XDEST:%.*]] = alloca i32
+ // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
// CHECK: [[I:%.*]] = alloca i32
// CHECK: call void @_ZN1YC1Ev
// CHECK-NEXT: br
@@ -152,7 +152,7 @@ void for_destruct(int z) {
// -> %for.body, %for.cond.cleanup
// %for.cond.cleanup: Exit cleanup staging.
- // CHECK: store i32 1, i32* [[XDEST]]
+ // CHECK: store i32 2, i32* [[CLEANUPDEST]]
// CHECK-NEXT: br
// -> %cleanup
@@ -166,21 +166,21 @@ void for_destruct(int z) {
// CHECK: [[TMP:%.*]] = load i32* [[Z]]
// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1
// CHECK-NEXT: store i32 [[INC]], i32* [[Z]]
- // CHECK-NEXT: store i32 2, i32* [[XDEST]]
+ // CHECK-NEXT: store i32 0, i32* [[CLEANUPDEST]]
// CHECK-NEXT: br
// -> %cleanup
// %cleanup: Destroys X.
// CHECK: call void @_ZN1XD1Ev
- // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32* [[XDEST]]
+ // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32* [[CLEANUPDEST]]
// CHECK-NEXT: switch i32 [[YDESTTMP]]
- // 1 -> %cleanup4, 2 -> %cleanup.cont
+ // 0 -> %cleanup.cont, default -> %cleanup1
// %cleanup.cont: (eliminable)
// CHECK: br
// -> %for.cond
- // %cleanup4: Destroys Y.
+ // %cleanup1: Destroys Y.
// CHECK: call void @_ZN1YD1Ev(
// CHECK-NEXT: br
// -> %for.end
diff --git a/test/CodeGenCXX/copy-constructor-elim-2.cpp b/test/CodeGenCXX/copy-constructor-elim-2.cpp
index 3a06c10ff186..73e9b94bcd11 100644
--- a/test/CodeGenCXX/copy-constructor-elim-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-elim-2.cpp
@@ -5,3 +5,29 @@ A f() { return A(0); }
// CHECK: define void @_Z1fv
// CHECK: call void @_ZN1AC1Ei
// CHECK-NEXT: ret void
+
+// Verify that we do not elide copies when constructing a base class.
+namespace no_elide_base {
+ struct Base {
+ Base(const Base&);
+ ~Base();
+ };
+
+ struct Other {
+ operator Base() const;
+ };
+
+ struct Derived : public virtual Base {
+ Derived(const Other &O);
+ };
+
+ // CHECK: define void @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE
+ Derived::Derived(const Other &O)
+ // CHECK: call void @_ZNK13no_elide_base5OthercvNS_4BaseEEv
+ // CHECK: call void @_ZN13no_elide_base4BaseC2ERKS0_
+ // CHECK: call void @_ZN13no_elide_base4BaseD1Ev
+ : Base(O)
+ {
+ // CHECK: ret void
+ }
+}
diff --git a/test/CodeGenCXX/debug-info-byval.cpp b/test/CodeGenCXX/debug-info-byval.cpp
new file mode 100644
index 000000000000..c99518e7a6b8
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-byval.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang -g -S %s -o - | FileCheck %s
+// Test to check presense of debug info for byval parameter.
+// Radar 8350436.
+class DAG {
+public:
+ int i;
+ int j;
+};
+
+class EVT {
+public:
+ int a;
+ int b;
+ int c;
+};
+
+class VAL {
+public:
+ int x;
+ int y;
+};
+void foo(EVT e);
+EVT bar();
+
+void get(int *i, unsigned dl, VAL v, VAL *p, unsigned n, EVT missing_arg) {
+//CHECK: .ascii "missing_arg"
+ EVT e = bar();
+ if (dl == n)
+ foo(missing_arg);
+}
+
diff --git a/test/CodeGenCXX/debug-info-class.cpp b/test/CodeGenCXX/debug-info-class.cpp
new file mode 100644
index 000000000000..151c5f90534c
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-class.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang -emit-llvm -g -S %s -o - | grep HdrSize
+struct A {
+ int one;
+ static const int HdrSize = 52;
+ int two;
+ A() {
+ int x = 1;
+ }
+};
+int main() {
+ A a;
+}
diff --git a/test/CodeGenCXX/debug-info-ctor.cpp b/test/CodeGenCXX/debug-info-ctor.cpp
new file mode 100644
index 000000000000..c31eebe163ca
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-ctor.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang -emit-llvm -g -S %s -o - | FileCheck %s
+
+struct X {
+ X(int v);
+
+ int value;
+};
+
+X::X(int v) {
+ // CHECK_TEMPORARILY_DISABLED: call void @_ZN1XC2Ei(%struct.X* %this1, i32 %tmp), !dbg
+ // TEMPORARY CHECK: X
+ value = v;
+}
+
diff --git a/test/CodeGenCXX/debug-info-enum.cpp b/test/CodeGenCXX/debug-info-enum.cpp
new file mode 100644
index 000000000000..c08fc35af5b9
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-enum.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang -fverbose-asm -S -g %s -o - | grep DW_TAG_enumeration_type
+
+int v;
+enum index { MAX };
+void foo(void)
+{
+ v = MAX;
+}
diff --git a/test/CodeGenCXX/debug-info-friend.cpp b/test/CodeGenCXX/debug-info-friend.cpp
new file mode 100644
index 000000000000..c50f281a3b8f
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-friend.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang -fverbose-asm -S -g %s -o - | grep DW_TAG_friend
+
+class MyFriend;
+
+class SomeClass
+{
+ friend class MyFriend;
+};
+
+SomeClass sc;
+
diff --git a/test/CodeGenCXX/debug-info-template.cpp b/test/CodeGenCXX/debug-info-template.cpp
new file mode 100644
index 000000000000..233090c04992
--- /dev/null
+++ b/test/CodeGenCXX/debug-info-template.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-llvm-only -g -S %s -o - | grep "TC<int>"
+template<typename T>
+class TC {
+public:
+ TC(const TC &) {}
+ TC() {}
+};
+
+TC<int> tci;
diff --git a/test/CodeGenCXX/debug-info.cpp b/test/CodeGenCXX/debug-info.cpp
index 6bb9533a477e..71c8603a9faa 100644
--- a/test/CodeGenCXX/debug-info.cpp
+++ b/test/CodeGenCXX/debug-info.cpp
@@ -50,3 +50,8 @@ namespace VirtualBase {
B b;
}
}
+
+void foo() {
+ const wchar_t c = L'x';
+ wchar_t d = c;
+}
diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp
index 87f8698b84c3..1f52a783e628 100644
--- a/test/CodeGenCXX/delete.cpp
+++ b/test/CodeGenCXX/delete.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s
void t1(int *a) {
delete a;
@@ -57,3 +57,51 @@ namespace test0 {
// CHECK: define linkonce_odr void @_ZN5test01AD1Ev
// CHECK: define linkonce_odr void @_ZN5test01AdlEPv
}
+
+namespace test1 {
+ struct A {
+ int x;
+ ~A();
+ };
+
+ // CHECK: define void @_ZN5test14testEPA10_A20_NS_1AE(
+ void test(A (*arr)[10][20]) {
+ delete [] arr;
+ // CHECK: icmp eq [10 x [20 x [[S:%.*]]]]* [[PTR:%.*]], null
+ // CHECK-NEXT: br i1
+
+ // CHECK: [[ARR:%.*]] = getelementptr inbounds [10 x [20 x [[S]]]]* [[PTR]], i32 0, i32 0, i32 0
+ // CHECK-NEXT: bitcast {{.*}} to i8*
+ // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds {{.*}}, i64 -8
+ // CHECK-NEXT: bitcast i8* [[ALLOC]] to i64*
+ // CHECK-NEXT: load
+ // CHECK-NEXT: store i64 {{.*}}, i64* [[IDX:%.*]]
+
+ // CHECK: load i64* [[IDX]]
+ // CHECK-NEXT: icmp ne {{.*}}, 0
+ // CHECK-NEXT: br i1
+
+ // CHECK: load i64* [[IDX]]
+ // CHECK-NEXT: [[I:%.*]] = sub i64 {{.*}}, 1
+ // CHECK-NEXT: getelementptr inbounds [[S]]* [[ARR]], i64 [[I]]
+ // CHECK-NEXT: call void @_ZN5test11AD1Ev(
+ // CHECK-NEXT: br label
+
+ // CHECK: load i64* [[IDX]]
+ // CHECK-NEXT: sub
+ // CHECK-NEXT: store {{.*}}, i64* [[IDX]]
+ // CHECK-NEXT: br label
+
+ // CHECK: call void @_ZdaPv(i8* [[ALLOC]])
+ }
+}
+
+namespace test2 {
+ // CHECK: define void @_ZN5test21fEPb
+ void f(bool *b) {
+ // CHECK: call void @_ZdlPv(i8*
+ delete b;
+ // CHECK: call void @_ZdaPv(i8*
+ delete [] b;
+ }
+}
diff --git a/test/CodeGenCXX/dependent-type-member-pointer.cpp b/test/CodeGenCXX/dependent-type-member-pointer.cpp
new file mode 100644
index 000000000000..41bb5e29d58c
--- /dev/null
+++ b/test/CodeGenCXX/dependent-type-member-pointer.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -emit-llvm-only -verify %s
+// PR7736
+
+template <class scriptmemberptr> int InitMember(scriptmemberptr);
+
+template <class>
+struct contentmap
+{
+ static void InitDataMap()
+ { InitMember(&contentmap::SizeHolder); }
+ int SizeHolder;
+};
+
+void ReadFrom( )
+{
+ contentmap<int>::InitDataMap();
+}
+
diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp
index 8efaf01f3c60..2eba30f778c2 100644
--- a/test/CodeGenCXX/destructors.cpp
+++ b/test/CodeGenCXX/destructors.cpp
@@ -260,12 +260,53 @@ namespace test5 {
}
}
-// Checks from test3:
+namespace test6 {
+ void opaque();
- // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(
- // CHECK: call void @_ZN5test31BD2Ev(
- // CHECK: call void @_ZN5test31AD2Ev(
- // CHECK: ret void
+ struct A { ~A(); };
+ template <unsigned> struct B { B(); ~B(); int _; };
+ struct C : B<0>, B<1>, virtual B<2>, virtual B<3> {
+ A x, y, z;
+
+ C();
+ ~C();
+ };
+
+ C::C() { opaque(); }
+ // CHECK: define void @_ZN5test61CC1Ev
+ // CHECK: call void @_ZN5test61BILj2EEC2Ev
+ // CHECK: invoke void @_ZN5test61BILj3EEC2Ev
+ // CHECK: invoke void @_ZN5test61BILj0EEC2Ev
+ // CHECK: invoke void @_ZN5test61BILj1EEC2Ev
+ // CHECK: invoke void @_ZN5test66opaqueEv
+ // CHECK: ret void
+ // FIXME: way too much EH cleanup code follows
+
+ C::~C() { opaque(); }
+ // CHECK: define void @_ZN5test61CD1Ev
+ // CHECK: invoke void @_ZN5test61CD2Ev
+ // CHECK: invoke void @_ZN5test61BILj3EED2Ev
+ // CHECK: call void @_ZN5test61BILj2EED2Ev
+ // CHECK: ret void
+ // CHECK: invoke void @_ZN5test61BILj3EED2Ev
+ // CHECK: invoke void @_ZN5test61BILj2EED2Ev
+
+ // CHECK: define void @_ZN5test61CD2Ev
+ // CHECK: invoke void @_ZN5test66opaqueEv
+ // CHECK: invoke void @_ZN5test61AD1Ev
+ // CHECK: invoke void @_ZN5test61AD1Ev
+ // CHECK: invoke void @_ZN5test61AD1Ev
+ // CHECK: invoke void @_ZN5test61BILj1EED2Ev
+ // CHECK: call void @_ZN5test61BILj0EED2Ev
+ // CHECK: ret void
+ // CHECK: invoke void @_ZN5test61AD1Ev
+ // CHECK: invoke void @_ZN5test61AD1Ev
+ // CHECK: invoke void @_ZN5test61AD1Ev
+ // CHECK: invoke void @_ZN5test61BILj1EED2Ev
+ // CHECK: invoke void @_ZN5test61BILj0EED2Ev
+}
+
+// Checks from test3:
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(
// CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev(
@@ -289,6 +330,11 @@ namespace test5 {
// CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
// CHECK: ret void
+ // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(
+ // CHECK: invoke void @_ZN5test31BD2Ev(
+ // CHECK: call void @_ZN5test31AD2Ev(
+ // CHECK: ret void
+
// CHECK: declare void @_ZN5test31BD2Ev(
// CHECK: declare void @_ZN5test31AD2Ev(
diff --git a/test/CodeGenCXX/dyncast.cpp b/test/CodeGenCXX/dyncast.cpp
index 906d44b3c5ec..723e12b15fdc 100644
--- a/test/CodeGenCXX/dyncast.cpp
+++ b/test/CodeGenCXX/dyncast.cpp
@@ -86,15 +86,12 @@ void test1() {
// CHECK-LL-NEXT: [[tmp:%.*]] = load %class.test1_A** [[bp]]
// CHECK-LL-NEXT: [[v4:%.*]] = icmp ne %class.test1_A* [[tmp]], null
// CHECK-LL-NEXT: br i1 [[v4]], label %[[v5:.*]], label %[[v9:.*]]
-// CHECK-LL: ; <label>:[[v5]]
-// CHECK-LL-NEXT: [[v6:%.*]] = bitcast %class.test1_A* [[tmp]] to i8*
-// CHECK-LL-NEXT: [[v7:%.*]] = call i8* @__dynamic_cast(i8* [[v6]], i8* bitcast (%0* @_ZTI7test1_B to i8*), i8* bitcast (%1* @_ZTI7test1_D to i8*), i64 -1) ; <i8*> [#uses=1]
+// CHECK-LL: [[v6:%.*]] = bitcast %class.test1_A* [[tmp]] to i8*
+// CHECK-LL-NEXT: [[v7:%.*]] = call i8* @__dynamic_cast(i8* [[v6]], i8* bitcast (%0* @_ZTI7test1_B to i8*), i8* bitcast (%1* @_ZTI7test1_D to i8*), i64 -1)
// CHECK-LL-NEXT: [[v8:%.*]] = bitcast i8* [[v7]] to %class.test1_D*
// CHECK-LL-NEXT: br label %[[v10:.*]]
-// CHECK-LL: ; <label>:[[v9]]
-// CHECK-LL-NEXT: br label %[[v10]]
-// CHECK-LL: ; <label>:[[v10]]
-// CHECK-LL-NEXT: [[v11:%.*]] = phi %class.test1_D* [ [[v8]], %[[v5]] ], [ null, %[[v9]] ]
+// CHECK-LL: br label %[[v10]]
+// CHECK-LL: [[v11:%.*]] = phi %class.test1_D* [ [[v8]], %[[v5]] ], [ null, %[[v9]] ]
// CHECK-LL-NEXT: store %class.test1_D* [[v11]], %class.test1_D** [[dp]]
// CHECK-LL-NEXT: [[tmp4:%.*]] = load %class.test1_D** [[dp]]
// CHECK-LL-NEXT: [[cmp:%.*]] = icmp eq %class.test1_D* [[tmp4]], null
@@ -109,15 +106,12 @@ void test1() {
// CHECK-LL-NEXT: [[tmp6:%.*]] = load %class.test1_A** [[bp]]
// CHECK-LL-NEXT: [[v12:%.*]] = icmp ne %class.test1_A* [[tmp6]], null
// CHECK-LL-NEXT: br i1 [[v12]], label %[[v13:.*]], label %[[v17:.*]]
-// CHECK-LL: ; <label>:[[v13]]
-// CHECK-LL-NEXT: [[v14:%.*]] = bitcast %class.test1_A* [[tmp6]] to i8*
+// CHECK-LL: [[v14:%.*]] = bitcast %class.test1_A* [[tmp6]] to i8*
// CHECK-LL-NEXT: [[v15:%.*]] = call i8* @__dynamic_cast(i8* [[v14]], i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i64 -1)
// CHECK-LL-NEXT: [[v16:%.*]] = bitcast i8* [[v15]] to %class.test1_A*
// CHECK-LL-NEXT: br label %[[v18:.*]]
-// CHECK-LL: ; <label>:[[v17]]
-// CHECK-LL-NEXT: br label %[[v18]]
-// CHECK-LL: ; <label>:[[v18]]
-// CHECK-LL-NEXT: [[v19:%.*]] = phi %class.test1_A* [ [[v16]], %[[v13]] ], [ null, %[[v17]] ]
+// CHECK-LL: br label %[[v18]]
+// CHECK-LL: [[v19:%.*]] = phi %class.test1_A* [ [[v16]], %[[v13]] ], [ null, %[[v17]] ]
// CHECK-LL-NEXT: store %class.test1_A* [[v19]], %class.test1_A** [[ap]]
// CHECK-LL-NEXT: [[tmp7:%.*]] = load %class.test1_A** [[ap]]
// CHECK-LL-NEXT: [[cmp8:%.*]] = icmp eq %class.test1_A* [[tmp7]], null
@@ -132,15 +126,12 @@ void test1() {
// CHECK-LL-NEXT: [[tmp14:%.*]] = load %class.test1_A** [[ap]]
// CHECK-LL-NEXT: [[v20:%.*]] = icmp ne %class.test1_A* [[tmp14]], null
// CHECK-LL-NEXT: br i1 [[v20]], label %[[v21:.*]], label %[[v25:.*]]
-// CHECK-LL: ; <label>:[[v21]]
-// CHECK-LL-NEXT: [[v22:%.*]] = bitcast %class.test1_A* [[tmp14]] to i8*
+// CHECK-LL: [[v22:%.*]] = bitcast %class.test1_A* [[tmp14]] to i8*
// CHECK-LL-NEXT: [[v23:%.*]] = call i8* @__dynamic_cast({{.*}} [[v22]], i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_B to i8*), i64 -1)
// CHECK-LL-NEXT: [[v24:%.*]] = bitcast i8* [[v23]] to %class.test1_A*
// CHECK-LL-NEXT: br label %[[v26:.*]]
-// CHECK-LL: ; <label>:[[v25]]
-// CHECK-LL-NEXT: br label %[[v26]]
-// CHECK-LL: ; <label>:[[v26]]
-// CHECK-LL-NEXT: [[v27:%.*]] = phi %class.test1_A* [ [[v24]], %[[v21]] ], [ null, %[[v25]] ]
+// CHECK-LL: br label %[[v26]]
+// CHECK-LL: [[v27:%.*]] = phi %class.test1_A* [ [[v24]], %[[v21]] ], [ null, %[[v25]] ]
// CHECK-LL-NEXT: store %class.test1_A* [[v27]], %class.test1_A** [[bp]]
// CHECK-LL-NEXT: [[tmp15:%.*]] = load %class.test1_A** [[bp]]
// CHECK-LL-NEXT: [[cmp16:%.*]] = icmp eq %class.test1_A* [[tmp15]], null
@@ -203,15 +194,12 @@ void test1() {
// CHECK-LL-NEXT: [[tmp54:%.*]] = load %class.test1_A** [[ap37]]
// CHECK-LL-NEXT: [[v34:%.*]] = icmp ne %class.test1_A* [[tmp54]], null
// CHECK-LL-NEXT: br i1 [[v34]], label %[[v35:.*]], label %[[v39:.*]]
-// CHECK-LL: ; <label>:[[v35]]
-// CHECK-LL-NEXT: [[v36:%.*]] = bitcast %class.test1_A* [[tmp54]] to i8*
+// CHECK-LL: [[v36:%.*]] = bitcast %class.test1_A* [[tmp54]] to i8*
// CHECK-LL-NEXT: [[v37:%.*]] = call i8* @__dynamic_cast(i8* [[v36]], i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1)
// CHECK-LL-NEXT: [[v38:%.*]] = bitcast i8* [[v37]] to %class.test1_D*
// CHECK-LL-NEXT: br label %[[v40:.*]]
-// CHECK-LL: ; <label>:[[v39]]
-// CHECK-LL-NEXT: br label %[[v40]]
-// CHECK-LL: ; <label>:[[v40]]
-// CHECK-LL-NEXT: [[v41:%.*]] = phi %class.test1_D* [ [[v38]], %[[v35]] ], [ null, %[[v39]] ]
+// CHECK-LL: br label %[[v40]]
+// CHECK-LL: [[v41:%.*]] = phi %class.test1_D* [ [[v38]], %[[v35]] ], [ null, %[[v39]] ]
// CHECK-LL-NEXT: store %class.test1_D* [[v41]], %class.test1_D** [[dp53]]
// CHECK-LL-NEXT: [[tmp55:%.*]] = load %class.test1_D** [[dp53]]
// CHECK-LL-NEXT: [[cmp56:%.*]] = icmp eq %class.test1_D* [[tmp55]], null
@@ -226,15 +214,12 @@ void test1() {
// CHECK-LL-NEXT: [[tmp63:%.*]] = load %class.test1_A** [[ap37]]
// CHECK-LL-NEXT: [[v42:%.*]] = icmp ne %class.test1_A* [[tmp63]], null
// CHECK-LL-NEXT: br i1 [[v42]], label %[[v43:.*]], label %[[v47:.*]]
-// CHECK-LL: ; <label>:[[v43]]
-// CHECK-LL-NEXT: [[v44:%.*]] = bitcast %class.test1_A* [[tmp63]] to i8*
+// CHECK-LL: [[v44:%.*]] = bitcast %class.test1_A* [[tmp63]] to i8*
// CHECK-LL-NEXT: [[v45:%.*]] = call i8* @__dynamic_cast(i8* [[v44]], i8* bitcast ({{.*}} @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_E to i8*), i64 -1)
// CHECK-LL-NEXT: [[v46:%.*]] = bitcast i8* [[v45]] to %class.test1_E*
// CHECK-LL-NEXT: br label %[[v48:.*]]
-// CHECK-LL: ; <label>:[[v47]]
-// CHECK-LL-NEXT: br label %[[v48]]
-// CHECK-LL: ; <label>:[[v48]]
-// CHECK-LL-NEXT: [[v49:%.*]] = phi %class.test1_E* [ [[v46]], %[[v43]] ], [ null, %[[v47]] ]
+// CHECK-LL: br label %[[v48]]
+// CHECK-LL: [[v49:%.*]] = phi %class.test1_E* [ [[v46]], %[[v43]] ], [ null, %[[v47]] ]
// CHECK-LL-NEXT: store %class.test1_E* [[v49]], %class.test1_E** [[ep1]]
// CHECK-LL-NEXT: [[tmp64:%.*]] = load %class.test1_E** [[ep1]]
// CHECK-LL-NEXT: [[cmp65:%.*]] = icmp ne %class.test1_E* [[tmp64]], null
@@ -269,14 +254,11 @@ void test1() {
// CHECK-LL-NEXT: br label %[[ifend85]]
// CHECK-LL: [[ifend85]]
// CHECK-LL-NEXT: br i1 false, label %[[v50:.*]], label %[[v53:.*]]
-// CHECK-LL: ; <label>:[[v50]]
-// CHECK-LL-NEXT: [[v51:%.*]] = call i8* @__dynamic_cast(i8* null, i8* bitcast ({{.*}}* @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1)
+// CHECK-LL: [[v51:%.*]] = call i8* @__dynamic_cast(i8* null, i8* bitcast ({{.*}}* @_ZTI7test1_A to i8*), i8* bitcast ({{.*}} @_ZTI7test1_D to i8*), i64 -1)
// CHECK-LL-NEXT: [[v52:%.*]] = bitcast i8* [[v51]] to %class.test1_D*
// CHECK-LL-NEXT: br label %[[v54:.*]]
-// CHECK-LL: ; <label>:[[v53]]
-// CHECK-LL-NEXT: br label %[[v54]]
-// CHECK-LL: ; <label>:[[v54]]
-// CHECK-LL-NEXT: [[v55:%.*]] = phi %class.test1_D* [ [[v52]], %[[v50]] ], [ null, %[[v53]] ]
+// CHECK-LL: br label %[[v54]]
+// CHECK-LL: [[v55:%.*]] = phi %class.test1_D* [ [[v52]], %[[v50]] ], [ null, %[[v53]] ]
// CHECK-LL-NEXT: store %class.test1_D* [[v55]], %class.test1_D** [[dp]]
// CHECK-LL-NEXT: [[tmp86:%.*]] = load %class.test1_D** [[dp]]
// CHECK-LL-NEXT: [[cmp87:%.*]] = icmp eq %class.test1_D* [[tmp86]], null
@@ -327,7 +309,7 @@ void test1() {
// CHECK-LL: [[ifend113]]
// CHECK-LL-NEXT: store %class.test1_E* bitcast (%class.test1_F* @test1_f to %class.test1_E*), %class.test1_E** [[ep]]
// CHECK-LL-NEXT: [[tmp118:%.*]] = load %class.test1_E** [[ep]]
-// CHECK-LL-NEXT: [[cmp122:%.*]] = icmp eq %class.test1_E* [[tmp118]], bitcast (%class.test1_F* @test1_f to %class.test1_E*) ; <i1> [#uses=1]
+// CHECK-LL-NEXT: [[cmp122:%.*]] = icmp eq %class.test1_E* [[tmp118]], bitcast (%class.test1_F* @test1_f to %class.test1_E*)
// CHECK-LL-NEXT: br i1 [[cmp122]], label %[[ifthen123:.*]], label %[[ifelse125:.*]]
// CHECK-LL: [[ifthen123]]
@@ -340,18 +322,15 @@ void test1() {
// CHECK-LL-NEXT: [[tmp129:%.*]] = load %class.test1_A** [[ap]]
// CHECK-LL-NEXT: [[v64:%.*]] = icmp ne %class.test1_A* [[tmp129]], null
// CHECK-LL-NEXT: br i1 [[v64]], label %[[v65:.*]], label %[[v70:.*]]
-// CHECK-LL: ; <label>:[[v65]]
-// CHECK-LL-NEXT: [[v66:%.*]] = bitcast %class.test1_A* [[tmp129]] to i64**
+// CHECK-LL: [[v66:%.*]] = bitcast %class.test1_A* [[tmp129]] to i64**
// CHECK-LL-NEXT: [[vtable130:%.*]] = load i64** [[v66]]
// CHECK-LL-NEXT: [[v67:%.*]] = getelementptr inbounds i64* [[vtable130]], i64 -2
// CHECK-LL-NEXT: [[offsettotop:%.*]] = load i64* [[v67]]
// CHECK-LL-NEXT: [[v68:%.*]] = bitcast %class.test1_A* [[tmp129]] to i8*
// CHECK-LL-NEXT: [[v69:%.*]] = getelementptr inbounds i8* [[v68]], i64 [[offsettotop]]
// CHECK-LL-NEXT: br label %[[v71:.*]]
-// CHECK-LL: ; <label>:[[v70]]
-// CHECK-LL-NEXT: br label %[[v71]]
-// CHECK-LL: ; <label>:[[v71]]
-// CHECK-LL-NEXT: [[v72:%.*]] = phi i8* [ [[v69]], %[[v65]] ], [ null, %[[v70]] ]
+// CHECK-LL: br label %[[v71]]
+// CHECK-LL: [[v72:%.*]] = phi i8* [ [[v69]], %[[v65]] ], [ null, %[[v70]] ]
// CHECK-LL-NEXT: store i8* [[v72]], 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)
@@ -366,18 +345,15 @@ void test1() {
// CHECK-LL-NEXT: [[tmp139:%.*]] = load %class.test1_A** [[ap]]
// CHECK-LL-NEXT: [[v73:%.*]] = icmp ne %class.test1_A* [[tmp139]], null
// CHECK-LL-NEXT: br i1 [[v73]], label %[[v74:.*]], label %[[v79:.*]]
-// CHECK-LL: ; <label>:[[v74]]
-// CHECK-LL-NEXT: [[v75:%.*]] = bitcast %class.test1_A* [[tmp139]] to i64**
+// CHECK-LL: [[v75:%.*]] = bitcast %class.test1_A* [[tmp139]] to i64**
// CHECK-LL-NEXT: [[vtable140:%.*]] = load i64** [[v75]]
// CHECK-LL-NEXT: [[v76:%.*]] = getelementptr inbounds i64* [[vtable140]], i64 -2
// CHECK-LL-NEXT: [[offsettotop141:%.*]] = load i64* [[v76]]
// CHECK-LL-NEXT: [[v77:%.*]] = bitcast %class.test1_A* [[tmp139]] to i8*
// CHECK-LL-NEXT: [[v78:%.*]] = getelementptr inbounds i8* [[v77]], i64 [[offsettotop141]]
// CHECK-LL-NEXT: br label %[[v80:.*]]
-// CHECK-LL: ; <label>:[[v79]]
-// CHECK-LL-NEXT: br label %[[v80]]
-// CHECK-LL: ; <label>:[[v80]]
-// CHECK-LL-NEXT: [[v81:%.*]] = phi i8* [ [[v78]], %[[v74]] ], [ null, %[[v79]] ]
+// CHECK-LL: br label %[[v80]]
+// CHECK-LL: [[v81:%.*]] = phi i8* [ [[v78]], %[[v74]] ], [ null, %[[v79]] ]
// CHECK-LL-NEXT: store i8* [[v81]], 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)
diff --git a/test/CodeGenCXX/eh.cpp b/test/CodeGenCXX/eh.cpp
index 6d79c3e17b51..0960ec381b89 100644
--- a/test/CodeGenCXX/eh.cpp
+++ b/test/CodeGenCXX/eh.cpp
@@ -39,6 +39,7 @@ void test2() {
// CHECK: [[FREEVAR:%.*]] = alloca i1
// CHECK-NEXT: [[EXNOBJVAR:%.*]] = alloca i8*
// CHECK-NEXT: [[EXNSLOTVAR:%.*]] = alloca i8*
+// CHECK-NEXT: [[CLEANUPDESTVAR:%.*]] = alloca i32
// CHECK-NEXT: store i1 false, i1* [[FREEVAR]]
// CHECK-NEXT: [[EXNOBJ:%.*]] = call i8* @__cxa_allocate_exception(i64 16)
// CHECK-NEXT: store i8* [[EXNOBJ]], i8** [[EXNOBJVAR]]
@@ -124,6 +125,7 @@ namespace test7 {
// CHECK-NEXT: [[EXNALLOCVAR:%.*]] = alloca i8*
// CHECK-NEXT: [[CAUGHTEXNVAR:%.*]] = alloca i8*
// CHECK-NEXT: [[INTCATCHVAR:%.*]] = alloca i32
+// CHECK-NEXT: [[EHCLEANUPDESTVAR:%.*]] = alloca i32
// CHECK-NEXT: store i1 false, i1* [[FREEEXNOBJ]]
try {
try {
@@ -153,6 +155,7 @@ namespace test7 {
// CHECK: [[CAUGHTEXN:%.*]] = call i8* @llvm.eh.exception()
// CHECK-NEXT: store i8* [[CAUGHTEXN]], i8** [[CAUGHTEXNVAR]]
// CHECK-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector(i8* [[CAUGHTEXN]], i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*), i8* null)
+// CHECK-NEXT: store i32 1, i32* [[EHCLEANUPDESTVAR]]
// CHECK-NEXT: call void @__cxa_end_catch()
// CHECK-NEXT: br label
// CHECK: load i8** [[CAUGHTEXNVAR]]
@@ -249,3 +252,165 @@ namespace test10 {
// CHECK: call void @_ZN6test101AD1Ev(
}
}
+
+// __cxa_begin_catch returns pointers by value, even when catching by reference
+// <rdar://problem/8212123>
+namespace test11 {
+ void opaque();
+
+ // CHECK: define void @_ZN6test113fooEv()
+ void foo() {
+ try {
+ // CHECK: invoke void @_ZN6test116opaqueEv()
+ opaque();
+ } catch (int**&p) {
+ // CHECK: [[EXN:%.*]] = load i8**
+ // CHECK-NEXT: call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
+ // CHECK-NEXT: [[ADJ1:%.*]] = getelementptr i8* [[EXN]], i32 32
+ // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to i32***
+ // CHECK-NEXT: store i32*** [[ADJ2]], i32**** [[P:%.*]]
+ // CHECK-NEXT: call void @__cxa_end_catch() nounwind
+ }
+ }
+
+ struct A {};
+
+ // CHECK: define void @_ZN6test113barEv()
+ void bar() {
+ try {
+ // CHECK: [[EXNSLOT:%.*]] = alloca i8*
+ // CHECK-NEXT: [[P:%.*]] = alloca [[A:%.*]]**,
+ // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]]*
+ // CHECK-NEXT: invoke void @_ZN6test116opaqueEv()
+ opaque();
+ } catch (A*&p) {
+ // CHECK: [[EXN:%.*]] = load i8** [[EXNSLOT]]
+ // CHECK-NEXT: [[ADJ1:%.*]] = call i8* @__cxa_begin_catch(i8* [[EXN]]) nounwind
+ // CHECK-NEXT: [[ADJ2:%.*]] = bitcast i8* [[ADJ1]] to [[A]]*
+ // CHECK-NEXT: store [[A]]* [[ADJ2]], [[A]]** [[TMP]]
+ // CHECK-NEXT: store [[A]]** [[TMP]], [[A]]*** [[P]]
+ // CHECK-NEXT: call void @__cxa_end_catch() nounwind
+ }
+ }
+}
+
+// PR7686
+namespace test12 {
+ struct A { ~A(); };
+ bool opaque(const A&);
+
+ // CHECK: define void @_ZN6test124testEv()
+ void test() {
+ // CHECK: [[X:%.*]] = alloca [[A:%.*]],
+ // CHECK: [[EHCLEANUPDEST:%.*]] = alloca i32
+ // CHECK: [[Y:%.*]] = alloca [[A]]
+ // CHECK: [[Z:%.*]] = alloca [[A]]
+ // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
+
+ A x;
+ // CHECK: invoke zeroext i1 @_ZN6test126opaqueERKNS_1AE(
+ if (opaque(x)) {
+ A y;
+ A z;
+
+ // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Z]])
+ // CHECK: invoke void @_ZN6test121AD1Ev([[A]]* [[Y]])
+
+ // It'd be great if something eliminated this switch.
+ // CHECK: load i32* [[CLEANUPDEST]]
+ // CHECK-NEXT: switch i32
+ goto success;
+ }
+
+ success:
+ bool _ = true;
+
+ // CHECK: call void @_ZN6test121AD1Ev([[A]]* [[X]])
+ // CHECK-NEXT: ret void
+ }
+}
+
+// Reduced from some TableGen code that was causing a self-host crash.
+namespace test13 {
+ struct A { ~A(); };
+
+ void test0(int x) {
+ try {
+ switch (x) {
+ case 0:
+ break;
+ case 1:{
+ A a;
+ break;
+ }
+ default:
+ return;
+ }
+ return;
+ } catch (int x) {
+ }
+ return;
+ }
+
+ void test1(int x) {
+ A y;
+ try {
+ switch (x) {
+ default: break;
+ }
+ } catch (int x) {}
+ }
+}
+
+// rdar://problem/8231514
+namespace test14 {
+ struct A { ~A(); };
+ struct B { ~B(); };
+
+ B b();
+ void opaque();
+
+ void foo() {
+ A a;
+ try {
+ B str = b();
+ opaque();
+ } catch (int x) {
+ }
+ }
+}
+
+// rdar://problem/8231514
+// JumpDests shouldn't get confused by scopes that aren't normal cleanups.
+namespace test15 {
+ struct A { ~A(); };
+
+ bool opaque(int);
+
+ // CHECK: define void @_ZN6test153fooEv()
+ void foo() {
+ A a;
+
+ try {
+ // CHECK: [[X:%.*]] = alloca i32
+ // CHECK: store i32 10, i32* [[X]]
+ // CHECK-NEXT: br label
+ // -> while.cond
+ int x = 10;
+
+ while (true) {
+ // CHECK: load i32* [[X]]
+ // CHECK-NEXT: [[COND:%.*]] = invoke zeroext i1 @_ZN6test156opaqueEi
+ // CHECK: br i1 [[COND]]
+ if (opaque(x))
+ // CHECK: br label
+ break;
+
+ // CHECK: br label
+ }
+ // CHECK: br label
+ } catch (int x) { }
+
+ // CHECK: call void @_ZN6test151AD1Ev
+ }
+}
diff --git a/test/CodeGenCXX/exceptions-no-rtti.cpp b/test/CodeGenCXX/exceptions-no-rtti.cpp
index c26abb26af9c..66b4c4ac33b1 100644
--- a/test/CodeGenCXX/exceptions-no-rtti.cpp
+++ b/test/CodeGenCXX/exceptions-no-rtti.cpp
@@ -18,9 +18,12 @@ namespace test0 {
}
namespace test1 {
- // These classes have key functions defined out-of-line.
- // Under normal circumstances, we wouldn't generate RTTI for them;
- // under -fno-rtti, we generate RTTI only when required by EH.
+ // These classes have key functions defined out-of-line. Under
+ // normal circumstances, we wouldn't generate RTTI for them; under
+ // -fno-rtti, we generate RTTI only when required by EH. But
+ // everything gets hidden visibility because we assume that all
+ // users are also compiled under -fno-rtti and therefore will be
+ // emitting RTTI regardless of key function.
class A { virtual void foo(); };
class B { virtual void foo(); };
class C { virtual void foo(); };
diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp
index 24d1a6739229..b82958568a8a 100644
--- a/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/test/CodeGenCXX/explicit-instantiation.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s
+// This check logically is attached to 'template int S<int>::i;' below.
+// CHECK: @_ZN1SIiE1iE = weak global i32
+
template<typename T, typename U, typename Result>
struct plus {
Result operator()(const T& t, const U& u) const;
@@ -12,3 +15,31 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
// CHECK: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
template struct plus<int, long, long>;
+
+// Check that we emit definitions from explicit instantiations even when they
+// occur prior to the definition itself.
+template <typename T> struct S {
+ void f();
+ static void g();
+ static int i;
+ struct S2 {
+ void h();
+ };
+};
+
+// CHECK: define weak_odr void @_ZN1SIiE1fEv
+template void S<int>::f();
+
+// CHECK: define weak_odr void @_ZN1SIiE1gEv
+template void S<int>::g();
+
+// See the check line at the top of the file.
+template int S<int>::i;
+
+// CHECK: define weak_odr void @_ZN1SIiE2S21hEv
+template void S<int>::S2::h();
+
+template <typename T> void S<T>::f() {}
+template <typename T> void S<T>::g() {}
+template <typename T> int S<T>::i;
+template <typename T> void S<T>::S2::h() {}
diff --git a/test/CodeGenCXX/expr.cpp b/test/CodeGenCXX/expr.cpp
index d92cfb46a454..33e8e63de2f4 100644
--- a/test/CodeGenCXX/expr.cpp
+++ b/test/CodeGenCXX/expr.cpp
@@ -14,3 +14,24 @@ void test1() {
// PR5514
int a;
void test2() { ++a+=10; }
+
+// PR7892
+int test3(const char*);
+int test3g = test3(__PRETTY_FUNCTION__);
+
+
+// PR7889
+struct test4A {
+ int j : 2;
+};
+int test4() {
+ test4A a;
+ (a.j = 2) = 3;
+}
+
+// Incomplete type in conditional operator.
+// Check operations on incomplete types.
+struct s5;
+struct s5 &f5_0(bool cond, struct s5 &a, struct s5 &b) {
+ return cond ? a : b;
+}
diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp
index 8ee087e29d11..6ff9598afce1 100644
--- a/test/CodeGenCXX/global-init.cpp
+++ b/test/CodeGenCXX/global-init.cpp
@@ -14,6 +14,9 @@ struct D { ~D(); };
// CHECK: @c = global %struct.C zeroinitializer, align 8
+// It's okay if we ever implement the IR-generation optimization to remove this.
+// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8]*
+
// CHECK: call void @_ZN1AC1Ev(%struct.A* @a)
// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1AD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @a, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
A a;
@@ -29,7 +32,52 @@ C c;
// CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.A*)* @_ZN1DD1Ev to void (i8*)*), i8* getelementptr inbounds (%struct.A* @d, i32 0, i32 0), i8* bitcast (i8** @__dso_handle to i8*))
D d;
+// <rdar://problem/7458115>
+namespace test1 {
+ int f();
+ const int x = f(); // This has side-effects and gets emitted immediately.
+ const int y = x - 1; // This gets deferred.
+ const int z = ~y; // This also gets deferred, but gets "undeferred" before y.
+ int test() { return z; }
+// CHECK: define i32 @_ZN5test14testEv()
+
+ // All of these initializers end up delayed, so we check them later.
+}
+
+// <rdar://problem/8246444>
+namespace test2 {
+ struct allocator { allocator(); ~allocator(); };
+ struct A { A(const allocator &a = allocator()); ~A(); };
+
+ A a;
+// CHECK: call void @_ZN5test29allocatorC1Ev(
+// CHECK: invoke void @_ZN5test21AC1ERKNS_9allocatorE(
+// CHECK: call void @_ZN5test29allocatorD1Ev(
+// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN5test21AD1Ev {{.*}} @_ZN5test21aE
+}
+
+namespace test3 {
+ // Tested at the beginning of the file.
+ const char * const var = "string";
+ extern const char * const var;
+
+ const char *test() { return var; }
+}
+
+// CHECK: define internal void [[TEST1_Z_INIT:@.*]]()
+// CHECK: load i32* @_ZN5test1L1yE
+// CHECK-NEXT: xor
+// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1zE
+// CHECK: define internal void [[TEST1_Y_INIT:@.*]]()
+// CHECK: load i32* @_ZN5test1L1xE
+// CHECK-NEXT: sub
+// CHECK-NEXT: store i32 {{.*}}, i32* @_ZN5test1L1yE
+
+// At the end of the file, we check that y is initialized before z.
+
// CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
+// CHECK: call void [[TEST1_Y_INIT]]
+// CHECK: call void [[TEST1_Z_INIT]]
// rdar://problem/8090834: this should be nounwind
// CHECK-NOEXC: define internal void @_GLOBAL__I_a() nounwind section "__TEXT,__StaticInit,regular,pure_instructions" {
diff --git a/test/CodeGenCXX/key-function-vtable.cpp b/test/CodeGenCXX/key-function-vtable.cpp
index 1cfeb0c5022d..15c058da9460 100644
--- a/test/CodeGenCXX/key-function-vtable.cpp
+++ b/test/CodeGenCXX/key-function-vtable.cpp
@@ -12,11 +12,11 @@ testb *testbvar = new testb;
struct testc { virtual void a(); };
inline void testc::a() {}
-// Key functions with inline specifier (PR5705)
+// Functions with inline specifier are not key functions (PR5705)
struct testd { inline virtual void a(); };
void testd::a() {}
-// Key functions with inline specifier (PR5705)
+// Functions with inline specifier are not key functions (PR5705)
struct teste { inline virtual void a(); };
teste *testevar = new teste;
diff --git a/test/CodeGenCXX/mangle-exprs.cpp b/test/CodeGenCXX/mangle-exprs.cpp
index d68425f5a578..7322171856dc 100644
--- a/test/CodeGenCXX/mangle-exprs.cpp
+++ b/test/CodeGenCXX/mangle-exprs.cpp
@@ -39,6 +39,6 @@ namespace Casts {
// CHECK: define weak_odr void @_ZN5Casts7static_ILj4EEEvPN9enable_ifIXleT_cvjLi4EEvE4typeE
template void static_<4>(void*);
- // CHECK: define weak_odr i8 @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
+ // CHECK: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
template T<6> f<6>();
}
diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp
index 814a7592fad0..55357c7d63a4 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -507,3 +507,120 @@ namespace test13 {
// CHECK: define weak_odr void @_ZN6test133fooINS_1BEEEvRKNS_1AIT_EE(
template void foo(const A<B> &a);
}
+
+namespace test14 {
+ extern "C" {
+ struct S {
+ static int a(), x;
+ };
+ // CHECK: define i32 @_ZN6test141S1aEv
+ // CHECK: load i32* @_ZN6test141S1xE
+ int S::a() { return S::x; }
+ }
+}
+
+// rdar://problem/8204122
+namespace test15 {
+ enum E { e = 3 };
+ template <int I> struct S {};
+
+ template <int I> void f(S<I + e>) {}
+
+ // CHECK: define weak_odr void @_ZN6test151fILi7EEEvNS_1SIXplT_LNS_1EE3EEEE(
+ template void f<7>(S<7 + e>);
+}
+
+// rdar://problem/8125400. Don't crash.
+namespace test16 {
+ static union {};
+ static union { union {}; };
+ static union { struct {}; };
+ static union { union { union {}; }; };
+ static union { union { struct {}; }; };
+ static union { struct { union {}; }; };
+ static union { struct { struct {}; }; };
+}
+
+// rdar://problem/8302148
+namespace test17 {
+ template <int N> struct A {};
+
+ struct B {
+ static int foo(void);
+ };
+
+ template <class T> A<sizeof(T::foo())> func(void);
+
+ // CHECK: define void @_ZN6test174testEv()
+ // CHECK: call {{.*}} @_ZN6test174funcINS_1BEEENS_1AIXszclsrT_3fooEEEEv()
+ void test() {
+ func<B>();
+ }
+}
+
+// PR7891
+namespace test18 {
+ struct A {
+ int operator+();
+ int operator-();
+ int operator*();
+ int operator&();
+ };
+ template <int (A::*)()> struct S {};
+
+ template <typename T> void f(S<&T::operator+>) {}
+ template void f<A>(S<&A::operator+>);
+
+ template <typename T> void f(S<&T::operator- >) {}
+ template void f<A>(S<&A::operator- >);
+
+ template <typename T> void f(S<&T::operator*>) {}
+ template void f<A>(S<&A::operator*>);
+
+ template <typename T> void f(S<&T::operator&>) {}
+ template void f<A>(S<&A::operator&>);
+
+ // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_plEEE
+ // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_miEEE
+ // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_mlEEE
+ // CHECK: define weak_odr void @_ZN6test181fINS_1AEEEvNS_1SIXadsrT_anEEE
+}
+
+// rdar://problem/8332117
+namespace test19 {
+ struct A {
+ template <typename T> int f();
+ int operator+();
+ operator int();
+ template <typename T> int operator-();
+ };
+
+ template <int (A::*)()> struct S {};
+
+ template <typename T> void g (S<&T::template f<int> >) {}
+ template <typename T> void g (S<&T::operator+ >) {}
+ template <typename T> void g (S<&T::operator int>) {}
+ template <typename T> void g (S<&T::template operator- <double> >) {}
+
+ // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_1fIiEEEE(
+ template void g<A>(S<&A::f<int> >);
+ // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_plEEE(
+ template void g<A>(S<&A::operator+>);
+ // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_cviEEE(
+ template void g<A>(S<&A::operator int>);
+ // CHECK: define weak_odr void @_ZN6test191gINS_1AEEEvNS_1SIXadsrT_miIdEEEE(
+ template void g<A>(S<&A::operator-<double> >);
+}
+
+namespace test20 {
+ template <class T> T *f(const T&);
+ template <class T> T *f(T*);
+
+ // CHECK: define weak_odr void @_ZN6test205test0IiEEvDTcl1fIPT_ELi0EEE(
+ template <class T> void test0(decltype(f<T*>(0))) {}
+ template void test0<int>(decltype(f<int*>(0)));
+
+ // CHECK: define weak_odr void @_ZN6test205test1IiEEvDTcl1fIEcvT__EEE(
+ template <class T> void test1(decltype(f<>(T()))) {}
+ template void test1<int>(decltype(f<>(int())));
+}
diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp
index e4beee15bb17..78a571e196e4 100644
--- a/test/CodeGenCXX/member-function-pointers.cpp
+++ b/test/CodeGenCXX/member-function-pointers.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin9 | FileCheck %s
// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-apple-darwin9 | FileCheck -check-prefix LP32 %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=armv7-unknown-unknown | FileCheck -check-prefix ARM %s
struct A { int a; void f(); virtual void vf1(); virtual void vf2(); };
struct B { int b; virtual void g(); };
@@ -28,50 +29,38 @@ void (C::*pc2)() = &C::f;
void (A::*pc3)() = &A::vf1;
void f() {
- // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0)
- // CHECK: store i64 0, i64* getelementptr inbounds (%0* @pa, i32 0, i32 1)
+ // CHECK: store %0 zeroinitializer, %0* @pa
pa = 0;
- // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 0)
- // CHECK: volatile store i64 0, i64* getelementptr inbounds (%0* @vpa, i32 0, i32 1)
+ // Is this okay? What are LLVM's volatile semantics for structs?
+ // CHECK: volatile store %0 zeroinitializer, %0* @vpa
vpa = 0;
- // 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)
+ // CHECK: [[TMP:%.*]] = load %0* @pa, align 8
+ // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1
+ // CHECK: [[ADJ:%.*]] = add nsw i64 [[TMPADJ]], 16
+ // CHECK: [[RES:%.*]] = insertvalue %0 [[TMP]], i64 [[ADJ]], 1
+ // CHECK: store %0 [[RES]], %0* @pc, align 8
pc = pa;
- // CHECK: store i64 {{.*}}, i64* getelementptr inbounds (%0* @pa, i32 0, i32 0)
- // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub i64 {{.*}}, 16
- // CHECK: store i64 [[ADJ]], i64* getelementptr inbounds (%0* @pa, i32 0, i32 1)
+ // CHECK: [[TMP:%.*]] = load %0* @pc, align 8
+ // CHECK: [[TMPADJ:%.*]] = extractvalue %0 [[TMP]], 1
+ // CHECK: [[ADJ:%.*]] = sub nsw i64 [[TMPADJ]], 16
+ // CHECK: [[RES:%.*]] = insertvalue %0 [[TMP]], i64 [[ADJ]], 1
+ // CHECK: store %0 [[RES]], %0* @pa, align 8
pa = static_cast<void (A::*)()>(pc);
}
void f2() {
- // CHECK: [[pa2ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 0
- // CHECK: store i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64* [[pa2ptr]]
- // CHECK: [[pa2adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa2, i32 0, i32 1
- // CHECK: store i64 0, i64* [[pa2adj]]
+ // CHECK: store %0 { i64 ptrtoint (void (%struct.A*)* @_ZN1A1fEv to i64), i64 0 }
void (A::*pa2)() = &A::f;
- // 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* [[pa3adj]]
- // CHECK-LP32: [[pa3ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 0
- // CHECK-LP32: store i32 1, i32* [[pa3ptr]]
- // CHECK-LP32: [[pa3adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa3, i32 0, i32 1
- // CHECK-LP32: store i32 0, i32* [[pa3adj]]
+ // CHECK: store %0 { i64 1, i64 0 }
+ // CHECK-LP32: store %0 { i32 1, i32 0 }
void (A::*pa3)() = &A::vf1;
- // CHECK: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0
- // CHECK: store i64 9, i64* [[pa4ptr]]
- // CHECK: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1
- // CHECK: store i64 0, i64* [[pa4adj]]
- // CHECK-LP32: [[pa4ptr:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 0
- // CHECK-LP32: store i32 5, i32* [[pa4ptr]]
- // CHECK-LP32: [[pa4adj:%[a-zA-Z0-9\.]+]] = getelementptr inbounds %0* %pa4, i32 0, i32 1
- // CHECK-LP32: store i32 0, i32* [[pa4adj]]
+ // CHECK: store %0 { i64 9, i64 0 }
+ // CHECK-LP32: store %0 { i32 5, i32 0 }
void (A::*pa4)() = &A::vf2;
}
@@ -190,3 +179,33 @@ namespace PR7027 {
struct X { void test( ); };
void testX() { &X::test; }
}
+
+namespace test7 {
+ struct A { void foo(); virtual void vfoo(); };
+ struct B { void foo(); virtual void vfoo(); };
+ struct C : A, B { void foo(); virtual void vfoo(); };
+
+ // CHECK-ARM: @_ZN5test74ptr0E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71A3fooEv to i32), i32 0 }
+ // CHECK-ARM: @_ZN5test74ptr1E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71B3fooEv to i32), i32 8 }
+ // CHECK-ARM: @_ZN5test74ptr2E = global {{.*}} { i32 ptrtoint ({{.*}}* @_ZN5test71C3fooEv to i32), i32 0 }
+ // CHECK-ARM: @_ZN5test74ptr3E = global {{.*}} { i32 0, i32 1 }
+ // CHECK-ARM: @_ZN5test74ptr4E = global {{.*}} { i32 0, i32 9 }
+ // CHECK-ARM: @_ZN5test74ptr5E = global {{.*}} { i32 0, i32 1 }
+ void (C::*ptr0)() = &A::foo;
+ void (C::*ptr1)() = &B::foo;
+ void (C::*ptr2)() = &C::foo;
+ void (C::*ptr3)() = &A::vfoo;
+ void (C::*ptr4)() = &B::vfoo;
+ void (C::*ptr5)() = &C::vfoo;
+}
+
+namespace test8 {
+ struct X { };
+ typedef int (X::*pmf)(int);
+
+ // CHECK: {{define.*_ZN5test81fEv}}
+ pmf f() {
+ // CHECK: {{ret.*zeroinitializer}}
+ return pmf();
+ }
+}
diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp
index b363552a4806..a60d24ad6212 100644
--- a/test/CodeGenCXX/member-functions.cpp
+++ b/test/CodeGenCXX/member-functions.cpp
@@ -58,6 +58,6 @@ struct T {
void test3() {
T t1, t2;
- // RUN: grep "call i8 @_ZN1TplERKS_" %t
+ // RUN: grep "call void @_ZN1TplERKS_" %t
T result = t1 + t2;
}
diff --git a/test/CodeGenCXX/member-qual-debug-info.cpp b/test/CodeGenCXX/member-qual-debug-info.cpp
deleted file mode 100644
index c6e0991eeac9..000000000000
--- a/test/CodeGenCXX/member-qual-debug-info.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %clang_cc1 -g -S -masm-verbose -x c++ -o %t %s
-// RUN: grep DW_TAG_volatile_type %t | count 3
-// RUN: grep DW_TAG_const_type %t | count 3
-// one for decl, one for def, one for abbrev
-
-namespace A {
- class B {
- public:
- void dump() const volatile;
- };
-}
-
-int main () {
- using namespace A;
- B b;
- return 0;
-}
-
-void A::B::dump() const volatile{
-}
diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp
index 885158f8a054..10a6f7f4890c 100644
--- a/test/CodeGenCXX/new.cpp
+++ b/test/CodeGenCXX/new.cpp
@@ -73,6 +73,10 @@ void t8(int n) {
new U[n];
}
+// noalias
+// CHECK: declare noalias i8* @_Znam
+void *operator new[](size_t);
+
void t9() {
bool b;
@@ -90,19 +94,72 @@ A* t10() {
return new(1, 2, 3.45, 100) A;
}
+// CHECK: define void @_Z3t11i
struct B { int a; };
-void t11() {
+struct Bmemptr { int Bmemptr::* memptr; int a; };
+
+void t11(int n) {
// CHECK: call noalias i8* @_Znwm
// CHECK: call void @llvm.memset.p0i8.i64(
B* b = new B();
+
+ // CHECK: call noalias i8* @_Znam
+ // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}}
+ B *b2 = new B[n]();
+
+ // CHECK: call noalias i8* @_Znam
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+ // CHECK: br
+ Bmemptr *b_memptr = new Bmemptr[n]();
+
+ // CHECK: ret void
}
struct Empty { };
// We don't need to initialize an empty class.
+// CHECK: define void @_Z3t12v
void t12() {
- // CHECK: define void @_Z3t12v
- // CHECK-NOT: br label
- // CHECK: ret void
+ // CHECK: call noalias i8* @_Znam
+ // CHECK-NOT: br
(void)new Empty[10];
+
+ // CHECK: call noalias i8* @_Znam
+ // CHECK-NOT: br
+ (void)new Empty[10]();
+
+ // CHECK: ret void
+}
+
+// Zero-initialization
+// CHECK: define void @_Z3t13i
+void t13(int n) {
+ // CHECK: call noalias i8* @_Znwm
+ // CHECK: store i32 0, i32*
+ (void)new int();
+
+ // CHECK: call noalias i8* @_Znam
+ // CHECK: {{call void.*llvm.memset.p0i8.i64.*i8 0, i64 %}}
+ (void)new int[n]();
+
+ // CHECK-NEXT: ret void
+}
+
+struct Alloc{
+ int x;
+ void* operator new[](size_t size);
+ void operator delete[](void* p);
+ ~Alloc();
+};
+
+void f() {
+ // CHECK: call i8* @_ZN5AllocnaEm(i64 808)
+ // CHECK: store i64 200
+ // CHECK: call void @_ZN5AllocD1Ev(
+ // CHECK: call void @_ZN5AllocdaEPv(i8*
+ delete[] new Alloc[10][20];
+ // CHECK: call noalias i8* @_Znwm
+ // CHECK: call void @_ZdlPv(i8*
+ delete new bool;
+ // CHECK: ret void
}
diff --git a/test/CodeGenCXX/nonconst-init.cpp b/test/CodeGenCXX/nonconst-init.cpp
new file mode 100644
index 000000000000..21129b9b2a63
--- /dev/null
+++ b/test/CodeGenCXX/nonconst-init.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
+
+int a();
+// CHECK: call i32 @_Z1av()
+struct x {int x, y : 10;} x = {1, a()};
diff --git a/test/CodeGenCXX/operator-new.cpp b/test/CodeGenCXX/operator-new.cpp
index f718faebef00..db56cda6cdd1 100644
--- a/test/CodeGenCXX/operator-new.cpp
+++ b/test/CodeGenCXX/operator-new.cpp
@@ -11,7 +11,19 @@ public:
};
void f1() {
- // CHECK-SANE: declare noalias i8* @_Znwj(
- // CHECK-SANENOT: declare i8* @_Znwj(
+ // SANE: declare noalias i8* @_Znwj(
+ // SANENOT: declare i8* @_Znwj(
new teste();
}
+
+
+// rdar://5739832 - operator new should check for overflow in multiply.
+void *f2(long N) {
+ return new int[N];
+
+// SANE: [[UWO:%.*]] = call {{.*}} @llvm.umul.with.overflow
+// SANE-NEXT: [[OVER:%.*]] = extractvalue {{.*}} [[UWO]], 1
+// SANE-NEXT: [[SUM:%.*]] = extractvalue {{.*}} [[UWO]], 0
+// SANE-NEXT: [[RESULT:%.*]] = select i1 [[OVER]], i32 -1, i32 [[SUM]]
+// SANE-NEXT: call noalias i8* @_Znaj(i32 [[RESULT]])
+}
diff --git a/test/CodeGenCXX/pointers-to-data-members.cpp b/test/CodeGenCXX/pointers-to-data-members.cpp
index 70308c6abc5f..38c7d2815a08 100644
--- a/test/CodeGenCXX/pointers-to-data-members.cpp
+++ b/test/CodeGenCXX/pointers-to-data-members.cpp
@@ -65,15 +65,21 @@ int A::*pa;
int C::*pc;
void f() {
- // CHECK: store i64 -1, i64* @_ZN5Casts2paE
+ // CHECK: store i64 -1, i64* @_ZN5Casts2paE
pa = 0;
- // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = add nsw i64 {{.*}}, 4
- // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2pcE
+ // CHECK-NEXT: [[TMP:%.*]] = load i64* @_ZN5Casts2paE, align 8
+ // CHECK-NEXT: [[ADJ:%.*]] = add nsw i64 [[TMP]], 4
+ // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i64 [[TMP]], -1
+ // CHECK-NEXT: [[RES:%.*]] = select i1 [[ISNULL]], i64 [[TMP]], i64 [[ADJ]]
+ // CHECK-NEXT: store i64 [[RES]], i64* @_ZN5Casts2pcE
pc = pa;
- // CHECK: [[ADJ:%[a-zA-Z0-9\.]+]] = sub nsw i64 {{.*}}, 4
- // CHECK: store i64 [[ADJ]], i64* @_ZN5Casts2paE
+ // CHECK-NEXT: [[TMP:%.*]] = load i64* @_ZN5Casts2pcE, align 8
+ // CHECK-NEXT: [[ADJ:%.*]] = sub nsw i64 [[TMP]], 4
+ // CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i64 [[TMP]], -1
+ // CHECK-NEXT: [[RES:%.*]] = select i1 [[ISNULL]], i64 [[TMP]], i64 [[ADJ]]
+ // CHECK-NEXT: store i64 [[RES]], i64* @_ZN5Casts2paE
pa = static_cast<int A::*>(pc);
}
@@ -183,3 +189,17 @@ struct A {
A a;
}
+
+namespace BoolPtrToMember {
+ struct X {
+ bool member;
+ };
+
+ // CHECK: define i8* @_ZN15BoolPtrToMember1fERNS_1XEMS0_b
+ bool &f(X &x, bool X::*member) {
+ // CHECK: {{bitcast.* to i8\*}}
+ // CHECK-NEXT: getelementptr inbounds i8*
+ // CHECK-NEXT: ret i8*
+ return x.*member;
+ }
+}
diff --git a/test/CodeGenCXX/pragma-visibility.cpp b/test/CodeGenCXX/pragma-visibility.cpp
new file mode 100644
index 000000000000..05de78670a04
--- /dev/null
+++ b/test/CodeGenCXX/pragma-visibility.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+#pragma GCC visibility push(hidden)
+struct x {
+ static int y;
+};
+#pragma GCC visibility pop
+int x::y = 10;
+// CHECK: @_ZN1x1yE = hidden global
+
+#pragma GCC visibility push(hidden)
+struct __attribute((visibility("default"))) x2 {
+ static int y;
+};
+int x2::y = 10;
+// CHECK: @_ZN2x21yE = global
+#pragma GCC visibility pop
+
+#pragma GCC visibility push(hidden)
+struct x3 {
+ static int y;
+} __attribute((visibility("default")));
+int x3::y = 10;
+// CHECK: @_ZN2x31yE = global
+#pragma GCC visibility pop
+
+#pragma GCC visibility push(hidden)
+template<class T> struct x4 {
+ static int y;
+};
+#pragma GCC visibility pop
+template<> int x4<int>::y = 10;
+// CHECK: @_ZN2x4IiE1yE = hidden global i32
+
+#pragma GCC visibility push(hidden)
+template<int x> int f() { return x; }
+extern "C" int g() { return f<3>(); }
+#pragma GCC visibility pop
+// CHECK: define hidden i32 @g()
+// CHECK: define linkonce_odr hidden i32 @_Z1fILi3EEiv()
+
+#pragma GCC visibility push(hidden)
+template<class T> struct x5 {
+ void y();
+};
+#pragma GCC visibility pop
+template<> void x5<int>::y() {}
+// CHECK: define hidden void @_ZN2x5IiE1yEv
+
+#pragma GCC visibility push(hidden)
+namespace n __attribute((visibility("default"))) {
+ void f() {}
+ // CHECK: define void @_ZN1n1fEv
+}
+#pragma GCC visibility pop
+
+namespace n __attribute((visibility("default"))) {
+ extern int foofoo; // FIXME: Shouldn't be necessary, but otherwise the pragma
+ // gets to Sema before the namespace!
+#pragma GCC visibility push(hidden)
+ void g() {}
+ // CHECK: define hidden void @_ZN1n1gEv
+#pragma GCC visibility pop
+}
+
+namespace n __attribute((visibility("hidden"))) {
+ extern int foofoo; // FIXME: Shouldn't be necessary, but otherwise the pragma
+ // gets to Sema before the namespace!
+ #pragma GCC visibility pop
+ void h() {}
+ // CHECK: define void @_ZN1n1hEv
+}
diff --git a/test/CodeGenCXX/reference-cast.cpp b/test/CodeGenCXX/reference-cast.cpp
new file mode 100644
index 000000000000..585d1dbd4084
--- /dev/null
+++ b/test/CodeGenCXX/reference-cast.cpp
@@ -0,0 +1,170 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s
+
+// PR6024
+extern int i;
+
+// CHECK: define i32* @_Z16lvalue_noop_castv() nounwind
+const int &lvalue_noop_cast() {
+ if (i == 0)
+ // CHECK: store i32 17, i32*
+ return (const int&)17;
+ else if (i == 1)
+ // CHECK: store i32 17, i32*
+ return static_cast<const int&>(17);
+ // CHECK: store i32 17, i32*
+ return 17;
+}
+
+// CHECK: define i16* @_Z20lvalue_integral_castv()
+const short &lvalue_integral_cast() {
+ if (i == 0)
+ // CHECK: store i16 17, i16*
+ return (const short&)17;
+ else if (i == 1)
+ // CHECK: store i16 17, i16*
+ return static_cast<const short&>(17);
+ // CHECK: store i16 17, i16*
+ return 17;
+}
+
+// CHECK: define i16* @_Z29lvalue_floating_integral_castv()
+const short &lvalue_floating_integral_cast() {
+ if (i == 0)
+ // CHECK: store i16 17, i16*
+ return (const short&)17.5;
+ else if (i == 1)
+ // CHECK: store i16 17, i16*
+ return static_cast<const short&>(17.5);
+ // CHECK: store i16 17, i16*
+ return 17.5;
+}
+
+// CHECK: define float* @_Z29lvalue_integral_floating_castv()
+const float &lvalue_integral_floating_cast() {
+ if (i == 0)
+ // CHECK: store float 1.700000e+{{0*}}1, float*
+ return (const float&)17;
+ else if (i == 1)
+ // CHECK: store float 1.700000e+{{0*}}1, float*
+ return static_cast<const float&>(17);
+ // CHECK: store float 1.700000e+{{0*}}1, float*
+ return 17;
+}
+
+// CHECK: define float* @_Z20lvalue_floating_castv()
+const float &lvalue_floating_cast() {
+ if (i == 0)
+ // CHECK: store float 1.700000e+{{0*}}1, float*
+ return (const float&)17.0;
+ else if (i == 1)
+ // CHECK: store float 1.700000e+{{0*}}1, float*
+ return static_cast<const float&>(17.0);
+ // CHECK: store float 1.700000e+{{0*}}1, float*
+ return 17.0;
+}
+
+int get_int();
+
+// CHECK: define i8* @_Z24lvalue_integer_bool_castv()
+const bool &lvalue_integer_bool_cast() {
+ if (i == 0)
+ // CHECK: call i32 @_Z7get_intv()
+ // CHECK: store i8
+ return (const bool&)get_int();
+ else if (i == 1)
+ // CHECK: call i32 @_Z7get_intv()
+ // CHECK: store i8
+ return static_cast<const bool&>(get_int());
+ // CHECK: call i32 @_Z7get_intv()
+ // CHECK: store i8
+ return get_int();
+}
+
+float get_float();
+
+// CHECK: define i8* @_Z25lvalue_floating_bool_castv()
+const bool &lvalue_floating_bool_cast() {
+ if (i == 0)
+ // CHECK: call float @_Z9get_floatv()
+ // CHECK: fcmp une float
+ // CHECK: store i8
+ return (const bool&)get_float();
+ else if (i == 1)
+ // CHECK: call float @_Z9get_floatv()
+ // CHECK: fcmp une float
+ // CHECK: store i8
+ return static_cast<const bool&>(get_float());
+ // CHECK: call float @_Z9get_floatv()
+ // CHECK: fcmp une float
+ // CHECK: store i8
+ return get_float();
+}
+
+struct X { };
+typedef int X::*pm;
+typedef int (X::*pmf)(int);
+
+pm get_pointer_to_member_data();
+pmf get_pointer_to_member_function();
+
+// CHECK: define i8* @_Z26lvalue_ptrmem_to_bool_castv()
+const bool &lvalue_ptrmem_to_bool_cast() {
+ if (i == 0)
+ // CHECK: call i64 @_Z26get_pointer_to_member_datav()
+ // CHECK: store i8
+ // CHECK: store i8*
+ return (const bool&)get_pointer_to_member_data();
+ else if (i == 1)
+ // CHECK: call i64 @_Z26get_pointer_to_member_datav()
+ // CHECK: store i8
+ // CHECK: store i8*
+ return static_cast<const bool&>(get_pointer_to_member_data());
+ // CHECK: call i64 @_Z26get_pointer_to_member_datav()
+ // CHECK: store i8
+ // CHECK: store i8*
+ return get_pointer_to_member_data();
+}
+
+// CHECK: define i8* @_Z27lvalue_ptrmem_to_bool_cast2v
+const bool &lvalue_ptrmem_to_bool_cast2() {
+ if (i == 0)
+ // CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
+ // CHECK: store i8
+ // CHECK: store i8*
+ return (const bool&)get_pointer_to_member_function();
+ else if (i == 1)
+ // CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
+ // CHECK: store i8
+ // CHECK: store i8*
+ return static_cast<const bool&>(get_pointer_to_member_function());
+ // CHECK: {{call.*_Z30get_pointer_to_member_functionv}}
+ // CHECK: store i8
+ // CHECK: store i8*
+ return get_pointer_to_member_function();
+}
+
+_Complex double get_complex_double();
+
+// CHECK: {{define.*_Z2f1v}}
+const _Complex float &f1() {
+ if (i == 0)
+ // CHECK: {{call.*_Z18get_complex_doublev}}
+ // CHECK: fptrunc
+ // CHECK: fptrunc
+ // CHECK: store float
+ // CHECK: store float
+ return (const _Complex float&)get_complex_double();
+ else if (i == 1)
+ // CHECK: {{call.*_Z18get_complex_doublev}}
+ // CHECK: fptrunc
+ // CHECK: fptrunc
+ // CHECK: store float
+ // CHECK: store float
+ return static_cast<const _Complex float&>(get_complex_double());
+ // CHECK: {{call.*_Z18get_complex_doublev}}
+ // CHECK: fptrunc
+ // CHECK: fptrunc
+ // CHECK: store float
+ // CHECK: store float
+ return get_complex_double();
+}
diff --git a/test/CodeGenCXX/rtti-fundamental.cpp b/test/CodeGenCXX/rtti-fundamental.cpp
index 6826321cd5eb..7f80d99b70e1 100644
--- a/test/CodeGenCXX/rtti-fundamental.cpp
+++ b/test/CodeGenCXX/rtti-fundamental.cpp
@@ -14,60 +14,60 @@ namespace __cxxabiv1 {
__fundamental_type_info::~__fundamental_type_info() { }
}
-// CHECK: @_ZTIv = weak_odr constant
-// CHECK: @_ZTIPv = weak_odr constant
-// CHECK: @_ZTIPKv = weak_odr constant
-// CHECK: @_ZTIDi = weak_odr constant
-// CHECK: @_ZTIPDi = weak_odr constant
-// CHECK: @_ZTIPKDi = weak_odr constant
-// CHECK: @_ZTIDs = weak_odr constant
-// CHECK: @_ZTIPDs = weak_odr constant
-// CHECK: @_ZTIPKDs = weak_odr constant
-// CHECK: @_ZTIy = weak_odr constant
-// CHECK: @_ZTIPy = weak_odr constant
-// CHECK: @_ZTIPKy = weak_odr constant
-// CHECK: @_ZTIx = weak_odr constant
-// CHECK: @_ZTIPx = weak_odr constant
-// CHECK: @_ZTIPKx = weak_odr constant
-// CHECK: @_ZTIw = weak_odr constant
-// CHECK: @_ZTIPw = weak_odr constant
-// CHECK: @_ZTIPKw = weak_odr constant
-// CHECK: @_ZTIt = weak_odr constant
-// CHECK: @_ZTIPt = weak_odr constant
-// CHECK: @_ZTIPKt = weak_odr constant
-// CHECK: @_ZTIs = weak_odr constant
-// CHECK: @_ZTIPs = weak_odr constant
-// CHECK: @_ZTIPKs = weak_odr constant
-// CHECK: @_ZTIm = weak_odr constant
-// CHECK: @_ZTIPm = weak_odr constant
-// CHECK: @_ZTIPKm = weak_odr constant
-// CHECK: @_ZTIl = weak_odr constant
-// CHECK: @_ZTIPl = weak_odr constant
-// CHECK: @_ZTIPKl = weak_odr constant
-// CHECK: @_ZTIj = weak_odr constant
-// CHECK: @_ZTIPj = weak_odr constant
-// CHECK: @_ZTIPKj = weak_odr constant
-// CHECK: @_ZTIi = weak_odr constant
-// CHECK: @_ZTIPi = weak_odr constant
-// CHECK: @_ZTIPKi = weak_odr constant
-// CHECK: @_ZTIh = weak_odr constant
-// CHECK: @_ZTIPh = weak_odr constant
-// CHECK: @_ZTIPKh = weak_odr constant
-// CHECK: @_ZTIf = weak_odr constant
-// CHECK: @_ZTIPf = weak_odr constant
-// CHECK: @_ZTIPKf = weak_odr constant
-// CHECK: @_ZTIe = weak_odr constant
-// CHECK: @_ZTIPe = weak_odr constant
-// CHECK: @_ZTIPKe = weak_odr constant
-// CHECK: @_ZTId = weak_odr constant
-// CHECK: @_ZTIPd = weak_odr constant
-// CHECK: @_ZTIPKd = weak_odr constant
-// CHECK: @_ZTIc = weak_odr constant
-// CHECK: @_ZTIPc = weak_odr constant
-// CHECK: @_ZTIPKc = weak_odr constant
-// CHECK: @_ZTIb = weak_odr constant
-// CHECK: @_ZTIPb = weak_odr constant
-// CHECK: @_ZTIPKb = weak_odr constant
-// CHECK: @_ZTIa = weak_odr constant
-// CHECK: @_ZTIPa = weak_odr constant
-// CHECK: @_ZTIPKa = weak_odr constant
+// CHECK: @_ZTIv = constant
+// CHECK: @_ZTIPv = constant
+// CHECK: @_ZTIPKv = constant
+// CHECK: @_ZTIDi = constant
+// CHECK: @_ZTIPDi = constant
+// CHECK: @_ZTIPKDi = constant
+// CHECK: @_ZTIDs = constant
+// CHECK: @_ZTIPDs = constant
+// CHECK: @_ZTIPKDs = constant
+// CHECK: @_ZTIy = constant
+// CHECK: @_ZTIPy = constant
+// CHECK: @_ZTIPKy = constant
+// CHECK: @_ZTIx = constant
+// CHECK: @_ZTIPx = constant
+// CHECK: @_ZTIPKx = constant
+// CHECK: @_ZTIw = constant
+// CHECK: @_ZTIPw = constant
+// CHECK: @_ZTIPKw = constant
+// CHECK: @_ZTIt = constant
+// CHECK: @_ZTIPt = constant
+// CHECK: @_ZTIPKt = constant
+// CHECK: @_ZTIs = constant
+// CHECK: @_ZTIPs = constant
+// CHECK: @_ZTIPKs = constant
+// CHECK: @_ZTIm = constant
+// CHECK: @_ZTIPm = constant
+// CHECK: @_ZTIPKm = constant
+// CHECK: @_ZTIl = constant
+// CHECK: @_ZTIPl = constant
+// CHECK: @_ZTIPKl = constant
+// CHECK: @_ZTIj = constant
+// CHECK: @_ZTIPj = constant
+// CHECK: @_ZTIPKj = constant
+// CHECK: @_ZTIi = constant
+// CHECK: @_ZTIPi = constant
+// CHECK: @_ZTIPKi = constant
+// CHECK: @_ZTIh = constant
+// CHECK: @_ZTIPh = constant
+// CHECK: @_ZTIPKh = constant
+// CHECK: @_ZTIf = constant
+// CHECK: @_ZTIPf = constant
+// CHECK: @_ZTIPKf = constant
+// CHECK: @_ZTIe = constant
+// CHECK: @_ZTIPe = constant
+// CHECK: @_ZTIPKe = constant
+// CHECK: @_ZTId = constant
+// CHECK: @_ZTIPd = constant
+// CHECK: @_ZTIPKd = constant
+// CHECK: @_ZTIc = constant
+// CHECK: @_ZTIPc = constant
+// CHECK: @_ZTIPKc = constant
+// CHECK: @_ZTIb = constant
+// CHECK: @_ZTIPb = constant
+// CHECK: @_ZTIPKb = constant
+// CHECK: @_ZTIa = constant
+// CHECK: @_ZTIPa = constant
+// CHECK: @_ZTIPKa = constant
diff --git a/test/CodeGenCXX/rtti-linkage.cpp b/test/CodeGenCXX/rtti-linkage.cpp
index f8c1167b53db..efa336dda4ec 100644
--- a/test/CodeGenCXX/rtti-linkage.cpp
+++ b/test/CodeGenCXX/rtti-linkage.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -emit-llvm -o - | sort | FileCheck %s
+// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | sort | FileCheck %s
// FIXME: Fails on Win32, dunno why.
// XFAIL: win32
@@ -11,13 +11,16 @@
-// CHECK: _ZTI1A = weak_odr constant
+// CHECK: _ZTI1A = weak_odr hidden constant
// CHECK: _ZTI1B = constant
// CHECK: _ZTI1C = internal constant
-// CHECK: _ZTIA10_i = weak_odr constant
+// CHECK: _ZTI1TILj0EE = weak_odr constant
+// CHECK: _ZTI1TILj1EE = weak_odr constant
+// CHECK: _ZTI1TILj2EE = external constant
+// CHECK: _ZTIA10_i = weak_odr hidden constant
// CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant
// CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant
-// CHECK: _ZTIFvvE = weak_odr
+// CHECK: _ZTIFvvE = weak_odr hidden constant
// CHECK: _ZTIM1A1C = internal constant
// CHECK: _ZTIM1AP1C = internal constant
// CHECK: _ZTIM1CPS_ = internal constant
@@ -26,7 +29,7 @@
// CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant
// CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant
// CHECK: _ZTIP1C = internal constant
-// CHECK: _ZTIPFvvE = weak_odr constant
+// CHECK: _ZTIPFvvE = weak_odr hidden constant
// CHECK: _ZTIPM1Ci = internal constant
// CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant
// CHECK: _ZTIPP1C = internal constant
@@ -118,3 +121,14 @@ namespace Arrays {
return typeid(A::a);
}
}
+
+template <unsigned N> class T {
+ virtual void anchor() {}
+};
+template class T<1>;
+template <> class T<2> { virtual void anchor(); };
+void t3() {
+ (void) typeid(T<0>);
+ (void) typeid(T<1>);
+ (void) typeid(T<2>);
+}
diff --git a/test/CodeGenCXX/static-init-2.cpp b/test/CodeGenCXX/static-init-2.cpp
index 7eb4a7d5aa79..65ab3bb1262d 100644
--- a/test/CodeGenCXX/static-init-2.cpp
+++ b/test/CodeGenCXX/static-init-2.cpp
@@ -3,4 +3,4 @@
// 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; // expected-warning {{use of logical && with constant operand}}
+int y = x() && 0;
diff --git a/test/CodeGenCXX/template-anonymous-types.cpp b/test/CodeGenCXX/template-anonymous-types.cpp
new file mode 100644
index 000000000000..5e7a71fd8772
--- /dev/null
+++ b/test/CodeGenCXX/template-anonymous-types.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck %s
+
+struct S {
+ enum { FOO = 42 };
+ enum { BAR = 42 };
+};
+
+template <typename T> struct X {
+ T value;
+ X(T t) : value(t) {}
+ int f() { return value; }
+};
+
+template <typename T> int f(T t) {
+ X<T> x(t);
+ return x.f();
+}
+
+void test() {
+ // Look for two instantiations, entirely internal to this TU, one for FOO's
+ // type and one for BAR's.
+ // CHECK: define internal i32 @"_Z1fIN1S3$_0EEiT_"(i32 %t)
+ (void)f(S::FOO);
+ // CHECK: define internal i32 @"_Z1fIN1S3$_1EEiT_"(i32 %t)
+ (void)f(S::BAR);
+
+ // Now check for the class template instantiations. Annoyingly, they are in
+ // reverse order.
+ //
+ // BAR's instantiation of X:
+ // CHECK: define internal i32 @"_ZN1XIN1S3$_1EE1fEv"(%struct.X* %this)
+ // CHECK: define internal void @"_ZN1XIN1S3$_1EEC2ES1_"(%struct.X* %this, i32 %t)
+ //
+ // FOO's instantiation of X:
+ // CHECK: define internal i32 @"_ZN1XIN1S3$_0EE1fEv"(%struct.X* %this)
+ // CHECK: define internal void @"_ZN1XIN1S3$_0EEC2ES1_"(%struct.X* %this, i32 %t)
+}
diff --git a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
index 17c10301d4fa..c91590fd58b8 100644
--- a/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
+++ b/test/CodeGenCXX/threadsafe-statics-exceptions.cpp
@@ -17,7 +17,7 @@ void f() {
static X x;
// CHECK: call i8* @__cxa_allocate_exception
- // CHECK: invoke void @__cxa_throw
+ // CHECK: call void @__cxa_throw
throw Y();
// Finally, the landing pad.
diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp
index 1de576128a11..ba60385ab6f3 100644
--- a/test/CodeGenCXX/thunks.cpp
+++ b/test/CodeGenCXX/thunks.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o - | FileCheck -check-prefix=HIDDEN %s
namespace Test1 {
@@ -246,6 +247,19 @@ namespace Test9 {
}
}
+namespace Test10 {
+ struct A { virtual void foo(); };
+ struct B { virtual void foo(); };
+ struct C : A, B { void foo() {} };
+
+ // CHECK-HIDDEN: define linkonce_odr void @_ZN6Test101C3fooEv
+ // CHECK-HIDDEN: define linkonce_odr hidden void @_ZThn8_N6Test101C3fooEv
+
+ void test() {
+ C c;
+ }
+}
+
/**** The following has to go at the end of the file ****/
// This is from Test5:
diff --git a/test/CodeGenCXX/uncode-string.cpp b/test/CodeGenCXX/uncode-string.cpp
new file mode 100644
index 000000000000..e5431497479e
--- /dev/null
+++ b/test/CodeGenCXX/uncode-string.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
+// rdar://8360841
+
+wchar_t s[] = L"\u2722";
+
+// CHECK: @s = global [8 x i8] c"\22'\00\00\00\00\00\00"
diff --git a/test/CodeGenCXX/value-init.cpp b/test/CodeGenCXX/value-init.cpp
index 35be159aac9d..c4eb1c899096 100644
--- a/test/CodeGenCXX/value-init.cpp
+++ b/test/CodeGenCXX/value-init.cpp
@@ -49,3 +49,92 @@ void test_enum_holder_and_int() {
enum_holder_and_int();
// CHECK-NEXT: ret void
}
+
+// PR7834: don't crash.
+namespace test1 {
+ struct A {
+ int A::*f;
+ A();
+ A(const A&);
+ A &operator=(const A &);
+ };
+
+ struct B {
+ A base;
+ };
+
+ void foo() {
+ B();
+ }
+}
+
+namespace ptrmem {
+ struct S {
+ int mem1;
+ int S::*mem2;
+ };
+
+ // CHECK: define i32 @_ZN6ptrmem4testEPNS_1SE
+ int test(S *s) {
+ // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
+ // CHECK: getelementptr
+ // CHECK: ret
+ return s->*S().mem2;
+ }
+}
+
+namespace zeroinit {
+ struct S { int i; };
+
+ // CHECK: define i32 @_ZN8zeroinit4testEv()
+ int test() {
+ // CHECK: call void @llvm.memset.p0i8.i64
+ // CHECK: getelementptr
+ // CHECK: ret i32
+ return S().i;
+ }
+
+ struct X0 {
+ X0() { }
+ int x;
+ };
+
+ struct X1 : X0 {
+ int x1;
+ void f();
+ };
+
+ // CHECK: define void @_ZN8zeroinit9testX0_X1Ev
+ void testX0_X1() {
+ // CHECK: call void @llvm.memset.p0i8.i64
+ // CHECK-NEXT: call void @_ZN8zeroinit2X1C1Ev
+ // CHECK-NEXT: call void @_ZN8zeroinit2X11fEv
+ X1().f();
+ }
+
+ template<typename>
+ struct X2 : X0 {
+ int x2;
+ void f();
+ };
+
+ template<typename>
+ struct X3 : X2<int> {
+ X3() : X2<int>() { }
+ };
+
+
+ // CHECK: define void @_ZN8zeroinit9testX0_X3Ev
+ void testX0_X3() {
+ // CHECK-NOT: call void @llvm.memset
+ // CHECK: call void @_ZN8zeroinit2X3IiEC1Ev
+ // CHECK: call void @_ZN8zeroinit2X2IiE1fEv
+ // CHECK-NEXT: ret void
+ X3<int>().f();
+ }
+
+ // CHECK: define linkonce_odr void @_ZN8zeroinit2X3IiEC2Ev
+ // CHECK: call void @llvm.memset.p0i8.i64
+ // CHECK-NEXT: call void @_ZN8zeroinit2X2IiEC2Ev
+ // CHECK-NEXT: ret void
+}
diff --git a/test/CodeGenCXX/virt-template-vtable.cpp b/test/CodeGenCXX/virt-template-vtable.cpp
index b968f38c8263..d60cfb9043ac 100644
--- a/test/CodeGenCXX/virt-template-vtable.cpp
+++ b/test/CodeGenCXX/virt-template-vtable.cpp
@@ -10,4 +10,13 @@ class B : A<int> {
};
B::B() {}
+template class A<long>;
+
+extern template class A<short>;
+template class A<short>;
+
+
+// CHECK: @_ZTV1B = weak_odr constant
+// CHECK: @_ZTV1AIlE = weak_odr constant
+// CHECK: @_ZTV1AIsE = weak_odr constant
// CHECK: @_ZTV1AIiE = weak_odr constant
diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp
new file mode 100644
index 000000000000..58f433f1e15c
--- /dev/null
+++ b/test/CodeGenCXX/volatile.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// Check that IR gen doesn't try to do an lvalue-to-rvalue conversion
+// on a volatile reference result. rdar://problem/8338198
+namespace test0 {
+ struct A {
+ A(const A& t);
+ A& operator=(const A& t);
+ volatile A& operator=(const volatile A& t) volatile;
+ };
+
+ volatile A *array;
+
+ // CHECK: define void @_ZN5test04testENS_1AE(
+ void test(A t) {
+ // CHECK: [[ARR:%.*]] = load [[A:%.*]]** @_ZN5test05arrayE, align 8
+ // CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [[A]]* [[ARR]], i64 0
+ // CHECK-NEXT: [[TMP:%.*]] = call [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* [[T:%.*]])
+ // CHECK-NEXT: ret void
+ array[0] = t;
+ }
+}
+
+namespace test1 {
+ volatile int *x;
+
+ // CHECK: define void @_ZN5test14testEv()
+ void test() {
+ // CHECK: [[TMP:%.*]] = load i32** @_ZN5test11xE, align 8
+ // *** FIXME: no! bad! should not be loaded! ***
+ // CHECK-NEXT: [[TMP1:%.*]] = volatile load i32* [[TMP]]
+ // CHECK-NEXT: ret void
+ *x;
+ }
+}
diff --git a/test/CodeGenCXX/vtable-linkage.cpp b/test/CodeGenCXX/vtable-linkage.cpp
index b3b68703c6d3..cf988d131222 100644
--- a/test/CodeGenCXX/vtable-linkage.cpp
+++ b/test/CodeGenCXX/vtable-linkage.cpp
@@ -1,16 +1,21 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o %t
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fhidden-weak-vtables -emit-llvm -o %t.hidden
// RUN: FileCheck --check-prefix=CHECK-1 %s < %t
// RUN: FileCheck --check-prefix=CHECK-2 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-2-HIDDEN %s < %t.hidden
// RUN: FileCheck --check-prefix=CHECK-3 %s < %t
// RUN: FileCheck --check-prefix=CHECK-4 %s < %t
// RUN: FileCheck --check-prefix=CHECK-5 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-5-HIDDEN %s < %t.hidden
// RUN: FileCheck --check-prefix=CHECK-6 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-6-HIDDEN %s < %t.hidden
// RUN: FileCheck --check-prefix=CHECK-7 %s < %t
// RUN: FileCheck --check-prefix=CHECK-8 %s < %t
// RUN: FileCheck --check-prefix=CHECK-9 %s < %t
// RUN: FileCheck --check-prefix=CHECK-10 %s < %t
// RUN: FileCheck --check-prefix=CHECK-11 %s < %t
// RUN: FileCheck --check-prefix=CHECK-12 %s < %t
+// RUN: FileCheck --check-prefix=CHECK-13 %s < %t
namespace {
struct A {
@@ -83,22 +88,27 @@ struct F<char> {
template struct F<short>;
extern template struct F<int>;
-void use_F(F<char> &fc) {
+void use_F() {
+ F<char> fc;
+ fc.foo();
F<int> fi;
fi.foo();
F<long> fl;
(void)fl;
- fc.foo();
}
// B has a key function that is not defined in this translation unit so its vtable
// has external linkage.
// CHECK-1: @_ZTV1B = external constant
-// C has no key function, so its vtable should have weak_odr linkage.
+// C has no key function, so its vtable should have weak_odr linkage
+// and hidden visibility (rdar://problem/7523229).
// CHECK-2: @_ZTV1C = weak_odr constant
// CHECK-2: @_ZTS1C = weak_odr constant
// CHECK-2: @_ZTI1C = weak_odr constant
+// CHECK-2-HIDDEN: @_ZTV1C = weak_odr hidden constant
+// CHECK-2-HIDDEN: @_ZTS1C = weak_odr constant
+// CHECK-2-HIDDEN: @_ZTI1C = weak_odr hidden constant
// D has a key function that is defined in this translation unit so its vtable is
// defined in the translation unit.
@@ -119,12 +129,18 @@ void use_F(F<char> &fc) {
// CHECK-5: @_ZTV1EIsE = weak_odr constant
// CHECK-5: @_ZTS1EIsE = weak_odr constant
// CHECK-5: @_ZTI1EIsE = weak_odr constant
+// CHECK-5-HIDDEN: @_ZTV1EIsE = weak_odr constant
+// CHECK-5-HIDDEN: @_ZTS1EIsE = weak_odr constant
+// CHECK-5-HIDDEN: @_ZTI1EIsE = weak_odr constant
// F<short> is an explicit template instantiation without a key
// function, so its vtable should have weak_odr linkage
// CHECK-6: @_ZTV1FIsE = weak_odr constant
// CHECK-6: @_ZTS1FIsE = weak_odr constant
// CHECK-6: @_ZTI1FIsE = weak_odr constant
+// CHECK-6-HIDDEN: @_ZTV1FIsE = weak_odr constant
+// CHECK-6-HIDDEN: @_ZTS1FIsE = weak_odr constant
+// CHECK-6-HIDDEN: @_ZTI1FIsE = weak_odr constant
// E<long> is an implicit template instantiation with a key function
// defined in this translation unit, so its vtable should have
@@ -160,6 +176,12 @@ void use_F(F<char> &fc) {
// CHECK-12: @_ZTSN12_GLOBAL__N_11AE = internal constant
// CHECK-12: @_ZTIN12_GLOBAL__N_11AE = internal constant
+// F<char> is an explicit specialization without a key function, so
+// its vtable should have weak_odr linkage.
+// CHECK-13: @_ZTV1FIcE = weak_odr constant
+// CHECK-13: @_ZTS1FIcE = weak_odr constant
+// CHECK-13: @_ZTI1FIcE = weak_odr constant
+
// RUN: FileCheck --check-prefix=CHECK-G %s < %t
//
// CHECK-G: @_ZTV1GIiE = weak_odr constant
diff --git a/test/CodeGenCXX/vtt-layout.cpp b/test/CodeGenCXX/vtt-layout.cpp
index d7d4227ed01d..814adf0e94ff 100644
--- a/test/CodeGenCXX/vtt-layout.cpp
+++ b/test/CodeGenCXX/vtt-layout.cpp
@@ -59,6 +59,6 @@ namespace Test4 {
}
// CHECK: @_ZTTN5Test11BE = constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ([4 x i8*]* @_ZTVN5Test11BE, i64 0, i64 3) to i8*)]
-// CHECK: @_ZTTN5Test41DE = weak_odr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 10) to i8*)] ; <[19 x i8*]*> [#uses=4]
-// CHECK: @_ZTTN5Test31DE = weak_odr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 6) to i8*)] ; <[13 x i8*]*> [#uses=3]
-// CHECK: @_ZTTN5Test21CE = weak_odr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)] ; <[2 x i8*]*> [#uses=0]
+// CHECK: @_ZTTN5Test41DE = weak_odr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE0_NS_2C1E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 12) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTCN5Test41DE16_NS_2C2E, i64 0, i64 18) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 17) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 20) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([25 x i8*]* @_ZTVN5Test41DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test41DE40_NS_2V1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 7) to i8*), i8* bitcast (i8** getelementptr inbounds ([11 x i8*]* @_ZTCN5Test41DE72_NS_2V2E, i64 0, i64 10) to i8*)]
+// CHECK: @_ZTTN5Test31DE = weak_odr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 5) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE0_NS_2C1E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 6) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 10) to i8*), i8* bitcast (i8** getelementptr inbounds ([14 x i8*]* @_ZTCN5Test31DE16_NS_2C2E, i64 0, i64 13) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 15) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 0, i64 11) to i8*), i8* bitcast (i8** getelementptr inbounds ([19 x i8*]* @_ZTVN5Test31DE, i64 1, i64 0) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 3) to i8*), i8* bitcast (i8** getelementptr inbounds ([7 x i8*]* @_ZTCN5Test31DE64_NS_2V2E, i64 0, i64 6) to i8*)]
+// CHECK: @_ZTTN5Test21CE = weak_odr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*), i8* bitcast (i8** getelementptr inbounds ([5 x i8*]* @_ZTVN5Test21CE, i64 0, i64 4) to i8*)]
diff --git a/test/CodeGenCXX/x86_32-arguments.cpp b/test/CodeGenCXX/x86_32-arguments.cpp
index 023b7297c7d7..e94e2cade59c 100644
--- a/test/CodeGenCXX/x86_32-arguments.cpp
+++ b/test/CodeGenCXX/x86_32-arguments.cpp
@@ -89,7 +89,7 @@ struct s5 { s5(); int &x; };
s5 f5() { return s5(); }
// CHECK: define i32 @_Z4f6_0M2s6i(i32 %a)
-// CHECK: define i64 @_Z4f6_1M2s6FivE(%{{.*}} byval %a)
+// CHECK: define i64 @_Z4f6_1M2s6FivE(%{{.*}} byval)
// FIXME: It would be nice to avoid byval on the previous case.
struct s6 {};
typedef int s6::* s6_mdp;
diff --git a/test/CodeGenCXX/x86_64-arguments.cpp b/test/CodeGenCXX/x86_64-arguments.cpp
index df0c78ad941e..e7316989feaa 100644
--- a/test/CodeGenCXX/x86_64-arguments.cpp
+++ b/test/CodeGenCXX/x86_64-arguments.cpp
@@ -19,11 +19,12 @@ struct f2_s1 : public f2_s0 { char d;};
void f2(f2_s1 a0) { }
// PR5831
+// CHECK: define void @_Z2f34s3_1(i64 %x.coerce)
struct s3_0 {};
struct s3_1 { struct s3_0 a; long b; };
void f3(struct s3_1 x) {}
-// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a.coerce)
+// CHECK: define i64 @_Z4f4_0M2s4i(i64 %a)
// CHECK: define {{.*}} @_Z4f4_1M2s4FivE(i64 %a.coerce0, i64 %a.coerce1)
struct s4 {};
typedef int s4::* s4_mdp;
@@ -44,4 +45,73 @@ void foo() {
// CHECK: call void @_ZN6PR752310AddKeywordENS_9StringRefEi(i8* {{.*}}, i32 4)
AddKeyword(StringRef(), 4);
}
-} \ No newline at end of file
+}
+
+namespace PR7742 { // Also rdar://8250764
+ struct s2 {
+ float a[2];
+ };
+
+ struct c2 : public s2 {};
+
+ // CHECK: define double @_ZN6PR77423fooEPNS_2c2E(%"struct.PR7742::c2"* %P)
+ c2 foo(c2 *P) {
+ }
+
+}
+
+namespace PR5179 {
+ struct B {};
+
+ struct B1 : B {
+ int* pa;
+ };
+
+ struct B2 : B {
+ B1 b1;
+ };
+
+ // CHECK: define i8* @_ZN6PR51793barENS_2B2E(i32* %b2.coerce)
+ const void *bar(B2 b2) {
+ return b2.b1.pa;
+ }
+}
+
+namespace test5 {
+ struct Xbase { };
+ struct Empty { };
+ struct Y;
+ struct X : public Xbase {
+ Empty empty;
+ Y f();
+ };
+ struct Y : public X {
+ Empty empty;
+ };
+ X getX();
+ int takeY(const Y&, int y);
+ void g() {
+ // rdar://8340348 - The temporary for the X object needs to have a defined
+ // address when passed into X::f as 'this'.
+ takeY(getX().f(), 42);
+ }
+ // CHECK: void @_ZN5test51gEv()
+ // CHECK: alloca %"struct.test5::Y"
+ // CHECK: alloca %"struct.test5::X"
+ // CHECK: alloca %"struct.test5::Y"
+}
+
+
+// rdar://8360877
+namespace test6 {
+ struct outer {
+ int x;
+ struct epsilon_matcher {} e;
+ int f;
+ };
+
+ int test(outer x) {
+ return x.x + x.f;
+ }
+ // CHECK: define i32 @_ZN5test64testENS_5outerE(i64 %x.coerce0, i32 %x.coerce1)
+}
diff --git a/test/CodeGenObjC/bitfield-access.m b/test/CodeGenObjC/bitfield-access.m
new file mode 100644
index 000000000000..16b0001ddfda
--- /dev/null
+++ b/test/CodeGenObjC/bitfield-access.m
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -o %t %s
+// RUN: FileCheck -check-prefix=CHECK-I386 < %t %s
+// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -emit-llvm -o %t %s
+// RUN: FileCheck -check-prefix=CHECK-ARM < %t %s
+
+@interface I0 {
+@public
+ unsigned x:15;
+ unsigned y: 1;
+}
+@end
+
+// Check that we don't try to use an i32 load here, which would reach beyond the
+// end of the structure.
+//
+// CHECK-I386: define i32 @f0(
+// CHECK-I386: [[t0_0:%.*]] = load i16* {{.*}}, align 1
+// CHECK-I386: lshr i16 [[t0_0]], 7
+// CHECK-I386: }
+int f0(I0 *a) {
+ return a->y;
+}
+
+// Check that we can handled straddled loads.
+//
+// CHECK-ARM: define i32 @f1(
+// CHECK-ARM: [[t1_ptr:%.*]] = getelementptr
+// CHECK-ARM: [[t1_base:%.*]] = bitcast i8* [[t1_ptr]] to i32*
+// CHECK-ARM: [[t1_0:%.*]] = load i32* [[t1_base]], align 1
+// CHECK-ARM: lshr i32 [[t1_0]], 1
+// CHECK-ARM: [[t1_base_2_cast:%.*]] = bitcast i32* %{{.*}} to i8*
+// CHECK-ARM: [[t1_base_2:%.*]] = getelementptr i8* [[t1_base_2_cast]]
+// CHECK-ARM: [[t1_1:%.*]] = load i8* [[t1_base_2]], align 1
+// CHECK-ARM: and i8 [[t1_1:%.*]], 1
+// CHECK-ARM: }
+@interface I1 {
+@public
+ unsigned x: 1;
+ unsigned y:32;
+}
+@end
+
+int f1(I1 *a) { return a->y; }
diff --git a/test/CodeGenObjC/block-var-layout.m b/test/CodeGenObjC/block-var-layout.m
new file mode 100644
index 000000000000..bf9ba8df75e2
--- /dev/null
+++ b/test/CodeGenObjC/block-var-layout.m
@@ -0,0 +1,123 @@
+// RUN: %clang_cc1 -fblocks -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: %clang_cc1 -x objective-c++ -fblocks -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
+
+struct S {
+ int i1;
+ id o1;
+ struct V {
+ int i2;
+ id o2;
+ } v1;
+ int i3;
+ id o3;
+};
+
+__weak id wid;
+void x(id y) {}
+void y(int a) {}
+
+void f() {
+ __block int byref_int = 0;
+ char ch = 'a';
+ char ch1 = 'b';
+ char ch2 = 'c';
+ short sh = 2;
+ const id bar = (id)0;
+ id baz = 0;
+ __strong void *strong_void_sta;
+ __block id byref_bab = (id)0;
+ __block void *bl_var1;
+ int i; double dob;
+
+ void (^b)() = ^{
+ byref_int = sh + ch+ch1+ch2 ;
+ x(bar);
+ x(baz);
+ x((id)strong_void_sta);
+ x(byref_bab);
+ };
+ b();
+
+// Test 2
+ void (^c)() = ^{
+ byref_int = sh + ch+ch1+ch2 ;
+ x(bar);
+ x(baz);
+ x((id)strong_void_sta);
+ x(wid);
+ bl_var1 = 0;
+ x(byref_bab);
+ };
+ c();
+
+// Test 3
+void (^d)() = ^{
+ byref_int = sh + ch+ch1+ch2 ;
+ x(bar);
+ x(baz);
+ x(wid);
+ bl_var1 = 0;
+ y(i + dob);
+ x(byref_bab);
+ };
+ d();
+
+// Test4
+ struct S s2;
+ void (^e)() = ^{
+ x(s2.o1);
+ };
+ e();
+}
+
+// Test 5 (unions/structs and their nesting):
+void Test5() {
+struct S5 {
+ int i1;
+ id o1;
+ struct V {
+ int i2;
+ id o2;
+ } v1;
+ int i3;
+ union UI {
+ void * i1;
+ id o1;
+ int i3;
+ id o3;
+ }ui;
+};
+
+union U {
+ void * i1;
+ id o1;
+ int i3;
+ id o3;
+}ui;
+
+struct S5 s2;
+union U u2;
+void (^c)() = ^{
+ x(s2.ui.o1);
+ x(u2.o1);
+};
+c();
+
+}
+
+// CHECK-LP64: L_OBJC_CLASS_NAME_:
+// CHECK-LP64-NEXT: .asciz "A\024"
+
+// CHECK-LP64: L_OBJC_CLASS_NAME_1:
+// CHECK-LP64-NEXT: .asciz "A\025"
+
+// CHECK-LP64: L_OBJC_CLASS_NAME_6:
+// CHECK-LP64-NEXT: .asciz "A\023!"
+
+// CHECK-LP64: L_OBJC_CLASS_NAME_11:
+// CHECK-LP64-NEXT: .asciz "Q\021\021"
+
+// CHECK-LP64: L_OBJC_CLASS_NAME_14:
+// CHECK-LP64-NEXT: .asciz "Q\021\022p"
diff --git a/test/CodeGenObjC/debug-info-linkagename.m b/test/CodeGenObjC/debug-info-linkagename.m
index 2b10e2bd67b8..b606e5d5dfca 100644
--- a/test/CodeGenObjC/debug-info-linkagename.m
+++ b/test/CodeGenObjC/debug-info-linkagename.m
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -g -S -o %t %s
-// RUN: not grep 001 %t
+// RUN: not grep "001-[F bar" %t
+// Linkage name should not use 001 prefix in debug info.
@interface F
-(int) bar;
diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m
index 5be695932b0f..b431e3712473 100644
--- a/test/CodeGenObjC/exceptions.m
+++ b/test/CodeGenObjC/exceptions.m
@@ -25,15 +25,111 @@ void f1() {
// CHECK-NEXT: icmp
// CHECK-NEXT: br i1
@try {
- // CHECK: call void @foo()
+ // CHECK: call void asm sideeffect "", "*m"
+ // CHECK-NEXT: call void @foo()
foo();
- // CHECK: call void @objc_exception_try_exit
+ // CHECK-NEXT: call void @objc_exception_try_exit
// CHECK-NEXT: ret void
- // CHECK: call i8* @objc_exception_extract
+ // CHECK: call void asm sideeffect "", "=*m"
// CHECK-NEXT: ret void
} @finally {
break;
}
}
}
+
+// Test that modifications to local variables are respected under
+// optimization. rdar://problem/8160285
+
+// CHECK: define i32 @f2()
+int f2() {
+ extern void foo(void);
+
+ // CHECK: [[X:%.*]] = alloca i32
+ // CHECK: store i32 5, i32* [[X]]
+ int x = 0;
+ x += 5;
+
+ // CHECK: [[SETJMP:%.*]] = call i32 @_setjmp
+ // CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
+ // CHECK-NEXT: br i1 [[CAUGHT]]
+ @try {
+ // If the optimizers ever figure out how to make this store 6,
+ // that's okay.
+ // CHECK: [[T1:%.*]] = load i32* [[X]]
+ // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
+ // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
+ x++;
+ // CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
+ // CHECK-NEXT: call void @foo()
+ // CHECK-NEXT: call void @objc_exception_try_exit
+ // CHECK-NEXT: [[T:%.*]] = load i32* [[X]]
+ // CHECK-NEXT: ret i32 [[T]]
+ foo();
+ } @catch (id) {
+ // Landing pad. Note that we elide the re-enter.
+ // CHECK: call void asm sideeffect "", "=*m,=*m"(i32* [[X]]
+ // CHECK-NEXT: call i8* @objc_exception_extract
+ // CHECK-NEXT: [[T1:%.*]] = load i32* [[X]]
+ // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], -1
+
+ // This store is dead.
+ // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
+
+ // CHECK-NEXT: ret i32 [[T2]]
+ x--;
+ }
+ return x;
+}
+
+// Test that the cleanup destination is saved when entering a finally
+// block. rdar://problem/8293901
+// CHECK: define void @f3()
+void f3() {
+ extern void f3_helper(int, int*);
+
+ // CHECK: [[X:%.*]] = alloca i32
+ // CHECK: store i32 0, i32* [[X]]
+ int x = 0;
+
+ // CHECK: call void @objc_exception_try_enter(
+ // CHECK: call i32 @_setjmp
+ // CHECK-NEXT: icmp eq
+ // CHECK-NEXT: br i1
+
+ @try {
+ // CHECK: call void @f3_helper(i32 0, i32* [[X]])
+ // CHECK: call void @objc_exception_try_exit(
+ f3_helper(0, &x);
+ } @finally {
+ // CHECK: [[DEST1:%.*]] = phi i32 [ 0, {{%.*}} ], [ 3, {{%.*}} ]
+ // CHECK: call void @objc_exception_try_enter
+ // CHECK: call i32 @_setjmp
+ @try {
+ // CHECK: call void @f3_helper(i32 1, i32* [[X]])
+ // CHECK: call void @objc_exception_try_exit(
+ f3_helper(1, &x);
+ } @finally {
+ // CHECK: [[DEST2:%.*]] = phi i32 [ 0, {{%.*}} ], [ 5, {{%.*}} ]
+ // CHECK: call void @f3_helper(i32 2, i32* [[X]])
+ f3_helper(2, &x);
+
+ // This loop is large enough to dissuade the optimizer from just
+ // duplicating the finally block.
+ while (x) f3_helper(3, &x);
+
+ // This is a switch or maybe some chained branches, but relying
+ // on a specific result from the optimizer is really unstable.
+ // CHECK: [[DEST2]]
+ }
+
+ // This is a switch or maybe some chained branches, but relying
+ // on a specific result from the optimizer is really unstable.
+ // CHECK: [[DEST1]]
+ }
+
+ // CHECK: call void @f3_helper(i32 4, i32* [[X]])
+ // CHECK-NEXT: ret void
+ f3_helper(4, &x);
+}
diff --git a/test/CodeGenObjC/for-in.m b/test/CodeGenObjC/for-in.m
index 354ff32c0ef9..7e6098a7eb57 100644
--- a/test/CodeGenObjC/for-in.m
+++ b/test/CodeGenObjC/for-in.m
@@ -23,7 +23,7 @@ void t0() {
p("array.length: %d\n", [array count]);
unsigned index = 0;
- for (NSString *i in array) {
+ for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}}
p("element %d: %s\n", index++, [i cString]);
}
}
@@ -33,7 +33,7 @@ void t1() {
p("array.length: %d\n", [array count]);
unsigned index = 0;
- for (NSString *i in array) {
+ for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}}
index++;
if (index == 10)
continue;
diff --git a/test/CodeGenObjC/fpret.m b/test/CodeGenObjC/fpret.m
new file mode 100644
index 000000000000..48848885c1f6
--- /dev/null
+++ b/test/CodeGenObjC/fpret.m
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-X86_32 %s
+//
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-X86_64 %s
+//
+// RUN: %clang_cc1 -triple armv7-apple-darwin10 -emit-llvm -target-abi apcs-gnu -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-ARMV7 %s
+
+@interface A
+-(float) floatValue;
+-(double) doubleValue;
+-(long double) longDoubleValue;
+@end
+
+
+// CHECK-X86_32: define void @t0()
+// CHECK-X86_32: call float bitcast {{.*}} @objc_msgSend_fpret to
+// CHECK-X86_32: call double {{.*}} @objc_msgSend_fpret(
+// CHECK-X86_32: call x86_fp80 bitcast {{.*}} @objc_msgSend_fpret to
+// CHECK-X86_32: }
+//
+// CHECK-X86_64: define void @t0()
+// CHECK-X86_64: call float bitcast {{.*}} @objc_msgSend to
+// CHECK-X86_64: call double bitcast {{.*}} @objc_msgSend to
+// CHECK-X86_64: call x86_fp80 bitcast {{.*}} @objc_msgSend_fpret to
+// CHECK-X86_64: }
+//
+// CHECK-ARMV7: define void @t0()
+// CHECK-ARMV7: call float bitcast {{.*}} @objc_msgSend to
+// CHECK-ARMV7: call double bitcast {{.*}} @objc_msgSend to
+// CHECK-ARMV7: call double bitcast {{.*}} @objc_msgSend to
+// CHECK-ARMV7: }
+void t0() {
+ [(A*)0 floatValue];
+ [(A*)0 doubleValue];
+ [(A*)0 longDoubleValue];
+}
diff --git a/test/CodeGenObjC/gnu-exceptions.m b/test/CodeGenObjC/gnu-exceptions.m
new file mode 100644
index 000000000000..6790a2993750
--- /dev/null
+++ b/test/CodeGenObjC/gnu-exceptions.m
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fgnu-runtime -o - %s | FileCheck %s
+
+void opaque(void);
+void log(int i);
+
+@class C;
+
+// CHECK: define void @test0() {
+void test0() {
+ @try {
+ // CHECK: invoke void @opaque()
+ opaque();
+
+ // CHECK: call void @log(i32 1)
+
+ } @catch (C *c) {
+ // CHECK: call i8* @llvm.eh.exception()
+ // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gnu_objc_personality_v0
+ // CHECK: br i1
+
+ // CHECK: call void @log(i32 0)
+
+ // CHECK: call void @objc_exception_throw
+
+ log(0);
+ }
+
+ log(1);
+}
diff --git a/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m
new file mode 100644
index 000000000000..b474caa7a48a
--- /dev/null
+++ b/test/CodeGenObjC/ivar-layout-nonfragile-abi2.m
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi2 -emit-llvm -o %t %s
+// rdar: // 7824380
+
+@interface Super {
+ int ivar_super_a : 5;
+}
+@end
+
+@interface A : Super {
+@public
+ int ivar_a : 5;
+}
+@end
+
+int f0(A *a) {
+ return a->ivar_a;
+}
+
+@interface A () {
+@public
+ int ivar_ext_a : 5;
+ int ivar_ext_b : 5;
+}@end
+
+int f1(A *a) {
+ return a->ivar_ext_a + a->ivar_a;
+}
+
+@interface A () {
+@public
+ int ivar_ext2_a : 5;
+ int ivar_ext2_b : 5;
+}@end
+
+int f2(A* a) {
+ return a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a;
+}
+
+@implementation A {
+@public
+ int ivar_b : 5;
+ int ivar_c : 5;
+ int ivar_d : 5;
+}
+@end
+
+int f3(A *a) {
+ return a->ivar_d + a->ivar_ext2_a + a->ivar_ext_a + a->ivar_a;
+}
+
diff --git a/test/CodeGenObjC/property-dbg.m b/test/CodeGenObjC/property-dbg.m
index 5bbb04644e05..42ab6110541d 100644
--- a/test/CodeGenObjC/property-dbg.m
+++ b/test/CodeGenObjC/property-dbg.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -S -g -masm-verbose -x objective-c < %s | grep setI | grep DW_AT_name
+// RUN: %clang_cc1 -S -g -masm-verbose -x objective-c < %s | grep DW_AT_name
@interface Foo {
int i;
}
diff --git a/test/CodeGenObjC/return-objc-object.mm b/test/CodeGenObjC/return-objc-object.mm
new file mode 100644
index 000000000000..95cce23a8682
--- /dev/null
+++ b/test/CodeGenObjC/return-objc-object.mm
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | FileCheck %s
+
+@protocol P1 @end
+@interface NSOperationQueue
+{
+ char ch[64];
+ double d;
+}
+@end
+
+NSOperationQueue &f();
+NSOperationQueue<P1> &f1();
+
+void call_once() {
+ f();
+ f1();
+}
+// CHECK: call %0* @_Z1fv()
+// CHECK: call %0* @_Z2f1v()
diff --git a/test/CodeGenObjC/super-dotsyntax-struct-property.m b/test/CodeGenObjC/super-dotsyntax-struct-property.m
new file mode 100644
index 000000000000..aac4c1de06a3
--- /dev/null
+++ b/test/CodeGenObjC/super-dotsyntax-struct-property.m
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -emit-llvm %s -o - | FileCheck %s
+// rdar: // 8203426
+
+
+typedef double CGFloat;
+struct CGPoint {
+ CGFloat x;
+ CGFloat y;
+};
+typedef struct CGPoint CGPoint;
+
+
+
+struct CGSize {
+ CGFloat width;
+ CGFloat height;
+};
+typedef struct CGSize CGSize;
+
+
+struct CGRect {
+ CGPoint origin;
+ CGSize size;
+};
+typedef struct CGRect CGRect;
+
+@interface UIView {
+}
+@property CGRect frame;
+@end
+
+@interface crashclass : UIView {
+
+}
+
+@end
+
+@implementation crashclass
+- (void)setFrame:(CGRect)frame
+{
+ super.frame = frame;
+ [super setFrame:frame];
+}
+
+@end
+// CHECK-NOT: declare void @objc_msgSendSuper2_stret
+// CHECK: declare i8* @objc_msgSendSuper2
diff --git a/test/CodeGenObjC/synchronized.m b/test/CodeGenObjC/synchronized.m
index 1af82345e0bc..2a809063fe03 100644
--- a/test/CodeGenObjC/synchronized.m
+++ b/test/CodeGenObjC/synchronized.m
@@ -1,6 +1,4 @@
-// RUN: %clang_cc1 -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
+// RUN: %clang_cc1 -emit-llvm -triple=i686-apple-darwin9 -o - %s -O2 | FileCheck %s
@interface MyClass
{
@@ -10,31 +8,71 @@
@implementation MyClass
+// CHECK: define internal void @"\01-[MyClass method]"
- (void)method
{
- @synchronized(self)
- {
- }
+ // CHECK: call void @objc_sync_enter
+ // CHECK: call void @objc_exception_try_enter
+ // CHECK: call i32 @_setjmp
+ @synchronized(self) {
+ }
}
@end
+// CHECK: define void @foo(
void foo(id a) {
+ // CHECK: [[A:%.*]] = alloca i8*
+ // CHECK: [[SYNC:%.*]] = alloca i8*
+
+ // CHECK: store i8* [[AVAL:%.*]], i8** [[A]]
+ // CHECK-NEXT: call void @objc_sync_enter(i8* [[AVAL]])
+ // CHECK-NEXT: store i8* [[AVAL]], i8** [[SYNC]]
+ // CHECK-NEXT: call void @objc_exception_try_enter
+ // CHECK: call i32 @_setjmp
@synchronized(a) {
+ // This is unreachable, but the optimizers can't know that.
+ // CHECK: call void asm sideeffect "", "=*m,=*m,=*m"(i8** [[A]], i8** [[SYNC]]
+ // CHECK: call void @objc_sync_exit
+ // CHECK: call i8* @objc_exception_extract
+ // CHECK: call void @objc_exception_throw
+ // CHECK: unreachable
+
+ // CHECK: call void @objc_exception_try_exit
+ // CHECK: [[T:%.*]] = load i8** [[SYNC]]
+ // CHECK-NEXT: call void @objc_sync_exit
+ // CHECK: ret void
return;
}
+
}
+// CHECK: define i32 @f0(
int f0(id a) {
+ // TODO: we can optimize the ret to a constant if we can figure out
+ // either that x isn't stored to within the synchronized block or
+ // that the synchronized block can't longjmp.
+
+ // CHECK: [[X:%.*]] = alloca i32
+ // CHECK: store i32 1, i32* [[X]]
int x = 0;
@synchronized((x++, a)) {
}
- return x; // ret i32 1
+
+ // CHECK: [[T:%.*]] = load i32* [[X]]
+ // CHECK: ret i32 [[T]]
+ return x;
}
+// CHECK: define void @f1(
void f1(id a) {
- // The trick here is that the return shouldn't go through clean up,
- // but there isn't a simple way to check this property.
+ // Check that the return doesn't go through the cleanup.
+ extern void opaque(void);
+ opaque();
+
+ // CHECK: call void @opaque()
+ // CHECK-NEXT: ret void
+
@synchronized(({ return; }), a) {
return;
}
diff --git a/test/CodeGenObjC/unwind-fn.m b/test/CodeGenObjC/unwind-fn.m
index 48217f07f974..5bfc7dce31a2 100644
--- a/test/CodeGenObjC/unwind-fn.m
+++ b/test/CodeGenObjC/unwind-fn.m
@@ -2,7 +2,7 @@
// RUN: %clang_cc1 -fsjlj-exceptions -fobjc-nonfragile-abi -fexceptions -emit-llvm -o - %s | FileCheck --check-prefix=SJLJ_EH %s
// DEFAULT_EH: declare void @_Unwind_Resume_or_Rethrow(i8*)
-// SJLJ_EH: declare void @_Unwind_SjLj_Resume(i8*)
+// SJLJ_EH: declare void @_Unwind_SjLj_Resume_or_Rethrow(i8*)
void f1(), f2();
void f0() {
diff --git a/test/CodeGenObjC/x86_64-struct-return-gc.m b/test/CodeGenObjC/x86_64-struct-return-gc.m
index c62a33f2d162..8022d5903ecf 100644
--- a/test/CodeGenObjC/x86_64-struct-return-gc.m
+++ b/test/CodeGenObjC/x86_64-struct-return-gc.m
@@ -9,7 +9,7 @@ struct Coerce coerce_func(void);
void Coerce_test(void) {
struct Coerce c;
- // CHECK: call i64 @coerce_func
+ // CHECK: call i8* @coerce_func
// CHECK: call i8* @objc_memmove_collectable(
c = coerce_func();
}
diff --git a/test/CodeGenObjCXX/exceptions.mm b/test/CodeGenObjCXX/exceptions.mm
new file mode 100644
index 000000000000..00de88c15220
--- /dev/null
+++ b/test/CodeGenObjCXX/exceptions.mm
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fexceptions -o - %s | FileCheck %s
+
+@interface OCType @end
+void opaque();
+
+namespace test0 {
+
+ // CHECK: define void @_ZN5test03fooEv
+ void foo() {
+ try {
+ // CHECK: invoke void @_Z6opaquev
+ opaque();
+ } catch (OCType *T) {
+ // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__objc_personality_v0 {{.*}} @"OBJC_EHTYPE_$_OCType"
+ }
+ }
+}
diff --git a/test/CodeGenObjCXX/property-objects.mm b/test/CodeGenObjCXX/property-objects.mm
index 662dacc55d7d..724cf6826822 100644
--- a/test/CodeGenObjCXX/property-objects.mm
+++ b/test/CodeGenObjCXX/property-objects.mm
@@ -25,6 +25,8 @@ struct CGRect {
- (void)setFrame:(CGRect)frameRect;
- (CGRect)frame;
- (void) initWithOwner;
+- (struct CGRect)extent;
+- (void)dealloc;
@end
@implementation I
@@ -40,6 +42,12 @@ struct CGRect {
labelLayerFrame = self.bounds;
_labelLayer.frame = labelLayerFrame;
}
+// rdar://8366604
+- (void)dealloc
+ {
+ CGRect cgrect = self.extent;
+ }
+- (struct CGRect)extent {return bounds;}
@end
int main() {
diff --git a/test/CodeGenObjCXX/references.mm b/test/CodeGenObjCXX/references.mm
index c2232e2e02f8..8875fd624074 100644
--- a/test/CodeGenObjCXX/references.mm
+++ b/test/CodeGenObjCXX/references.mm
@@ -19,7 +19,27 @@ struct A { ~A(); };
// CHECK: define void @_Z1fP1B
// CHECK: objc_msgSend to
+// CHECK-NOT: call void @_ZN1AD1Ev
// CHECK: ret void
void f(B* b) {
(void)[b getA];
}
+
+// PR7741
+@protocol P1 @end
+@protocol P2 @end
+@protocol P3 @end
+@interface foo<P1> {} @end
+@interface bar : foo <P1, P2> {} @end
+typedef bar baz;
+void f5(foo&);
+void f5b(foo<P1>&);
+void f5c(foo<P2>&);
+void f5d(foo<P3>&);
+void f6(baz* x) {
+ f5(*x);
+ f5b(*x);
+ f5c(*x);
+ f5d(*x);
+ (void)((foo&)*x);
+}
diff --git a/test/CodeGenObjCXX/rtti.mm b/test/CodeGenObjCXX/rtti.mm
new file mode 100644
index 000000000000..27d24cb68ee5
--- /dev/null
+++ b/test/CodeGenObjCXX/rtti.mm
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// PR7864. This all follows GCC's lead.
+
+namespace std { class type_info; }
+
+// CHECK: @_ZTI1A = weak_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A
+@interface A
+@end
+
+// CHECK: @_ZTI1B = weak_odr constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A
+@interface B : A
+@end
+
+// CHECK: @_ZTIP1B = weak_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP1B{{.*}}), i32 0, {{.*}}@_ZTI1B
+// CHECK: @_ZTI11objc_object = weak_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object
+// CHECK: @_ZTIP11objc_object = weak_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP11objc_object{{.*}}@_ZTI11objc_object
+// CHECK: @_ZTI10objc_class = weak_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class
+// CHECK: @_ZTIP10objc_class = weak_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP10objc_class{{.*}}@_ZTI10objc_class
+
+@protocol P;
+
+int main() {
+ // CHECK: store {{.*}} @_ZTIP1B
+ // CHECK: store {{.*}} @_ZTI1B
+ const std::type_info &t1 = typeid(B*);
+ const std::type_info &t2 = typeid(B);
+
+ // CHECK: store {{.*}} @_ZTIP11objc_object
+ // CHECK: store {{.*}} @_ZTI11objc_object
+ id i = 0;
+ const std::type_info &t3 = typeid(i);
+ const std::type_info &t4 = typeid(*i);
+
+ // CHECK: store {{.*}} @_ZTIP10objc_class
+ // CHECK: store {{.*}} @_ZTI10objc_class
+ Class c = 0;
+ const std::type_info &t5 = typeid(c);
+ const std::type_info &t6 = typeid(*c);
+
+ // CHECK: store {{.*}} @_ZTIP11objc_object
+ // CHECK: store {{.*}} @_ZTI11objc_object
+ id<P> i2 = 0;
+ const std::type_info &t7 = typeid(i2);
+ const std::type_info &t8 = typeid(*i2);
+
+ // CHECK: store {{.*}} @_ZTIP10objc_class
+ // CHECK: store {{.*}} @_ZTI10objc_class
+ Class<P> c2 = 0;
+ const std::type_info &t9 = typeid(c2);
+ const std::type_info &t10 = typeid(*c2);
+}
diff --git a/test/Coverage/parse-callbacks.c b/test/Coverage/parse-callbacks.c
deleted file mode 100644
index 02f3a8374bc7..000000000000
--- a/test/Coverage/parse-callbacks.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang_cc1 -parse-noop %s
-// RUN: %clang_cc1 -parse-print-callbacks %s
-
-#include "c-language-features.inc"
diff --git a/test/Coverage/parse-callbacks.m b/test/Coverage/parse-callbacks.m
deleted file mode 100644
index f023d3d0648b..000000000000
--- a/test/Coverage/parse-callbacks.m
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang_cc1 -parse-noop %s
-// RUN: %clang_cc1 -parse-print-callbacks %s
-
-#include "objc-language-features.inc"
diff --git a/test/Driver/at_file.c b/test/Driver/at_file.c
new file mode 100644
index 000000000000..4ad2a5fde3d6
--- /dev/null
+++ b/test/Driver/at_file.c
@@ -0,0 +1,30 @@
+// RUN: %clang -E %s @%s.args -o %t.log
+// RUN: FileCheck --input-file=%t.log %s
+
+// CHECK: bar1
+// CHECK-NEXT: bar2 zed2
+// CHECK-NEXT: bar3 zed3
+// CHECK-NEXT: bar4 zed4
+// CHECK-NEXT: bar5 zed5
+// CHECK-NEXT: 'bar6 zed6'
+// CHECK-NEXT: "bar7 zed7"
+// CHECK-NEXT: foo8bar8zed8
+// CHECK-NEXT: foo9'bar9'zed9
+// CHECK-NEXT: foo10"bar10"zed10
+// CHECK: bar
+// CHECK: zed12
+
+foo1
+foo2
+foo3
+foo4
+foo5
+foo6
+foo7
+foo8
+foo9
+foo10
+#ifdef foo11
+bar
+#endif
+foo12
diff --git a/test/Driver/at_file.c.args b/test/Driver/at_file.c.args
new file mode 100644
index 000000000000..9a2b4ee93bd3
--- /dev/null
+++ b/test/Driver/at_file.c.args
@@ -0,0 +1,11 @@
+-Dfoo1=bar1 -Dfoo2="bar2 zed2"
+-Dfoo3='bar3 zed3'
+"-Dfoo4=bar4 zed4"
+'-Dfoo5=bar5 zed5'
+-Dfoo6="'bar6 zed6'"
+-Dfoo7='"bar7 zed7"'
+-Dfoo8=foo8"bar8"zed8
+-Dfoo9=foo9\'bar9\'zed9
+-Dfoo10=foo10\"bar10\"zed10
+-D foo11
+-Dfoo12=zed12\
diff --git a/test/Driver/bindings.c b/test/Driver/bindings.c
index e7ec0c597d4b..b825420b7151 100644
--- a/test/Driver/bindings.c
+++ b/test/Driver/bindings.c
@@ -15,12 +15,6 @@
// 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
diff --git a/test/Driver/cxx-pth.cpp b/test/Driver/cxx-pth.cpp
deleted file mode 100644
index 97afb5ebe8a8..000000000000
--- a/test/Driver/cxx-pth.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// Test forced PTH for CXX support.
-
-// RUN: %clangxx -x c++-header %s -### 2> %t.log
-// RUN: FileCheck -check-prefix EMIT -input-file %t.log %s
-
-// EMIT: "{{.*}}/clang{{.*}}" {{.*}} "-emit-pth" "{{.*}}.cpp.gch" "-x" "c++-header" "{{.*}}.cpp"
-
-// RUN: touch %t.h.gch
-// RUN: %clangxx -E -include %t.h %s -### 2> %t.log
-// RUN: FileCheck -check-prefix USE -input-file %t.log %s
-
-// USE: "{{.*}}/clang{{.*}}" {{.*}}"-include-pth" "{{.*}}.h.gch" {{.*}}"-x" "c++" "{{.*}}.cpp"
diff --git a/test/Driver/darwin-as.c b/test/Driver/darwin-as.c
index 6410df085637..7d4cdbfcd379 100644
--- a/test/Driver/darwin-as.c
+++ b/test/Driver/darwin-as.c
@@ -1,10 +1,16 @@
// 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: FileCheck -check-prefix=STATIC-64 --input-file %t %s
-
+//
// CHECK-STATIC-64: as{{(.exe)?}}" "-arch" "x86_64" "-force_cpusubtype_ALL" "-o"
+// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -### \
+// RUN: -arch armv6 -x assembler -c %s 2>%t
+// RUN: FileCheck -check-prefix=ARMV6 --input-file %t %s
+//
+// CHECK-ARMV6: as{{(.exe)?}}" "-arch" "armv6" "-o"
+
diff --git a/test/Driver/darwin-cc.c b/test/Driver/darwin-cc.c
index 3cb9df6ceac6..b068bb4e3fd4 100644
--- a/test/Driver/darwin-cc.c
+++ b/test/Driver/darwin-cc.c
@@ -1,5 +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" "-FARG1" "-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: grep ' ".*cc1" "-E" "-nostdinc" "-v" "-I" "ARG0" "-FARG1" "-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" "-m32" "-mkernel" "-mtune=core2" "-mmacosx-version-min=10.6.0" "-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" "-m32" "-mkernel" "-mtune=core2" "-mmacosx-version-min=10.6.0" "-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
diff --git a/test/Driver/darwin-debug-flags.c b/test/Driver/darwin-debug-flags.c
index 6f245271d582..3394e4e8079c 100644
--- a/test/Driver/darwin-debug-flags.c
+++ b/test/Driver/darwin-debug-flags.c
@@ -2,8 +2,8 @@
// <rdar://problem/7256886>
// CHECK: !1 = metadata !{
-// CHECK: -mmacosx-version-min=10.5.0
// CHECK: -g -Os
+// CHECK: -mmacosx-version-min=10.5.0
// CHECK: [ DW_TAG_compile_unit ]
int x;
diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c
index 448446885a1b..074957d625a1 100644
--- a/test/Driver/darwin-ld.c
+++ b/test/Driver/darwin-ld.c
@@ -3,20 +3,6 @@
// 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
@@ -82,3 +68,26 @@
//
// LINK_EXPLICIT_NO_PIE: ld"
// LINK_EXPLICIT_NO_PIE: "-no_pie"
+
+// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -### %t.o \
+// RUN: -mlinker-version=100 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_NEWER_DEMANGLE %s < %t.log
+//
+// LINK_NEWER_DEMANGLE: ld"
+// LINK_NEWER_DEMANGLE: "-demangle"
+
+// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -### %t.o \
+// RUN: -mlinker-version=100 -Wl,--no-demangle 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_NEWER_NODEMANGLE %s < %t.log
+//
+// LINK_NEWER_NODEMANGLE: ld"
+// LINK_NEWER_NODEMANGLE-NOT: "-demangle"
+// LINK_NEWER_NODEMANGLE: "-lSystem"
+
+// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -### %t.o \
+// RUN: -mlinker-version=95 2> %t.log
+// RUN: FileCheck -check-prefix=LINK_OLDER_NODEMANGLE %s < %t.log
+//
+// LINK_OLDER_NODEMANGLE: ld"
+// LINK_OLDER_NODEMANGLE-NOT: "-demangle"
+// LINK_OLDER_NODEMANGLE: "-lSystem"
diff --git a/test/Driver/darwin-xarch.c b/test/Driver/darwin-xarch.c
new file mode 100644
index 000000000000..cd7fa845d03e
--- /dev/null
+++ b/test/Driver/darwin-xarch.c
@@ -0,0 +1,8 @@
+// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -### \
+// RUN: -arch i386 -Xarch_i386 -mmacosx-version-min=10.4 \
+// RUN: -arch x86_64 -Xarch_x86_64 -mmacosx-version-min=10.5 \
+// RUN: -c %s 2> %t
+// RUN: FileCheck < %t %s
+//
+// CHECK: clang{{.*}}" "-cc1" "-triple" "i386-apple-darwin8.0.0"
+// CHECK: clang{{.*}}" "-cc1" "-triple" "x86_64-apple-darwin9.0.0"
diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c
index 3deee46f9a01..e8bc22345713 100644
--- a/test/Driver/freebsd.c
+++ b/test/Driver/freebsd.c
@@ -1,7 +1,21 @@
-// 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
+// RUN: %clang -ccc-clang-archs "" -ccc-host-triple powerpc64-pc-freebsd8 %s -### 2> %t
+// RUN: FileCheck --check-prefix=CHECK-PPC < %t %s
+//
+// CHECK-PPC: clang{{.*}}" "-cc1" "-triple" "powerpc64-pc-freebsd8"
+// CHECK-PPC: as{{.*}}" "-o" "{{.*}}.o" "{{.*}}.s
+// CHECK-PPC: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "{{.*}}ld-elf{{.*}}" "-o" "a.out" "{{.*}}crt1.o" "{{.*}}crti.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "{{.*}}crtend.o" "{{.*}}crtn.o"
-// CHECK: clang{{.*}}" "-cc1" "-triple" "powerpc64-pc-freebsd8"
-// CHECK: as{{.*}}" "-o" "{{.*}}.o" "{{.*}}.s
-// CHECK: ld{{.*}}" "--eh-frame-hdr" "-dynamic-linker" "{{.*}}ld-elf{{.*}}" "-o" "a.out" "{{.*}}crt1.o" "{{.*}}crti.o" "{{.*}}crtbegin.o" "{{.*}}.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "{{.*}}crtend.o" "{{.*}}crtn.o"
+
+// Check that -m32 properly adjusts the toolchain flags.
+//
+// RUN: %clang -ccc-host-triple x86_64-pc-freebsd8 -m32 -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-LIB32 < %t %s
+//
+// CHECK-LIB32: clang{{.*}}" "-cc1" "-triple" "i386-pc-freebsd8"
+// CHECK-LIB32: as{{.*}}" "--32"
+// CHECK-LIB32: ld{{.*}}" {{.*}} "-m" "elf_i386_fbsd"
+//
+// RUN: %clang -ccc-host-triple x86_64-pc-freebsd8 -m32 -print-search-dirs %s > %t
+// RUN: FileCheck --check-prefix=CHECK-LIB32PATHS < %t %s
+//
+// CHECK-LIB32PATHS: libraries: ={{.*}}:/usr/lib32
diff --git a/test/Driver/gcc_forward.c b/test/Driver/gcc_forward.c
new file mode 100644
index 000000000000..c584a4e8faf5
--- /dev/null
+++ b/test/Driver/gcc_forward.c
@@ -0,0 +1,13 @@
+// Check that we don't try to forward -Xclang or -mlinker-version to GCC.
+//
+// RUN: %clang -ccc-host-triple powerpc-unknown-unknown \
+// RUN: -ccc-clang-archs i386 -c %s \
+// RUN: -Xclang foo-bar \
+// RUN: -mlinker-version=10 -### 2> %t
+// RUN: FileCheck < %t %s
+//
+// CHECK: gcc{{.*}}"
+// CHECK-NOT: "-mlinker-version=10"
+// CHECK-NOT: "-Xclang"
+// CHECK-NOT: "foo-bar"
+// CHECK: gcc_forward
diff --git a/test/Driver/rewrite-objc.m b/test/Driver/rewrite-objc.m
index 38993fc8978c..ac77d79c20cb 100644
--- a/test/Driver/rewrite-objc.m
+++ b/test/Driver/rewrite-objc.m
@@ -1,6 +1,10 @@
// RUN: %clang -ccc-host-triple unknown -rewrite-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST0 %s
-// TEST0: clang{{.*}}" "-rewrite-objc"
+// TEST0: clang{{.*}}" "-cc1"
+// TEST0: "-rewrite-objc"
+// FIXME: CHECK-NOT is broken somehow, it doesn't work here. Check adjacency instead.
+// TEST0: "-fmessage-length" "0" "-fdiagnostics-show-option"
+// TEST0: rewrite-objc.m"
// RUN: not %clang -ccc-no-clang -ccc-host-triple unknown -rewrite-objc %s -o - -### 2>&1 | \
// RUN: FileCheck -check-prefix=TEST1 %s
diff --git a/test/FixIt/fixit.c b/test/FixIt/fixit.c
index b799fa3b3b88..890fb10b41d5 100644
--- a/test/FixIt/fixit.c
+++ b/test/FixIt/fixit.c
@@ -38,3 +38,6 @@ int test_cond(int y, int fooBar) {
int x = y ? 1 4+foobar;
return x;
}
+
+// CHECK: typedef int int_t;
+typedef typedef int int_t;
diff --git a/test/Frontend/Inputs/lit.local.cfg b/test/Frontend/Inputs/lit.local.cfg
new file mode 100644
index 000000000000..e6f55eef7af5
--- /dev/null
+++ b/test/Frontend/Inputs/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = []
diff --git a/test/Frontend/Inputs/test.h b/test/Frontend/Inputs/test.h
new file mode 100644
index 000000000000..98cc459a2426
--- /dev/null
+++ b/test/Frontend/Inputs/test.h
@@ -0,0 +1 @@
+#include "test2.h"
diff --git a/test/Frontend/Inputs/test2.h b/test/Frontend/Inputs/test2.h
new file mode 100644
index 000000000000..6d1a0d47b7f7
--- /dev/null
+++ b/test/Frontend/Inputs/test2.h
@@ -0,0 +1 @@
+int x;
diff --git a/test/Frontend/Inputs/test3.h b/test/Frontend/Inputs/test3.h
new file mode 100644
index 000000000000..92ff4b8fac05
--- /dev/null
+++ b/test/Frontend/Inputs/test3.h
@@ -0,0 +1 @@
+int y;
diff --git a/test/Frontend/print-header-includes.c b/test/Frontend/print-header-includes.c
new file mode 100644
index 000000000000..7773d2069d98
--- /dev/null
+++ b/test/Frontend/print-header-includes.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -include Inputs/test3.h -E -H -o %t.out %s 2> %t.err
+// RUN: FileCheck < %t.err %s
+
+// CHECK-NOT: test3.h
+// CHECK: . {{.*test.h}}
+// CHECK: .. {{.*test2.h}}
+
+#include "Inputs/test.h"
diff --git a/test/Headers/x86-intrinsics-headers.c b/test/Headers/x86-intrinsics-headers.c
index 08abcefed7a7..ba833ec03893 100644
--- a/test/Headers/x86-intrinsics-headers.c
+++ b/test/Headers/x86-intrinsics-headers.c
@@ -4,29 +4,16 @@
#if defined(i386) || defined(__x86_64__)
-# if defined(__MMX__)
-#include <emmintrin.h>
+#ifdef __MMX__
#include <mm_malloc.h>
-# endif
-
-# if defined(__SSE__)
-#include <xmmintrin.h>
-# endif
-
-# if defined(__SSE3__)
-#include <pmmintrin.h>
-# endif
-
-# if defined(__SSSE3__)
-#include <tmmintrin.h>
-# endif
-
-# if defined(__SSE4_1__)
-#include <smmintrin.h>
-# endif
+#endif
-# if defined(__SSE4_2__)
+#ifdef __SSE4_2__
+// nmmintrin forwards to smmintrin.
#include <nmmintrin.h>
-# endif
+#endif
+
+// immintrin includes all other intel intrinsic headers.
+#include <immintrin.h>
#endif
diff --git a/test/Index/Inputs/crash-recovery-code-complete-remap.c b/test/Index/Inputs/crash-recovery-code-complete-remap.c
new file mode 100644
index 000000000000..50a86580a136
--- /dev/null
+++ b/test/Index/Inputs/crash-recovery-code-complete-remap.c
@@ -0,0 +1,12 @@
+// RUN: echo env CINDEXTEST_EDITING=1 \
+// RUN: not c-index-test -test-load-source-reparse 1 local \
+// RUN: -remap-file="%s;%S/Inputs/crash-recovery-code-complete-remap.c" \
+// RUN: %s 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-CODE-COMPLETE-CRASH %s
+// CHECK-CODE-COMPLETE-CRASH: Unable to reparse translation unit
+//
+// XFAIL: win32
+
+#warning parsing original file
+
+#pragma clang __debug crash
diff --git a/test/Index/Inputs/crash-recovery-reparse-remap.c b/test/Index/Inputs/crash-recovery-reparse-remap.c
new file mode 100644
index 000000000000..0357dbe748a8
--- /dev/null
+++ b/test/Index/Inputs/crash-recovery-reparse-remap.c
@@ -0,0 +1,11 @@
+
+#warning parsing remapped file
+
+
+
+int x;
+
+#pragma clang __debug crash
+
+int x;
+
diff --git a/test/Index/Inputs/preamble-reparse-1.c b/test/Index/Inputs/preamble-reparse-1.c
new file mode 100644
index 000000000000..139597f9cb07
--- /dev/null
+++ b/test/Index/Inputs/preamble-reparse-1.c
@@ -0,0 +1,2 @@
+
+
diff --git a/test/Index/Inputs/preamble-reparse-2.c b/test/Index/Inputs/preamble-reparse-2.c
new file mode 100644
index 000000000000..6d1a0d47b7f7
--- /dev/null
+++ b/test/Index/Inputs/preamble-reparse-2.c
@@ -0,0 +1 @@
+int x;
diff --git a/test/Index/Inputs/preamble.h b/test/Index/Inputs/preamble.h
new file mode 100644
index 000000000000..b59c234e1732
--- /dev/null
+++ b/test/Index/Inputs/preamble.h
@@ -0,0 +1,6 @@
+inline int bar(int i) {
+ int *ptr = 0;
+ float *ptr1;
+ ptr = ptr1;
+ return 0;
+}
diff --git a/test/Index/Inputs/prefix.h b/test/Index/Inputs/prefix.h
new file mode 100644
index 000000000000..82ba2da360bf
--- /dev/null
+++ b/test/Index/Inputs/prefix.h
@@ -0,0 +1,4 @@
+#ifndef PREFIX_H
+#define PREFIX_H
+int foo(int);
+#endif
diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m
index b55c8623a514..09a7d48cfdd3 100644
--- a/test/Index/TestClassDecl.m
+++ b/test/Index/TestClassDecl.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-nonfragile-abi -fblocks -emit-pch -x objective-c %s -o %t.ast
+// RUN: c-index-test -write-pch %t.ast -fobjc-nonfragile-abi -fblocks -x objective-c %s
// 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
diff --git a/test/Index/annotate-tokens-pp.c b/test/Index/annotate-tokens-pp.c
index 485786e1c4e8..55ee7630eb36 100644
--- a/test/Index/annotate-tokens-pp.c
+++ b/test/Index/annotate-tokens-pp.c
@@ -7,7 +7,25 @@ int BAR STILL_NOTHING;
#include "foo.h"
#undef BAR
-// RUN: c-index-test -test-annotate-tokens=%s:2:1:9:1 -I%S/Inputs %s | FileCheck %s
+#define REVERSE_MACRO(x,y) y + x
+#define TWICE_MACRO(y) y + y
+
+void test_macro_args() {
+ int z = 1;
+ int t = 2;
+ int k = REVERSE_MACRO(t,z);
+ int j = TWICE_MACRO(k + k);
+ int w = j + j;
+}
+
+#define fun_with_macro_bodies(x, y) do { if (x) y } while (0)
+
+void test() {
+ int x = 10;
+ fun_with_macro_bodies(x, { int z = x; ++z; });
+}
+
+// RUN: c-index-test -test-annotate-tokens=%s:2:1:26:1 -I%S/Inputs %s | FileCheck %s
// CHECK: Punctuation: "#" [2:1 - 2:2] preprocessing directive=
// CHECK: Identifier: "define" [2:2 - 2:8] preprocessing directive=
// CHECK: Identifier: "STILL_NOTHING" [2:9 - 2:22] macro definition=STILL_NOTHING
@@ -56,3 +74,114 @@ int BAR STILL_NOTHING;
// CHECK: Punctuation: "#" [8:1 - 8:2] preprocessing directive=
// CHECK: Identifier: "undef" [8:2 - 8:7] preprocessing directive=
// CHECK: Identifier: "BAR" [8:8 - 8:11] preprocessing directive=
+// CHECK: Punctuation: "#" [10:1 - 10:2] preprocessing directive=
+// CHECK: Identifier: "define" [10:2 - 10:8] preprocessing directive=
+// CHECK: Identifier: "REVERSE_MACRO" [10:9 - 10:22] macro definition=REVERSE_MACRO
+// CHECK: Punctuation: "(" [10:22 - 10:23] preprocessing directive=
+// CHECK: Identifier: "x" [10:23 - 10:24] preprocessing directive=
+// CHECK: Punctuation: "," [10:24 - 10:25] preprocessing directive=
+// CHECK: Identifier: "y" [10:25 - 10:26] preprocessing directive=
+// CHECK: Punctuation: ")" [10:26 - 10:27] preprocessing directive=
+// CHECK: Identifier: "y" [10:28 - 10:29] preprocessing directive=
+// CHECK: Punctuation: "+" [10:30 - 10:31] preprocessing directive=
+// CHECK: Identifier: "x" [10:32 - 10:33] preprocessing directive=
+// CHECK: Punctuation: "#" [11:1 - 11:2] preprocessing directive=
+// CHECK: Identifier: "define" [11:2 - 11:8] preprocessing directive=
+// CHECK: Identifier: "TWICE_MACRO" [11:9 - 11:20] macro definition=TWICE_MACRO
+// CHECK: Punctuation: "(" [11:20 - 11:21] preprocessing directive=
+// CHECK: Identifier: "y" [11:21 - 11:22] preprocessing directive=
+// CHECK: Punctuation: ")" [11:22 - 11:23] preprocessing directive=
+// CHECK: Identifier: "y" [11:24 - 11:25] preprocessing directive=
+// CHECK: Punctuation: "+" [11:26 - 11:27] preprocessing directive=
+// CHECK: Identifier: "y" [11:28 - 11:29] preprocessing directive=
+// CHECK: Keyword: "void" [13:1 - 13:5] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Identifier: "test_macro_args" [13:6 - 13:21] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Punctuation: "(" [13:21 - 13:22] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Punctuation: ")" [13:22 - 13:23] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Punctuation: "{" [13:24 - 13:25] UnexposedStmt=
+// CHECK: Keyword: "int" [14:3 - 14:6] VarDecl=z:14:7 (Definition)
+// CHECK: Identifier: "z" [14:7 - 14:8] VarDecl=z:14:7 (Definition)
+// CHECK: Punctuation: "=" [14:9 - 14:10] VarDecl=z:14:7 (Definition)
+// CHECK: Literal: "1" [14:11 - 14:12] UnexposedExpr=
+// CHECK: Punctuation: ";" [14:12 - 14:13] UnexposedStmt=
+// CHECK: Keyword: "int" [15:3 - 15:6] VarDecl=t:15:7 (Definition)
+// CHECK: Identifier: "t" [15:7 - 15:8] VarDecl=t:15:7 (Definition)
+// CHECK: Punctuation: "=" [15:9 - 15:10] VarDecl=t:15:7 (Definition)
+// CHECK: Literal: "2" [15:11 - 15:12] UnexposedExpr=
+// CHECK: Punctuation: ";" [15:12 - 15:13] UnexposedStmt=
+// CHECK: Keyword: "int" [16:3 - 16:6] VarDecl=k:16:7 (Definition)
+// CHECK: Identifier: "k" [16:7 - 16:8] VarDecl=k:16:7 (Definition)
+// CHECK: Punctuation: "=" [16:9 - 16:10] VarDecl=k:16:7 (Definition)
+// CHECK: Identifier: "REVERSE_MACRO" [16:11 - 16:24] macro instantiation=REVERSE_MACRO:10:9
+// CHECK: Punctuation: "(" [16:24 - 16:25] UnexposedStmt=
+// CHECK: Identifier: "t" [16:25 - 16:26] DeclRefExpr=t:15:7
+// CHECK: Punctuation: "," [16:26 - 16:27] UnexposedStmt=
+// CHECK: Identifier: "z" [16:27 - 16:28] DeclRefExpr=z:14:7
+// CHECK: Punctuation: ")" [16:28 - 16:29] UnexposedStmt=
+// CHECK: Punctuation: ";" [16:29 - 16:30] UnexposedStmt=
+// CHECK: Keyword: "int" [17:3 - 17:6] VarDecl=j:17:7 (Definition)
+// CHECK: Identifier: "j" [17:7 - 17:8] VarDecl=j:17:7 (Definition)
+// CHECK: Punctuation: "=" [17:9 - 17:10] VarDecl=j:17:7 (Definition)
+// CHECK: Identifier: "TWICE_MACRO" [17:11 - 17:22] macro instantiation=TWICE_MACRO:11:9
+// CHECK: Punctuation: "(" [17:22 - 17:23] UnexposedStmt=
+// CHECK: Identifier: "k" [17:23 - 17:24] DeclRefExpr=k:16:7
+// CHECK: Punctuation: "+" [17:25 - 17:26] UnexposedStmt=
+// CHECK: Identifier: "k" [17:27 - 17:28] DeclRefExpr=k:16:7
+// CHECK: Punctuation: ")" [17:28 - 17:29] UnexposedStmt=
+// CHECK: Punctuation: ";" [17:29 - 17:30] UnexposedStmt=
+// CHECK: Keyword: "int" [18:3 - 18:6] VarDecl=w:18:7 (Definition)
+// CHECK: Identifier: "w" [18:7 - 18:8] VarDecl=w:18:7 (Definition)
+// CHECK: Punctuation: "=" [18:9 - 18:10] VarDecl=w:18:7 (Definition)
+// CHECK: Identifier: "j" [18:11 - 18:12] DeclRefExpr=j:17:7
+// CHECK: Punctuation: "+" [18:13 - 18:14] UnexposedExpr=
+// CHECK: Identifier: "j" [18:15 - 18:16] DeclRefExpr=j:17:7
+// CHECK: Punctuation: ";" [18:16 - 18:17] UnexposedStmt=
+// CHECK: Punctuation: "}" [19:1 - 19:2] UnexposedStmt=
+// CHECK: Punctuation: "#" [21:1 - 21:2] preprocessing directive=
+// CHECK: Identifier: "define" [21:2 - 21:8] preprocessing directive=
+// CHECK: Identifier: "fun_with_macro_bodies" [21:9 - 21:30] macro definition=fun_with_macro_bodies
+// CHECK: Punctuation: "(" [21:30 - 21:31] preprocessing directive=
+// CHECK: Identifier: "x" [21:31 - 21:32] preprocessing directive=
+// CHECK: Punctuation: "," [21:32 - 21:33] preprocessing directive=
+// CHECK: Identifier: "y" [21:34 - 21:35] preprocessing directive=
+// CHECK: Punctuation: ")" [21:35 - 21:36] preprocessing directive=
+// CHECK: Keyword: "do" [21:37 - 21:39] preprocessing directive=
+// CHECK: Punctuation: "{" [21:40 - 21:41] preprocessing directive=
+// CHECK: Keyword: "if" [21:42 - 21:44] preprocessing directive=
+// CHECK: Punctuation: "(" [21:45 - 21:46] preprocessing directive=
+// CHECK: Identifier: "x" [21:46 - 21:47] preprocessing directive=
+// CHECK: Punctuation: ")" [21:47 - 21:48] preprocessing directive=
+// CHECK: Identifier: "y" [21:49 - 21:50] preprocessing directive=
+// CHECK: Punctuation: "}" [21:51 - 21:52] preprocessing directive=
+// CHECK: Keyword: "while" [21:53 - 21:58] preprocessing directive=
+// CHECK: Punctuation: "(" [21:59 - 21:60] preprocessing directive=
+// CHECK: Literal: "0" [21:60 - 21:61] preprocessing directive=
+// CHECK: Punctuation: ")" [21:61 - 21:62] preprocessing directive=
+// CHECK: Keyword: "void" [23:1 - 23:5] FunctionDecl=test:23:6 (Definition)
+// CHECK: Identifier: "test" [23:6 - 23:10] FunctionDecl=test:23:6 (Definition)
+// CHECK: Punctuation: "(" [23:10 - 23:11] FunctionDecl=test:23:6 (Definition)
+// CHECK: Punctuation: ")" [23:11 - 23:12] FunctionDecl=test:23:6 (Definition)
+// CHECK: Punctuation: "{" [23:13 - 23:14] UnexposedStmt=
+// CHECK: Keyword: "int" [24:3 - 24:6] VarDecl=x:24:7 (Definition)
+// CHECK: Identifier: "x" [24:7 - 24:8] VarDecl=x:24:7 (Definition)
+// CHECK: Punctuation: "=" [24:9 - 24:10] VarDecl=x:24:7 (Definition)
+// CHECK: Literal: "10" [24:11 - 24:13] UnexposedExpr=
+// CHECK: Punctuation: ";" [24:13 - 24:14] UnexposedStmt=
+// CHECK: Identifier: "fun_with_macro_bodies" [25:3 - 25:24] macro instantiation=fun_with_macro_bodies:21:9
+// CHECK: Punctuation: "(" [25:24 - 25:25] UnexposedStmt=
+// CHECK: Identifier: "x" [25:25 - 25:26] DeclRefExpr=x:24:7
+// CHECK: Punctuation: "," [25:26 - 25:27] UnexposedStmt=
+// CHECK: Punctuation: "{" [25:28 - 25:29] UnexposedStmt=
+// CHECK: Keyword: "int" [25:30 - 25:33] UnexposedStmt=
+// CHECK: Identifier: "z" [25:34 - 25:35] VarDecl=z:25:3 (Definition)
+// CHECK: Punctuation: "=" [25:36 - 25:37] UnexposedStmt=
+// CHECK: Identifier: "x" [25:38 - 25:39] DeclRefExpr=x:24:7
+// CHECK: Punctuation: ";" [25:39 - 25:40] UnexposedStmt=
+// CHECK: Punctuation: "++" [25:41 - 25:43] UnexposedExpr=
+// CHECK: Identifier: "z" [25:43 - 25:44] DeclRefExpr=z:25:3
+// CHECK: Punctuation: ";" [25:44 - 25:45] UnexposedStmt=
+// CHECK: Punctuation: "}" [25:46 - 25:47] UnexposedStmt=
+// CHECK: Punctuation: ")" [25:47 - 25:48] UnexposedStmt=
+// CHECK: Punctuation: ";" [25:48 - 25:49] UnexposedStmt=
+// CHECK: Punctuation: "}" [26:1 - 26:2] UnexposedStmt=
+
diff --git a/test/Index/annotate-tokens.c b/test/Index/annotate-tokens.c
index 41f182d27148..e251596c8002 100644
--- a/test/Index/annotate-tokens.c
+++ b/test/Index/annotate-tokens.c
@@ -9,7 +9,14 @@ void f(void *ptr) {
const char * hello = "Hello";
}
-// RUN: c-index-test -test-annotate-tokens=%s:4:1:9:32 %s | FileCheck %s
+typedef int Int;
+void g(int i, ...) {
+ __builtin_va_list va;
+ (void)__builtin_va_arg(va, Int);
+ (void)__builtin_types_compatible_p(Int, Int);
+}
+
+// RUN: c-index-test -test-annotate-tokens=%s:4:1:17:1 %s | FileCheck %s
// CHECK: Identifier: "T" [4:3 - 4:4] TypeRef=T:1:13
// CHECK: Punctuation: "*" [4:4 - 4:5] VarDecl=t_ptr:4:6 (Definition)
// CHECK: Identifier: "t_ptr" [4:6 - 4:11] VarDecl=t_ptr:4:6 (Definition)
@@ -61,5 +68,11 @@ void f(void *ptr) {
// CHECK: Literal: ""Hello"" [9:24 - 9:31] UnexposedExpr=
// CHECK: Punctuation: ";" [9:31 - 9:32] UnexposedStmt=
// CHECK: Punctuation: "}" [10:1 - 10:2] UnexposedStmt=
+// CHECK: Keyword: "__builtin_va_arg" [15:9 - 15:25] UnexposedExpr=
+// CHECK: Identifier: "Int" [15:30 - 15:33] TypeRef=Int:12:13
+// CHECK: Keyword: "__builtin_types_compatible_p" [16:9 - 16:37] UnexposedExpr=
+// CHECK: Identifier: "Int" [16:38 - 16:41] TypeRef=Int:12:13
+// CHECK: Punctuation: "," [16:41 - 16:42] UnexposedExpr=
+// CHECK: Identifier: "Int" [16:43 - 16:46] TypeRef=Int:12:13
// RUN: c-index-test -test-annotate-tokens=%s:4:1:165:32 %s | FileCheck %s
// RUN: c-index-test -test-annotate-tokens=%s:4:1:165:38 %s | FileCheck %s
diff --git a/test/Index/annotate-tokens.cpp b/test/Index/annotate-tokens.cpp
new file mode 100644
index 000000000000..dca7af2bf740
--- /dev/null
+++ b/test/Index/annotate-tokens.cpp
@@ -0,0 +1,23 @@
+struct bonk { };
+void test(bonk X) {
+ X = X;
+}
+
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:5:5 %s
+// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition)
+// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition)
+// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition)
+// CHECK: Punctuation: "}" [1:15 - 1:16] StructDecl=bonk:1:8 (Definition)
+// CHECK: Punctuation: ";" [1:16 - 1:17]
+// CHECK: Keyword: "void" [2:1 - 2:5] FunctionDecl=test:2:6 (Definition)
+// CHECK: Identifier: "test" [2:6 - 2:10] FunctionDecl=test:2:6 (Definition)
+// CHECK: Punctuation: "(" [2:10 - 2:11] FunctionDecl=test:2:6 (Definition)
+// CHECK: Identifier: "bonk" [2:11 - 2:15] TypeRef=struct bonk:1:8
+// CHECK: Identifier: "X" [2:16 - 2:17] ParmDecl=X:2:16 (Definition)
+// CHECK: Punctuation: ")" [2:17 - 2:18] FunctionDecl=test:2:6 (Definition)
+// CHECK: Punctuation: "{" [2:19 - 2:20] UnexposedStmt=
+// CHECK: Identifier: "X" [3:5 - 3:6] DeclRefExpr=X:2:16
+// CHECK: Punctuation: "=" [3:7 - 3:8] DeclRefExpr=operator=:1:8
+// CHECK: Identifier: "X" [3:9 - 3:10] DeclRefExpr=X:2:16
+// CHECK: Punctuation: ";" [3:10 - 3:11] UnexposedStmt=
+// CHECK: Punctuation: "}" [4:1 - 4:2] UnexposedStmt=
diff --git a/test/Index/annotate-tokens.m b/test/Index/annotate-tokens.m
index c6e746bcb1b2..336951b7fe1a 100644
--- a/test/Index/annotate-tokens.m
+++ b/test/Index/annotate-tokens.m
@@ -56,7 +56,30 @@ extern int ibaction_test(void);
@property IBOutlet int * aPropOutlet;
@end
-// RUN: c-index-test -test-annotate-tokens=%s:1:1:58:1 %s -DIBOutlet='__attribute__((iboutlet))' -DIBAction='void)__attribute__((ibaction)' | FileCheck %s
+// From <rdar://problem/7974151>. The first 'foo:' wasn't being annotated as
+// being part of the Objective-C message expression since the argument
+// was expanded from a macro.
+
+#define VAL 0
+
+@interface R7974151
+- (int) foo:(int)arg;
+- (int) method;
+@end
+
+@implementation R7974151
+- (int) foo:(int)arg {
+ return arg;
+}
+- (int) method
+{
+ int local = [self foo:VAL];
+ int second = [self foo:0];
+ return local;
+}
+@end
+
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:80:4 %s -DIBOutlet='__attribute__((iboutlet))' -DIBAction='void)__attribute__((ibaction)' | FileCheck %s
// CHECK: Punctuation: "@" [1:1 - 1:2] ObjCInterfaceDecl=Foo:1:12
// CHECK: Keyword: "interface" [1:2 - 1:11] ObjCInterfaceDecl=Foo:1:12
// CHECK: Identifier: "Foo" [1:12 - 1:15] ObjCInterfaceDecl=Foo:1:12
@@ -224,7 +247,7 @@ extern int ibaction_test(void);
// CHECK: Keyword: "interface" [51:2 - 51:11] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Identifier: "IBOutletTests" [51:12 - 51:25] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Punctuation: "{" [52:1 - 52:2] ObjCInterfaceDecl=IBOutletTests:51:12
-// CHECK: Identifier: "IBOutlet" [53:5 - 53:13] macro instantiation=IBOutlet:{{[0-9]+}}:{{[0-9]+}}
+// CHECK: Identifier: "IBOutlet" [53:5 - 53:13] macro instantiation=IBOutlet
// CHECK: Keyword: "char" [53:14 - 53:18] ObjCIvarDecl=anOutlet:53:21 (Definition)
// CHECK: Punctuation: "*" [53:19 - 53:20] ObjCIvarDecl=anOutlet:53:21 (Definition)
// CHECK: Identifier: "anOutlet" [53:21 - 53:29] ObjCIvarDecl=anOutlet:53:21 (Definition)
@@ -243,11 +266,86 @@ extern int ibaction_test(void);
// CHECK: Punctuation: ";" [55:34 - 55:35] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Punctuation: "@" [56:1 - 56:2] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Keyword: "property" [56:2 - 56:10] ObjCInterfaceDecl=IBOutletTests:51:12
-// CHECK: Identifier: "IBOutlet" [56:11 - 56:19] macro instantiation=IBOutlet:{{[0-9]+}}:{{[0-9]+}}
+// CHECK: Identifier: "IBOutlet" [56:11 - 56:19] macro instantiation=IBOutlet
// CHECK: Keyword: "int" [56:20 - 56:23] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Punctuation: "*" [56:24 - 56:25] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Identifier: "aPropOutlet" [56:26 - 56:37] ObjCPropertyDecl=aPropOutlet:56:26
// CHECK: Punctuation: ";" [56:37 - 56:38] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Punctuation: "@" [57:1 - 57:2] ObjCInterfaceDecl=IBOutletTests:51:12
// CHECK: Keyword: "end" [57:2 - 57:5] ObjCInterfaceDecl=IBOutletTests:51:12
-
+// CHECK: Punctuation: "#" [63:1 - 63:2] preprocessing directive=
+// CHECK: Identifier: "define" [63:2 - 63:8] preprocessing directive=
+// CHECK: Identifier: "VAL" [63:9 - 63:12] macro definition=VAL
+// CHECK: Literal: "0" [63:13 - 63:14] preprocessing directive=
+// CHECK: Punctuation: "@" [65:1 - 65:2] ObjCInterfaceDecl=R7974151:65:12
+// CHECK: Keyword: "interface" [65:2 - 65:11] ObjCInterfaceDecl=R7974151:65:12
+// CHECK: Identifier: "R7974151" [65:12 - 65:20] ObjCInterfaceDecl=R7974151:65:12
+// CHECK: Punctuation: "-" [66:1 - 66:2] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Punctuation: "(" [66:3 - 66:4] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Keyword: "int" [66:4 - 66:7] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Punctuation: ")" [66:7 - 66:8] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Identifier: "foo" [66:9 - 66:12] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Punctuation: ":" [66:12 - 66:13] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Punctuation: "(" [66:13 - 66:14] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Keyword: "int" [66:14 - 66:17] ParmDecl=arg:66:18 (Definition)
+// CHECK: Punctuation: ")" [66:17 - 66:18] ParmDecl=arg:66:18 (Definition)
+// CHECK: Identifier: "arg" [66:18 - 66:21] ParmDecl=arg:66:18 (Definition)
+// CHECK: Punctuation: ";" [66:21 - 66:22] ObjCInstanceMethodDecl=foo::66:1
+// CHECK: Punctuation: "-" [67:1 - 67:2] ObjCInstanceMethodDecl=method:67:1
+// CHECK: Punctuation: "(" [67:3 - 67:4] ObjCInstanceMethodDecl=method:67:1
+// CHECK: Keyword: "int" [67:4 - 67:7] ObjCInstanceMethodDecl=method:67:1
+// CHECK: Punctuation: ")" [67:7 - 67:8] ObjCInstanceMethodDecl=method:67:1
+// CHECK: Identifier: "method" [67:9 - 67:15] ObjCInstanceMethodDecl=method:67:1
+// CHECK: Punctuation: ";" [67:15 - 67:16] ObjCInstanceMethodDecl=method:67:1
+// CHECK: Punctuation: "@" [68:1 - 68:2] ObjCInterfaceDecl=R7974151:65:12
+// CHECK: Keyword: "end" [68:2 - 68:5] ObjCInterfaceDecl=R7974151:65:12
+// CHECK: Punctuation: "@" [70:1 - 70:2] ObjCImplementationDecl=R7974151:70:1 (Definition)
+// CHECK: Keyword: "implementation" [70:2 - 70:16] ObjCImplementationDecl=R7974151:70:1 (Definition)
+// CHECK: Identifier: "R7974151" [70:17 - 70:25] ObjCImplementationDecl=R7974151:70:1 (Definition)
+// CHECK: Punctuation: "-" [71:1 - 71:2] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Punctuation: "(" [71:3 - 71:4] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Keyword: "int" [71:4 - 71:7] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Punctuation: ")" [71:7 - 71:8] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Identifier: "foo" [71:9 - 71:12] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Punctuation: ":" [71:12 - 71:13] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Punctuation: "(" [71:13 - 71:14] ObjCInstanceMethodDecl=foo::71:1 (Definition)
+// CHECK: Keyword: "int" [71:14 - 71:17] ParmDecl=arg:71:18 (Definition)
+// CHECK: Punctuation: ")" [71:17 - 71:18] ParmDecl=arg:71:18 (Definition)
+// CHECK: Identifier: "arg" [71:18 - 71:21] ParmDecl=arg:71:18 (Definition)
+// CHECK: Punctuation: "{" [71:22 - 71:23] UnexposedStmt=
+// CHECK: Keyword: "return" [72:3 - 72:9] UnexposedStmt=
+// CHECK: Identifier: "arg" [72:10 - 72:13] DeclRefExpr=arg:71:18
+// CHECK: Punctuation: ";" [72:13 - 72:14] UnexposedStmt=
+// CHECK: Punctuation: "}" [73:1 - 73:2] UnexposedStmt=
+// CHECK: Punctuation: "-" [74:1 - 74:2] ObjCInstanceMethodDecl=method:74:1 (Definition)
+// CHECK: Punctuation: "(" [74:3 - 74:4] ObjCInstanceMethodDecl=method:74:1 (Definition)
+// CHECK: Keyword: "int" [74:4 - 74:7] ObjCInstanceMethodDecl=method:74:1 (Definition)
+// CHECK: Punctuation: ")" [74:7 - 74:8] ObjCInstanceMethodDecl=method:74:1 (Definition)
+// CHECK: Identifier: "method" [74:9 - 74:15] ObjCInstanceMethodDecl=method:74:1 (Definition)
+// CHECK: Punctuation: "{" [75:1 - 75:2] UnexposedStmt=
+// CHECK: Keyword: "int" [76:5 - 76:8] VarDecl=local:76:9 (Definition)
+// CHECK: Identifier: "local" [76:9 - 76:14] VarDecl=local:76:9 (Definition)
+// CHECK: Punctuation: "=" [76:15 - 76:16] VarDecl=local:76:9 (Definition)
+// CHECK: Punctuation: "[" [76:17 - 76:18] ObjCMessageExpr=foo::66:1
+// CHECK: Identifier: "self" [76:18 - 76:22] DeclRefExpr=self:0:0
+// CHECK: Identifier: "foo" [76:23 - 76:26] ObjCMessageExpr=foo::66:1
+// CHECK: Punctuation: ":" [76:26 - 76:27] ObjCMessageExpr=foo::66:1
+// CHECK: Identifier: "VAL" [76:27 - 76:30] macro instantiation=VAL:63:9
+// CHECK: Punctuation: "]" [76:30 - 76:31] ObjCMessageExpr=foo::66:1
+// CHECK: Punctuation: ";" [76:31 - 76:32] UnexposedStmt=
+// CHECK: Keyword: "int" [77:5 - 77:8] VarDecl=second:77:9 (Definition)
+// CHECK: Identifier: "second" [77:9 - 77:15] VarDecl=second:77:9 (Definition)
+// CHECK: Punctuation: "=" [77:16 - 77:17] VarDecl=second:77:9 (Definition)
+// CHECK: Punctuation: "[" [77:18 - 77:19] ObjCMessageExpr=foo::66:1
+// CHECK: Identifier: "self" [77:19 - 77:23] DeclRefExpr=self:0:0
+// CHECK: Identifier: "foo" [77:24 - 77:27] ObjCMessageExpr=foo::66:1
+// CHECK: Punctuation: ":" [77:27 - 77:28] ObjCMessageExpr=foo::66:1
+// CHECK: Literal: "0" [77:28 - 77:29] UnexposedExpr=
+// CHECK: Punctuation: "]" [77:29 - 77:30] ObjCMessageExpr=foo::66:1
+// CHECK: Punctuation: ";" [77:30 - 77:31] UnexposedStmt=
+// CHECK: Keyword: "return" [78:5 - 78:11] UnexposedStmt=
+// CHECK: Identifier: "local" [78:12 - 78:17] DeclRefExpr=local:76:9
+// CHECK: Punctuation: ";" [78:17 - 78:18] UnexposedStmt=
+// CHECK: Punctuation: "}" [79:1 - 79:2] UnexposedStmt=
+// CHECK: Punctuation: "@" [80:1 - 80:2] ObjCImplementationDecl=R7974151:70:1 (Definition)
+// CHECK: Keyword: "end" [80:2 - 80:5]
diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m
index 4e5eed43697a..5fe7cd669bc2 100644
--- a/test/Index/c-index-api-loadTU-test.m
+++ b/test/Index/c-index-api-loadTU-test.m
@@ -6,7 +6,7 @@
__attribute__((iboutlet)) id myoutlet;
}
- (void) __attribute__((ibaction)) myMessage:(id)msg;
-- foo;
+- foo __attribute__((deprecated));
+ fooC;
@end
@@ -56,7 +56,7 @@ int main (int argc, const char * argv[]) {
// Test attribute traversal.
#define IBOutlet __attribute__((iboutlet))
-#define IBOutletCollection(ClassName) __attribute__((iboutletcollection))
+#define IBOutletCollection(ClassName) __attribute__((iboutletcollection(ClassName)))
#define IBAction void)__attribute__((ibaction)
@interface TestAttributes {
@@ -78,7 +78,7 @@ struct X0 {};
// CHECK: <invalid loc>:0:0: attribute(ibaction)=
// CHECK: c-index-api-loadTU-test.m:8:50: ParmDecl=msg:8:50 (Definition) Extent=[8:47 - 8:53]
// CHECK: c-index-api-loadTU-test.m:8:47: TypeRef=id:0:0 Extent=[8:47 - 8:49]
-// CHECK: c-index-api-loadTU-test.m:9:1: ObjCInstanceMethodDecl=foo:9:1 Extent=[9:1 - 9:7]
+// CHECK: c-index-api-loadTU-test.m:9:1: ObjCInstanceMethodDecl=foo:9:1 (deprecated) Extent=[9:1 - 9:35]
// CHECK: c-index-api-loadTU-test.m:10:1: ObjCClassMethodDecl=fooC:10:1 Extent=[10:1 - 10:8]
// CHECK: c-index-api-loadTU-test.m:14:12: ObjCInterfaceDecl=Bar:14:12 Extent=[14:1 - 18:5]
// CHECK: c-index-api-loadTU-test.m:14:18: ObjCSuperClassRef=Foo:4:12 Extent=[14:18 - 14:21]
@@ -143,10 +143,15 @@ struct X0 {};
// CHECK: c-index-api-loadTU-test.m:63:19: ObjCIvarDecl=anOutlet:63:19 (Definition) Extent=[63:19 - 63:27]
// CHECK: <invalid loc>:0:0: attribute(iboutlet)=
// CHECK: c-index-api-loadTU-test.m:64:29: ObjCIvarDecl=anOutletCollection:64:29 (Definition) Extent=[64:29 - 64:47]
-// CHECK: <invalid loc>:0:0: attribute(iboutletcollection)=
+// CHECK: <invalid loc>:0:0: attribute(iboutletcollection)= [IBOutletCollection=ObjCObjectPointer]
// CHECK: c-index-api-loadTU-test.m:64:26: TypeRef=id:0:0 Extent=[64:26 - 64:28]
// CHECK: c-index-api-loadTU-test.m:66:1: ObjCInstanceMethodDecl=actionMethod::66:1 Extent=[66:1 - 66:35]
// CHECK: <invalid loc>:0:0: attribute(ibaction)=
// CHECK: c-index-api-loadTU-test.m:66:31: ParmDecl=arg:66:31 (Definition) Extent=[66:28 - 66:34]
// CHECK: c-index-api-loadTU-test.m:66:28: TypeRef=id:0:0 Extent=[66:28 - 66:30]
+// CHECK: c-index-api-loadTU-test.m:69:16: StructDecl=X0:69:16 Extent=[69:9 - 69:18]
+// CHECK: c-index-api-loadTU-test.m:69:19: TypedefDecl=X1:69:19 (Definition) Extent=[69:19 - 69:21]
+// CHECK: c-index-api-loadTU-test.m:69:16: TypeRef=struct X0:71:8 Extent=[69:16 - 69:18]
+// CHECK: c-index-api-loadTU-test.m:70:8: StructDecl=X0:70:8 Extent=[70:1 - 70:10]
+// CHECK: c-index-api-loadTU-test.m:71:8: StructDecl=X0:71:8 (Definition) Extent=[71:1 - 71:14]
diff --git a/test/Index/cindex-from-source.m b/test/Index/cindex-from-source.m
index 86e794db8916..f226e4533530 100644
--- a/test/Index/cindex-from-source.m
+++ b/test/Index/cindex-from-source.m
@@ -7,3 +7,6 @@
// CHECK: cindex-from-source.m:9:1: TypeRef=t0:1:13 Extent=[9:1 - 9:3]
struct s0 {};
t0 g0;
+
+// RUN: c-index-test -test-load-source-reparse 5 local %s -include %t.pfx.h > %t
+// RUN: FileCheck %s < %t
diff --git a/test/Index/code-completion.cpp b/test/Index/code-completion.cpp
index 1d50fd3469a1..7b0c8d75d81e 100644
--- a/test/Index/code-completion.cpp
+++ b/test/Index/code-completion.cpp
@@ -15,9 +15,9 @@ struct Z : X, Y {
double member;
operator int() const;
};
-
+struct W { };
struct Z get_Z();
-
+namespace N { }
void test_Z() {
// RUN: c-index-test -code-completion-at=%s:23:11 %s | FileCheck -check-prefix=CHECK-MEMBER %s
get_Z().member = 17;
@@ -40,28 +40,28 @@ Z::operator int() const {
// CHECK-MEMBER: FieldDecl:{ResultType double}{TypedText member}
// CHECK-MEMBER: FieldDecl:{ResultType int}{Text X::}{TypedText member}
// CHECK-MEMBER: FieldDecl:{ResultType float}{Text Y::}{TypedText member}
-// CHECK-MEMBER: FunctionDecl:{ResultType void}{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )}
-// CHECK-MEMBER: FunctionDecl:{ResultType int}{TypedText operator int}{LeftParen (}{RightParen )}{Informative const}
-// CHECK-MEMBER: FunctionDecl:{ResultType Z &}{TypedText operator=}{LeftParen (}{Placeholder Z const &}{RightParen )}
-// CHECK-MEMBER: FunctionDecl:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder X const &}{RightParen )}
-// CHECK-MEMBER: FunctionDecl:{ResultType Y &}{Text Y::}{TypedText operator=}{LeftParen (}{Placeholder Y const &}{RightParen )}
+// CHECK-MEMBER: CXXMethod:{ResultType void}{Informative Y::}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )}
+// CHECK-MEMBER: CXXConversion:{ResultType int}{TypedText operator int}{LeftParen (}{RightParen )}{Informative const}
+// CHECK-MEMBER: CXXMethod:{ResultType Z &}{TypedText operator=}{LeftParen (}{Placeholder Z const &}{RightParen )}
+// CHECK-MEMBER: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder X const &}{RightParen )}
+// CHECK-MEMBER: CXXMethod:{ResultType Y &}{Text Y::}{TypedText operator=}{LeftParen (}{Placeholder Y const &}{RightParen )}
// CHECK-MEMBER: EnumConstantDecl:{ResultType X::E}{Informative E::}{TypedText Val1}
// CHECK-MEMBER: StructDecl:{TypedText X}{Text ::}
// CHECK-MEMBER: StructDecl:{TypedText Y}{Text ::}
// CHECK-MEMBER: StructDecl:{TypedText Z}{Text ::}
-// CHECK-MEMBER: FunctionDecl:{ResultType void}{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )}
-// CHECK-MEMBER: FunctionDecl:{ResultType void}{Informative Y::}{TypedText ~Y}{LeftParen (}{RightParen )}
-// CHECK-MEMBER: FunctionDecl:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )}
+// CHECK-MEMBER: CXXDestructor:{ResultType void}{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )}
+// CHECK-MEMBER: CXXDestructor:{ResultType void}{Informative Y::}{TypedText ~Y}{LeftParen (}{RightParen )}
+// CHECK-MEMBER: CXXDestructor:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )}
// CHECK-OVERLOAD: NotImplemented:{ResultType int &}{Text overloaded}{LeftParen (}{Text Z z}{Comma , }{CurrentParameter int second}{RightParen )}
// CHECK-OVERLOAD: NotImplemented:{ResultType float &}{Text overloaded}{LeftParen (}{Text int i}{Comma , }{CurrentParameter long second}{RightParen )}
// CHECK-OVERLOAD: NotImplemented:{ResultType double &}{Text overloaded}{LeftParen (}{Text float f}{Comma , }{CurrentParameter int second}{RightParen )}
// RUN: c-index-test -code-completion-at=%s:37:10 %s | FileCheck -check-prefix=CHECK-EXPR %s
-// CHECK-EXPR: NotImplemented:{TypedText int} (40)
-// CHECK-EXPR: NotImplemented:{TypedText long} (40)
+// CHECK-EXPR: NotImplemented:{TypedText int} (65)
+// CHECK-EXPR: NotImplemented:{TypedText long} (65)
// CHECK-EXPR: FieldDecl:{ResultType double}{TypedText member} (10)
// CHECK-EXPR: FieldDecl:{ResultType int}{Text X::}{TypedText member} (5)
// CHECK-EXPR: FieldDecl:{ResultType float}{Text Y::}{TypedText member} (11)
-// CHECK-EXPR: FunctionDecl:{ResultType void}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )} (22)
-
+// CHECK-EXPR: CXXMethod:{ResultType void}{TypedText memfunc}{LeftParen (}{Optional {Placeholder int i}}{RightParen )} (22)
+// CHECK-EXPR: Namespace:{TypedText N}{Text ::} (75)
diff --git a/test/Index/complete-at-exprstmt.m b/test/Index/complete-at-exprstmt.m
index 85370989fd83..cccfa261ca79 100644
--- a/test/Index/complete-at-exprstmt.m
+++ b/test/Index/complete-at-exprstmt.m
@@ -9,6 +9,16 @@
@synchronized (@encode(MyClass)) { }
}
@end
+
+@interface A
++ (int)add:(int)x to:(int)y;
++ (int)add:(int)x to:(int)y plus:(int)z;
+@end
+
+void f() {
+ @selector(add:to:);
+}
+
// RUN: c-index-test -code-completion-at=%s:9:4 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: {TypedText encode}{LeftParen (}{Placeholder type-name}{RightParen )}
// CHECK-CC1: {TypedText protocol}{LeftParen (}{Placeholder protocol-name}{RightParen )}
@@ -35,3 +45,11 @@
// CHECK-CC3: ObjCInterfaceDecl:{TypedText MyClass}
// CHECK-CC3: TypedefDecl:{TypedText SEL}
// CHECK-CC3: NotImplemented:{ResultType MyClass *}{TypedText self}
+// RUN: c-index-test -code-completion-at=%s:19:13 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: NotImplemented:{TypedText add:to:} (30)
+// CHECK-CC4: NotImplemented:{TypedText add:to:plus:} (30)
+// CHECK-CC4: NotImplemented:{TypedText myMethod:} (30)
+// RUN: c-index-test -code-completion-at=%s:19:17 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: NotImplemented:{Informative add:}{TypedText to:} (30)
+// CHECK-CC5: NotImplemented:{Informative add:}{TypedText to:plus:} (30)
+
diff --git a/test/Index/complete-blocks.m b/test/Index/complete-blocks.m
new file mode 100644
index 000000000000..7233efb8b00f
--- /dev/null
+++ b/test/Index/complete-blocks.m
@@ -0,0 +1,24 @@
+// The line and column layout of this test is significant. Run lines
+// are at the end.
+typedef void (^block_t)(float f, double d);
+void f(int (^block)(int x, int y));
+void g(block_t b);
+
+void test_f() {
+
+}
+
+@interface A
+- method:(int (^)(int x, int y))b;
+- method2:(block_t)b;
+@end
+
+void test_A(A *a) {
+ [a method:0];
+}
+// RUN: c-index-test -code-completion-at=%s:8:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText f}{LeftParen (}{Placeholder int (^)(int x, int y)}{RightParen )} (45)
+// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{Placeholder void (^)(float f, double d)}{RightParen )} (45)
+// RUN: c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType id}{TypedText method2:}{Placeholder void (^)(float f, double d)} (20)
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType id}{TypedText method:}{Placeholder int (^)(int x, int y)} (20)
diff --git a/test/Index/complete-ctor-inits.cpp b/test/Index/complete-ctor-inits.cpp
new file mode 100644
index 000000000000..f9cc7022eafb
--- /dev/null
+++ b/test/Index/complete-ctor-inits.cpp
@@ -0,0 +1,40 @@
+// The run lines are below, because this test is line- and
+// column-number sensitive.
+
+template<typename T>
+struct X {
+ X(T);
+};
+
+struct Virt { };
+struct Y : virtual Virt { };
+
+struct Z : public X<int>, public Y {
+ Z();
+
+ int a, b, c;
+};
+
+Z::Z() : ::X<int>(0), Virt(), b(), c() { }
+
+// RUN: c-index-test -code-completion-at=%s:18:10 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20)
+
+// RUN: c-index-test -code-completion-at=%s:18:23 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (7)
+
+// RUN: c-index-test -code-completion-at=%s:18:36 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20)
+// CHECK-CC3-NOT: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )}
+// CHECK-CC3: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7)
+// CHECK-CC3-NOT: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )}
+// CHECK-CC3: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20)
diff --git a/test/Index/complete-declarators.cpp b/test/Index/complete-declarators.cpp
new file mode 100644
index 000000000000..8fba4db2f988
--- /dev/null
+++ b/test/Index/complete-declarators.cpp
@@ -0,0 +1,39 @@
+// This test is line- and column-sensitive, so test commands are at the bottom.
+namespace N {
+ struct X {
+ int f(X);
+ };
+}
+
+int g(int a);
+
+struct Y { };
+
+struct Z {
+ int member;
+ friend int N::X::f(N::X);
+};
+
+// RUN: c-index-test -code-completion-at=%s:8:5 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: NotImplemented:{TypedText const} (30)
+// CHECK-CC1: Namespace:{TypedText N}{Text ::} (75)
+// CHECK-CC1: NotImplemented:{TypedText operator} (30)
+// CHECK-CC1: NotImplemented:{TypedText volatile} (30)
+// RUN: c-index-test -code-completion-at=%s:8:11 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: NotImplemented:{TypedText const} (30)
+// CHECK-CC2-NOT: Namespace:{TypedText N}{Text ::} (75)
+// CHECK-CC2-NOT: NotImplemented:{TypedText operator} (30)
+// CHECK-CC2: NotImplemented:{TypedText volatile} (30)
+// RUN: c-index-test -code-completion-at=%s:13:7 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: NotImplemented:{TypedText const} (30)
+// CHECK-CC3-NOT: Namespace:{TypedText N}{Text ::} (75)
+// CHECK-CC3: NotImplemented:{TypedText operator} (30)
+// CHECK-CC3: NotImplemented:{TypedText volatile} (30)
+// RUN: c-index-test -code-completion-at=%s:14:14 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: NotImplemented:{TypedText const} (30)
+// CHECK-CC4: Namespace:{TypedText N}{Text ::} (75)
+// CHECK-CC4: NotImplemented:{TypedText operator} (30)
+// CHECK-CC4: NotImplemented:{TypedText volatile} (30)
+// CHECK-CC4: StructDecl:{TypedText Y} (65)
+// CHECK-CC4: StructDecl:{TypedText Z} (20)
+
diff --git a/test/Index/complete-declarators.m b/test/Index/complete-declarators.m
new file mode 100644
index 000000000000..3a69282df437
--- /dev/null
+++ b/test/Index/complete-declarators.m
@@ -0,0 +1,45 @@
+// This test is line- and column-sensitive, so test commands are at the bottom.
+@protocol P
+- (int)method:(id)param1;
+@end
+
+@interface A <P>
+- (int)method:(id)param1;
+
+@property int prop1;
+@end
+
+@implementation A
+- (int)method:(id)param1 {
+ int q2;
+ for(id q in param1) {
+ int y;
+ }
+ id q;
+ for(q in param1) {
+ int y;
+ }
+}
+@end
+
+// RUN: c-index-test -code-completion-at=%s:7:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1-NOT: NotImplemented:{TypedText extern} (30)
+// CHECK-CC1: NotImplemented:{TypedText param1} (30)
+// RUN: c-index-test -code-completion-at=%s:9:15 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:15:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:16:9 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: NotImplemented:{TypedText const} (30)
+// CHECK-CC2-NOT: int
+// CHECK-CC2: NotImplemented:{TypedText restrict} (30)
+// CHECK-CC2: NotImplemented:{TypedText volatile} (30)
+// RUN: c-index-test -code-completion-at=%s:15:15 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ParmDecl:{ResultType id}{TypedText param1} (8)
+// CHECK-CC3-NOT: VarDecl:{ResultType int}{TypedText q2} (8)
+// CHECK-CC3-NOT: VarDecl:{ResultType id}{TypedText q} (8)
+// CHECK-CC3: NotImplemented:{ResultType A *}{TypedText self} (8)
+// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
+// RUN: c-index-test -code-completion-at=%s:15:15 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: ParmDecl:{ResultType id}{TypedText param1} (8)
+// CHECK-CC4-NOT: VarDecl:{ResultType int}{TypedText q2} (8)
+// CHECK-CC4: NotImplemented:{ResultType A *}{TypedText self} (8)
+// CHECK-CC4: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c
index b7bed8c5fde8..2a7a1e212122 100644
--- a/test/Index/complete-exprs.c
+++ b/test/Index/complete-exprs.c
@@ -1,27 +1,37 @@
// Note: the run lines follow their respective tests, since line/column
// matter in this test.
-int f(int);
+int f(int) __attribute__((unavailable));
int test(int i, int j, int k, int l) {
return i | j | k & l;
}
-struct X f1 = { 17 };
+struct X __attribute__((deprecated)) f1 = { 17 };
void f2() { f1(17); }
const char *str = "Hello, \nWorld";
+void f3(const char*, ...) __attribute__((sentinel(0)));
+
+#define NULL __null
+void f4(const char* str) {
+ f3(str, NULL);
+}
// RUN: c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: NotImplemented:{TypedText __PRETTY_FUNCTION__} (60)
// CHECK-CC1: macro definition:{TypedText __VERSION__} (70)
-// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12)
-// CHECK-CC1-NOT: NotImplemented:{TypedText float} (40)
+// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12) (unavailable)
+// CHECK-CC1-NOT: NotImplemented:{TypedText float} (65)
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2)
// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: macro definition:{TypedText __VERSION__} (70)
// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
-// CHECK-CC3-NOT: NotImplemented:{TypedText float} (40)
+// CHECK-CC3-NOT: NotImplemented:{TypedText float} (65)
// CHECK-CC3: ParmDecl:{ResultType int}{TypedText j} (8)
// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expressio
@@ -30,13 +40,14 @@ const char *str = "Hello, \nWorld";
// RUN: c-index-test -code-completion-at=%s:7:2 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: macro definition:{TypedText __VERSION__} (70)
// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
-// CHECK-CC2: NotImplemented:{TypedText float} (40)
+// CHECK-CC2: NotImplemented:{TypedText float} (65)
// CHECK-CC2: ParmDecl:{ResultType int}{TypedText j} (8)
// CHECK-CC2: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
// RUN: c-index-test -code-completion-at=%s:11:16 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
-// CHECK-CC4: VarDecl:{ResultType struct X}{TypedText f1} (50)
+// CHECK-CC4: VarDecl:{ResultType struct X}{TypedText f1} (50) (deprecated)
-// RUN: c-index-test -code-completion-at=%s:13:28 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: NotImplemented:{TypedText void} (40)
-// CHECK-CC5: NotImplemented:{TypedText volatile} (40)
+// RUN: c-index-test -code-completion-at=%s:19:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC6 %s
+// CHECK-CC6: FunctionDecl:{ResultType void}{TypedText f3}{LeftParen (}{Placeholder char const *, ...}{Text , NULL}{RightParen )} (45)
+// CHECK-CC6: NotImplemented:{TypedText void} (65)
+// CHECK-CC6: NotImplemented:{TypedText volatile} (65)
diff --git a/test/Index/complete-hiding.c b/test/Index/complete-hiding.c
new file mode 100644
index 000000000000..f2e177571c0c
--- /dev/null
+++ b/test/Index/complete-hiding.c
@@ -0,0 +1,29 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+struct StructA { };
+struct StructB { };
+struct StructC { };
+int ValueA;
+int ValueB;
+
+void f() {
+
+ int ValueA = 0;
+ int StructA = 0;
+ struct StructB { };
+
+ struct StructA sa = { };
+}
+
+// RUN: c-index-test -code-completion-at=%s:16:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:16:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: VarDecl:{ResultType int}{TypedText StructA} (8)
+// CHECK-CC1: VarDecl:{ResultType int}{TypedText ValueA} (8)
+// CHECK-CC1-NOT: VarDecl:{ResultType int}{TypedText ValueA} (50)
+// CHECK-CC1: VarDecl:{ResultType int}{TypedText ValueB} (50)
+// RUN: c-index-test -code-completion-at=%s:16:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: StructDecl:{TypedText StructA} (65)
+// CHECK-CC2-NOT: StructDecl:{TypedText StructB} (65)
+// CHECK-CC2: StructDecl:{TypedText StructC} (65)
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:16:10 %s | FileCheck -check-prefix=CHECK-CC2 %s
diff --git a/test/Index/complete-macros.c b/test/Index/complete-macros.c
index 9a898e152a7f..26a63b151b7b 100644
--- a/test/Index/complete-macros.c
+++ b/test/Index/complete-macros.c
@@ -16,9 +16,12 @@ void f2() {
}
// RUN: c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: macro definition:{TypedText FOO}{LeftParen (}{Placeholder Arg1}{Comma , }{Placeholder Arg2}{RightParen )}
// RUN: c-index-test -code-completion-at=%s:13:13 %s | FileCheck -check-prefix=CHECK-CC2 %s
// RUN: c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: macro definition:{TypedText nil} (30)
// RUN: c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: macro definition:{TypedText nil} (60)
diff --git a/test/Index/complete-memfunc-cvquals.cpp b/test/Index/complete-memfunc-cvquals.cpp
new file mode 100644
index 000000000000..4e2e8200ab51
--- /dev/null
+++ b/test/Index/complete-memfunc-cvquals.cpp
@@ -0,0 +1,86 @@
+// The run lines are below, because this test is line- and
+// column-number sensitive.
+struct Foo {
+ void babble() const volatile;
+ void bar();
+ void baz() const;
+ void bingo() volatile;
+ void theend() const volatile;
+};
+
+template<typename T>
+struct smart_ptr {
+ T *operator->();
+ const T* operator->() const;
+};
+
+void text(Foo f, Foo *fp, const Foo &fc, const Foo *fcp,
+ smart_ptr<Foo> sf, const smart_ptr<Foo> &sfc, Foo volatile *fvp) {
+ f.bar();
+ fp->bar();
+ fc.baz();
+ fcp->baz();
+ sf->bar();
+ sfc->baz();
+ fvp->babble();
+}
+
+void Foo::bar() {
+
+}
+
+void Foo::baz() const {
+
+}
+
+void Foo::bingo() volatile {
+
+}
+
+// Check member access expressions.
+// RUN: c-index-test -code-completion-at=%s:19:5 %s | FileCheck -check-prefix=CHECK-NOQUALS %s
+// RUN: c-index-test -code-completion-at=%s:20:7 %s | FileCheck -check-prefix=CHECK-NOQUALS %s
+// RUN: c-index-test -code-completion-at=%s:23:7 %s | FileCheck -check-prefix=CHECK-NOQUALS %s
+// CHECK-NOQUALS: CXXMethod:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative const volatile} (20)
+// CHECK-NOQUALS: CXXMethod:{ResultType void}{TypedText bar}{LeftParen (}{RightParen )} (19)
+// CHECK-NOQUALS: CXXMethod:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative const} (20)
+// CHECK-NOQUALS: CXXMethod:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative volatile} (20)
+// RUN: c-index-test -code-completion-at=%s:21:6 %s | FileCheck -check-prefix=CHECK-CONST %s
+// RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CONST %s
+// RUN: c-index-test -code-completion-at=%s:24:8 %s | FileCheck -check-prefix=CHECK-CONST %s
+// CHECK-CONST: CXXMethod:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative const volatile} (20)
+// CHECK-CONST-NOT: bar
+// CHECK-CONST: CXXMethod:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative const} (19)
+// CHECK-CONST-NOT: bingo
+// CHECK-CONST: theend
+// RUN: c-index-test -code-completion-at=%s:25:8 %s | FileCheck -check-prefix=CHECK-VOLATILE %s
+// CHECK-VOLATILE: CXXMethod:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative const volatile} (20)
+// CHECK-VOLATILE-NOT: baz
+// CHECK-VOLATILE: CXXMethod:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative volatile} (19)
+
+// Check implicit member access expressions.
+// RUN: c-index-test -code-completion-at=%s:29:2 %s | FileCheck -check-prefix=CHECK-IMPLICIT-NOQUALS %s
+// CHECK-IMPLICIT-NOQUALS: CXXMethod:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative const volatile} (15)
+// CHECK-IMPLICIT-NOQUALS: CXXMethod:{ResultType void}{TypedText bar}{LeftParen (}{RightParen )} (14)
+// CHECK-IMPLICIT-NOQUALS: CXXMethod:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative const} (15)
+// CHECK-IMPLICIT-NOQUALS: CXXMethod:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative volatile} (15)
+
+// RUN: c-index-test -code-completion-at=%s:33:1 %s | FileCheck -check-prefix=CHECK-IMPLICIT-CONST %s
+// CHECK-IMPLICIT-CONST: CXXMethod:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative const volatile} (15)
+// CHECK-IMPLICIT-CONST-NOT: bar
+// CHECK-IMPLICIT-CONST: CXXMethod:{ResultType void}{TypedText baz}{LeftParen (}{RightParen )}{Informative const} (14)
+// CHECK-IMPLICIT-CONST-NOT: bingo
+// CHECK-IMPLICIT-CONST: theend
+
+// RUN: c-index-test -code-completion-at=%s:37:1 %s | FileCheck -check-prefix=CHECK-IMPLICIT-VOLATILE %s
+// CHECK-IMPLICIT-VOLATILE: CXXMethod:{ResultType void}{TypedText babble}{LeftParen (}{RightParen )}{Informative const volatile} (15)
+// CHECK-IMPLICIT-VOLATILE-NOT: baz
+// CHECK-IMPLICIT-VOLATILE: CXXMethod:{ResultType void}{TypedText bingo}{LeftParen (}{RightParen )}{Informative volatile} (14)
+
+// RUN: c-index-test -code-completion-at=%s:4:17 %s | FileCheck -check-prefix=CHECK-CVQUAL-AFTER %s
+// CHECK-CVQUAL-AFTER: NotImplemented:{TypedText const} (30)
+// CHECK-CVQUAL-AFTER: NotImplemented:{TypedText volatile} (30)
+
+// RUN: c-index-test -code-completion-at=%s:4:23 %s | FileCheck -check-prefix=CHECK-CVQUAL-AFTER2 %s
+// CHECK-CVQUAL-AFTER2-NOT: NotImplemented:{TypedText const} (30)
+// CHECK-CVQUAL-AFTER2: NotImplemented:{TypedText volatile} (30)
diff --git a/test/Index/complete-method-decls.m b/test/Index/complete-method-decls.m
index a30874b8a28e..1324ae4a6970 100644
--- a/test/Index/complete-method-decls.m
+++ b/test/Index/complete-method-decls.m
@@ -52,43 +52,51 @@
- (int)first:(int)x second2:(float)y third:(double)z;
@end
+@implementation D
+- (int)first:(int)x second2:(float)y third:(double)z { }
+@end
+
+@interface Passing
+- (oneway void)method:(in id x);
+@end
+
// RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText abc}
-// CHECK-CC1: NotImplemented:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}
-// CHECK-CC1: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}
-// CHECK-CC1: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}
-// CHECK-CC1: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc}
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}
+// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}
// RUN: c-index-test -code-completion-at=%s:17:7 %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: NotImplemented:{TypedText abc}
-// CHECK-CC2-NEXT: NotImplemented:{TypedText getSelf}
-// CHECK-CC2: NotImplemented:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}
-// CHECK-CC2: NotImplemented:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}
+// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText abc}
+// CHECK-CC2-NEXT: ObjCInstanceMethodDecl:{TypedText getSelf}
+// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}
+// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}
// RUN: c-index-test -code-completion-at=%s:24:7 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: NotImplemented:{TypedText abc}
-// CHECK-CC3-NEXT: NotImplemented:{TypedText getSelf}
-// CHECK-CC3: NotImplemented:{TypedText init}
-// CHECK-CC3: NotImplemented:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}
-// CHECK-CC3: NotImplemented:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}
+// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText abc}
+// CHECK-CC3-NEXT: ObjCInstanceMethodDecl:{TypedText getSelf}
+// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText init}
+// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}
+// CHECK-CC3: ObjCInstanceMethodDecl:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}
// RUN: c-index-test -code-completion-at=%s:33:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText abc}
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text int}{RightParen )}{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC4: NotImplemented:{LeftParen (}{Text int}{RightParen )}{TypedText setValue}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Text return}{HorizontalSpace }{Placeholder expression}{SemiColon ;}{VerticalSpace }{RightBrace }} (32)
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Text return}{HorizontalSpace }{Placeholder expression}{SemiColon ;}{VerticalSpace }{RightBrace }} (30)
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText setValue}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// RUN: c-index-test -code-completion-at=%s:33:8 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: NotImplemented:{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC5: NotImplemented:{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// CHECK-CC5-NOT: {TypedText getSelf}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC5: NotImplemented:{TypedText setValue}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText setValue}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// RUN: c-index-test -code-completion-at=%s:37:7 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC6 %s
-// CHECK-CC6: NotImplemented:{TypedText abc}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC6: ObjCInstanceMethodDecl:{TypedText abc}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// CHECK-CC6-NOT: getSelf
-// CHECK-CC6: NotImplemented:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
-// CHECK-CC6: NotImplemented:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC6: ObjCInstanceMethodDecl:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC6: ObjCInstanceMethodDecl:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// RUN: c-index-test -code-completion-at=%s:42:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC7 %s
-// CHECK-CC7: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText categoryFunction}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
+// CHECK-CC7: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText categoryFunction}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// RUN: c-index-test -code-completion-at=%s:52:21 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC8 %s
// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y2}{HorizontalSpace }{Text third:}{Text (double)z} (20)
// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType void *}{Informative first:}{TypedText second3:}{Text (float)y3}{HorizontalSpace }{Text third:}{Text (double)z} (20)
@@ -99,5 +107,53 @@
// CHECK-CC9: NotImplemented:{TypedText xxx} (30)
// RUN: c-index-test -code-completion-at=%s:52:36 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CCA %s
// CHECK-CCA: NotImplemented:{TypedText y2} (30)
-
-
+// RUN: c-index-test -code-completion-at=%s:56:3 %s | FileCheck -check-prefix=CHECK-CCB %s
+// CHECK-CCB: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText first}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second2}{Colon :}{LeftParen (}{Text float}{RightParen )}{Text y}{HorizontalSpace }{Text third}{Colon :}{LeftParen (}{Text double}{RightParen )}{Text z} (30)
+// RUN: c-index-test -code-completion-at=%s:56:8 %s | FileCheck -check-prefix=CHECK-CCC %s
+// CHECK-CCC: ObjCInstanceMethodDecl:{TypedText first}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second2}{Colon :}{LeftParen (}{Text float}{RightParen )}{Text y}{HorizontalSpace }{Text third}{Colon :}{LeftParen (}{Text double}{RightParen )}{Text z} (30)
+// RUN: c-index-test -code-completion-at=%s:56:21 %s | FileCheck -check-prefix=CHECK-CCD %s
+// FIXME: These results could be more precise.
+// CHECK-CCD: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y2}{HorizontalSpace }{Text third:}{Text (double)z} (20)
+// CHECK-CCD: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{TypedText second2:}{Text (float)y}{HorizontalSpace }{Text third:}{Text (double)z} (5)
+// CHECK-CCD: ObjCInstanceMethodDecl:{ResultType void *}{Informative first:}{TypedText second3:}{Text (float)y3}{HorizontalSpace }{Text third:}{Text (double)z} (20)
+// CHECK-CCD: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{TypedText second:}{Text (float)y}{HorizontalSpace }{Text third:}{Text (double)z} (5)
+// RUN: c-index-test -code-completion-at=%s:56:38 %s | FileCheck -check-prefix=CHECK-CCE %s
+// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (20)
+// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (5)
+// RUN: c-index-test -code-completion-at=%s:60:4 %s | FileCheck -check-prefix=CHECK-CCF %s
+// CHECK-CCF: ObjCInterfaceDecl:{TypedText A} (65)
+// CHECK-CCF: ObjCInterfaceDecl:{TypedText B} (65)
+// CHECK-CCF: NotImplemented:{TypedText bycopy} (30)
+// CHECK-CCF: NotImplemented:{TypedText byref} (30)
+// CHECK-CCF: NotImplemented:{TypedText in} (30)
+// CHECK-CCF: NotImplemented:{TypedText inout} (30)
+// CHECK-CCF: NotImplemented:{TypedText oneway} (30)
+// CHECK-CCF: NotImplemented:{TypedText out} (30)
+// CHECK-CCF: NotImplemented:{TypedText unsigned} (65)
+// CHECK-CCF: NotImplemented:{TypedText void} (65)
+// CHECK-CCF: NotImplemented:{TypedText volatile} (65)
+// RUN: c-index-test -code-completion-at=%s:60:11 %s | FileCheck -check-prefix=CHECK-CCG %s
+// CHECK-CCG: ObjCInterfaceDecl:{TypedText A} (65)
+// CHECK-CCG: ObjCInterfaceDecl:{TypedText B} (65)
+// CHECK-CCG-NOT: NotImplemented:{TypedText bycopy} (30)
+// CHECK-CCG-NOT: NotImplemented:{TypedText byref} (30)
+// CHECK-CCG: NotImplemented:{TypedText in} (30)
+// CHECK-CCG: NotImplemented:{TypedText inout} (30)
+// CHECK-CCG-NOT: NotImplemented:{TypedText oneway} (30)
+// CHECK-CCG: NotImplemented:{TypedText out} (30)
+// CHECK-CCG: NotImplemented:{TypedText unsigned} (65)
+// CHECK-CCG: NotImplemented:{TypedText void} (65)
+// CHECK-CCG: NotImplemented:{TypedText volatile} (65)
+// RUN: c-index-test -code-completion-at=%s:60:24 %s | FileCheck -check-prefix=CHECK-CCF %s
+// RUN: c-index-test -code-completion-at=%s:60:26 %s | FileCheck -check-prefix=CHECK-CCH %s
+// CHECK-CCH: ObjCInterfaceDecl:{TypedText A} (65)
+// CHECK-CCH: ObjCInterfaceDecl:{TypedText B} (65)
+// CHECK-CCH: NotImplemented:{TypedText bycopy} (30)
+// CHECK-CCH: NotImplemented:{TypedText byref} (30)
+// CHECK-CCH-NOT: NotImplemented:{TypedText in} (30)
+// CHECK-CCH: NotImplemented:{TypedText inout} (30)
+// CHECK-CCH: NotImplemented:{TypedText oneway} (30)
+// CHECK-CCH: NotImplemented:{TypedText out} (30)
+// CHECK-CCH: NotImplemented:{TypedText unsigned} (65)
+// CHECK-CCH: NotImplemented:{TypedText void} (65)
+// CHECK-CCH: NotImplemented:{TypedText volatile} (65)
diff --git a/test/Index/complete-natural.m b/test/Index/complete-natural.m
new file mode 100644
index 000000000000..e1aba393ae71
--- /dev/null
+++ b/test/Index/complete-natural.m
@@ -0,0 +1,56 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+const char *in_string = "string";
+char in_char = 'a';
+// in comment
+/* in comment */
+#warning blarg
+#error blarg
+#pragma mark this is the spot
+// RUN: c-index-test -code-completion-at=%s:4:32 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// CHECK-CC1-NOT: :
+// CHECK-CC1: DONE
+// RUN: c-index-test -code-completion-at=%s:5:18 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: c-index-test -code-completion-at=%s:6:7 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: c-index-test -code-completion-at=%s:7:7 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: c-index-test -code-completion-at=%s:8:10 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: c-index-test -code-completion-at=%s:9:9 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: c-index-test -code-completion-at=%s:10:19 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+
+// Same tests as above, but with completion caching.
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:4:32 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:5:18 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:6:7 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:7 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:8:10 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:9:9 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:10:19 %s > %t
+// RUN: echo "DONE" >> %t
+// RUN: FileCheck -check-prefix=CHECK-CC1 %s < %t
diff --git a/test/Index/complete-objc-message-id.m b/test/Index/complete-objc-message-id.m
index a75ee4a81d5c..be42b9b855ef 100644
--- a/test/Index/complete-objc-message-id.m
+++ b/test/Index/complete-objc-message-id.m
@@ -26,6 +26,11 @@ void message_id(B *b) {
[[b superclass] B_method];
}
+@implementation Unrelated
++ (id)alloc {
+ return [A alloc];
+}
+@end
// RUN: c-index-test -code-completion-at=%s:24:14 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: ObjCInstanceMethodDecl:{ResultType id}{TypedText autorelease}
// CHECK-CC1-NOT: B_method
@@ -40,3 +45,10 @@ void message_id(B *b) {
// CHECK-CC3: ObjCInstanceMethodDecl:{ResultType id}{TypedText retain}
+// RUN: c-index-test -code-completion-at=%s:31:13 %s | FileCheck -check-prefix=CHECK-SELECTOR-PREF %s
+// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType id}{TypedText alloc} (17)
+// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType Class}{TypedText class} (20)
+// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType id}{TypedText init} (20)
+// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType id}{TypedText new} (20)
+// CHECK-SELECTOR-PREF: ObjCClassMethodDecl:{ResultType Class}{TypedText superclass} (20)
+
diff --git a/test/Index/complete-objc-message.m b/test/Index/complete-objc-message.m
index 321d75f3fe17..f9d671037ba5 100644
--- a/test/Index/complete-objc-message.m
+++ b/test/Index/complete-objc-message.m
@@ -1,6 +1,6 @@
// Note: the run lines follow their respective tests, since line/column
// matter in this test.
-
+#define nil (void*)0
@protocol FooTestProtocol
+ protocolClassMethod;
- protocolInstanceMethod : (int)value;
@@ -96,9 +96,9 @@ void test_overload(Overload *ovl) {
}
@interface Ellipsis
-- (int)Method:(int)i, ...;
+- (int)Method:(int)i, ...;
+- (int)SentinelMethod:(int)i, ... __attribute__((sentinel(0,1)));
@end
-
void f(Ellipsis *e) {
[e Method:1, 2, 3];
}
@@ -122,43 +122,55 @@ void msg_id(id x) {
[id Method:1 Arg1:1 OtherArg:ovl];
}
+@interface A
+- (void)method1;
+@end
+
+@interface B : A
+- (void)method2;
+@end
+
+void test_ranking(B *b) {
+ [b method1];
+}
+
// 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}{HorizontalSpace }{Text withKeyword:}{Placeholder (int)b}
+// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace }{Text withKeyword:}{Placeholder (int)}
// 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}
+// CHECK-CC2: {TypedText protocolInstanceMethod:}{Placeholder (int)}
// RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)obj}
+// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)}
// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyPrivateMethod}
// RUN: c-index-test -code-completion-at=%s:65:16 %s | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)x}{HorizontalSpace }{Text second:}{Placeholder (id)y}
+// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{Text second:}{Placeholder (id)}
// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyPrivateInstMethod}
// RUN: c-index-test -code-completion-at=%s:74:9 %s | FileCheck -check-prefix=CHECK-CC5 %s
-// CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)x}{HorizontalSpace }{Text second:}{Placeholder (id)y}
+// CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{Text second:}{Placeholder (id)}
// CHECK-CC5: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod}
// RUN: c-index-test -code-completion-at=%s:82:8 %s | FileCheck -check-prefix=CHECK-CC6 %s
-// CHECK-CC6: ObjCInstanceMethodDecl:{ResultType id}{TypedText protocolInstanceMethod:}{Placeholder (int)value}
+// CHECK-CC6: ObjCInstanceMethodDecl:{ResultType id}{TypedText protocolInstanceMethod:}{Placeholder (int)}
// CHECK-CC6: ObjCInstanceMethodDecl:{ResultType int}{TypedText secondProtocolInstanceMethod}
// RUN: c-index-test -code-completion-at=%s:95:8 %s | FileCheck -check-prefix=CHECK-CC7 %s
// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method}
-// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i}
-// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text SomeArg:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
+// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)}
+// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
+// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
+// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)}{HorizontalSpace }{Text SomeArg:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
+// CHECK-CC7: ObjCInstanceMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
// RUN: c-index-test -code-completion-at=%s:95:17 %s | FileCheck -check-prefix=CHECK-CC8 %s
// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText }
-// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText SomeArg:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{TypedText SomeArg:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
// RUN: c-index-test -code-completion-at=%s:95:24 %s | FileCheck -check-prefix=CHECK-CC9 %s
-// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
-// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj}
+// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)}
+// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)}
// RUN: c-index-test -code-completion-at=%s:61:11 %s | FileCheck -check-prefix=CHECK-CCA %s
// CHECK-CCA: TypedefDecl:{TypedText Class}
// CHECK-CCA-NEXT: ObjCInterfaceDecl:{TypedText Foo}
@@ -170,22 +182,23 @@ void msg_id(id x) {
// CHECK-CCA: {ResultType Class}{TypedText self}
// CHECK-CCA: {TypedText super}
// RUN: c-index-test -code-completion-at=%s:103:6 %s | FileCheck -check-prefix=CHECK-CCB %s
-// CHECK-CCB: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i}{Placeholder , ...}
+// CHECK-CCB: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int), ...}
+// CHECK-CCB: ObjCInstanceMethodDecl:{ResultType int}{TypedText SentinelMethod:}{Placeholder (int), ...}{Text , nil}
// RUN: c-index-test -code-completion-at=%s:116:14 %s | FileCheck -check-prefix=CHECK-CCC %s
// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method}
-// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i}
-// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text SomeArg:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
+// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)}
+// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
+// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
+// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)}{HorizontalSpace }{Text SomeArg:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
+// CHECK-CCC: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
// RUN: c-index-test -code-completion-at=%s:116:23 %s | FileCheck -check-prefix=CHECK-CCD %s
// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText }
-// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText SomeArg:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
+// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
+// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText Arg1:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
+// CHECK-CCD: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{TypedText SomeArg:}{Placeholder (int)}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)}
// RUN: c-index-test -code-completion-at=%s:116:30 %s | FileCheck -check-prefix=CHECK-CCE %s
-// CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)i2}
-// CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)obj}
+// CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText Arg2:}{Placeholder (int)}
+// CHECK-CCE: ObjCClassMethodDecl:{ResultType int}{Informative Method:}{Informative Arg1:}{TypedText OtherArg:}{Placeholder (id)}
// RUN: c-index-test -code-completion-at=%s:61:11 %s | FileCheck -check-prefix=CHECK-CCF %s
// CHECK-CCF: TypedefDecl:{TypedText Class}
// CHECK-CCF: ObjCInterfaceDecl:{TypedText Foo}
@@ -199,31 +212,25 @@ void msg_id(id x) {
// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText categoryInstanceMethod}
// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText instanceMethod1}
// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text SomeArg:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)x}{HorizontalSpace }{Text second:}{Placeholder (id)y}
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyInstMethod:}{Placeholder (id)}{HorizontalSpace }{Text second:}{Placeholder (id)}
// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MyPrivateInstMethod}
// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText MySubInstMethod:}{Placeholder (id)obj}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText protocolInstanceMethod:}{Placeholder (int)value}
+// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType id}{TypedText protocolInstanceMethod:}{Placeholder (int)}
// CHECK-CCG: ObjCInstanceMethodDecl:{ResultType int}{TypedText secondProtocolInstanceMethod}
// RUN: c-index-test -code-completion-at=%s:121:14 %s | FileCheck -check-prefix=CHECK-CCG %s
// RUN: c-index-test -code-completion-at=%s:122:7 %s | FileCheck -check-prefix=CHECK-CCH %s
// CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText categoryClassMethod}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod1:}{Placeholder (id)a}{HorizontalSpace }{Text withKeyword:}{Placeholder (int)b}
+// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace }{Text withKeyword:}{Placeholder (int)}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType void}{TypedText classMethod2}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText Method}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)i}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (float)f}{HorizontalSpace }{Text SomeArg:}{Placeholder (int)i1}{HorizontalSpace }{Text OtherArg:}{Placeholder (id)obj}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)obj}
+// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText Method:}{Placeholder (int)}
+// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText MyPrivateMethod}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText MySubClassMethod}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText MySubPrivateMethod}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText new}
-// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2}
+// CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)}{HorizontalSpace }{Text Arg1:}{Placeholder (int)}{HorizontalSpace }{Text Arg2:}{Placeholder (int)}
// CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText protocolClassMethod}
+// RUN: c-index-test -code-completion-at=%s:134:6 %s | FileCheck -check-prefix=CHECK-CCI %s
+// CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method1} (22)
+// CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} (20)
diff --git a/test/Index/complete-pch.m b/test/Index/complete-pch.m
index 09192ae1139d..517d49c6351e 100644
--- a/test/Index/complete-pch.m
+++ b/test/Index/complete-pch.m
@@ -16,11 +16,11 @@ void msg_id(id x) {
// Run the actual tests
// RUN: c-index-test -code-completion-at=%s:10:7 -include %t.h %s | FileCheck -check-prefix=CHECK-CC1 %s
-// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod1:}{Placeholder (double)d}
-// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod2:}{Placeholder (float)f}
-// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod3:}{Placeholder (float)f}
+// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod1:}{Placeholder (double)}
+// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod2:}{Placeholder (float)}
+// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod3:}{Placeholder (float)}
// RUN: c-index-test -code-completion-at=%s:11:6 -include %t.h %s | FileCheck -check-prefix=CHECK-CC2 %s
-// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod1:}{Placeholder (int)x}
-// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod2:}{Placeholder (int)x}
-// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod3:}{Placeholder (int)x}
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod1:}{Placeholder (int)}
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod2:}{Placeholder (int)}
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod3:}{Placeholder (int)}
diff --git a/test/Index/complete-preprocessor.m b/test/Index/complete-preprocessor.m
new file mode 100644
index 000000000000..1873dad6f359
--- /dev/null
+++ b/test/Index/complete-preprocessor.m
@@ -0,0 +1,80 @@
+// The line and column layout of this test is significant. Run lines
+// are at the end.
+
+#if 1
+#endif
+
+#define FOO(a, b) a##b
+#define BAR
+#ifdef FOO
+#endif
+#if defined(FOO)
+#endif
+
+FOO(in,t) value;
+
+// RUN: c-index-test -code-completion-at=%s:4:2 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: NotImplemented:{TypedText define}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText define}{HorizontalSpace }{Placeholder macro}{LeftParen (}{Placeholder args}{RightParen )} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText error}{HorizontalSpace }{Placeholder message} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText if}{HorizontalSpace }{Placeholder condition} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText ifdef}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText ifndef}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText import}{HorizontalSpace }{Text "}{Placeholder header}{Text "} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText import}{HorizontalSpace }{Text <}{Placeholder header}{Text >} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText include}{HorizontalSpace }{Text "}{Placeholder header}{Text "} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText include}{HorizontalSpace }{Text <}{Placeholder header}{Text >} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText include_next}{HorizontalSpace }{Text "}{Placeholder header}{Text "} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText include_next}{HorizontalSpace }{Text <}{Placeholder header}{Text >} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText line}{HorizontalSpace }{Placeholder number} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText line}{HorizontalSpace }{Placeholder number}{HorizontalSpace }{Text "}{Placeholder filename}{Text "} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText pragma}{HorizontalSpace }{Placeholder arguments} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText undef}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC1-NEXT: NotImplemented:{TypedText warning}{HorizontalSpace }{Placeholder message} (30)
+// RUN: c-index-test -code-completion-at=%s:5:2 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: NotImplemented:{TypedText define}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText define}{HorizontalSpace }{Placeholder macro}{LeftParen (}{Placeholder args}{RightParen )} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText elif}{HorizontalSpace }{Placeholder condition} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText else} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText endif} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText error}{HorizontalSpace }{Placeholder message} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText if}{HorizontalSpace }{Placeholder condition} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText ifdef}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText ifndef}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText import}{HorizontalSpace }{Text "}{Placeholder header}{Text "} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText import}{HorizontalSpace }{Text <}{Placeholder header}{Text >} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText include}{HorizontalSpace }{Text "}{Placeholder header}{Text "} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText include}{HorizontalSpace }{Text <}{Placeholder header}{Text >} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText include_next}{HorizontalSpace }{Text "}{Placeholder header}{Text "} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText include_next}{HorizontalSpace }{Text <}{Placeholder header}{Text >} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText line}{HorizontalSpace }{Placeholder number} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText line}{HorizontalSpace }{Placeholder number}{HorizontalSpace }{Text "}{Placeholder filename}{Text "} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText pragma}{HorizontalSpace }{Placeholder arguments} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText undef}{HorizontalSpace }{Placeholder macro} (30)
+// CHECK-CC2-NEXT: NotImplemented:{TypedText warning}{HorizontalSpace }{Placeholder message} (30)
+// RUN: c-index-test -code-completion-at=%s:9:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: NotImplemented:{TypedText BAR} (30)
+// CHECK-CC3: NotImplemented:{TypedText FOO} (30)
+// RUN: c-index-test -code-completion-at=%s:11:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:11:13 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:11:5 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: macro definition:{TypedText BAR} (70)
+// CHECK-CC4: macro definition:{TypedText FOO}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (70)
+// RUN: c-index-test -code-completion-at=%s:14:5 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: NotImplemented:{TypedText const} (65)
+// CHECK-CC5: NotImplemented:{TypedText double} (65)
+// CHECK-CC5: NotImplemented:{TypedText enum} (65)
+// CHECK-CC5: NotImplemented:{TypedText extern} (30)
+// CHECK-CC5: NotImplemented:{TypedText float} (65)
+// CHECK-CC5: macro definition:{TypedText FOO}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (70)
+// CHECK-CC5: TypedefDecl:{TypedText id} (65)
+// CHECK-CC5: NotImplemented:{TypedText inline} (30)
+// CHECK-CC5: NotImplemented:{TypedText int} (65)
+// CHECK-CC5: NotImplemented:{TypedText long} (65)
+
+// Same tests as above, but with completion caching.
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:4:2 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:5:2 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:9:8 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:11:5 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:14:5 %s | FileCheck -check-prefix=CHECK-CC5 %s
diff --git a/test/Index/complete-recovery.m b/test/Index/complete-recovery.m
index e03834ee15b7..fbd92c794d8f 100644
--- a/test/Index/complete-recovery.m
+++ b/test/Index/complete-recovery.m
@@ -18,7 +18,7 @@
// CHECK-CC1: VarDecl:{ResultType A *}{TypedText a}
// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )}
-// RUN: c-index-test -code-completion-at=%s:10:24 -Xclang -code-completion-patterns %s 2>%t | FileCheck -check-prefix=CHECK-CC2 %s
+// RUN: c-index-test -code-completion-at=%s:10:24 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: NotImplemented:{TypedText @encode}{LeftParen (}{Placeholder type-name}{RightParen )}
// CHECK-CC2: NotImplemented:{TypedText _Bool}
// CHECK-CC2: VarDecl:{ResultType A *}{TypedText a}
diff --git a/test/Index/complete-super.cpp b/test/Index/complete-super.cpp
new file mode 100644
index 000000000000..49f94e40d245
--- /dev/null
+++ b/test/Index/complete-super.cpp
@@ -0,0 +1,33 @@
+// The run lines are below, because this test is line- and
+// column-number sensitive.
+
+struct A {
+ virtual void foo(int x, int y);
+ virtual void bar(double x);
+ virtual void bar(float x);
+};
+
+struct B : A {
+ void foo(int a, int b);
+ void bar(float real);
+};
+
+void B::foo(int a, int b) {
+ A::foo(a, b);
+}
+
+void B::bar(float real) {
+ A::bar(real);
+}
+
+// RUN: c-index-test -code-completion-at=%s:16:3 %s | FileCheck -check-prefix=CHECK-FOO-UNQUAL %s
+// CHECK-FOO-UNQUAL: CXXMethod:{Text A::}{TypedText foo}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (8)
+
+// RUN: c-index-test -code-completion-at=%s:20:3 %s | FileCheck -check-prefix=CHECK-BAR-UNQUAL %s
+// CHECK-BAR-UNQUAL: CXXMethod:{Text A::}{TypedText bar}{LeftParen (}{Placeholder real}{RightParen )} (8)
+// CHECK-BAR-UNQUAL: CXXMethod:{ResultType void}{TypedText bar}{LeftParen (}{Placeholder float real}{RightParen )} (14)
+// CHECK-BAR-UNQUAL: CXXMethod:{ResultType void}{Text A::}{TypedText bar}{LeftParen (}{Placeholder double x}{RightParen )} (16)
+
+// RUN: c-index-test -code-completion-at=%s:16:6 %s | FileCheck -check-prefix=CHECK-FOO-QUAL %s
+// CHECK-FOO-QUAL: CXXMethod:{TypedText foo}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (8)
+
diff --git a/test/Index/complete-super.m b/test/Index/complete-super.m
new file mode 100644
index 000000000000..fc60c6c42d6a
--- /dev/null
+++ b/test/Index/complete-super.m
@@ -0,0 +1,55 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+typedef int Bool;
+
+@interface A
+- (void)add:(int)x to:(int)y;
++ (void)select:(Bool)condition first:(int)x second:(int)y;
+- (void)last;
++ (void)last;
+@end
+
+@interface B : A
+- (void)add:(int)x to:(int)y;
++ (void)select:(Bool)condition first:(int)x second:(int)y;
+@end
+
+@implementation B
+- (void)add:(int)a to:(int)b {
+ [super add:a to:b];
+}
+
++ (void)select:(Bool)condition first:(int)a second:(int)b {
+ [super selector:condition first:a second:b];
+}
+@end
+
+// Check "super" completion as a message receiver.
+// RUN: c-index-test -code-completion-at=%s:20:4 %s | FileCheck -check-prefix=CHECK-ADD-RECEIVER %s
+// CHECK-ADD-RECEIVER: ObjCInstanceMethodDecl:{ResultType void}{TypedText super}{HorizontalSpace }{Text add:}{Placeholder a}{HorizontalSpace }{Text to:}{Placeholder b} (8)
+
+// RUN: c-index-test -code-completion-at=%s:24:4 %s | FileCheck -check-prefix=CHECK-SELECT-RECEIVER %s
+// CHECK-SELECT-RECEIVER: ObjCClassMethodDecl:{ResultType void}{TypedText super}{HorizontalSpace }{Text select:}{Placeholder condition}{HorizontalSpace }{Text first:}{Placeholder a}{HorizontalSpace }{Text second:}{Placeholder b} (8)
+
+// Check "super" completion at the first identifier
+// RUN: c-index-test -code-completion-at=%s:20:10 %s | FileCheck -check-prefix=CHECK-ADD-ADD %s
+// CHECK-ADD-ADD: ObjCInstanceMethodDecl:{ResultType void}{TypedText add:}{Placeholder a}{HorizontalSpace }{Text to:}{Placeholder b} (8)
+// CHECK-ADD-ADD-NOT: add
+// CHECK-ADD-ADD: ObjCInstanceMethodDecl:{ResultType void}{TypedText last} (20)
+
+// RUN: c-index-test -code-completion-at=%s:24:10 %s | FileCheck -check-prefix=CHECK-SELECTOR-SELECTOR %s
+// CHECK-SELECTOR-SELECTOR-NOT: x
+// CHECK-SELECTOR-SELECTOR: ObjCClassMethodDecl:{ResultType void}{TypedText last} (20)
+// CHECK-SELECTOR-SELECTOR: ObjCClassMethodDecl:{ResultType void}{TypedText select:}{Placeholder condition}{HorizontalSpace }{Text first:}{Placeholder a}{HorizontalSpace }{Text second:}{Placeholder b} (8)
+
+// Check "super" completion at the second identifier
+// RUN: c-index-test -code-completion-at=%s:20:16 %s | FileCheck -check-prefix=CHECK-ADD-TO %s
+// CHECK-ADD-TO: ObjCInstanceMethodDecl:{ResultType void}{Informative add:}{TypedText to:}{Placeholder b} (8)
+
+// RUN: c-index-test -code-completion-at=%s:24:28 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s
+// CHECK-SELECTOR-FIRST: ObjCClassMethodDecl:{ResultType void}{Informative select:}{TypedText first:}{Placeholder a}{HorizontalSpace }{Text second:}{Placeholder b} (8)
+
+// Check "super" completion at the third identifier
+// RUN: c-index-test -code-completion-at=%s:24:37 %s | FileCheck -check-prefix=CHECK-SELECTOR-SECOND %s
+// CHECK-SELECTOR-SECOND: ObjCClassMethodDecl:{ResultType void}{Informative select:}{Informative first:}{TypedText second:}{Placeholder b} (8)
diff --git a/test/Index/complete-templates.cpp b/test/Index/complete-templates.cpp
new file mode 100644
index 000000000000..2f2302d08d82
--- /dev/null
+++ b/test/Index/complete-templates.cpp
@@ -0,0 +1,19 @@
+// Tests are line- and column-sensive, so run lines are below.
+
+template<typename T>
+class X {
+ X();
+ X(const X&);
+
+ template<typename U> X(U);
+};
+
+template<typename T> void f(T);
+
+void test() {
+
+}
+
+// RUN: c-index-test -code-completion-at=%s:14:2 %s | FileCheck %s
+// CHECK: FunctionTemplate:{ResultType void}{TypedText f}{LeftParen (}{Placeholder T}{RightParen )} (45)
+// CHECK: ClassTemplate:{TypedText X}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50)
diff --git a/test/Index/complete-unterminated.c b/test/Index/complete-unterminated.c
new file mode 100644
index 000000000000..56e6ae13786e
--- /dev/null
+++ b/test/Index/complete-unterminated.c
@@ -0,0 +1,30 @@
+typedef int Integer;
+
+#if 0
+
+
+#endif
+
+/* blah */
+
+void f0(const char*);
+void f1(char);
+
+const char *hello = "Hello, world";
+const char a = 'a';
+
+#define FOO(a, b) a b
+
+FOO(int, x);
+
+// RUN: c-index-test -code-completion-at=%s:5:1 -pedantic %s 2> %t.err | FileCheck %s
+// RUN: not grep error %t.err
+// CHECK: {TypedText Integer}
+// RUN: c-index-test -code-completion-at=%s:8:6 -pedantic %s 2> %t.err
+// RUN: not grep error %t.err
+// RUN: c-index-test -code-completion-at=%s:10:28 -pedantic %s 2> %t.err
+// RUN: not grep unterminated %t.err
+// RUN: c-index-test -code-completion-at=%s:11:17 -pedantic %s 2> %t.err
+// RUN: not grep unterminated %t.err
+// RUN: c-index-test -code-completion-at=%s:18:10 -pedantic %s 2> %t.err
+// RUN: not grep unterminated %t.err
diff --git a/test/Index/crash-recovery-code-complete.c b/test/Index/crash-recovery-code-complete.c
new file mode 100644
index 000000000000..a80bdc2aee80
--- /dev/null
+++ b/test/Index/crash-recovery-code-complete.c
@@ -0,0 +1,10 @@
+// RUN: env CINDEXTEST_EDITING=1 \
+// RUN: not c-index-test -code-completion-at=%s:20:1 \
+// RUN: "-remap-file=%s;%S/Inputs/crash-recovery-code-complete-remap.c" \
+// RUN: %s 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-CODE-COMPLETE-CRASH %s
+// CHECK-CODE-COMPLETE-CRASH: Unable to perform code completion!
+//
+// REQUIRES: crash-recovery
+
+#warning parsing original file
diff --git a/test/Index/crash-recovery-reparse.c b/test/Index/crash-recovery-reparse.c
new file mode 100644
index 000000000000..e394bd18dfb5
--- /dev/null
+++ b/test/Index/crash-recovery-reparse.c
@@ -0,0 +1,10 @@
+// RUN: env CINDEXTEST_EDITING=1 \
+// RUN: not c-index-test -test-load-source-reparse 1 local \
+// RUN: -remap-file="%s;%S/Inputs/crash-recovery-reparse-remap.c" \
+// RUN: %s 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-REPARSE-SOURCE-CRASH %s
+// CHECK-REPARSE-SOURCE-CRASH: Unable to reparse translation unit
+//
+// REQUIRES: crash-recovery
+
+#warning parsing original file
diff --git a/test/Index/crash-recovery.c b/test/Index/crash-recovery.c
new file mode 100644
index 000000000000..b7f6e0b2b9e9
--- /dev/null
+++ b/test/Index/crash-recovery.c
@@ -0,0 +1,7 @@
+// RUN: not c-index-test -test-load-source all %s 2> %t.err
+// RUN: FileCheck < %t.err -check-prefix=CHECK-LOAD-SOURCE-CRASH %s
+// CHECK-LOAD-SOURCE-CRASH: Unable to load translation unit
+//
+// REQUIRES: crash-recovery
+
+#pragma clang __debug crash
diff --git a/test/Index/index-templates.cpp b/test/Index/index-templates.cpp
new file mode 100644
index 000000000000..a4f1ee8d2c80
--- /dev/null
+++ b/test/Index/index-templates.cpp
@@ -0,0 +1,147 @@
+// Test is line- and column-sensitive. See run lines below.
+
+template<typename T, T Value, template<typename U, U ValU> class X>
+void f(X<T, Value> x);
+
+template<typename T> class allocator;
+
+template<typename T, typename Alloc = allocator<T> >
+class vector {
+ void clear();
+};
+
+template<typename T>
+class vector<T*> { };
+
+struct Z1 { };
+
+template class vector<Z1>;
+
+struct Z2 { };
+
+template<>
+class vector<Z2> {
+ void clear();
+};
+
+template<typename T, typename U>
+struct Y {
+ using typename T::type;
+ using U::operator Z2;
+};
+
+struct Z3 { };
+
+const unsigned OneDimension = 1;
+template<typename T, unsigned Dimensions = OneDimension>
+struct array { };
+
+template<template<typename, unsigned> class DataStructure = array>
+struct storage { };
+
+typedef unsigned Unsigned;
+
+template<typename T, Unsigned Value>
+struct value_c;
+
+template class vector<int*>;
+
+struct Z4 {
+ template<typename T> T getAs();
+};
+
+void template_exprs() {
+ f<Unsigned, OneDimension, array>(array<Unsigned, OneDimension>());
+ Z4().getAs<Unsigned>();
+}
+
+// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-LOAD %s
+// CHECK-LOAD: index-templates.cpp:4:6: FunctionTemplate=f:4:6 Extent=[3:1 - 4:22]
+// CHECK-LOAD: index-templates.cpp:3:19: TemplateTypeParameter=T:3:19 (Definition) Extent=[3:19 - 3:20]
+// CHECK-LOAD: index-templates.cpp:3:24: NonTypeTemplateParameter=Value:3:24 (Definition) Extent=[3:22 - 3:29]
+// FIXME: Need the template type parameter here
+// CHECK-LOAD: index-templates.cpp:3:66: TemplateTemplateParameter=X:3:66 (Definition) Extent=[3:31 - 3:67]
+// CHECK-LOAD: index-templates.cpp:4:20: ParmDecl=x:4:20 (Definition) Extent=[4:8 - 4:21]
+// CHECK-LOAD: index-templates.cpp:4:8: TemplateRef=X:3:66 Extent=[4:8 - 4:9]
+// FIXME: Need the template type parameter here
+// CHECK-LOAD: index-templates.cpp:4:13: DeclRefExpr=Value:3:24 Extent=[4:13 - 4:18]
+// CHECK-LOAD: index-templates.cpp:6:28: ClassTemplate=allocator:6:28 Extent=[6:1 - 6:37]
+// CHECK-LOAD: index-templates.cpp:6:19: TemplateTypeParameter=T:6:19 (Definition) Extent=[6:19 - 6:20]
+// CHECK-LOAD: index-templates.cpp:9:7: ClassTemplate=vector:9:7 (Definition) Extent=[8:1 - 11:2]
+// CHECK-LOAD: index-templates.cpp:8:19: TemplateTypeParameter=T:8:19 (Definition) Extent=[8:19 - 8:20]
+// CHECK-LOAD: index-templates.cpp:8:31: TemplateTypeParameter=Alloc:8:31 (Definition) Extent=[8:31 - 8:36]
+// CHECK-LOAD: index-templates.cpp:8:39: TemplateRef=allocator:6:28 Extent=[8:39 - 8:48]
+// CHECK-LOAD: index-templates.cpp:10:8: CXXMethod=clear:10:8 Extent=[10:8 - 10:15]
+// CHECK-LOAD: index-templates.cpp:14:7: ClassTemplatePartialSpecialization=vector:14:7 (Definition) [Specialization of vector:9:7] Extent=[13:1 - 14:21]
+// CHECK-LOAD: index-templates.cpp:13:19: TemplateTypeParameter=T:13:19 (Definition) Extent=[13:19 - 13:20]
+// CHECK-LOAD: index-templates.cpp:16:8: StructDecl=Z1:16:8 (Definition) Extent=[16:1 - 16:14]
+// CHECK-LOAD: index-templates.cpp:18:16: ClassDecl=vector:18:16 (Definition) [Specialization of vector:9:7] Extent=[18:1 - 18:22]
+// CHECK-LOAD: index-templates.cpp:18:23: TypeRef=struct Z1:16:8 Extent=[18:23 - 18:25]
+// CHECK-LOAD-NOT: CXXMethod=clear
+// CHECK-LOAD: index-templates.cpp:20:8: StructDecl=Z2:20:8 (Definition) Extent=[20:1 - 20:14]
+// CHECK-LOAD: index-templates.cpp:23:7: ClassDecl=vector:23:7 (Definition) [Specialization of vector:9:7] Extent=[22:1 - 25:2]
+// CHECK-LOAD: index-templates.cpp:23:14: TypeRef=struct Z2:20:8 Extent=[23:14 - 23:16]
+// CHECK-LOAD: index-templates.cpp:24:8: CXXMethod=clear:24:8 Extent=[24:8 - 24:15]
+// CHECK-LOAD: index-templates.cpp:28:8: ClassTemplate=Y:28:8 (Definition) Extent=[27:1 - 31:2]
+// CHECK-LOAD: index-templates.cpp:27:19: TemplateTypeParameter=T:27:19 (Definition) Extent=[27:19 - 27:20]
+// CHECK-LOAD: index-templates.cpp:27:31: TemplateTypeParameter=U:27:31 (Definition) Extent=[27:31 - 27:32]
+// CHECK-LOAD: index-templates.cpp:29:21: UsingDeclaration=type:29:21 Extent=[29:3 - 29:25]
+// CHECK-LOAD: index-templates.cpp:30:12: UsingDeclaration=operator Z2:30:12 Extent=[30:3 - 30:23]
+// CHECK-LOAD: index-templates.cpp:30:21: TypeRef=struct Z2:20:8 Extent=[30:21 - 30:23]
+// CHECK-LOAD: index-templates.cpp:35:16: VarDecl=OneDimension:35:16 (Definition) Extent=[35:7 - 35:32]
+// CHECK-LOAD: index-templates.cpp:35:31: UnexposedExpr= Extent=[35:31 - 35:32]
+// CHECK-LOAD: index-templates.cpp:35:31: UnexposedExpr= Extent=[35:31 - 35:32]
+// CHECK-LOAD: index-templates.cpp:37:8: ClassTemplate=array:37:8 (Definition) Extent=[36:1 - 37:17]
+// CHECK-LOAD: index-templates.cpp:36:19: TemplateTypeParameter=T:36:19 (Definition) Extent=[36:19 - 36:20]
+// CHECK-LOAD: index-templates.cpp:36:31: NonTypeTemplateParameter=Dimensions:36:31 (Definition) Extent=[36:22 - 36:41]
+// CHECK-LOAD: index-templates.cpp:36:44: DeclRefExpr=OneDimension:35:16 Extent=[36:44 - 36:56]
+// CHECK-LOAD: index-templates.cpp:40:8: ClassTemplate=storage:40:8 (Definition) Extent=[39:1 - 40:19]
+// CHECK-LOAD: index-templates.cpp:39:45: TemplateTemplateParameter=DataStructure:39:45 (Definition) Extent=[39:10 - 39:66]
+// CHECK-LOAD: index-templates.cpp:39:19: TemplateTypeParameter=:39:19 (Definition) Extent=[39:19 - 39:27]
+// CHECK-LOAD: index-templates.cpp:39:37: NonTypeTemplateParameter=:39:37 (Definition) Extent=[39:29 - 39:38]
+// CHECK-LOAD: index-templates.cpp:39:61: TemplateRef=array:37:8 Extent=[39:61 - 39:66]
+// CHECK-LOAD: index-templates.cpp:42:18: TypedefDecl=Unsigned:42:18 (Definition) Extent=[42:18 - 42:26]
+// CHECK-LOAD: index-templates.cpp:45:8: ClassTemplate=value_c:45:8 Extent=[44:1 - 45:15]
+// CHECK-LOAD: index-templates.cpp:44:19: TemplateTypeParameter=T:44:19 (Definition) Extent=[44:19 - 44:20]
+// CHECK-LOAD: index-templates.cpp:44:31: NonTypeTemplateParameter=Value:44:31 (Definition) Extent=[44:22 - 44:36]
+// CHECK-LOAD: index-templates.cpp:44:22: TypeRef=Unsigned:42:18 Extent=[44:22 - 44:30]
+// CHECK-LOAD: index-templates.cpp:47:16: ClassDecl=vector:47:16 (Definition) [Specialization of vector:14:7] Extent=[47:1 - 47:22]
+// CHECK-LOAD: index-templates.cpp:49:8: StructDecl=Z4:49:8 (Definition) Extent=[49:1 - 51:2]
+// CHECK-LOAD: index-templates.cpp:50:26: FunctionTemplate=getAs:50:26 Extent=[50:3 - 50:33]
+// CHECK-LOAD: index-templates.cpp:50:21: TemplateTypeParameter=T:50:21 (Definition) Extent=[50:21 - 50:22]
+// CHECK-LOAD: index-templates.cpp:53:6: FunctionDecl=template_exprs:53:6 (Definition)
+// CHECK-LOAD: <invalid loc>:0:0: UnexposedStmt=
+// CHECK-LOAD: index-templates.cpp:54:3: CallExpr=f:4:6 Extent=[54:3 - 54:68]
+// CHECK-LOAD: index-templates.cpp:54:3: UnexposedExpr=f:4:6 Extent=[54:3 - 54:35]
+// CHECK-LOAD: index-templates.cpp:54:3: DeclRefExpr=f:4:6 Extent=[54:3 - 54:35]
+// CHECK-LOAD: index-templates.cpp:54:5: TypeRef=Unsigned:42:18 Extent=[54:5 - 54:13]
+// CHECK-LOAD: index-templates.cpp:54:15: DeclRefExpr=OneDimension:35:16 Extent=[54:15 - 54:27]
+// CHECK-LOAD: index-templates.cpp:54:29: TemplateRef=array:37:8 Extent=[54:29 - 54:34]
+// CHECK-LOAD: index-templates.cpp:55:8: MemberRefExpr=getAs:50:26 Extent=[55:3 - 55:23]
+// CHECK-LOAD: index-templates.cpp:55:3: CallExpr= Extent=[55:3 - 55:7]
+// CHECK-LOAD: index-templates.cpp:55:14: TypeRef=Unsigned:42:18 Extent=[55:14 - 55:22]
+
+// RUN: c-index-test -test-load-source-usrs all %s | FileCheck -check-prefix=CHECK-USRS %s
+// CHECK-USRS: index-templates.cpp c:@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0# Extent=[3:1 - 4:22]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@79 Extent=[3:19 - 3:20]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@82 Extent=[3:22 - 3:29]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@91 Extent=[3:31 - 3:67]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@136@FT@>3#T#Nt0.0#t>2#T#Nt1.0f#>t0.22t0.0#@x Extent=[4:8 - 4:21]
+// CHECK-USRS: index-templates.cpp c:@CT>1#T@allocator Extent=[6:1 - 6:37]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@171 Extent=[6:19 - 6:20]
+// CHECK-USRS: index-templates.cpp c:@CT>2#T#T@vector Extent=[8:1 - 11:2]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@210 Extent=[8:19 - 8:20]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@222 Extent=[8:31 - 8:36]
+// CHECK-USRS: index-templates.cpp c:@CT>2#T#T@vector@F@clear# Extent=[10:8 - 10:15]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@280@CP>1#T@vector>#*t0.0#>@CT>1#T@allocator1*t0.0 Extent=[13:1 - 14:21]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@298 Extent=[13:19 - 13:20]
+// CHECK-USRS: index-templates.cpp c:@S@Z1 Extent=[16:1 - 16:14]
+// CHECK-USRS: index-templates.cpp c:@C@vector>#$@S@Z1#$@C@allocator>#$@S@Z1 Extent=[18:1 - 18:22]
+// CHECK-USRS: index-templates.cpp c:@S@Z2 Extent=[20:1 - 20:14]
+// CHECK-USRS: index-templates.cpp c:@C@vector>#$@S@Z2#$@C@allocator>#$@S@Z2 Extent=[22:1 - 25:2]
+// CHECK-USRS: index-templates.cpp c:@C@vector>#$@S@Z2#$@C@allocator>#$@S@Z2@F@clear# Extent=[24:8 - 24:15]
+// CHECK-USRS: index-templates.cpp c:@ST>2#T#T@Y Extent=[27:1 - 31:2]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@452 Extent=[27:19 - 27:20]
+// CHECK-USRS: index-templates.cpp c:index-templates.cpp@464 Extent=[27:31 - 27:32]
+// CHECK-USRS-NOT: type
+// CHECK-USRS: index-templates.cpp c:@S@Z3 Extent=[33:1 - 33:14]
diff --git a/test/Index/invalid-rdar-8236270.cpp b/test/Index/invalid-rdar-8236270.cpp
new file mode 100644
index 000000000000..6fd088dcc813
--- /dev/null
+++ b/test/Index/invalid-rdar-8236270.cpp
@@ -0,0 +1,11 @@
+// RUN: c-index-test -test-load-source all %s 2>&1 | FileCheck %s
+
+// This test case previously just crashed the frontend.
+
+struct abc *P;
+int main(
+
+// CHECK: StructDecl=abc:5:8 Extent=[5:1 - 5:11]
+// CHECK: VarDecl=P:5:13 (Definition) Extent=[5:8 - 5:14]
+// CHECK: VarDecl=main:6:5 (Definition) Extent=[6:1 - 6:9]
+
diff --git a/test/Index/load-classes.cpp b/test/Index/load-classes.cpp
new file mode 100644
index 000000000000..349ebdecd750
--- /dev/null
+++ b/test/Index/load-classes.cpp
@@ -0,0 +1,28 @@
+// Test is line- and column-sensitive; see below.
+
+struct X {
+ X(int value);
+ X(const X& x);
+ ~X();
+ operator X*();
+};
+
+X::X(int value) {
+}
+
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+// CHECK: load-classes.cpp:3:8: StructDecl=X:3:8 (Definition) Extent=[3:1 - 8:2]
+// CHECK: load-classes.cpp:4:3: CXXConstructor=X:4:3 Extent=[4:3 - 4:15]
+// FIXME: missing TypeRef in the constructor name
+// CHECK: load-classes.cpp:4:9: ParmDecl=value:4:9 (Definition) Extent=[4:5 - 4:14]
+// CHECK: load-classes.cpp:5:3: CXXConstructor=X:5:3 Extent=[5:3 - 5:16]
+// FIXME: missing TypeRef in the constructor name
+// CHECK: load-classes.cpp:5:14: ParmDecl=x:5:14 (Definition) Extent=[5:11 - 5:15]
+// CHECK: load-classes.cpp:5:11: TypeRef=struct X:3:8 Extent=[5:11 - 5:12]
+// CHECK: load-classes.cpp:6:3: CXXDestructor=~X:6:3 Extent=[6:3 - 6:7]
+// FIXME: missing TypeRef in the destructor name
+// CHECK: load-classes.cpp:7:3: CXXConversion=operator struct X *:7:3 Extent=[7:3 - 7:16]
+// CHECK: load-classes.cpp:7:12: TypeRef=struct X:3:8 Extent=[7:12 - 7:13]
+// CHECK: load-classes.cpp:10:4: CXXConstructor=X:10:4 (Definition) Extent=[10:4 - 11:2]
+// CHECK: load-classes.cpp:10:1: TypeRef=struct X:3:8 Extent=[10:1 - 10:2]
+// CHECK: load-classes.cpp:10:10: ParmDecl=value:10:10 (Definition) Extent=[10:6 - 10:15]
diff --git a/test/Index/load-decls.c b/test/Index/load-decls.c
new file mode 100644
index 000000000000..cf88f4285c66
--- /dev/null
+++ b/test/Index/load-decls.c
@@ -0,0 +1,16 @@
+enum Color {
+ Red,
+ Green,
+ Blue,
+
+ Rouge = Red
+};
+
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+// CHECK: load-decls.c:1:6: EnumDecl=Color:1:6 (Definition) Extent=[1:1 - 7:2]
+// CHECK: load-decls.c:2:3: EnumConstantDecl=Red:2:3 (Definition) Extent=[2:3 - 2:6]
+// CHECK: load-decls.c:3:3: EnumConstantDecl=Green:3:3 (Definition) Extent=[3:3 - 3:8]
+// CHECK: load-decls.c:4:3: EnumConstantDecl=Blue:4:3 (Definition) Extent=[4:3 - 4:7]
+// CHECK: load-decls.c:6:3: EnumConstantDecl=Rouge:6:3 (Definition) Extent=[6:3 - 6:14]
+// CHECK: load-decls.c:6:11: UnexposedExpr=Red:2:3 Extent=[6:11 - 6:14]
+// CHECK: load-decls.c:6:11: DeclRefExpr=Red:2:3 Extent=[6:11 - 6:14]
diff --git a/test/Index/load-namespaces.cpp b/test/Index/load-namespaces.cpp
new file mode 100644
index 000000000000..241e2413a7ac
--- /dev/null
+++ b/test/Index/load-namespaces.cpp
@@ -0,0 +1,50 @@
+// Test is line- and column-sensitive; see below.
+
+namespace std {
+ namespace rel_ops {
+ void f();
+ }
+}
+
+namespace std {
+ void g();
+}
+
+namespace std98 = std;
+namespace std0x = std98;
+
+using namespace std0x;
+
+namespace std {
+ int g(int);
+}
+
+using std::g;
+
+void std::g() {
+}
+
+namespace my_rel_ops = std::rel_ops;
+
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+// CHECK: load-namespaces.cpp:3:11: Namespace=std:3:11 (Definition) Extent=[3:11 - 7:2]
+// CHECK: load-namespaces.cpp:4:13: Namespace=rel_ops:4:13 (Definition) Extent=[4:13 - 6:4]
+// CHECK: load-namespaces.cpp:5:10: FunctionDecl=f:5:10 Extent=[5:10 - 5:13]
+// CHECK: load-namespaces.cpp:9:11: Namespace=std:9:11 (Definition) Extent=[9:11 - 11:2]
+// CHECK: load-namespaces.cpp:10:8: FunctionDecl=g:10:8 Extent=[10:8 - 10:11]
+// CHECK: load-namespaces.cpp:13:11: NamespaceAlias=std98:13:11 Extent=[13:1 - 13:22]
+// CHECK: load-namespaces.cpp:13:19: NamespaceRef=std:3:11 Extent=[13:19 - 13:22]
+// CHECK: load-namespaces.cpp:14:11: NamespaceAlias=std0x:14:11 Extent=[14:1 - 14:24]
+// CHECK: load-namespaces.cpp:14:19: NamespaceRef=std98:13:11 Extent=[14:19 - 14:24]
+// CHECK: load-namespaces.cpp:16:17: UsingDirective=:16:17 Extent=[16:1 - 16:22]
+// CHECK: load-namespaces.cpp:16:17: NamespaceRef=std0x:14:11 Extent=[16:17 - 16:22]
+// CHECK: load-namespaces.cpp:18:11: Namespace=std:18:11 (Definition) Extent=[18:11 - 20:2]
+// CHECK: load-namespaces.cpp:19:7: FunctionDecl=g:19:7 Extent=[19:7 - 19:13]
+// CHECK: load-namespaces.cpp:19:12: ParmDecl=:19:12 (Definition) Extent=[19:9 - 19:13]
+// CHECK: load-namespaces.cpp:22:12: UsingDeclaration=g:22:12 Extent=[22:1 - 22:13]
+// CHECK: load-namespaces.cpp:22:7: NamespaceRef=std:18:11 Extent=[22:7 - 22:10]
+// CHECK: load-namespaces.cpp:24:11: FunctionDecl=g:24:11 (Definition) Extent=[24:11 - 25:2]
+// CHECK: load-namespaces.cpp:24:6: NamespaceRef=std:18:11 Extent=[24:6 - 24:9]
+// CHECK: load-namespaces.cpp:27:11: NamespaceAlias=my_rel_ops:27:11 Extent=[27:1 - 27:36]
+// CHECK: load-namespaces.cpp:27:24: NamespaceRef=std:18:11 Extent=[27:24 - 27:27]
+// CHECK: load-namespaces.cpp:27:29: NamespaceRef=rel_ops:4:13 Extent=[27:29 - 27:36]
diff --git a/test/Index/load-stmts.cpp b/test/Index/load-stmts.cpp
index cb99aee3ad6d..503219f71e15 100644
--- a/test/Index/load-stmts.cpp
+++ b/test/Index/load-stmts.cpp
@@ -10,6 +10,66 @@ void f(int x) {
}
}
+// Test handling of C++ base specifiers.
+class A {
+ void doA();
+};
+
+class B {
+ void doB();
+};
+
+class C : public A, private B {
+ void doC();
+};
+
+class D : virtual public C, virtual private A {};
+
+namespace std {
+ class type_info { };
+}
+
+void test_exprs(C *c) {
+ int typeid_marker;
+ typeid(C);
+ typeid(c);
+ typedef int Integer;
+ Integer *int_ptr;
+ int_ptr->Integer::~Integer();
+}
+
+namespace N {
+ int f(int);
+ float f(float);
+
+ template<typename T> T g(T);
+ template<typename T> T g(T*);
+}
+
+template<typename T>
+void test_dependent_exprs(T t) {
+ N::f(t);
+ typedef T type;
+ N::g<type>(t);
+ type::template f<type*>(t);
+ t->type::template f<type*>();
+}
+
+struct Y {
+ int f(int);
+ float f(float);
+
+ template<typename T> T g(T);
+ template<typename T> T g(T*);
+};
+
+template<typename T>
+void test_more_dependent_exprs(T t, Y y) {
+ y.Y::f(t);
+ typedef T type;
+ y.g<type>(t);
+}
+
// RUN: c-index-test -test-load-source all %s | FileCheck %s
// CHECK: load-stmts.cpp:1:13: TypedefDecl=T:1:13 (Definition) Extent=[1:13 - 1:14]
// CHECK: load-stmts.cpp:2:8: StructDecl=X:2:8 (Definition) Extent=[2:1 - 2:23]
@@ -56,4 +116,47 @@ void f(int x) {
// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:3 - 9:17]
// CHECK: load-stmts.cpp:9:8: UnexposedExpr= Extent=[9:8 - 9:10]
// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:12 - 9:17]
-
+// CHECK: load-stmts.cpp:14:7: ClassDecl=A:14:7 (Definition) Extent=[14:1 - 16:2]
+// CHECK: load-stmts.cpp:15:8: CXXMethod=doA:15:8 Extent=[15:8 - 15:13]
+// CHECK: load-stmts.cpp:18:7: ClassDecl=B:18:7 (Definition) Extent=[18:1 - 20:2]
+// CHECK: load-stmts.cpp:19:8: CXXMethod=doB:19:8 Extent=[19:8 - 19:13]
+// CHECK: load-stmts.cpp:22:7: ClassDecl=C:22:7 (Definition) Extent=[22:1 - 24:2]
+// CHECK: <invalid loc>:0:0: C++ base class specifier=class A:14:7 [access=public isVirtual=false]
+// CHECK: <invalid loc>:0:0: C++ base class specifier=class B:18:7 [access=private isVirtual=false]
+// CHECK: load-stmts.cpp:23:8: CXXMethod=doC:23:8 Extent=[23:8 - 23:13]
+// CHECK: load-stmts.cpp:26:7: ClassDecl=D:26:7 (Definition) Extent=[26:1 - 26:49]
+// CHECK: <invalid loc>:0:0: C++ base class specifier=class C:22:7 [access=public isVirtual=true]
+// CHECK: <invalid loc>:0:0: C++ base class specifier=class A:14:7 [access=private isVirtual=true]
+// CHECK: load-stmts.cpp:33:7: VarDecl=typeid_marker:33:7 (Definition)
+// CHECK: load-stmts.cpp:34:10: TypeRef=class C:22:7 Extent=[34:10 - 34:11]
+// CHECK: load-stmts.cpp:35:10: DeclRefExpr=c:32:20 Extent=[35:10 - 35:11]
+// CHECK: load-stmts.cpp:37:12: VarDecl=int_ptr:37:12 (Definition) Extent=[37:3 - 37:19]
+// CHECK: load-stmts.cpp:37:3: TypeRef=Integer:36:15 Extent=[37:3 - 37:10]
+// CHECK: load-stmts.cpp:38:3: DeclRefExpr=int_ptr:37:12 Extent=[38:3 - 38:10]
+// CHECK: load-stmts.cpp:38:12: TypeRef=Integer:36:15 Extent=[38:12 - 38:19]
+// CHECK: load-stmts.cpp:38:22: TypeRef=Integer:36:15 Extent=[38:22 - 38:29]
+// CHECK: load-stmts.cpp:50:6: FunctionTemplate=test_dependent_exprs:50:6 (Definition)
+// CHECK: load-stmts.cpp:51:3: CallExpr= Extent=[51:3 - 51:10]
+// CHECK: load-stmts.cpp:51:3: NamespaceRef=N:41:11 Extent=[51:3 - 51:4]
+// CHECK: load-stmts.cpp:51:8: DeclRefExpr=t:50:29 Extent=[51:8 - 51:9]
+// CHECK: load-stmts.cpp:52:13: TypedefDecl=type:52:13 (Definition) Extent=[52:13 - 52:17]
+// CHECK: load-stmts.cpp:53:3: CallExpr= Extent=[53:3 - 53:16]
+// CHECK: load-stmts.cpp:53:3: NamespaceRef=N:41:11 Extent=[53:3 - 53:4]
+// CHECK: load-stmts.cpp:53:8: TypeRef=type:52:13 Extent=[53:8 - 53:12]
+// CHECK: load-stmts.cpp:53:14: DeclRefExpr=t:50:29 Extent=[53:14 - 53:15]
+// CHECK: load-stmts.cpp:54:3: CallExpr= Extent=[54:3 - 54:29]
+// CHECK: load-stmts.cpp:54:3: TypeRef=type:52:13 Extent=[54:3 - 54:7]
+// CHECK: load-stmts.cpp:54:20: TypeRef=type:52:13 Extent=[54:20 - 54:24]
+// CHECK: load-stmts.cpp:54:27: DeclRefExpr=t:50:29 Extent=[54:27 - 54:28]
+// CHECK: load-stmts.cpp:55:3: CallExpr= Extent=[55:3 - 55:31]
+// CHECK: load-stmts.cpp:55:3: DeclRefExpr=t:50:29 Extent=[55:3 - 55:4]
+// CHECK: load-stmts.cpp:55:23: TypeRef=type:52:13 Extent=[55:23 - 55:27]
+// CHECK: load-stmts.cpp:67:6: FunctionTemplate=test_more_dependent_exprs:67:6 (Definition)
+// CHECK: load-stmts.cpp:68:3: CallExpr= Extent=[68:3 - 68:12]
+// CHECK: load-stmts.cpp:68:3: DeclRefExpr=y:67:39 Extent=[68:3 - 68:4]
+// CHECK: load-stmts.cpp:68:5: TypeRef=struct Y:58:8 Extent=[68:5 - 68:6]
+// CHECK: load-stmts.cpp:68:10: DeclRefExpr=t:67:34 Extent=[68:10 - 68:11]
+// CHECK: load-stmts.cpp:70:3: CallExpr= Extent=[70:3 - 70:15]
+// CHECK: load-stmts.cpp:70:3: DeclRefExpr=y:67:39 Extent=[70:3 - 70:4]
+// CHECK: load-stmts.cpp:70:7: TypeRef=type:69:13 Extent=[70:7 - 70:11]
+// CHECK: load-stmts.cpp:70:13: DeclRefExpr=t:67:34 Extent=[70:13 - 70:14]
diff --git a/test/Index/local-symbols.m b/test/Index/local-symbols.m
index 8557e7f49b2d..b9f4fe2aeabc 100644
--- a/test/Index/local-symbols.m
+++ b/test/Index/local-symbols.m
@@ -15,6 +15,17 @@
}
@end
+// From: <rdar://problem/8380046>
+
+@protocol Prot8380046
+@end
+
+@interface R8380046
+@end
+
+@interface R8380046 () <Prot8380046>
+@end
+
// CHECK: local-symbols.m:6:12: ObjCInterfaceDecl=Foo:6:12 Extent=[6:1 - 10:5]
// CHECK: local-symbols.m:7:6: ObjCIvarDecl=x:7:6 (Definition) Extent=[7:6 - 7:7]
// CHECK: local-symbols.m:7:3: TypeRef=id:0:0 Extent=[7:3 - 7:5]
@@ -23,4 +34,11 @@
// CHECK: local-symbols.m:12:1: ObjCImplementationDecl=Foo:12:1 (Definition) Extent=[12:1 - 16:2]
// CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) Extent=[13:1 - 15:2]
// CHECK: local-symbols.m:13:4: TypeRef=id:0:0 Extent=[13:4 - 13:6]
+// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
+// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
+// CHECK: local-symbols.m:20:1: ObjCProtocolDecl=Prot8380046:20:1 (Definition) Extent=[20:1 - 21:5]
+// CHECK: local-symbols.m:23:12: ObjCInterfaceDecl=R8380046:23:12 Extent=[23:1 - 24:5]
+// CHECK: local-symbols.m:26:12: ObjCCategoryDecl=:26:12 Extent=[26:1 - 27:5]
+// CHECK: local-symbols.m:26:12: ObjCClassRef=R8380046:23:12 Extent=[26:12 - 26:20]
+// CHECK: local-symbols.m:26:25: ObjCProtocolRef=Prot8380046:20:1 Extent=[26:25 - 26:36]
diff --git a/test/Index/preamble-reparse.c b/test/Index/preamble-reparse.c
new file mode 100644
index 000000000000..5bd03b3f4de4
--- /dev/null
+++ b/test/Index/preamble-reparse.c
@@ -0,0 +1,2 @@
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local "-remap-file=%S/Inputs/preamble-reparse-1.c;%S/Inputs/preamble-reparse-2.c" %S/Inputs/preamble-reparse-1.c | FileCheck %s
+// CHECK: preamble-reparse-1.c:1:5: VarDecl=x:1:5 Extent=[1:1 - 1:6]
diff --git a/test/Index/preamble.c b/test/Index/preamble.c
new file mode 100644
index 000000000000..54abf99ed149
--- /dev/null
+++ b/test/Index/preamble.c
@@ -0,0 +1,28 @@
+#include "prefix.h"
+#include "preamble.h"
+int wibble(int);
+
+void f(int x) {
+
+}
+// RUN: c-index-test -write-pch %t.pch -x c-header %S/Inputs/prefix.h
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -I %S/Inputs -include %t %s 2> %t.stderr.txt | FileCheck %s
+// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt
+// CHECK: preamble.h:1:12: FunctionDecl=bar:1:12 (Definition) Extent=[1:12 - 6:2]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[1:23 - 6:2]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[2:3 - 2:16]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[3:3 - 3:15]
+// CHECK: preamble.h:4:3: UnexposedExpr= Extent=[4:3 - 4:13]
+// CHECK: preamble.h:4:3: DeclRefExpr=ptr:2:8 Extent=[4:3 - 4:6]
+// CHECK: preamble.h:4:9: UnexposedExpr=ptr1:3:10 Extent=[4:9 - 4:13]
+// CHECK: preamble.h:4:9: DeclRefExpr=ptr1:3:10 Extent=[4:9 - 4:13]
+// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[5:3 - 5:11]
+// CHECK: preamble.h:5:10: UnexposedExpr= Extent=[5:10 - 5:11]
+// CHECK: preamble.c:3:5: FunctionDecl=wibble:3:5 Extent=[3:5 - 3:16]
+// CHECK: preamble.c:3:15: ParmDecl=:3:15 (Definition) Extent=[3:12 - 3:16]
+// CHECK-DIAG: preamble.h:4:7:{4:9-4:13}: warning: incompatible pointer types assigning to 'int *' from 'float *'
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:6:1 -I %S/Inputs -include %t %s 2> %t.stderr.txt | FileCheck -check-prefix CHECK-CC %s
+// CHECK-CC: FunctionDecl:{ResultType int}{TypedText bar}{LeftParen (}{Placeholder int i}{RightParen )} (50)
+// CHECK-CC: FunctionDecl:{ResultType void}{TypedText f}{LeftParen (}{Placeholder int x}{RightParen )} (45)
+// CHECK-CC: FunctionDecl:{ResultType int}{TypedText foo}{LeftParen (}{Placeholder int}{RightParen )} (50)
+// CHECK-CC: FunctionDecl:{ResultType int}{TypedText wibble}{LeftParen (}{Placeholder int}{RightParen )} (50)
diff --git a/test/Index/print-typekind.c b/test/Index/print-typekind.c
index 13b41198f127..18189c3c74ac 100644
--- a/test/Index/print-typekind.c
+++ b/test/Index/print-typekind.c
@@ -6,15 +6,20 @@ int *f(int *p, char *x, FooType z) {
}
// RUN: c-index-test -test-print-typekind %s | FileCheck %s
-// CHECK: TypedefDecl=FooType:1:13 (Definition) typekind=Typedef [canonical=Int]
-// CHECK: VarDecl=p:2:6 typekind=Pointer
-// CHECK: FunctionDecl=f:3:6 (Definition) typekind=FunctionProto [canonical=FunctionProto] [result=Pointer]
-// CHECK: ParmDecl=p:3:13 (Definition) typekind=Pointer
-// CHECK: ParmDecl=x:3:22 (Definition) typekind=Pointer
-// CHECK: ParmDecl=z:3:33 (Definition) typekind=Typedef [canonical=Int]
-// CHECK: VarDecl=w:4:11 (Definition) typekind=Typedef [canonical=Int]
-// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int]
-// CHECK: UnexposedExpr= typekind=Pointer
-// CHECK: DeclRefExpr=p:3:13 typekind=Pointer
-// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int]
+// CHECK: TypedefDecl=FooType:1:13 (Definition) typekind=Typedef [canonical=Int] [isPOD=1]
+// CHECK: VarDecl=p:2:6 typekind=Pointer [isPOD=1]
+// CHECK: FunctionDecl=f:3:6 (Definition) typekind=FunctionProto [canonical=FunctionProto] [result=Pointer] [isPOD=0]
+// CHECK: ParmDecl=p:3:13 (Definition) typekind=Pointer [isPOD=1]
+// CHECK: ParmDecl=x:3:22 (Definition) typekind=Pointer [isPOD=1]
+// CHECK: ParmDecl=z:3:33 (Definition) typekind=Typedef [canonical=Int] [isPOD=1]
+// CHECK: TypeRef=FooType:1:13 typekind=Invalid [isPOD=0]
+// CHECK: UnexposedStmt= typekind=Invalid [isPOD=0]
+// CHECK: UnexposedStmt= typekind=Invalid [isPOD=0]
+// CHECK: VarDecl=w:4:11 (Definition) typekind=Typedef [canonical=Int] [isPOD=1]
+// CHECK: TypeRef=FooType:1:13 typekind=Invalid [isPOD=0]
+// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int] [isPOD=1]
+// CHECK: UnexposedStmt= typekind=Invalid [isPOD=0]
+// CHECK: UnexposedExpr= typekind=Pointer [isPOD=1]
+// CHECK: DeclRefExpr=p:3:13 typekind=Pointer [isPOD=1]
+// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int] [isPOD=1]
diff --git a/test/Index/rdar-8288645-invalid-code.mm b/test/Index/rdar-8288645-invalid-code.mm
new file mode 100644
index 000000000000..3405f0a93270
--- /dev/null
+++ b/test/Index/rdar-8288645-invalid-code.mm
@@ -0,0 +1,8 @@
+// RUN: c-index-test -test-load-source all %s 2>&1 | FileCheck %s
+
+// This test case previously crashed Sema.
+
+extern "C" { @implementation Foo - (id)initWithBar:(Baz<WozBar>)pepper {
+
+// CHECK: warning: cannot find interface declaration for 'Foo'
+// CHECK: warning: '@end' is missing in implementation context
diff --git a/test/Index/usrs.cpp b/test/Index/usrs.cpp
index b6a6d3dadab6..698aded84381 100644
--- a/test/Index/usrs.cpp
+++ b/test/Index/usrs.cpp
@@ -55,23 +55,35 @@ extern "C" {
void rez(int a, int b);
}
+namespace foo_alias = foo;
+
+using namespace foo;
+
+namespace foo_alias2 = foo;
+
+using foo::ClsB;
+
+namespace foo_alias3 = foo;
+
// RUN: c-index-test -test-load-source-usrs all %s | FileCheck %s
// CHECK: usrs.cpp c:@N@foo Extent=[1:11 - 4:2]
// CHECK: usrs.cpp c:@N@foo@x Extent=[2:3 - 2:8]
// CHECK: usrs.cpp c:@N@foo@F@bar#I# Extent=[3:8 - 3:18]
-// CHECK: usrs.cpp c:usrs.cpp@3:12@N@foo@F@bar#I#@z Extent=[3:12 - 3:17]
+// CHECK: usrs.cpp c:usrs.cpp@36@N@foo@F@bar#I#@z Extent=[3:12 - 3:17]
// CHECK: usrs.cpp c:@N@bar Extent=[5:11 - 8:2]
-// CHECK: usrs.cpp c:usrs.cpp@6:15@N@bar@T@QType Extent=[6:15 - 6:20]
+// CHECK: usrs.cpp c:usrs.cpp@76@N@bar@T@QType Extent=[6:15 - 6:20]
// CHECK: usrs.cpp c:@N@bar@F@bar#I# Extent=[7:8 - 7:20]
-// CHECK: usrs.cpp c:usrs.cpp@7:12@N@bar@F@bar#I#@z Extent=[7:12 - 7:19]
+// CHECK: usrs.cpp c:usrs.cpp@94@N@bar@F@bar#I#@z Extent=[7:12 - 7:19]
// CHECK: usrs.cpp c:@C@ClsA Extent=[10:1 - 14:2]
+// CHECK: usrs.cpp c: Extent=[11:1 - 11:8]
// CHECK: usrs.cpp c:@C@ClsA@FI@a Extent=[12:7 - 12:8]
// CHECK: usrs.cpp c:@C@ClsA@FI@b Extent=[12:10 - 12:11]
// CHECK: usrs.cpp c:@C@ClsA@F@ClsA#I#I# Extent=[13:3 - 13:37]
-// CHECK: usrs.cpp c:usrs.cpp@13:8@C@ClsA@F@ClsA#I#I#@A Extent=[13:8 - 13:13]
-// CHECK: usrs.cpp c:usrs.cpp@13:15@C@ClsA@F@ClsA#I#I#@B Extent=[13:15 - 13:20]
+// CHECK: usrs.cpp c:usrs.cpp@147@C@ClsA@F@ClsA#I#I#@A Extent=[13:8 - 13:13]
+// CHECK: usrs.cpp c:usrs.cpp@154@C@ClsA@F@ClsA#I#I#@B Extent=[13:15 - 13:20]
// CHECK: usrs.cpp c:@N@foo Extent=[16:11 - 22:2]
// CHECK: usrs.cpp c:@N@foo@C@ClsB Extent=[17:3 - 21:4]
+// CHECK: usrs.cpp c: Extent=[18:3 - 18:10]
// CHECK: usrs.cpp c:@N@foo@C@ClsB@F@ClsB# Extent=[19:5 - 19:27]
// CHECK: usrs.cpp c:@N@foo@C@ClsB@F@result#1 Extent=[20:9 - 20:17]
// CHECK: usrs.cpp c:@N@foo@C@ClsB@F@result#1 Extent=[24:16 - 26:2]
@@ -81,27 +93,32 @@ extern "C" {
// CHECK: usrs.cpp c:@N@foo Extent=[35:11 - 40:2]
// CHECK: usrs.cpp c:@N@foo@N@taz Extent=[35:27 - 39:2]
// CHECK: usrs.cpp c:@N@foo@N@taz@x Extent=[36:3 - 36:8]
-// CHECK: usrs.cpp c:usrs.cpp@37:21@N@foo@N@taz@F@add#I#I# Extent=[37:21 - 37:56]
-// CHECK: usrs.cpp c:usrs.cpp@37:25@N@foo@N@taz@F@add#I#I#@a Extent=[37:25 - 37:30]
-// CHECK: usrs.cpp c:usrs.cpp@37:32@N@foo@N@taz@F@add#I#I#@b Extent=[37:32 - 37:37]
+// CHECK: usrs.cpp c:usrs.cpp@475@N@foo@N@taz@F@add#I#I# Extent=[37:21 - 37:56]
+// CHECK: usrs.cpp c:usrs.cpp@479@N@foo@N@taz@F@add#I#I#@a Extent=[37:25 - 37:30]
+// CHECK: usrs.cpp c:usrs.cpp@486@N@foo@N@taz@F@add#I#I#@b Extent=[37:32 - 37:37]
// CHECK: usrs.cpp c:@N@foo@N@taz@F@sub#I#I# Extent=[38:8 - 38:25]
-// CHECK: usrs.cpp c:usrs.cpp@38:12@N@foo@N@taz@F@sub#I#I#@a Extent=[38:12 - 38:17]
-// CHECK: usrs.cpp c:usrs.cpp@38:19@N@foo@N@taz@F@sub#I#I#@b Extent=[38:19 - 38:24]
+// CHECK: usrs.cpp c:usrs.cpp@522@N@foo@N@taz@F@sub#I#I#@a Extent=[38:12 - 38:17]
+// CHECK: usrs.cpp c:usrs.cpp@529@N@foo@N@taz@F@sub#I#I#@b Extent=[38:19 - 38:24]
// CHECK: usrs.cpp c:@N@foo Extent=[42:11 - 52:3]
// CHECK: usrs.cpp c:@N@foo@N@taz Extent=[42:27 - 52:2]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD Extent=[43:3 - 51:4]
+// CHECK: usrs.cpp c: Extent=[44:3 - 44:10]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD@F@operator=#I# Extent=[45:11 - 45:52]
-// CHECK: usrs.cpp c:usrs.cpp@45:21@N@foo@N@taz@C@ClsD@F@operator=#I#@x Extent=[45:21 - 45:26]
+// CHECK: usrs.cpp c:usrs.cpp@638@N@foo@N@taz@C@ClsD@F@operator=#I#@x Extent=[45:21 - 45:26]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD@F@operator=#d# Extent=[46:11 - 46:61]
-// CHECK: usrs.cpp c:usrs.cpp@46:21@N@foo@N@taz@C@ClsD@F@operator=#d#@x Extent=[46:21 - 46:29]
+// CHECK: usrs.cpp c:usrs.cpp@690@N@foo@N@taz@C@ClsD@F@operator=#d#@x Extent=[46:21 - 46:29]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD@F@operator=#&1$@N@foo@N@taz@C@ClsD# Extent=[47:11 - 47:62]
-// CHECK: usrs.cpp c:usrs.cpp@47:27@N@foo@N@taz@C@ClsD@F@operator=#&1$@N@foo@N@taz@C@ClsD#@x Extent=[47:27 - 47:34]
+// CHECK: usrs.cpp c:usrs.cpp@757@N@foo@N@taz@C@ClsD@F@operator=#&1$@N@foo@N@taz@C@ClsD#@x Extent=[47:27 - 47:34]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD@F@qux#S Extent=[48:16 - 48:21]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD@F@uz#I.#S Extent=[49:16 - 49:30]
-// CHECK: usrs.cpp c:usrs.cpp@49:19@N@foo@N@taz@C@ClsD@F@uz#I.#S@z Extent=[49:19 - 49:24]
+// CHECK: usrs.cpp c:usrs.cpp@833@N@foo@N@taz@C@ClsD@F@uz#I.#S@z Extent=[49:19 - 49:24]
// CHECK: usrs.cpp c:@N@foo@N@taz@C@ClsD@F@operator==#&1$@N@foo@N@taz@C@ClsD#1 Extent=[50:10 - 50:62]
-// CHECK: usrs.cpp c:usrs.cpp@50:27@N@foo@N@taz@C@ClsD@F@operator==#&1$@N@foo@N@taz@C@ClsD#1@x Extent=[50:27 - 50:34]
+// CHECK: usrs.cpp c:usrs.cpp@872@N@foo@N@taz@C@ClsD@F@operator==#&1$@N@foo@N@taz@C@ClsD#1@x Extent=[50:27 - 50:34]
// CHECK: usrs.cpp c:@F@rez Extent=[55:8 - 55:25]
-// CHECK: usrs.cpp c:usrs.cpp@55:12@F@rez@a Extent=[55:12 - 55:17]
-// CHECK: usrs.cpp c:usrs.cpp@55:19@F@rez@b Extent=[55:19 - 55:24]
-
+// CHECK: usrs.cpp c:usrs.cpp@941@F@rez@a Extent=[55:12 - 55:17]
+// CHECK: usrs.cpp c:usrs.cpp@948@F@rez@b Extent=[55:19 - 55:24]
+// CHECK: usrs.cpp c:@NA@foo_alias
+// CHECK-NOT: foo
+// CHECK: usrs.cpp c:@NA@foo_alias2
+// CHECK-NOT: ClsB
+// CHECK: usrs.cpp c:@NA@foo_alias3
diff --git a/test/Index/usrs.m b/test/Index/usrs.m
index 0b56cca1ef64..4b3de5c480ab 100644
--- a/test/Index/usrs.m
+++ b/test/Index/usrs.m
@@ -49,27 +49,39 @@ int z;
static int local_func(int x) { return x; }
@interface CWithExt
+- (id) meth1;
@end
@interface CWithExt ()
+- (id) meth2;
@end
@interface CWithExt ()
+- (id) meth3;
+@end
+@interface CWithExt (Bar)
+- (id) meth4;
@end
@implementation CWithExt
+- (id) meth1 { return 0; }
+- (id) meth2 { return 0; }
+- (id) meth3 { return 0; }
+@end
+@implementation CWithExt (Bar)
+- (id) meth4 { return 0; }
@end
-// CHECK: usrs.m c:usrs.m@3:19@F@my_helper Extent=[3:19 - 3:60]
-// CHECK: usrs.m c:usrs.m@3:29@F@my_helper@x Extent=[3:29 - 3:34]
-// CHECK: usrs.m c:usrs.m@3:36@F@my_helper@y Extent=[3:36 - 3:41]
-// CHECK: usrs.m c:usrs.m@5:1@Ea Extent=[5:1 - 8:2]
-// CHECK: usrs.m c:usrs.m@5:1@Ea@ABA Extent=[6:3 - 6:6]
-// CHECK: usrs.m c:usrs.m@5:1@Ea@CADABA Extent=[7:3 - 7:9]
-// CHECK: usrs.m c:usrs.m@10:1@Ea Extent=[10:1 - 13:2]
-// CHECK: usrs.m c:usrs.m@10:1@Ea@FOO Extent=[11:3 - 11:6]
-// CHECK: usrs.m c:usrs.m@10:1@Ea@BAR Extent=[12:3 - 12:6]
+// CHECK: usrs.m c:usrs.m@85@F@my_helper Extent=[3:19 - 3:60]
+// CHECK: usrs.m c:usrs.m@95@F@my_helper@x Extent=[3:29 - 3:34]
+// CHECK: usrs.m c:usrs.m@102@F@my_helper@y Extent=[3:36 - 3:41]
+// CHECK: usrs.m c:usrs.m@128@Ea Extent=[5:1 - 8:2]
+// CHECK: usrs.m c:usrs.m@128@Ea@ABA Extent=[6:3 - 6:6]
+// CHECK: usrs.m c:usrs.m@128@Ea@CADABA Extent=[7:3 - 7:9]
+// CHECK: usrs.m c:usrs.m@155@Ea Extent=[10:1 - 13:2]
+// CHECK: usrs.m c:usrs.m@155@Ea@FOO Extent=[11:3 - 11:6]
+// CHECK: usrs.m c:usrs.m@155@Ea@BAR Extent=[12:3 - 12:6]
// CHECK: usrs.m c:@SA@MyStruct Extent=[15:9 - 18:2]
// CHECK: usrs.m c:@SA@MyStruct@FI@wa Extent=[16:7 - 16:9]
// CHECK: usrs.m c:@SA@MyStruct@FI@moo Extent=[17:7 - 17:10]
-// CHECK: usrs.m c:usrs.m@18:3@T@MyStruct Extent=[18:3 - 18:11]
+// CHECK: usrs.m c:usrs.m@219@T@MyStruct Extent=[18:3 - 18:11]
// CHECK: usrs.m c:@E@Pizza Extent=[20:1 - 23:2]
// CHECK: usrs.m c:@E@Pizza@CHEESE Extent=[21:3 - 21:9]
// CHECK: usrs.m c:@E@Pizza@MUSHROOMS Extent=[22:3 - 22:12]
@@ -81,21 +93,30 @@ static int local_func(int x) { return x; }
// CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[30:1 - 30:17]
// CHECK: usrs.m c:objc(cs)Foo(im)d1 Extent=[31:15 - 31:17]
// CHECK: usrs.m c:objc(cs)Foo(im)setD1: Extent=[31:15 - 31:17]
-// CHECK: usrs.m c:usrs.m@31:15objc(cs)Foo(im)setD1:@d1 Extent=[31:15 - 31:17]
+// CHECK: usrs.m c:usrs.m@352objc(cs)Foo(im)setD1:@d1 Extent=[31:15 - 31:17]
// CHECK: usrs.m c:objc(cs)Foo Extent=[34:1 - 45:2]
// CHECK: usrs.m c:objc(cs)Foo(im)godzilla Extent=[35:1 - 39:2]
-// CHECK: usrs.m c:usrs.m@36:10objc(cs)Foo(im)godzilla@a Extent=[36:10 - 36:19]
+// CHECK: usrs.m c:usrs.m@409objc(cs)Foo(im)godzilla@a Extent=[36:10 - 36:19]
// CHECK: usrs.m c:objc(cs)Foo(im)godzilla@z Extent=[37:10 - 37:15]
// CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[40:1 - 43:2]
-// CHECK: usrs.m c:usrs.m@41:3objc(cs)Foo(cm)kingkong@local_var Extent=[41:3 - 41:16]
+// CHECK: usrs.m c:usrs.m@470objc(cs)Foo(cm)kingkong@local_var Extent=[41:3 - 41:16]
// CHECK: usrs.m c:objc(cs)Foo@d1 Extent=[44:13 - 44:15]
// CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[44:1 - 44:15]
// CHECK: usrs.m c:@z Extent=[47:1 - 47:6]
-// CHECK: usrs.m c:usrs.m@49:12@F@local_func Extent=[49:12 - 49:43]
-// CHECK: usrs.m c:usrs.m@49:23@F@local_func@x Extent=[49:23 - 49:28]
-// CHECK: usrs.m c:objc(cs)CWithExt Extent=[51:1 - 52:5]
-// CHECK: usrs.m c:objc(cy)CWithExt@ Extent=[53:1 - 54:5]
-// CHECK: usrs.m c:objc(cy)CWithExt@ Extent=[55:1 - 56:5]
-// CHECK: usrs.m c:objc(cs)CWithExt Extent=[57:1 - 58:2]
-
+// CHECK: usrs.m c:usrs.m@540@F@local_func Extent=[49:12 - 49:43]
+// CHECK: usrs.m c:usrs.m@551@F@local_func@x Extent=[49:23 - 49:28]
+// CHECK: usrs.m c:objc(cs)CWithExt Extent=[51:1 - 53:5]
+// CHECK: usrs.m c:objc(cs)CWithExt(im)meth1 Extent=[52:1 - 52:14]
+// CHECK: usrs.m c:objc(ext)CWithExt@usrs.m@612 Extent=[54:1 - 56:5]
+// CHECK: usrs.m c:objc(cs)CWithExt(im)meth2 Extent=[55:1 - 55:14]
+// CHECK: usrs.m c:objc(ext)CWithExt@usrs.m@654 Extent=[57:1 - 59:5]
+// CHECK: usrs.m c:objc(cs)CWithExt(im)meth3 Extent=[58:1 - 58:14]
+// CHECK: usrs.m c:objc(cy)CWithExt@Bar Extent=[60:1 - 62:5]
+// CHECK: usrs.m c:objc(cy)CWithExt@Bar(im)meth4 Extent=[61:1 - 61:14]
+// CHECK: usrs.m c:objc(cs)CWithExt Extent=[63:1 - 67:2]
+// CHECK: usrs.m c:objc(cs)CWithExt(im)meth1 Extent=[64:1 - 64:27]
+// CHECK: usrs.m c:objc(cs)CWithExt(im)meth2 Extent=[65:1 - 65:27]
+// CHECK: usrs.m c:objc(cs)CWithExt(im)meth3 Extent=[66:1 - 66:27]
+// CHECK: usrs.m c:objc(cy)CWithExt@Bar Extent=[68:1 - 70:2]
+// CHECK: usrs.m c:objc(cy)CWithExt@Bar(im)meth4 Extent=[69:1 - 69:27]
diff --git a/test/Lexer/c90.c b/test/Lexer/c90.c
index 6293d42a2f61..f19139710280 100644
--- a/test/Lexer/c90.c
+++ b/test/Lexer/c90.c
@@ -11,3 +11,19 @@ b;}
// comment accepted as extension /* expected-error {{// comments are not allowed in this language}}
+void test2() {
+ const char * str =
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds" // expected-error{{string literal of length 845 exceeds maximum length 509 that C90 compilers are required to support}}
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds"
+ "sdjflksdjf lksdjf skldfjsdkljflksdjf kldsjflkdsj fldks jflsdkjfds";
+}
diff --git a/test/Lexer/constants.c b/test/Lexer/constants.c
index 2602ec255656..de0962e97d22 100644
--- a/test/Lexer/constants.c
+++ b/test/Lexer/constants.c
@@ -62,3 +62,6 @@ double t1[] = {
-1.9e500, // expected-warning {{too large}}
-1.9e-500 // expected-warning {{too small}}
};
+
+// PR7888
+double g = 1e100000000; // expected-warning {{too large}}
diff --git a/test/Lexer/has_feature_cxx0x.cpp b/test/Lexer/has_feature_cxx0x.cpp
index 650e577ca72c..cc2ae28c58b0 100644
--- a/test/Lexer/has_feature_cxx0x.cpp
+++ b/test/Lexer/has_feature_cxx0x.cpp
@@ -99,3 +99,13 @@ int no_variadic_templates();
// CHECK-0X: no_variadic_templates
// CHECK-NO-0X: no_variadic_templates
+
+
+#if __has_feature(cxx_inline_namespaces)
+int inline_namespaces();
+#else
+int no_inline_namespaces();
+#endif
+
+// CHECK-0X: inline_namespaces
+// CHECK-NO-0X: inline_namespaces
diff --git a/test/Lexer/constants-ms.c b/test/Lexer/ms-extensions.c
index 97e660080d45..8b7d2e1efc0c 100644
--- a/test/Lexer/constants-ms.c
+++ b/test/Lexer/ms-extensions.c
@@ -23,3 +23,19 @@ void a() {
unsigned short s = USHORT;
unsigned char c = UCHAR;
}
+
+void pr_7968()
+{
+ int var1 = 0x1111111e+1;
+ int var2 = 0X1111111e+1;
+ int var3 = 0xe+1;
+ int var4 = 0XE+1;
+
+ int var5= 0\
+x1234e+1;
+
+ int var6=
+ /*expected-warning {{backslash and newline separated by space}} */ 0\
+x1234e+1;
+}
+
diff --git a/test/Lexer/preamble.c b/test/Lexer/preamble.c
new file mode 100644
index 000000000000..69cdbb7f241e
--- /dev/null
+++ b/test/Lexer/preamble.c
@@ -0,0 +1,37 @@
+// Preamble detection test: see below for comments and test commands.
+//
+#include <blah>
+#ifndef FOO
+#else
+#ifdef BAR
+#elif WIBBLE
+#endif
+#pragma unknown
+#endif
+#ifdef WIBBLE
+#include "honk"
+#else
+int foo();
+#endif
+
+// This test checks for detection of the preamble of a file, which
+// includes all of the starting comments and #includes. Note that any
+// changes to the preamble part of this file must be mirrored in
+// Inputs/preamble.txt, since we diff against it.
+
+// RUN: %clang_cc1 -print-preamble %s > %t
+// RUN: echo END. >> %t
+// RUN: FileCheck < %t %s
+// XFAIL: win32
+
+// CHECK: // Preamble detection test: see below for comments and test commands.
+// CHECK-NEXT: //
+// CHECK-NEXT: #include <blah>
+// CHECK-NEXT: #ifndef FOO
+// CHECK-NEXT: #else
+// CHECK-NEXT: #ifdef BAR
+// CHECK-NEXT: #elif WIBBLE
+// CHECK-NEXT: #endif
+// CHECK-NEXT: #pragma unknown
+// CHECK-NEXT: #endif
+// CHECK-NEXT: END.
diff --git a/test/Makefile b/test/Makefile
index ba3a64047945..5bb50c622afd 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -50,8 +50,4 @@ lit.site.cfg: FORCE
clean::
@ find . -name Output | xargs rm -fr
-# Daniel hates Chris.
-chris-lit:
- make LIT_ARGS='-j16 -s'
-
.PHONY: all report clean
diff --git a/test/PCH/Inputs/chain-cxx1.h b/test/PCH/Inputs/chain-cxx1.h
new file mode 100644
index 000000000000..7ea3ffb61c8f
--- /dev/null
+++ b/test/PCH/Inputs/chain-cxx1.h
@@ -0,0 +1,19 @@
+// Primary header for C++ chained PCH test
+
+void f();
+
+// Name not appearing in dependent
+void pf();
+
+namespace ns {
+ void g();
+
+ void pg();
+}
+
+template <typename T>
+struct S { typedef int G; };
+
+// Partially specialize
+template <typename T>
+struct S<T *> { typedef int H; };
diff --git a/test/PCH/Inputs/chain-cxx2.h b/test/PCH/Inputs/chain-cxx2.h
new file mode 100644
index 000000000000..adc10fd83681
--- /dev/null
+++ b/test/PCH/Inputs/chain-cxx2.h
@@ -0,0 +1,32 @@
+// Dependent header for C++ chained PCH test
+
+// Overload function from primary
+void f(int);
+
+// Add function with different name
+void f2();
+
+// Reopen namespace
+namespace ns {
+ // Overload function from primary
+ void g(int);
+
+ // Add different name
+ void g2();
+}
+
+// Specialize template from primary
+template <>
+struct S<int> { typedef int I; };
+
+// Partially specialize
+template <typename T>
+struct S<T &> { typedef int J; };
+
+// Specialize previous partial specialization
+template <>
+struct S<int *> { typedef int K; };
+
+// Specialize the partial specialization from this file
+template <>
+struct S<int &> { typedef int L; };
diff --git a/test/PCH/Inputs/chain-decls1.h b/test/PCH/Inputs/chain-decls1.h
new file mode 100644
index 000000000000..9de446164d6d
--- /dev/null
+++ b/test/PCH/Inputs/chain-decls1.h
@@ -0,0 +1,11 @@
+void f();
+
+struct one {};
+void two();
+
+void many(int i);
+struct many;
+void many(int j);
+struct many;
+
+void noret();
diff --git a/test/PCH/Inputs/chain-decls2.h b/test/PCH/Inputs/chain-decls2.h
new file mode 100644
index 000000000000..b8b7d0466dc3
--- /dev/null
+++ b/test/PCH/Inputs/chain-decls2.h
@@ -0,0 +1,12 @@
+void g();
+
+struct two {};
+void one();
+struct three {}; // for verification
+
+void many(int k);
+struct many;
+void many(int l);
+struct many {};
+
+void noret() __attribute__((noreturn));
diff --git a/test/PCH/Inputs/chain-ext_vector1.h b/test/PCH/Inputs/chain-ext_vector1.h
new file mode 100644
index 000000000000..51093364c92f
--- /dev/null
+++ b/test/PCH/Inputs/chain-ext_vector1.h
@@ -0,0 +1,3 @@
+// First header file for chain-ext_vector.c PCH test
+
+typedef __attribute__((ext_vector_type(2))) float float2;
diff --git a/test/PCH/Inputs/chain-ext_vector2.h b/test/PCH/Inputs/chain-ext_vector2.h
new file mode 100644
index 000000000000..bdaeccc130ee
--- /dev/null
+++ b/test/PCH/Inputs/chain-ext_vector2.h
@@ -0,0 +1,3 @@
+// Second header file for chain-ext_vector.c PCH test
+
+typedef __attribute__((ext_vector_type(4))) float float4;
diff --git a/test/PCH/Inputs/chain-external-defs1.h b/test/PCH/Inputs/chain-external-defs1.h
new file mode 100644
index 000000000000..36a2653f5f90
--- /dev/null
+++ b/test/PCH/Inputs/chain-external-defs1.h
@@ -0,0 +1,13 @@
+// Helper 1 for chain-external-defs.c test
+
+// Tentative definitions
+int x;
+int x2;
+
+// Should not show up
+static int z;
+
+int incomplete_array[];
+int incomplete_array2[];
+
+struct S s;
diff --git a/test/PCH/Inputs/chain-external-defs2.h b/test/PCH/Inputs/chain-external-defs2.h
new file mode 100644
index 000000000000..72af92f1a3d7
--- /dev/null
+++ b/test/PCH/Inputs/chain-external-defs2.h
@@ -0,0 +1,11 @@
+// Helper 2 for chain-external-defs.c test
+
+// Tentative definitions
+int y;
+int y2;
+
+// Should still not show up
+static int z;
+
+int incomplete_array[];
+int incomplete_array3[];
diff --git a/test/PCH/Inputs/chain-macro-override1.h b/test/PCH/Inputs/chain-macro-override1.h
new file mode 100644
index 000000000000..4f9321de93b1
--- /dev/null
+++ b/test/PCH/Inputs/chain-macro-override1.h
@@ -0,0 +1,4 @@
+void f() __attribute__((unavailable));
+void g();
+#define g() f()
+#define h() f()
diff --git a/test/PCH/Inputs/chain-macro-override2.h b/test/PCH/Inputs/chain-macro-override2.h
new file mode 100644
index 000000000000..f279e2ad48c0
--- /dev/null
+++ b/test/PCH/Inputs/chain-macro-override2.h
@@ -0,0 +1,4 @@
+#define f() g()
+#undef g
+#undef h
+#define h() g()
diff --git a/test/PCH/Inputs/chain-macro1.h b/test/PCH/Inputs/chain-macro1.h
new file mode 100644
index 000000000000..2e80e47aead0
--- /dev/null
+++ b/test/PCH/Inputs/chain-macro1.h
@@ -0,0 +1 @@
+#define FOOBAR void f();
diff --git a/test/PCH/Inputs/chain-macro2.h b/test/PCH/Inputs/chain-macro2.h
new file mode 100644
index 000000000000..e888228a4c00
--- /dev/null
+++ b/test/PCH/Inputs/chain-macro2.h
@@ -0,0 +1 @@
+#define BARFOO void g();
diff --git a/test/PCH/Inputs/chain-selectors1.h b/test/PCH/Inputs/chain-selectors1.h
new file mode 100644
index 000000000000..37c1c00b5741
--- /dev/null
+++ b/test/PCH/Inputs/chain-selectors1.h
@@ -0,0 +1,12 @@
+@interface X
+ -(void)f;
+ -(void)f2;
+ -(void)g:(int)p;
+ -(void)h:(int)p1 foo:(int)p2;
+@end
+
+void foo1() {
+ // FIXME: Can't verify warnings in headers
+ //(void)@selector(x);
+ (void)@selector(f);
+}
diff --git a/test/PCH/Inputs/chain-selectors2.h b/test/PCH/Inputs/chain-selectors2.h
new file mode 100644
index 000000000000..4d6b55663008
--- /dev/null
+++ b/test/PCH/Inputs/chain-selectors2.h
@@ -0,0 +1,11 @@
+@interface Y
+ -(void)f;
+ -(double)f2;
+ -(void)e;
+@end
+
+void foo2() {
+ // FIXME: Can't verify warnings in headers
+ //(void)@selector(y);
+ //(void)@selector(e);
+}
diff --git a/test/PCH/Inputs/chain-trivial1.h b/test/PCH/Inputs/chain-trivial1.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/PCH/Inputs/chain-trivial1.h
diff --git a/test/PCH/Inputs/chain-trivial2.h b/test/PCH/Inputs/chain-trivial2.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/test/PCH/Inputs/chain-trivial2.h
diff --git a/test/PCH/Inputs/preamble.h b/test/PCH/Inputs/preamble.h
new file mode 100644
index 000000000000..aee330a3f985
--- /dev/null
+++ b/test/PCH/Inputs/preamble.h
@@ -0,0 +1 @@
+int f(int);
diff --git a/test/PCH/chain-cxx.cpp b/test/PCH/chain-cxx.cpp
new file mode 100644
index 000000000000..3e46214c70b8
--- /dev/null
+++ b/test/PCH/chain-cxx.cpp
@@ -0,0 +1,28 @@
+// Test C++ chained PCH functionality
+
+// Without PCH
+// RUN: %clang_cc1 -fsyntax-only -verify -include %S/Inputs/chain-cxx1.h -include %S/Inputs/chain-cxx2.h %s
+
+// With PCH
+// RUN: %clang_cc1 -x c++ -emit-pch -o %t1 %S/Inputs/chain-cxx1.h
+// RUN: %clang_cc1 -x c++ -emit-pch -o %t2 %S/Inputs/chain-cxx2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s
+
+void test() {
+ f();
+ f(1);
+ pf();
+ f2();
+
+ ns::g();
+ ns::g(1);
+ ns::pg();
+ ns::g2();
+
+ typedef S<double>::G T1;
+ typedef S<double *>::H T2;
+ typedef S<int>::I T3;
+ typedef S<double &>::J T4;
+ typedef S<int *>::K T5;
+ typedef S<int &>::L T6;
+}
diff --git a/test/PCH/chain-decls.c b/test/PCH/chain-decls.c
new file mode 100644
index 000000000000..b3daa4a7b7cd
--- /dev/null
+++ b/test/PCH/chain-decls.c
@@ -0,0 +1,27 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/Inputs/chain-decls1.h -include %S/Inputs/chain-decls2.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-decls1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-decls2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -include-pch %t2 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -ast-print -include-pch %t2 %s | FileCheck %s
+
+// CHECK: void f();
+// CHECK: void g();
+
+int h() {
+ f();
+ g();
+
+ struct one x;
+ one();
+ struct two y;
+ two();
+ struct three z;
+
+ many(0);
+ struct many m;
+
+ noret();
+}
diff --git a/test/PCH/chain-ext_vector.c b/test/PCH/chain-ext_vector.c
new file mode 100644
index 000000000000..263507003d18
--- /dev/null
+++ b/test/PCH/chain-ext_vector.c
@@ -0,0 +1,11 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/Inputs/chain-ext_vector1.h -include %S/Inputs/chain-ext_vector2.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-ext_vector1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-ext_vector2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -include-pch %t2 -fsyntax-only -verify %s
+
+int test(float4 f4) {
+ return f4.xy; // expected-error{{float2}}
+}
diff --git a/test/PCH/chain-external-defs.c b/test/PCH/chain-external-defs.c
new file mode 100644
index 000000000000..dd92d8e63ac6
--- /dev/null
+++ b/test/PCH/chain-external-defs.c
@@ -0,0 +1,54 @@
+// Test with pch.
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-pch -o %t1.pch %S/Inputs/chain-external-defs1.h
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-pch -o %t2.pch %S/Inputs/chain-external-defs2.h -include-pch %t1.pch -chained-pch
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -include-pch %t2.pch -emit-llvm -o %t %s
+// RUN: echo FINI >> %t
+// RUN: FileCheck -input-file=%t -check-prefix=Z %s
+// RUN: FileCheck -input-file=%t -check-prefix=XA %s
+// RUN: FileCheck -input-file=%t -check-prefix=YA %s
+// RUN: FileCheck -input-file=%t -check-prefix=XB %s
+// RUN: FileCheck -input-file=%t -check-prefix=YB %s
+// RUN: FileCheck -input-file=%t -check-prefix=AA %s
+// RUN: FileCheck -input-file=%t -check-prefix=AB %s
+// RUN: FileCheck -input-file=%t -check-prefix=AC %s
+// RUN: FileCheck -input-file=%t -check-prefix=S %s
+
+// Z-NOT: @z
+
+// XA: @x = common global i32 0
+// XA-NOT: @x = common global i32 0
+
+// YA: @y = common global i32 0
+// YA-NOT: @y = common global i32 0
+
+// XB: @x2 = global i32 19
+// XB-NOT: @x2 = global i32 19
+int x2 = 19;
+// YB: @y2 = global i32 18
+// YB-NOT: @y2 = global i32 18
+int y2 = 18;
+
+// AA: @incomplete_array = common global [1 x i32]
+// AA-NOT: @incomplete_array = common global [1 x i32]
+// AB: @incomplete_array2 = common global [17 x i32]
+// AB-NOT: @incomplete_array2 = common global [17 x i32]
+int incomplete_array2[17];
+// AC: @incomplete_array3 = common global [1 x i32]
+// AC-NOT: @incomplete_array3 = common global [1 x i32]
+int incomplete_array3[];
+
+// S: @s = common global %struct.S
+// S-NOT: @s = common global %struct.S
+struct S {
+ int x, y;
+};
+
+// Z: FINI
+// XA: FINI
+// YA: FINI
+// XB: FINI
+// YB: FINI
+// AA: FINI
+// AB: FINI
+// AC: FINI
+// S: FINI
diff --git a/test/PCH/chain-macro-override.c b/test/PCH/chain-macro-override.c
new file mode 100644
index 000000000000..14478af35f19
--- /dev/null
+++ b/test/PCH/chain-macro-override.c
@@ -0,0 +1,13 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/Inputs/chain-macro-override1.h -include %S/Inputs/chain-macro-override2.h -fsyntax-only -verify %s
+
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-macro-override1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-macro-override2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -include-pch %t2 -fsyntax-only -verify %s
+
+void foo() {
+ f();
+ g();
+ h();
+}
diff --git a/test/PCH/chain-macro.c b/test/PCH/chain-macro.c
new file mode 100644
index 000000000000..b4dcdfe644d7
--- /dev/null
+++ b/test/PCH/chain-macro.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-macro1.h
+// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-macro2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s
+// RUN: %clang_cc1 -ast-print -include-pch %t2 %s | FileCheck %s
+
+// CHECK: void f();
+FOOBAR
+// CHECK: void g();
+BARFOO
diff --git a/test/PCH/chain-predecl.h b/test/PCH/chain-predecl.h
new file mode 100644
index 000000000000..bd332ff3ad0d
--- /dev/null
+++ b/test/PCH/chain-predecl.h
@@ -0,0 +1,3 @@
+// First header for chain-predecl.m
+@class Foo;
+@protocol Pro;
diff --git a/test/PCH/chain-predecl.m b/test/PCH/chain-predecl.m
new file mode 100644
index 000000000000..2b0444e15a2c
--- /dev/null
+++ b/test/PCH/chain-predecl.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -emit-pch -o %t1 %S/chain-predecl.h -x objective-c
+// RUN: %clang_cc1 -emit-pch -o %t2 %s -x objective-c -include-pch %t1 -chained-pch
+
+// Test predeclarations across chained PCH.
+@interface Foo
+-(void)bar;
+@end
+@interface Boom
+-(void)bar;
+@end
+@protocol Pro
+-(void)baz;
+@end
+@protocol Kaboom
+-(void)baz;
+@end
diff --git a/test/PCH/chain-selectors.m b/test/PCH/chain-selectors.m
new file mode 100644
index 000000000000..60db3f994b71
--- /dev/null
+++ b/test/PCH/chain-selectors.m
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wselector -include %S/Inputs/chain-selectors1.h -include %S/Inputs/chain-selectors2.h
+
+// RUN: %clang_cc1 -x objective-c -emit-pch -o %t1 %S/Inputs/chain-selectors1.h
+// RUN: %clang_cc1 -x objective-c -emit-pch -o %t2 %S/Inputs/chain-selectors2.h -include-pch %t1 -chained-pch
+// RUN: %clang_cc1 -fsyntax-only -verify %s -Wselector -include-pch %t2
+
+@implementation X
+-(void)f {}
+-(void)f2 {}
+-(void)g: (int)p {}
+-(void)h: (int)p1 foo: (int)p2 {}
+@end
+
+void bar() {
+ id a = 0;
+ [a nothing]; // expected-warning {{method '-nothing' not found}}
+ [a f];
+ // FIXME: Can't verify notes in headers
+ //[a f2];
+
+ (void)@selector(x); // expected-warning {{unimplemented selector}}
+ (void)@selector(y); // expected-warning {{unimplemented selector}}
+ (void)@selector(e); // expected-warning {{unimplemented selector}}
+}
diff --git a/test/PCH/chain-trivial.c b/test/PCH/chain-trivial.c
new file mode 100644
index 000000000000..c78b0e44ef30
--- /dev/null
+++ b/test/PCH/chain-trivial.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-pch -o %t1 %S/Inputs/chain-trivial1.h
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-pch -o %t2 -include-pch %t1 -chained-pch %S/Inputs/chain-trivial2.h
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-print -include-pch %t2 %s | FileCheck %s
+// CHECK: struct __va_list_tag {
diff --git a/test/PCH/cxx-offsetof-base.cpp b/test/PCH/cxx-offsetof-base.cpp
new file mode 100644
index 000000000000..18265deecc20
--- /dev/null
+++ b/test/PCH/cxx-offsetof-base.cpp
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-offsetof-base.h
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s
diff --git a/test/PCH/cxx-offsetof-base.h b/test/PCH/cxx-offsetof-base.h
new file mode 100644
index 000000000000..7c7810185d46
--- /dev/null
+++ b/test/PCH/cxx-offsetof-base.h
@@ -0,0 +1,5 @@
+// Header for PCH test cxx-offsetof-base.cpp
+
+struct Base { int x; };
+struct Derived : Base { int y; };
+int o = __builtin_offsetof(Derived, x);
diff --git a/test/PCH/cxx-required-decls.cpp b/test/PCH/cxx-required-decls.cpp
new file mode 100644
index 000000000000..8c4b11cd8414
--- /dev/null
+++ b/test/PCH/cxx-required-decls.cpp
@@ -0,0 +1,10 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/cxx-required-decls.h %s -emit-llvm -o - | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-required-decls.h
+// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: @_ZL5globS = internal global %struct.S zeroinitializer
+// CHECK: @_ZL3bar = internal global i32 0, align 4
+// CHECK: @glob_var = global i32 0
diff --git a/test/PCH/cxx-required-decls.h b/test/PCH/cxx-required-decls.h
new file mode 100644
index 000000000000..099d2da56c69
--- /dev/null
+++ b/test/PCH/cxx-required-decls.h
@@ -0,0 +1,12 @@
+// Header for PCH test cxx-required-decls.cpp
+
+struct S {
+ S();
+};
+
+static S globS;
+
+extern int ext_foo;
+static int bar = ++ext_foo;
+
+int glob_var;
diff --git a/test/PCH/cxx-static_assert.cpp b/test/PCH/cxx-static_assert.cpp
new file mode 100644
index 000000000000..34409218ecd4
--- /dev/null
+++ b/test/PCH/cxx-static_assert.cpp
@@ -0,0 +1,11 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/cxx-static_assert.h -verify -std=c++0x %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c++-header -std=c++0x -emit-pch -o %t %S/cxx-static_assert.h
+// RUN: %clang_cc1 -include-pch %t -verify -std=c++0x %s
+
+// expected-error {{static_assert failed "N is not 2!"}}
+
+T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}}
+T<2> t2;
diff --git a/test/PCH/cxx-static_assert.h b/test/PCH/cxx-static_assert.h
new file mode 100644
index 000000000000..ba41ab8feddb
--- /dev/null
+++ b/test/PCH/cxx-static_assert.h
@@ -0,0 +1,9 @@
+// Header for PCH test cxx-static_assert.cpp
+
+
+
+
+
+template<int N> struct T {
+ static_assert(N == 2, "N is not 2!");
+};
diff --git a/test/PCH/cxx-templates.cpp b/test/PCH/cxx-templates.cpp
index f12742755a9f..a862ea579e35 100644
--- a/test/PCH/cxx-templates.cpp
+++ b/test/PCH/cxx-templates.cpp
@@ -1,9 +1,14 @@
// Test this without pch.
-// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump
+// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump -o -
+// RUN: %clang_cc1 -include %S/cxx-templates.h %s -emit-llvm -o - | FileCheck %s
// Test with pch.
// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-templates.h
-// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump
+// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump -o -
+// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: define weak_odr void @_ZN2S4IiE1mEv
+// CHECK: define linkonce_odr void @_ZN2S3IiE1mEv
struct A {
typedef int type;
@@ -22,4 +27,9 @@ void test() {
Dep<A>::Ty ty;
Dep<A> a;
a.f();
+
+ S3<int> s3;
+ s3.m();
}
+
+template struct S4<int>;
diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h
index 396853686fad..978d768acc92 100644
--- a/test/PCH/cxx-templates.h
+++ b/test/PCH/cxx-templates.h
@@ -88,7 +88,8 @@ template<unsigned N>
bool isInt(int x);
template<> bool isInt<8>(int x) {
- return true;
+ try { ++x; } catch(...) { --x; }
+ return true;
}
template<typename _CharT>
@@ -100,3 +101,37 @@ class basic_streambuf
friend int __copy_streambufs_eof<>(int);
};
+// PR 7660
+template<typename T> struct S_PR7660 { void g(void (*)(T)); };
+ template<> void S_PR7660<int>::g(void(*)(int)) {}
+
+// PR 7670
+template<typename> class C_PR7670;
+template<> class C_PR7670<int>;
+template<> class C_PR7670<int>;
+
+template <bool B>
+struct S2 {
+ static bool V;
+};
+
+extern template class S2<true>;
+
+template <typename T>
+struct S3 {
+ void m();
+};
+
+template <typename T>
+inline void S3<T>::m() { }
+
+template <typename T>
+struct S4 {
+ void m() { }
+};
+extern template struct S4<int>;
+
+void S4ImplicitInst() {
+ S4<int> s;
+ s.m();
+}
diff --git a/test/PCH/cxx-traits.cpp b/test/PCH/cxx-traits.cpp
new file mode 100644
index 000000000000..69c64758aea6
--- /dev/null
+++ b/test/PCH/cxx-traits.cpp
@@ -0,0 +1,8 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/cxx-traits.h -fsyntax-only -verify %s
+
+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-traits.h
+// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s
+
+bool _Is_pod_comparator = __is_pod<int>::__value;
+bool _Is_empty_check = __is_empty<int>::__value;
diff --git a/test/PCH/cxx-traits.h b/test/PCH/cxx-traits.h
new file mode 100644
index 000000000000..62722ab1793a
--- /dev/null
+++ b/test/PCH/cxx-traits.h
@@ -0,0 +1,11 @@
+// Header for PCH test cxx-traits.cpp
+
+template<typename _Tp>
+struct __is_pod {
+ enum { __value };
+};
+
+template<typename _Tp>
+struct __is_empty {
+ enum { __value };
+};
diff --git a/test/PCH/cxx-typeid.cpp b/test/PCH/cxx-typeid.cpp
new file mode 100644
index 000000000000..41dd544807ea
--- /dev/null
+++ b/test/PCH/cxx-typeid.cpp
@@ -0,0 +1,9 @@
+// Test this without pch.
+// RUN: %clang -include %S/cxx-typeid.h -fsyntax-only -Xclang -verify %s
+
+// RUN: %clang -ccc-pch-is-pch -x c++-header -o %t.gch %S/cxx-typeid.h
+// RUN: %clang -ccc-pch-is-pch -include %t -fsyntax-only -Xclang -verify %s
+
+void f() {
+ (void)typeid(int);
+}
diff --git a/test/PCH/cxx-typeid.h b/test/PCH/cxx-typeid.h
new file mode 100644
index 000000000000..aa3b16aa0b49
--- /dev/null
+++ b/test/PCH/cxx-typeid.h
@@ -0,0 +1,3 @@
+// Header for PCH test cxx-typeid.cpp
+
+#include <typeinfo>
diff --git a/test/PCH/namespaces.cpp b/test/PCH/namespaces.cpp
index 532d627fadcf..b8a22e57a06e 100644
--- a/test/PCH/namespaces.cpp
+++ b/test/PCH/namespaces.cpp
@@ -37,7 +37,6 @@ void(*funp2)() = ext;
using N1::used_func;
void (*pused)() = used_func;
-// FIXME: Disabled until CXXRecord serialization is re-added.
-// using N1::used_cls;
-// used_cls s1;
-// used_cls* ps1 = &s1;
+using N1::used_cls;
+used_cls s1;
+used_cls* ps1 = &s1;
diff --git a/test/PCH/objcxx-ivar-class.h b/test/PCH/objcxx-ivar-class.h
new file mode 100644
index 000000000000..50ebda709db0
--- /dev/null
+++ b/test/PCH/objcxx-ivar-class.h
@@ -0,0 +1,15 @@
+struct S {
+ S();
+ S(const S&);
+ S& operator= (const S&);
+};
+
+@interface C {
+ S position;
+}
+@property(assign, nonatomic) S position;
+@end
+
+@implementation C
+ @synthesize position;
+@end
diff --git a/test/PCH/objcxx-ivar-class.mm b/test/PCH/objcxx-ivar-class.mm
new file mode 100644
index 000000000000..89d3e087f90f
--- /dev/null
+++ b/test/PCH/objcxx-ivar-class.mm
@@ -0,0 +1,15 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/objcxx-ivar-class.h -verify %s -emit-llvm -o - | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x objective-c++-header -emit-pch -o %t %S/objcxx-ivar-class.h
+// RUN: %clang_cc1 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
+
+// CHECK: [C position]
+// CHECK: call void @_ZN1SC1ERKS_
+
+// CHECK: [C setPosition:]
+// CHECK: call %struct.S* @_ZN1SaSERKS_
+
+// CHECK: [C .cxx_destruct]
+// CHECK: [C .cxx_construct]
diff --git a/test/PCH/pragma-weak.c b/test/PCH/pragma-weak.c
new file mode 100644
index 000000000000..18b45c889d12
--- /dev/null
+++ b/test/PCH/pragma-weak.c
@@ -0,0 +1,10 @@
+// Test this without pch.
+// RUN: %clang_cc1 -include %S/pragma-weak.h %s -verify -emit-llvm -o - | FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -x c-header -emit-pch -o %t %S/pragma-weak.h
+// RUN: %clang_cc1 -include-pch %t %s -verify -emit-llvm -o - | FileCheck %s
+
+// CHECK: @weakvar = weak global i32 0
+int weakvar;
+// expected-warning {{weak identifier 'undeclaredvar' never declared}}
diff --git a/test/PCH/pragma-weak.h b/test/PCH/pragma-weak.h
new file mode 100644
index 000000000000..42ecd50b9fe9
--- /dev/null
+++ b/test/PCH/pragma-weak.h
@@ -0,0 +1,10 @@
+// Header for PCH test pragma-weak.c
+
+#pragma weak weakvar
+
+
+
+
+
+
+#pragma weak undeclaredvar
diff --git a/test/PCH/preamble.c b/test/PCH/preamble.c
new file mode 100644
index 000000000000..bdc0aea65639
--- /dev/null
+++ b/test/PCH/preamble.c
@@ -0,0 +1,21 @@
+// Check that using the preamble option actually skips the preamble.
+
+// RUN: %clang_cc1 -emit-pch -o %t %S/Inputs/preamble.h
+// RUN: %clang_cc1 -include-pch %t -preamble-bytes=278,1 -DFOO=f -verify %s
+
+float f(int); // Not an error, because we skip this via the preamble!
+
+
+
+
+
+
+
+
+
+
+
+
+int g(int x) {
+ return FOO(x);
+}
diff --git a/test/PCH/pth.c b/test/PCH/pth.c
new file mode 100644
index 000000000000..1262f8aebd70
--- /dev/null
+++ b/test/PCH/pth.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-pth -o %t %S/pth.h
+// RUN: %clang_cc1 -triple i386-unknown-unknown -include-pth %t -fsyntax-only %s 2>&1 | FileCheck %s
+
+#error This is the only diagnostic
+
+// CHECK: This is the only diagnostic
+// CHECK: 1 error generated. \ No newline at end of file
diff --git a/test/PCH/pth.h b/test/PCH/pth.h
new file mode 100644
index 000000000000..9ae7021a5e4a
--- /dev/null
+++ b/test/PCH/pth.h
@@ -0,0 +1,12 @@
+// This case came up when using PTH with Boost (<rdar://problem/8227989>).
+
+# ifndef R8227989_PREPROCESSOR_CONFIG_CONFIG_HPP
+# ifndef R8227989_PP_CONFIG_FLAGS
+# endif
+#
+# ifndef R8227989_PP_CONFIG_ERRORS
+# ifdef NDEBUG
+# endif
+# endif
+# endif
+
diff --git a/test/PCH/reinclude.cpp b/test/PCH/reinclude.cpp
new file mode 100644
index 000000000000..6ab10027c9fa
--- /dev/null
+++ b/test/PCH/reinclude.cpp
@@ -0,0 +1,8 @@
+// Test without PCH
+// RUN: %clang_cc1 %s -include %S/reinclude1.h -include %S/reinclude2.h -fsyntax-only -verify
+
+// RUN: %clang_cc1 -x c++-header %S/reinclude1.h -emit-pch -o %t1
+// RUN: %clang_cc1 -x c++-header %S/reinclude2.h -include-pch %t1 -emit-pch -o %t2
+// RUN: %clang_cc1 %s -include-pch %t2 -fsyntax-only -verify
+
+int q2 = A::y;
diff --git a/test/PCH/reinclude1.h b/test/PCH/reinclude1.h
new file mode 100644
index 000000000000..4c8ccaef617e
--- /dev/null
+++ b/test/PCH/reinclude1.h
@@ -0,0 +1,4 @@
+namespace A {
+ int x;
+ int y;
+}
diff --git a/test/PCH/reinclude2.h b/test/PCH/reinclude2.h
new file mode 100644
index 000000000000..2aa6d31e8326
--- /dev/null
+++ b/test/PCH/reinclude2.h
@@ -0,0 +1 @@
+int q1 = A::x;
diff --git a/test/PCH/selector-warning.h b/test/PCH/selector-warning.h
new file mode 100644
index 000000000000..bd419293daf0
--- /dev/null
+++ b/test/PCH/selector-warning.h
@@ -0,0 +1,24 @@
+typedef struct objc_selector *SEL;
+
+@interface Foo
+- (void) NotOK;
+@end
+
+@implementation Foo
+- (void) foo
+{
+ SEL a = @selector(b1ar);
+ a = @selector(b1ar);
+ a = @selector(bar);
+ a = @selector(ok); // expected-warning {{unimplemented selector 'ok'}}
+ a = @selector(ok);
+ a = @selector(NotOK); // expected-warning {{unimplemented selector 'NotOK'}}
+ a = @selector(NotOK);
+
+ a = @selector(clNotOk); // expected-warning {{unimplemented selector 'clNotOk'}}
+
+ a = @selector (cl1);
+ a = @selector (cl2);
+ a = @selector (instNotOk); // expected-warning {{unimplemented selector 'instNotOk'}}
+}
+@end
diff --git a/test/PCH/selector-warning.m b/test/PCH/selector-warning.m
new file mode 100644
index 000000000000..413f64f54197
--- /dev/null
+++ b/test/PCH/selector-warning.m
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -x objective-c -emit-pch -o %t.h.pch %S/selector-warning.h
+// RUN: %clang_cc1 -include-pch %t.h.pch %s
+
+@interface Bar
++ (void) clNotOk;
+- (void) instNotOk;
++ (void) cl1;
+@end
+
+@implementation Bar
+- (void) bar {}
++ (void) cl1 {}
++ (void) cl2 {}
+@end
+
+@implementation Bar(CAT)
+- (void) b1ar {}
+@end
+
diff --git a/test/Parser/2008-10-31-parse-noop-failure.c b/test/Parser/2008-10-31-parse-noop-failure.c
deleted file mode 100755
index 6df508ee4dde..000000000000
--- a/test/Parser/2008-10-31-parse-noop-failure.c
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: %clang_cc1 -verify -parse-noop %s
-
-void add_attribute(id) int id; {}
-
diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c
index 0b2733e69461..ec272cdf9c80 100644
--- a/test/Parser/MicrosoftExtensions.c
+++ b/test/Parser/MicrosoftExtensions.c
@@ -1,8 +1,9 @@
-// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -x objective-c++ %s
+// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -Wno-missing-declarations -x objective-c++ %s
__stdcall int func0();
int __stdcall func();
typedef int (__cdecl *tptr)();
void (*__fastcall fastpfunc)();
+struct __declspec(uuid("00000000-0000-0000-C000-000000000046")) __declspec(novtable) IUnknown {};
extern __declspec(dllimport) void __stdcall VarR4FromDec();
__declspec(deprecated) __declspec(deprecated) char * __cdecl ltoa( long _Val, char * _DstBuf, int _Radix);
__declspec(noalias) __declspec(restrict) void * __cdecl xxx( void * _Memory );
@@ -34,3 +35,4 @@ typedef bool (__stdcall __stdcall *blarg)(int);
#define FOO(x) #@x
char x = FOO(a);
+typedef enum E { e1 };
diff --git a/test/Parser/asm-constraints-pr7869.c b/test/Parser/asm-constraints-pr7869.c
new file mode 100644
index 000000000000..d6f1725f1a84
--- /dev/null
+++ b/test/Parser/asm-constraints-pr7869.c
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int a, b, c, d, e, f, g, h, i, j, k, l;
+
+void
+f1 (void)
+{
+ __asm__ volatile (""
+ : [a] "+r" (a), [b] "+r" (b), [c] "+r" (c), [d] "+r" (d),
+ [e] "+r" (e), [f] "+r" (f), [g] "+r" (g), [h] "+r" (h),
+ [i] "+r" (i), [j] "+r" (j), [k] "+r" (k), [l] "+r" (l));
+}
+
+void
+f2 (void)
+{
+ __asm__ volatile (""
+ : [a] "+r,m" (a), [b] "+r,m" (b), [c] "+r,m" (c), [d] "+r,m" (d),
+ [e] "+r,m" (e), [f] "+r,m" (f), [g] "+r,m" (g), [h] "+r,m" (h),
+ [i] "+r,m" (i), [j] "+r,m" (j), [k] "+r,m" (k), [l] "+r,m" (l));
+}
+
+void
+f3 (void)
+{
+ __asm__ volatile (""
+ : [a] "=r" (a), [b] "=r" (b), [c] "=r" (c), [d] "=r" (d),
+ [e] "=r" (e), [f] "=r" (f), [g] "=r" (g), [h] "=r" (h),
+ [i] "=r" (i), [j] "=r" (j), [k] "=r" (k), [l] "=r" (l)
+ : "[a]" (a), "[b]" (b), "[c]" (c), "[d]" (d),
+ "[e]" (e), "[f]" (f), "[g]" (g), "[h]" (h),
+ "[i]" (i), "[j]" (j), "[k]" (k), "[l]" (l));
+}
+
+void
+f4 (void)
+{
+ __asm__ volatile (""
+ : [a] "=r,m" (a), [b] "=r,m" (b), [c] "=r,m" (c), [d] "=r,m" (d),
+ [e] "=r,m" (e), [f] "=r,m" (f), [g] "=r,m" (g), [h] "=r,m" (h),
+ [i] "=r,m" (i), [j] "=r,m" (j), [k] "=r,m" (k), [l] "=r,m" (l)
+ : "[a],m" (a), "[b],m" (b), "[c],m" (c), "[d],m" (d),
+ "[e],m" (e), "[f],m" (f), "[g],m" (g), "[h],m" (h),
+ "[i],m" (i), "[j],m" (j), "[k],m" (k), "[l],m" (l));
+}
diff --git a/test/Parser/asm.c b/test/Parser/asm.c
index df2e16feea5b..90818261513f 100644
--- a/test/Parser/asm.c
+++ b/test/Parser/asm.c
@@ -1,7 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
void f1() {
- asm ("ret" : : :); // expected-error {{expected string literal}}
+ // PR7673: Some versions of GCC support an empty clobbers section.
+ asm ("ret" : : :);
}
void f2() {
diff --git a/test/Parser/block-block-storageclass.c b/test/Parser/block-block-storageclass.c
index a4efc44b1828..97ba11349217 100644
--- a/test/Parser/block-block-storageclass.c
+++ b/test/Parser/block-block-storageclass.c
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -parse-noop %s
-#if 0
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
int printf(const char *, ...);
void _Block_byref_release(void*src){}
@@ -16,4 +15,3 @@ int main() {
return X;
}
-#endif
diff --git a/test/Parser/block-pointer-decl.c b/test/Parser/block-pointer-decl.c
index 2979b012c449..a8cc258ca375 100644
--- a/test/Parser/block-pointer-decl.c
+++ b/test/Parser/block-pointer-decl.c
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -parse-noop -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
+
+int printf(char const *, ...);
struct blockStruct {
int (^a)(float, int);
diff --git a/test/Parser/cxx-altivec.cpp b/test/Parser/cxx-altivec.cpp
index a70eea077e7a..8f463308112b 100644
--- a/test/Parser/cxx-altivec.cpp
+++ b/test/Parser/cxx-altivec.cpp
@@ -126,3 +126,38 @@ vector char v3 = (vector char)((vector int)('a', 'b', 'c', 'd'));
vector int v4 = (vector int)(1, 2, 3, 4);
vector float v5 = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
vector char v6 = (vector char)((vector int)(1+2, -2, (int)(2.0 * 3), -(5-3)));
+
+#if 0 // Not ready yet.
+// bug 7553 - Problem with '==' and vectors
+void func() {
+ vector int v10i = (vector int)(1, 2, 3, 4);
+ vector int v11i = (vector int)(1, 2, 3, 4);
+ bool r10ieq = (v10i == v11i);
+ bool r10ine = (v10i != v11i);
+ bool r10igt = (v10i > v11i);
+ bool r10ige = (v10i >= v11i);
+ bool r10ilt = (v10i < v11i);
+ bool r10ile = (v10i <= v11i);
+ vector float v10f = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
+ vector float v11f = (vector float)(1.0f, 2.0f, 3.0f, 4.0f);
+ bool r10feq = (v10f == v11f);
+ bool r10fne = (v10f != v11f);
+ bool r10fgt = (v10f > v11f);
+ bool r10fge = (v10f >= v11f);
+ bool r10flt = (v10f < v11f);
+ bool r10fle = (v10f <= v11f);
+}
+#endif
+
+// vecreturn attribute test
+struct Vector
+{
+ __vector float xyzw;
+} __attribute__((vecreturn));
+
+Vector Add(Vector lhs, Vector rhs)
+{
+ Vector result;
+ result.xyzw = vec_add(lhs.xyzw, rhs.xyzw);
+ return result; // This will (eventually) be returned in a register
+}
diff --git a/test/Parser/cxx-ambig-decl-expr-xfail.cpp b/test/Parser/cxx-ambig-decl-expr-xfail.cpp
new file mode 100644
index 000000000000..ac4accb2acf9
--- /dev/null
+++ b/test/Parser/cxx-ambig-decl-expr-xfail.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// XFAIL: *
+struct X {
+ template<typename T> X(T);
+ X(int, int);
+
+ X operator()(int, int) const;
+};
+
+template<typename T, typename U> struct Y { };
+
+X *x;
+void f() {
+ int y = 0;
+ X (*x)(int(y), int(y)) = Y<int, float>(), ++y;
+}
diff --git a/test/Parser/cxx-ambig-decl-expr.cpp b/test/Parser/cxx-ambig-decl-expr.cpp
new file mode 100644
index 000000000000..b5ff728b47c9
--- /dev/null
+++ b/test/Parser/cxx-ambig-decl-expr.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct X {
+ template<typename T, typename U>
+ static void f(int, int);
+};
+
+void f() {
+ void (*ptr)(int, int) = &X::f<int, int>;
+}
diff --git a/test/Parser/cxx-attributes.cpp b/test/Parser/cxx-attributes.cpp
index 192193a6dfdc..8603b3090016 100644
--- a/test/Parser/cxx-attributes.cpp
+++ b/test/Parser/cxx-attributes.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-
-class c {
- virtual void f1(const char* a, ...)
- __attribute__ (( __format__(__printf__,2,3) )) = 0;
- virtual void f2(const char* a, ...)
- __attribute__ (( __format__(__printf__,2,3) )) {}
-};
-
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+class c {
+ virtual void f1(const char* a, ...)
+ __attribute__ (( __format__(__printf__,2,3) )) = 0;
+ virtual void f2(const char* a, ...)
+ __attribute__ (( __format__(__printf__,2,3) )) {}
+};
+
diff --git a/test/Parser/cxx-condition.cpp b/test/Parser/cxx-condition.cpp
index a3991c45f24e..552d82362461 100644
--- a/test/Parser/cxx-condition.cpp
+++ b/test/Parser/cxx-condition.cpp
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -parse-noop -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
void f() {
int a;
while (a) ;
while (int x) ; // expected-error {{expected '=' after declarator}}
while (float x = 0) ;
- if (const int x = a) ;
+ if (const int x = a) ; // expected-warning{{empty body}}
switch (int x = a+10) {}
for (; int x = ++a; ) ;
}
diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp
index e4c703c334bd..e00ffd070fd8 100644
--- a/test/Parser/cxx-decl.cpp
+++ b/test/Parser/cxx-decl.cpp
@@ -76,3 +76,10 @@ class Class2 {
} // no ;
typedef Class1<Class2> Type1; // expected-error {{cannot combine with previous 'class' declaration specifier}}
+
+// rdar : // 8307865
+struct CodeCompleteConsumer {
+};
+
+void CodeCompleteConsumer::() { // expected-error {{xpected unqualified-id}}
+}
diff --git a/test/Parser/cxx-default-args.cpp b/test/Parser/cxx-default-args.cpp
index a084fb0812ba..7fe8474142ba 100644
--- a/test/Parser/cxx-default-args.cpp
+++ b/test/Parser/cxx-default-args.cpp
@@ -7,3 +7,10 @@ class C {
void m(int x = undecl + 0); // expected-error {{use of undeclared identifier 'undecl'}}
};
+typedef struct Inst {
+ void m(int x=0);
+} *InstPtr;
+
+struct X {
+ void f(int x = 1:); // expected-error {{unexpected end of default argument expression}}
+};
diff --git a/test/Parser/cxx-namespace-alias.cpp b/test/Parser/cxx-namespace-alias.cpp
index 2e4d7af6bf30..9b90aabb861b 100644
--- a/test/Parser/cxx-namespace-alias.cpp
+++ b/test/Parser/cxx-namespace-alias.cpp
@@ -1,8 +1,9 @@
-// RUN: %clang_cc1 -parse-noop -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
-namespace A = B;
+namespace A = B; // expected-error{{namespace name}}
namespace A = !; // expected-error {{expected namespace name}}
-namespace A = A::!; // expected-error {{expected namespace name}}
+namespace A = A::!; // expected-error {{expected namespace name}} \
+ // expected-error{{use of undeclared identifier 'A'}}
diff --git a/test/Parser/cxx-typeof.cpp b/test/Parser/cxx-typeof.cpp
index 7e891013e92c..4c598e9517ed 100644
--- a/test/Parser/cxx-typeof.cpp
+++ b/test/Parser/cxx-typeof.cpp
@@ -5,3 +5,9 @@ static void test() {
int x;
typeof pi[x] y;
}
+
+// Part of rdar://problem/8347416; from the gcc test suite.
+struct S {
+ int i;
+ __typeof(S::i) foo(); // expected-error {{invalid use of nonstatic data member 'i'}}
+};
diff --git a/test/Parser/declarators.c b/test/Parser/declarators.c
index fb69fa9c1d05..e245adb7cded 100644
--- a/test/Parser/declarators.c
+++ b/test/Parser/declarators.c
@@ -94,3 +94,6 @@ void test14() // expected-error {{expected ';' after top level declarator}}
void test14a();
void *test14b = (void*)test14a; // Make sure test14a didn't get skipped.
+
+// rdar://problem/8358508
+long struct X { int x; } test15(); // expected-error {{'long struct' is invalid}}
diff --git a/test/Parser/expressions.c b/test/Parser/expressions.c
index 44ebe661befd..ffc5c83a0a73 100644
--- a/test/Parser/expressions.c
+++ b/test/Parser/expressions.c
@@ -1,19 +1,17 @@
-// RUN: %clang_cc1 -parse-noop -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
void test1() {
- if (sizeof (int){ 1}); // sizeof compound literal
- if (sizeof (int)); // sizeof type
+ if (sizeof (int){ 1}) {} // sizeof compound literal
+ if (sizeof (int)) {} // sizeof type
- (int)4; // cast.
- (int){4}; // compound literal.
+ (void)(int)4; // cast.
+ (void)(int){4}; // compound literal.
- // FIXME: change this to the struct version when we can.
- //int A = (struct{ int a;}){ 1}.a;
- int A = (int){ 1}.a;
+ int A = (struct{ int a;}){ 1}.a;
}
int test2(int a, int b) {
- return a ? a,b : a;
+ return a ? (void)a,b : a;
}
int test3(int a, int b, int c) {
@@ -22,23 +20,27 @@ int test3(int a, int b, int c) {
int test4() {
test4();
+ return 0;
}
+struct X0 { struct { struct { int c[10][9]; } b; } a; };
+
int test_offsetof() {
- // FIXME: change into something that is semantically correct.
- __builtin_offsetof(int, a.b.c[4][5]);
+ (void)__builtin_offsetof(struct X0, a.b.c[4][5]);
+ return 0;
}
void test_sizeof(){
int arr[10];
- sizeof arr[0];
- sizeof(arr[0]);
- sizeof(arr)[0];
+ (void)sizeof arr[0];
+ (void)sizeof(arr[0]);
+ (void)sizeof(arr)[0];
}
// PR3418
int test_leading_extension() {
__extension__ (*(char*)0) = 1;
+ return 0;
}
// PR3972
diff --git a/test/Parser/expressions.m b/test/Parser/expressions.m
index e27f40506926..1f1005a792a7 100644
--- a/test/Parser/expressions.m
+++ b/test/Parser/expressions.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -parse-noop %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
void test1() {
@"s"; // expected-warning {{expression result unused}}
diff --git a/test/Parser/method-prototype-1.m b/test/Parser/method-prototype-1.m
index d2d9563a2ec4..a32bc2ec2765 100644
--- a/test/Parser/method-prototype-1.m
+++ b/test/Parser/method-prototype-1.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -parse-noop
+// RUN: %clang_cc1 %s -fsyntax-only
@interface MyObject
- (void) bycopy : (int) woodo, ... ;
- (void) break : (int) woodo, ... ;
diff --git a/test/Parser/objc-messaging-1.m b/test/Parser/objc-messaging-1.m
index 511290eabfc0..82450df9f2c3 100644
--- a/test/Parser/objc-messaging-1.m
+++ b/test/Parser/objc-messaging-1.m
@@ -1,19 +1,26 @@
-// RUN: %clang_cc1 %s -parse-noop
+// RUN: %clang_cc1 %s -fsyntax-only -verify
int main ()
{
int i,j;
struct S *p;
id a, b, c;
- [p ii];
- [p if: 1 :2];
- [p inout: 1 :2 another:(2,3,4)];
- [p inout: 1 :2 another:(2,3,4), 6,6,8];
- [p inout: 1 :2 another:(2,3,4), (6,4,5),6,8];
- [p inout: 1 :2 another:(i+10), (i,j-1,5),6,8];
- [p long: 1 :2 another:(i+10), (i,j-1,5),6,8];
- [p : "Hello\n" :2 another:(i+10), (i,j-1,5),6,8];
+ [a ii]; // expected-warning{{not found}}
+ [a if: 1 :2]; // expected-warning{{not found}}
+ [a inout: 1 :2 another:(2,3,4)]; // expected-warning{{not found}} \
+ // expected-warning 2{{expression result unused}}
+ [a inout: 1 :2 another:(2,3,4), 6,6,8]; // expected-warning{{not found}} \
+ // expected-warning 2{{expression result unused}}
+ [a inout: 1 :2 another:(2,3,4), (6,4,5),6,8]; // expected-warning{{not found}} \
+ // expected-warning 4{{expression result unused}}
+ [a inout: 1 :2 another:(i+10), (i,j-1,5),6,8]; // expected-warning{{not found}} \
+ // expected-warning 2{{expression result unused}}
+ [a long: 1 :2 another:(i+10), (i,j-1,5),6,8]; // expected-warning{{not found}} \
+ // expected-warning 2{{expression result unused}}
+ [a : "Hello\n" :2 another:(i+10), (i,j-1,5),6,8]; // expected-warning{{not found}} \
+ // expected-warning 2{{expression result unused}}
// Comma expression as receiver (rdar://6222856)
- [a, b, c foo];
+ [a, b, c foo]; // expected-warning{{not found}} \
+ // expected-warning 2{{expression result unused}}
}
diff --git a/test/Parser/pragma-options.c b/test/Parser/pragma-options.c
index daf385dddba7..7844e7108060 100644
--- a/test/Parser/pragma-options.c
+++ b/test/Parser/pragma-options.c
@@ -10,3 +10,13 @@
#pragma options align=reset
#pragma options align=mac68k
#pragma options align=power
+
+/* expected-warning {{expected '=' following '#pragma align'}} */ #pragma align
+/* expected-warning {{expected identifier in '#pragma align'}} */ #pragma align =
+/* expected-warning {{invalid alignment option in '#pragma align'}} */ #pragma align = foo
+/* expected-warning {{extra tokens at end of '#pragma align'}} */ #pragma align = reset foo
+
+#pragma align=natural
+#pragma align=reset
+#pragma align=mac68k
+#pragma align=power
diff --git a/test/Parser/pragma-visibility.c b/test/Parser/pragma-visibility.c
new file mode 100644
index 000000000000..cfc3d9eccd86
--- /dev/null
+++ b/test/Parser/pragma-visibility.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#pragma GCC visibility foo // expected-warning{{expected identifier in '#pragma visibility' - ignored}}
+#pragma GCC visibility pop foo // expected-warning{{extra tokens at end of '#pragma visibility' - ignored}}
+#pragma GCC visibility push // expected-warning{{missing '(' after '#pragma visibility'}}
+#pragma GCC visibility push( // expected-warning{{expected identifier in '#pragma visibility' - ignored}}
+#pragma GCC visibility push(hidden // expected-warning{{missing ')' after '#pragma visibility' - ignoring}}
+#pragma GCC visibility push(hidden)
+#pragma GCC visibility pop
diff --git a/test/Parser/selector-1.m b/test/Parser/selector-1.m
index 1f9cad62aee3..0f35ce79b20f 100644
--- a/test/Parser/selector-1.m
+++ b/test/Parser/selector-1.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -parse-noop %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
int main() {
SEL s = @selector(retain);
diff --git a/test/Parser/typeof.c b/test/Parser/typeof.c
index cf0e47a6b124..7953a69fed00 100644
--- a/test/Parser/typeof.c
+++ b/test/Parser/typeof.c
@@ -17,3 +17,10 @@ static void test() {
int xx;
int *i;
}
+
+// <rdar://problem/8237491>
+void test2() {
+ int a;
+ short b;
+ __typeof__(a) (*f)(__typeof__(b));
+}
diff --git a/test/Parser/types.c b/test/Parser/types.c
index 0e8a63d81fc0..53b9dd5e9eca 100644
--- a/test/Parser/types.c
+++ b/test/Parser/types.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -parse-noop
+// RUN: %clang_cc1 %s -fsyntax-only -verify
// Test the X can be overloaded inside the struct.
typedef int X;
diff --git a/test/Preprocessor/dump-macros-undef.c b/test/Preprocessor/dump-macros-undef.c
new file mode 100644
index 000000000000..358fd17e468d
--- /dev/null
+++ b/test/Preprocessor/dump-macros-undef.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -E -dD %s | FileCheck %s
+// PR7818
+
+// CHECK: # 1 "{{.+}}.c"
+#define X 3
+// CHECK: #define X 3
+#undef X
+// CHECK: #undef X
diff --git a/test/Preprocessor/init.c b/test/Preprocessor/init.c
index 8283671b6636..6c27a6c4316a 100644
--- a/test/Preprocessor/init.c
+++ b/test/Preprocessor/init.c
@@ -74,9 +74,10 @@
// C94:#define __STDC_VERSION__ 199409L
//
//
-// RUN: %clang_cc1 -fms-extensions -E -dM < /dev/null | FileCheck -check-prefix MSEXT %s
+// RUN: %clang_cc1 -fms-extensions -triple i686-pc-win32 -E -dM < /dev/null | FileCheck -check-prefix MSEXT %s
//
// MSEXT-NOT:#define __STDC__
+// MSEXT:#define _INTEGRAL_MAX_BITS 64
// MSEXT:#define __int16 __INT16_TYPE__
// MSEXT:#define __int32 __INT32_TYPE__
// MSEXT:#define __int64 __INT64_TYPE__
@@ -117,6 +118,13 @@
// SCHAR-NOT:#define __UNSIGNED_CHAR__
// SCHAR:#define __clang__ 1
//
+// RUN: %clang_cc1 -E -dM -fshort-wchar < /dev/null | FileCheck -check-prefix SHORTWCHAR %s
+//
+// SHORTWCHAR: #define __SIZEOF_WCHAR_T__ 2
+// SHORTWCHAR: #define __WCHAR_MAX__ 65535U
+// SHORTWCHAR: #define __WCHAR_TYPE__ unsigned short
+// SHORTWCHAR: #define __WCHAR_WIDTH__ 16
+//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -check-prefix ARM %s
//
// ARM:#define __APCS_32__ 1
diff --git a/test/Preprocessor/macro_fn_comma_swallow.c b/test/Preprocessor/macro_fn_comma_swallow.c
index 57425910b8a9..726a889f55e5 100644
--- a/test/Preprocessor/macro_fn_comma_swallow.c
+++ b/test/Preprocessor/macro_fn_comma_swallow.c
@@ -1,21 +1,28 @@
// Test the GNU comma swallowing extension.
-// RUN: %clang_cc1 %s -E | grep 'foo{A, }'
-// RUN: %clang_cc1 %s -E | grep 'fo2{A,}'
-// RUN: %clang_cc1 %s -E | grep '{foo}'
+// RUN: %clang_cc1 %s -E | FileCheck -strict-whitespace %s
+// CHECK: 1: foo{A, }
#define X(Y) foo{A, Y}
-X()
+1: X()
+
+// CHECK: 2: fo2{A,}
#define X2(Y) fo2{A,##Y}
-X2()
+2: X2()
// should eat the comma.
+// CHECK: 3: {foo}
#define X3(b, ...) {b, ## __VA_ARGS__}
-X3(foo)
+3: X3(foo)
-// RUN: %clang_cc1 %s -E | grep 'AA BB'
// PR3880
+// CHECK: 4: AA BB
#define X4(...) AA , ## __VA_ARGS__ BB
-X4()
+4: X4()
+
+// PR7943
+// CHECK: 5: 1
+#define X5(x,...) x##,##__VA_ARGS__
+5: X5(1)
diff --git a/test/Preprocessor/macro_paste_mscomment.c b/test/Preprocessor/macro_paste_msextensions.c
index 71324064f7cd..c5b42130b8ea 100644
--- a/test/Preprocessor/macro_paste_mscomment.c
+++ b/test/Preprocessor/macro_paste_msextensions.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -P -E -fms-extensions %s | FileCheck -strict-whitespace %s
+
// This horrible stuff should preprocess into (other than whitespace):
// int foo;
// int bar;
@@ -24,3 +25,10 @@ nested(baz) rise of the dead tokens
// CHECK: int baz
// CHECK: ;
+
+// rdar://8197149 - VC++ allows invalid token pastes: (##baz
+#define foo(x) abc(x)
+#define bar(y) foo(##baz(y))
+bar(q)
+
+// CHECK: abc(baz(q))
diff --git a/test/Preprocessor/pragma-pushpop-macro.c b/test/Preprocessor/pragma-pushpop-macro.c
new file mode 100644
index 000000000000..87cceaa4193a
--- /dev/null
+++ b/test/Preprocessor/pragma-pushpop-macro.c
@@ -0,0 +1,33 @@
+/* Test pragma pop_macro and push_macro directives from
+ http://msdn.microsoft.com/en-us/library/hsttss76.aspx */
+
+// pop_macro: Sets the value of the macro_name macro to the value on the top of
+// the stack for this macro.
+// #pragma pop_macro("macro_name")
+// push_macro: Saves the value of the macro_name macro on the top of the stack
+// for this macro.
+// #pragma push_macro("macro_name")
+//
+// RUN: %clang_cc1 -fms-extensions -E %s -o - | FileCheck %s
+
+#define X 1
+#define Y 2
+int pmx0 = X;
+int pmy0 = Y;
+#define Y 3
+#pragma push_macro("Y")
+#pragma push_macro("X")
+int pmx1 = X;
+#define X 2
+int pmx2 = X;
+#pragma pop_macro("X")
+int pmx3 = X;
+#pragma pop_macro("Y")
+int pmy1 = Y;
+
+// CHECK: int pmx0 = 1
+// CHECK: int pmy0 = 2
+// CHECK: int pmx1 = 1
+// CHECK: int pmx2 = 2
+// CHECK: int pmx3 = 1
+// CHECK: int pmy1 = 3
diff --git a/test/Preprocessor/pragma_diagnostic.c b/test/Preprocessor/pragma_diagnostic.c
index d157406b3dc6..818f02f0b90e 100644
--- a/test/Preprocessor/pragma_diagnostic.c
+++ b/test/Preprocessor/pragma_diagnostic.c
@@ -20,9 +20,8 @@
#endif
-
#define foo error
-#pragma GCC diagnostic foo "-Wundef" // expected-warning {{pragma diagnostic expected 'error', 'warning', 'ignored', or 'fatal'}}
+#pragma GCC diagnostic foo "-Wundef" // expected-warning {{pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop'}}
#pragma GCC diagnostic error 42 // expected-warning {{unexpected token in pragma diagnostic}}
diff --git a/test/Preprocessor/pragma_microsoft.c b/test/Preprocessor/pragma_microsoft.c
index 0201c451deaa..b68d6e363eb8 100644
--- a/test/Preprocessor/pragma_microsoft.c
+++ b/test/Preprocessor/pragma_microsoft.c
@@ -18,3 +18,23 @@
#pragma comment(user, "foo\abar\nbaz\tsome thing")
+
+// __pragma
+
+__pragma(comment(linker," bar=" BAR))
+
+#define MACRO_WITH__PRAGMA { \
+ __pragma(warning(push)); \
+ __pragma(warning(disable: 10000)); \
+ 2+2; \
+ __pragma(warning(pop)); \
+}
+
+void f()
+{
+ __pragma()
+
+ // If we ever actually *support* __pragma(warning(disable: x)),
+ // this warning should go away.
+ MACRO_WITH__PRAGMA // expected-warning {{expression result unused}}
+}
diff --git a/test/Preprocessor/pushable-diagnostics.c b/test/Preprocessor/pushable-diagnostics.c
index 6c861a1b3b6b..567a866fa339 100644
--- a/test/Preprocessor/pushable-diagnostics.c
+++ b/test/Preprocessor/pushable-diagnostics.c
@@ -2,7 +2,7 @@
#pragma clang diagnostic pop // expected-warning{{pragma diagnostic pop could not pop, no matching push}}
-#pragma clang diagnostic puhs // expected-warning{{pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal' 'push', or 'pop'}}
+#pragma clang diagnostic puhs // expected-warning {{pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal', 'push', or 'pop'}}
char a = 'df'; // expected-warning{{multi-character character constant}}
diff --git a/test/Rewriter/rewrite-block-consts.mm b/test/Rewriter/rewrite-block-consts.mm
new file mode 100644
index 000000000000..c74873f65739
--- /dev/null
+++ b/test/Rewriter/rewrite-block-consts.mm
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// rdar:// 8243071
+
+void x(int y) {}
+void f() {
+ const int bar = 3;
+ int baz = 4;
+ __block int bab = 4;
+ __block const int bas = 5;
+ void (^b)() = ^{
+ x(bar);
+ x(baz);
+ x(bab);
+ x(bas);
+ b();
+ };
+ b();
+}
diff --git a/test/Rewriter/rewrite-constructor-init.mm b/test/Rewriter/rewrite-constructor-init.mm
new file mode 100644
index 000000000000..534e7fa0440c
--- /dev/null
+++ b/test/Rewriter/rewrite-constructor-init.mm
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// rdar : // 8213998
+
+typedef unsigned int NSUInteger;
+
+typedef struct _NSRange {
+ NSUInteger location;
+ NSUInteger length;
+} NSRange;
+
+static __inline NSRange NSMakeRange(NSUInteger loc, NSUInteger len) {
+ NSRange r;
+ r.location = loc;
+ r.length = len;
+ return r;
+}
+
+void bar() {
+ __block NSRange previousRange = NSMakeRange(0, 0);
+ void (^blk)() = ^{
+ previousRange = NSMakeRange(1, 0);
+ };
+}
diff --git a/test/Sema/altivec-init.c b/test/Sema/altivec-init.c
index 57abc9304d5b..b5758bc71837 100644
--- a/test/Sema/altivec-init.c
+++ b/test/Sema/altivec-init.c
@@ -14,3 +14,22 @@ v8 foo(void) {
// FIXME: test that (type)(fn)(args) still works with -faltivec
// FIXME: test that c++ overloaded commas still work -faltivec
}
+
+void __attribute__((__overloadable__)) f(v4 a)
+{
+}
+
+void __attribute__((__overloadable__)) f(int a)
+{
+}
+
+void test()
+{
+ v4 vGCC;
+ vector int vAltiVec;
+
+ f(vAltiVec);
+ vGCC = vAltiVec;
+ vGCC = vGCC > vAltiVec;
+ vAltiVec = 0 ? vGCC : vGCC;
+}
diff --git a/test/Sema/array-init.c b/test/Sema/array-init.c
index f93b0878fd3f..0ee22c0f1994 100644
--- a/test/Sema/array-init.c
+++ b/test/Sema/array-init.c
@@ -210,7 +210,7 @@ struct bittest bittestvar = {1, 2, 3, 4}; //expected-warning{{excess elements in
// Not completely sure what should happen here...
int u1 = {}; //expected-warning{{use of GNU empty initializer extension}} expected-error{{scalar initializer cannot be empty}}
-int u2 = {{3}}; //expected-error{{too many braces around scalar initializer}}
+int u2 = {{3}}; //expected-warning{{too many braces around scalar initializer}}
// PR2362
void varArray() {
@@ -218,7 +218,8 @@ void varArray() {
}
// PR2151
-void emptyInit() {struct {} x[] = {6};} //expected-warning{{empty struct extension}} expected-error{{initializer for aggregate with no elements}}
+void emptyInit() {struct {} x[] = {6};} //expected-warning{{empty struct (accepted as an extension) has size 0 in C, size 1 in C++}} \
+// expected-error{{initializer for aggregate with no elements}}
void noNamedInit() {
struct {int:5;} x[] = {6}; //expected-error{{initializer for aggregate with no elements}}
@@ -241,7 +242,8 @@ struct soft_segment_descriptor gdt_segs[] = {
};
static void sppp_ipv6cp_up();
-const struct {} ipcp = { sppp_ipv6cp_up }; //expected-warning{{empty struct extension}} expected-warning{{excess elements in struct initializer}}
+const struct {} ipcp = { sppp_ipv6cp_up }; //expected-warning{{empty struct (accepted as an extension) has size 0 in C, size 1 in C++}} \
+// expected-warning{{excess elements in struct initializer}}
struct _Matrix { union { float m[4][4]; }; }; //expected-warning{{anonymous unions are a GNU extension in C}}
typedef struct _Matrix Matrix;
diff --git a/test/Sema/array-size-64.c b/test/Sema/array-size-64.c
new file mode 100644
index 000000000000..f22e8e77d215
--- /dev/null
+++ b/test/Sema/array-size-64.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -verify %s
+
+void f() {
+ int a[2147483647U][2147483647U]; // expected-error{{array is too large}}
+ int b[1073741825U - 1U][2147483647U];
+ int c[18446744073709551615U/sizeof(int)/2];
+}
diff --git a/test/Sema/array-size.c b/test/Sema/array-size.c
new file mode 100644
index 000000000000..7580e3ecc51c
--- /dev/null
+++ b/test/Sema/array-size.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple i686-apple-darwin -verify %s
+
+void f() {
+ int x0[1073741824]; // expected-error{{array is too large}}
+ int x1[1073741824 + 1]; // expected-error{{array is too large}}
+ int x2[(unsigned)1073741824]; // expected-error{{array is too large}}
+ int x3[(unsigned)1073741824 + 1]; // expected-error{{array is too large}}
+ int x4[1073741824 - 1];
+}
+
diff --git a/test/Sema/block-misc.c b/test/Sema/block-misc.c
index 92be5b189848..ec74a630045a 100644
--- a/test/Sema/block-misc.c
+++ b/test/Sema/block-misc.c
@@ -221,3 +221,8 @@ void test21() {
(void)b[1]; // expected-error {{cannot refer to declaration with an array type inside block}}
}();
}
+
+// rdar ://8218839
+const char * (^func)(void) = ^{ return __func__; };
+const char * (^function)(void) = ^{ return __FUNCTION__; };
+const char * (^pretty)(void) = ^{ return __PRETTY_FUNCTION__; };
diff --git a/test/Sema/builtins-arm.c b/test/Sema/builtins-arm.c
new file mode 100644
index 000000000000..4dd31e724050
--- /dev/null
+++ b/test/Sema/builtins-arm.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify -DTEST0 %s
+// RUN: %clang_cc1 -triple armv7 -fsyntax-only -verify -DTEST1 %s
+
+#ifdef TEST0
+void __clear_cache(char*, char*);
+#endif
+
+#ifdef TEST1
+void __clear_cache(void*, void*);
+#endif
+
diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c
index c0a2131868e4..787630c1a8c4 100644
--- a/test/Sema/builtins.c
+++ b/test/Sema/builtins.c
@@ -44,6 +44,11 @@ void test9(short v) {
// PR7600: Pointers are implicitly casted to integers and back.
void *old_ptr = __sync_val_compare_and_swap((void**)0, 0, 0);
+
+ // Ensure the return type is correct even when implicit casts are stripped
+ // away. This triggers an assertion while checking the comparison otherwise.
+ if (__sync_fetch_and_add(&old, 1) == 1) {
+ }
}
@@ -75,3 +80,18 @@ void test12(void) {
void test_unknown_builtin(int a, int b) {
__builtin_foo(a, b); // expected-error{{use of unknown builtin}}
}
+
+int test13() {
+ __builtin_eh_return(0, 0); // no warning, eh_return never returns.
+}
+
+// <rdar://problem/8228293>
+void test14() {
+ int old;
+ old = __sync_fetch_and_min((volatile int *)&old, 1);
+}
+
+// <rdar://problem/8336581>
+void test15(const char *s) {
+ __builtin_printf("string is %s\n", s);
+}
diff --git a/test/Sema/cast-incomplete.c b/test/Sema/cast-incomplete.c
new file mode 100644
index 000000000000..dd10e00d444a
--- /dev/null
+++ b/test/Sema/cast-incomplete.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+// PR5692
+
+enum x; // expected-note {{forward declaration}}
+extern struct y a; // expected-note {{forward declaration}}
+extern union z b; // expected-note 2 {{forward declaration}}
+
+void foo() {
+ (enum x)1; // expected-error {{cast to incomplete type}}
+ (struct y)a; // expected-error {{cast to incomplete type}}
+ (union z)b; // expected-error {{cast to incomplete type}}
+ (union z)1; // expected-error {{cast to incomplete type}}
+}
+
diff --git a/test/Sema/compound-literal.c b/test/Sema/compound-literal.c
index 08c30b3c876d..aade4641ace0 100644
--- a/test/Sema/compound-literal.c
+++ b/test/Sema/compound-literal.c
@@ -11,7 +11,7 @@ static int x = (int){1};
static int *p2 = (int []){2,x}; // -expected-error {{initializer element is not a compile-time constant}}
static long *p3 = (long []){2,"x"}; // -expected-warning {{incompatible pointer to integer conversion initializing 'long' with an expression of type 'char [2]'}}
-typedef struct { } cache_t; // -expected-warning{{use of empty struct extension}}
+typedef struct { } cache_t; // -expected-warning{{empty struct (accepted as an extension) has size 0 in C, size 1 in C++}}
static cache_t clo_I1_cache = ((cache_t) { } ); // -expected-warning{{use of GNU empty initializer extension}}
typedef struct Test {int a;int b;} Test;
diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c
index c132b347d7b2..42097e75f317 100644
--- a/test/Sema/const-eval.c
+++ b/test/Sema/const-eval.c
@@ -74,5 +74,9 @@ const _Bool constbool = 0;
EVAL_EXPR(35, constbool)
EVAL_EXPR(36, constbool)
-EVAL_EXPR(37, (1,2.0) == 2.0) // expected-warning {{expression result unused}}
-EVAL_EXPR(38, __builtin_expect(1,1) == 1)
+EVAL_EXPR(37, (1,2.0) == 2.0 ? 1 : -1)
+EVAL_EXPR(38, __builtin_expect(1,1) == 1 ? 1 : -1)
+
+// PR7884
+EVAL_EXPR(39, __real__(1.f) == 1 ? 1 : -1)
+EVAL_EXPR(40, __imag__(1.f) == 0 ? 1 : -1)
diff --git a/test/Sema/enum.c b/test/Sema/enum.c
index 057015011e8f..64aa31bc4b6f 100644
--- a/test/Sema/enum.c
+++ b/test/Sema/enum.c
@@ -96,3 +96,9 @@ char * s = (an_enum) an_enumerator; // expected-warning {{incompatible integer t
// PR4515
enum PR4515 {PR4515a=1u,PR4515b=(PR4515a-2)/2};
int CheckPR4515[PR4515b==0?1:-1];
+
+// PR7911
+extern enum PR7911T PR7911V; // expected-warning{{ISO C forbids forward references to 'enum' types}}
+void PR7911F() {
+ switch (PR7911V); // expected-error {{statement requires expression of integer type}}
+}
diff --git a/test/Sema/expr-comma-c89.c b/test/Sema/expr-comma-c89.c
index dc427028d0d1..d0883ba202f9 100644
--- a/test/Sema/expr-comma-c89.c
+++ b/test/Sema/expr-comma-c89.c
@@ -11,7 +11,7 @@ int B[sizeof((a.c)) == 17 ? 1 : -1];
// comma does array/function promotion in c99.
-int X[sizeof(0, (foo().c)) == sizeof(char*) ? 1 : -1]; // expected-warning {{expression result unused}}
-int Y[sizeof(0, (a,b).c) == sizeof(char*) ? 1 : -1]; // expected-warning {{expression result unused}} expected-warning {{expression result unused}}
-int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1]; // expected-warning {{expression result unused}}
+int X[sizeof(0, (foo().c)) == sizeof(char*) ? 1 : -1];
+int Y[sizeof(0, (a,b).c) == sizeof(char*) ? 1 : -1];
+int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1];
diff --git a/test/Sema/expr-comma.c b/test/Sema/expr-comma.c
index b004fc1ba3e2..d3e4020af637 100644
--- a/test/Sema/expr-comma.c
+++ b/test/Sema/expr-comma.c
@@ -11,7 +11,7 @@ int B[sizeof((a.c)) == 17 ? 1 : -1];
// comma does not promote array/function in c90 unless they are lvalues.
-int W[sizeof(0, a.c) == sizeof(char*) ? 1 : -1]; // expected-warning {{expression result unused}}
-int X[sizeof(0, (foo().c)) == 17 ? 1 : -1]; // expected-warning {{expression result unused}}
-int Y[sizeof(0, (a,b).c) == 17 ? 1 : -1]; // expected-warning {{expression result unused}} // expected-warning {{expression result unused}}
-int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1]; // expected-warning {{expression result unused}}
+int W[sizeof(0, a.c) == sizeof(char*) ? 1 : -1];
+int X[sizeof(0, (foo().c)) == 17 ? 1 : -1];
+int Y[sizeof(0, (a,b).c) == 17 ? 1 : -1];
+int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1];
diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c
index 9d3da908549f..56a52bed1bc3 100644
--- a/test/Sema/exprs.c
+++ b/test/Sema/exprs.c
@@ -145,5 +145,8 @@ void test19() {
int test20(int x) {
return x && 4; // expected-warning {{use of logical && with constant operand; switch to bitwise & or remove constant}}
- return x && sizeof(int) == 4; // no warning.
+ return x && sizeof(int) == 4; // no warning, RHS is logical op.
+
+ // no warning, this is an idiom for "true" in old C style.
+ return x && (signed char)1;
}
diff --git a/test/Sema/ext_vector_casts.c b/test/Sema/ext_vector_casts.c
index 76819534dbb3..75d41ca077ef 100644
--- a/test/Sema/ext_vector_casts.c
+++ b/test/Sema/ext_vector_casts.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fno-lax-vector-conversions %s
typedef __attribute__(( ext_vector_type(2) )) float float2;
typedef __attribute__(( ext_vector_type(4) )) int int4;
diff --git a/test/Sema/format-strings-scanf.c b/test/Sema/format-strings-scanf.c
new file mode 100644
index 000000000000..42b6c03ffbff
--- /dev/null
+++ b/test/Sema/format-strings-scanf.c
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral %s
+
+typedef __typeof(sizeof(int)) size_t;
+typedef struct _FILE FILE;
+typedef __WCHAR_TYPE__ wchar_t;
+
+int fscanf(FILE * restrict, const char * restrict, ...) ;
+int scanf(const char * restrict, ...) ;
+int sscanf(const char * restrict, const char * restrict, ...) ;
+
+void test(const char *s, int *i) {
+ scanf(s, i); // expected-warning{{ormat string is not a string literal}}
+ scanf("%0d", i); // expected-warning{{zero field width in scanf format string is unused}}
+ scanf("%00d", i); // expected-warning{{zero field width in scanf format string is unused}}
+ scanf("%d%[asdfasdfd", i, s); // expected-warning{{no closing ']' for '%[' in scanf format string}}
+
+ unsigned short s_x;
+ scanf ("%" "hu" "\n", &s_x); // no-warning
+ scanf("%y", i); // expected-warning{{invalid conversion specifier 'y'}}
+ scanf("%%"); // no-warning
+ scanf("%%%1$d", i); // no-warning
+ scanf("%1$d%%", i); // no-warning
+ scanf("%d", i, i); // expected-warning{{data argument not used by format string}}
+ scanf("%*d", i); // // expected-warning{{data argument not used by format string}}
+ scanf("%*d", i); // // expected-warning{{data argument not used by format string}}
+ scanf("%*d%1$d", i); // no-warning
+}
+
+void bad_length_modifiers(char *s, void *p, wchar_t *ws, long double *ld) {
+ scanf("%hhs", "foo"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}
+ scanf("%1$zp", p); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}
+ scanf("%ls", ws); // no-warning
+ scanf("%#.2Lf", ld); // expected-warning{{invalid conversion specifier '#'}}
+}
diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c
index c6dee6801e80..2325454c0b75 100644
--- a/test/Sema/format-strings.c
+++ b/test/Sema/format-strings.c
@@ -239,6 +239,8 @@ void test_positional_arguments() {
printf("%1$2.2d", (int) 2); // no-warning
printf("%2$*1$.2d", (int) 2, (int) 3); // no-warning
printf("%2$*8$d", (int) 2, (int) 3); // expected-warning{{specified field width is missing a matching 'int' argument}}
+ printf("%%%1$d", (int) 2); // no-warning
+ printf("%1$d%%", (int) 2); // no-warning
}
// PR 6697 - Handle format strings where the data argument is not adjacent to the format string
@@ -284,3 +286,18 @@ void bug7377_bad_length_mod_usage() {
printf("%-0f", 1.23); // expected-warning{{flag '0' is ignored when flag '-' is present}}
printf("%-+f", 1.23); // no-warning
}
+
+// PR 7981 - handle '%lc' (wint_t)
+#ifndef wint_t
+typedef int __darwin_wint_t;
+typedef __darwin_wint_t wint_t;
+#endif
+
+void pr7981(wint_t c, wchar_t c2) {
+ printf("%lc", c); // no-warning
+ printf("%lc", 1.0); // expected-warning{{the argument has type 'double'}}
+ printf("%lc", (char) 1); // no-warning
+ printf("%lc", &c); // expected-warning{{the argument has type 'wint_t *' (aka 'int *')}}
+ printf("%lc", c2); // no-warning
+}
+
diff --git a/test/Sema/knr-def-call.c b/test/Sema/knr-def-call.c
index 8ae0550dc8b1..66f2ec07f287 100644
--- a/test/Sema/knr-def-call.c
+++ b/test/Sema/knr-def-call.c
@@ -16,3 +16,14 @@ void f2(x) float x; { } // expected-warning{{promoted type 'double' of K&R funct
typedef void (*f3)(void);
f3 t3(int b) { return b? f0 : f1; } // okay
+
+// <rdar://problem/8193107>
+void f4() {
+ char *rindex();
+}
+
+char *rindex(s, c)
+ register char *s, c; // expected-warning{{promoted type 'char *' of K&R function parameter is not compatible with the parameter type 'char const *' declared in a previous prototype}}
+{
+ return 0;
+}
diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c
index 28c3e4cf8c90..8fb41a994c5d 100644
--- a/test/Sema/overloadable.c
+++ b/test/Sema/overloadable.c
@@ -41,7 +41,6 @@ double promote(float) __attribute__((__overloadable__)); // expected-note {{cand
double promote(double) __attribute__((__overloadable__)); // expected-note {{candidate}}
long double promote(long double) __attribute__((__overloadable__)); // expected-note {{candidate}}
-void promote() __attribute__((__overloadable__)); // expected-error{{'overloadable' function 'promote' must have a prototype}}
void promote(...) __attribute__((__overloadable__, __unavailable__)); // \
// expected-note{{candidate function}}
@@ -60,3 +59,13 @@ double magnitude(IntVec) __attribute__((__overloadable__));
double test_p6600(DoubleVec d) {
return magnitude(d) * magnitude(d);
}
+
+// PR7738
+extern int __attribute__((overloadable)) f0(); // expected-error{{'overloadable' function 'f0' must have a prototype}}
+typedef int f1_type();
+f1_type __attribute__((overloadable)) f1; // expected-error{{'overloadable' function 'f1' must have a prototype}}
+
+void test() {
+ f0();
+ f1();
+}
diff --git a/test/Sema/pragma-align-packed.c b/test/Sema/pragma-align-packed.c
index 30b87bf99695..74fbd13d162b 100644
--- a/test/Sema/pragma-align-packed.c
+++ b/test/Sema/pragma-align-packed.c
@@ -21,3 +21,10 @@ struct s2 {
};
extern int a[sizeof(struct s2) == 5 ? 1 : -1];
#pragma options align=reset
+
+#pragma pack(1)
+struct s3_0 { unsigned char f0; unsigned int f1; };
+int t3_0[sizeof(struct s3_0) == 5 ? 1 : -1];
+#pragma options align=reset
+struct s3_1 { unsigned char f0; unsigned int f1; };
+int t3_1[sizeof(struct s3_1) == 8 ? 1 : -1];
diff --git a/test/Sema/recover-goto.c b/test/Sema/recover-goto.c
index 0d665f9a60f5..0e8f6d3da4c8 100644
--- a/test/Sema/recover-goto.c
+++ b/test/Sema/recover-goto.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only %s -verify
-void a() {goto A; // expected-error {{use of undeclared label}}
+void a() { // expected-note {{to match this '{'}}
+ goto A; // expected-error {{use of undeclared label}}
// expected-error {{expected '}'}}
diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c
index f3881ed086ac..4ccb64c9aa07 100644
--- a/test/Sema/scope-check.c
+++ b/test/Sema/scope-check.c
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -std=gnu99 %s -Wno-unreachable-code
int test1(int x) {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
int b[x]; // expected-note {{jump bypasses initialization of variable length array}}
L:
@@ -9,7 +9,7 @@ int test1(int x) {
}
int test2(int x) {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
typedef int a[x]; // expected-note {{jump bypasses initialization of VLA typedef}}
L:
return sizeof(a);
@@ -18,14 +18,14 @@ int test2(int x) {
void test3clean(int*);
int test3() {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
int a __attribute((cleanup(test3clean))); // expected-note {{jump bypasses initialization of variable with __attribute__((cleanup))}}
L:
return a;
}
int test4(int x) {
- goto L; // expected-error{{illegal goto into protected scope}}
+ goto L; // expected-error{{goto into protected scope}}
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
test4(x);
L:
@@ -50,7 +50,7 @@ void test7(int x) {
switch (x) {
case 1: ;
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
- case 2: // expected-error {{illegal switch case into protected scope}}
+ case 2: // expected-error {{switch case is in protected scope}}
a[1] = 2;
break;
}
@@ -58,17 +58,17 @@ void test7(int x) {
int test8(int x) {
// For statement.
- goto L2; // expected-error {{illegal goto into protected scope}}
+ goto L2; // expected-error {{goto into protected scope}}
for (int arr[x]; // expected-note {{jump bypasses initialization of variable length array}}
; ++x)
L2:;
// Statement expressions.
- goto L3; // expected-error {{illegal goto into protected scope}}
+ goto L3; // expected-error {{goto into protected scope}}
int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L3: 4; });
- goto L4; // expected-error {{illegal goto into protected scope}}
+ goto L4; // expected-error {{goto into protected scope}}
{
int A[x], // expected-note {{jump bypasses initialization of variable length array}}
B[x]; // expected-note {{jump bypasses initialization of variable length array}}
@@ -91,7 +91,7 @@ int test8(int x) {
int A[x], B = ({ if (x)
goto L7;
else
- goto L8; // expected-error {{illegal goto into protected scope}}
+ goto L8; // expected-error {{goto into protected scope}}
4; }),
C[x]; // expected-note {{jump bypasses initialization of variable length array}}
L8:; // bad
@@ -103,7 +103,7 @@ int test8(int x) {
goto L9;
else
// FIXME:
- goto L10; // fixme-error {{illegal goto into protected scope}}
+ goto L10; // fixme-error {{goto into protected scope}}
4; })];
L10:; // bad
}
@@ -123,7 +123,7 @@ int test8(int x) {
}
// Statement expressions 2.
- goto L1; // expected-error {{illegal goto into protected scope}}
+ goto L1; // expected-error {{goto into protected scope}}
return x == ({
int a[x]; // expected-note {{jump bypasses initialization of variable length array}}
L1:
@@ -151,14 +151,14 @@ L4:
}
void test10(int n, void *P) {
- goto L0; // expected-error {{illegal goto into protected scope}}
+ goto L0; // expected-error {{goto into protected scope}}
typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}}
L0:
- goto L1; // expected-error {{illegal goto into protected scope}}
+ goto L1; // expected-error {{goto into protected scope}}
A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}}
L1:
- goto L2; // expected-error {{illegal goto into protected scope}}
+ goto L2; // expected-error {{goto into protected scope}}
A d[n]; // expected-note {{jump bypasses initialization of variable length array}}
L2:
return;
@@ -171,7 +171,7 @@ void test11(int n) {
case 2:
case 3:;
int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
- case 4: // expected-error {{illegal switch case into protected scope}}
+ case 4: // expected-error {{switch case is in protected scope}}
return;
}
};
@@ -185,7 +185,7 @@ void test12(int n) {
L1:
goto L2;
L2:
- goto L3; // expected-error {{illegal goto into protected scope}}
+ goto L3; // expected-error {{goto into protected scope}}
int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}}
L3:
goto L4;
diff --git a/test/Sema/switch.c b/test/Sema/switch.c
index 4e39e0f0c2d5..bb4822916cc7 100644
--- a/test/Sema/switch.c
+++ b/test/Sema/switch.c
@@ -50,14 +50,12 @@ void test4()
}
switch (cond) {
- case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} \
- expected-warning {{use of logical && with constant operand}}
+ case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}}
break;
}
switch (cond) {
- case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} \\
- expected-warning {{use of logical || with constant operand}}
+ case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}}
break;
}
}
diff --git a/test/Sema/typedef-variable-type.c b/test/Sema/typedef-variable-type.c
index f29896850b1b..b805b1e0578f 100644
--- a/test/Sema/typedef-variable-type.c
+++ b/test/Sema/typedef-variable-type.c
@@ -1,3 +1,8 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic
+// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic -Wno-typedef-redefinition
+// Make sure we accept a single typedef
+typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}
+
+// And make sure we accept identical redefinitions in system headers
+// (The test uses -Wno-typedef-redefinition to simulate this.)
typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}
diff --git a/test/Sema/vector-ops.c b/test/Sema/vector-ops.c
new file mode 100644
index 000000000000..20575ec510c3
--- /dev/null
+++ b/test/Sema/vector-ops.c
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -Wvector-conversions
+typedef unsigned int v2u __attribute__ ((vector_size (8)));
+typedef int v2s __attribute__ ((vector_size (8)));
+typedef float v2f __attribute__ ((vector_size(8)));
+
+void test1(v2u v2ua, v2s v2sa, v2f v2fa) {
+ // Bitwise binary operators
+ (void)(v2ua & v2ua);
+ (void)(v2fa & v2fa); // expected-error{{invalid operands to binary expression}}
+
+ // Unary operators
+ (void)(~v2ua);
+ (void)(~v2fa); // expected-error{{invalid argument type 'v2f' to unary}}
+
+ // Arrays
+ int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u'}}
+ int array2[17];
+ // FIXME: error message below needs type!
+ (void)(array2[v2ua]); // expected-error{{array subscript is not an integer}}
+
+ v2u *v2u_ptr = 0;
+ v2s *v2s_ptr;
+ v2s_ptr = v2u_ptr; // expected-warning{{converts between pointers to integer types with different sign}}
+}
+
diff --git a/test/Sema/warn-cast-align.c b/test/Sema/warn-cast-align.c
new file mode 100644
index 000000000000..11e3c4163642
--- /dev/null
+++ b/test/Sema/warn-cast-align.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -Wcast-align -verify %s
+
+// Simple casts.
+void test0(char *P) {
+ char *a = (char*) P;
+ short *b = (short*) P; // expected-warning {{cast from 'char *' to 'short *' increases required alignment from 1 to 2}}
+ int *c = (int*) P; // expected-warning {{cast from 'char *' to 'int *' increases required alignment from 1 to 4}}
+}
+
+// Casts from void* are a special case.
+void test1(void *P) {
+ char *a = (char*) P;
+ short *b = (short*) P;
+ int *c = (int*) P;
+
+ const volatile void *P2 = P;
+ char *d = (char*) P2;
+ short *e = (short*) P2;
+ int *f = (int*) P2;
+
+ const char *g = (const char*) P2;
+ const short *h = (const short*) P2;
+ const int *i = (const int*) P2;
+
+ const volatile char *j = (const volatile char*) P2;
+ const volatile short *k = (const volatile short*) P2;
+ const volatile int *l = (const volatile int*) P2;
+}
+
+// Aligned struct.
+__attribute__((align(16))) struct A {
+ char buffer[16];
+};
+void test2(char *P) {
+ struct A *a = (struct A*) P; // expected-warning {{cast from 'char *' to 'struct A *' increases required alignment from 1 to 16}}
+}
+
+// Incomplete type.
+void test3(char *P) {
+ struct B *b = (struct B*) P;
+}
diff --git a/test/Sema/warn-unused-function.c b/test/Sema/warn-unused-function.c
index d5e676b11603..24d4fade9b31 100644
--- a/test/Sema/warn-unused-function.c
+++ b/test/Sema/warn-unused-function.c
@@ -35,3 +35,15 @@ void bar2(void) { }
__attribute__((destructor)) static void bar3(void);
void bar3(void) { }
+
+static void f10(void); // expected-warning{{unused}}
+static void f10(void);
+
+static void f11(void);
+static void f11(void) { } // expected-warning{{unused}}
+
+static void f12(void) { } // expected-warning{{unused}}
+static void f12(void);
+
+// PR7923
+static void unused(void) { unused(); } // expected-warning{{unused}}
diff --git a/test/Sema/warn-write-strings.c b/test/Sema/warn-write-strings.c
index 04af00ca2d83..c936a1267bf5 100644
--- a/test/Sema/warn-write-strings.c
+++ b/test/Sema/warn-write-strings.c
@@ -2,3 +2,9 @@
// PR4804
char* x = "foo"; // expected-warning {{initializing 'char *' with an expression of type 'char const [4]' discards qualifiers}}
+
+// PR7192
+#include <stddef.h>
+void test(wchar_t *dst) {
+ dst[0] = 0; // Ok.
+}
diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp
new file mode 100644
index 000000000000..fb3107f44e97
--- /dev/null
+++ b/test/SemaCXX/MicrosoftExtensions.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -fms-extensions -fexceptions
+
+
+// ::type_info is predeclared with forward class declartion
+void f(const type_info &a);
+
+// The following three are all equivalent when ms-extensions are on
+void foo() throw(int);
+void foo() throw(int, long);
+void foo() throw(...);
+void foo(); // expected-note {{previous declaration}}
+
+// Only nothrow specification is treated specially.
+void foo() throw(); // expected-error {{exception specification in declaration does not match previous declaration}}
+
+// throw(...)
+void r3();
+void r3() throw(...);
+
+void r6() throw(...);
+void r6() throw(int); // okay
+
+struct Base {
+ virtual void f2();
+ virtual void f3() throw(...);
+};
+
+struct Derived : Base {
+ virtual void f2() throw(...);
+ virtual void f3();
+};
+
+// __stdcall handling
+struct M {
+ int __stdcall addP();
+ float __stdcall subtractP();
+};
+
+template<typename T> void h1(T (__stdcall M::* const )()) { }
+
+void m1() {
+ h1<int>(&M::addP);
+ h1(&M::subtractP);
+}
diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp
index f64fda4877e0..ad079c27c001 100644
--- a/test/SemaCXX/abstract.cpp
+++ b/test/SemaCXX/abstract.cpp
@@ -67,20 +67,23 @@ class F {
virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
};
+// Diagnosing in these cases is prohibitively expensive. We still
+// diagnose at the function definition, of course.
+
class Abstract;
-void t7(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}}
+void t7(Abstract a);
void t8() {
- void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}}
+ void h(Abstract a);
}
namespace N {
-void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}}
+void h(Abstract a);
}
class Abstract {
- virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
+ virtual void f() = 0;
};
// <rdar://problem/6854087>
@@ -186,3 +189,63 @@ namespace test1 {
C c;
}
}
+
+// rdar://problem/8302168
+namespace test2 {
+ struct X1 {
+ virtual void xfunc(void) = 0; // expected-note {{pure virtual function}}
+ void g(X1 parm7); // expected-error {{parameter type 'test2::X1' is an abstract class}}
+ void g(X1 parm8[2]); // expected-error {{array of abstract class type 'test2::X1'}}
+ };
+
+ template <int N>
+ struct X2 {
+ virtual void xfunc(void) = 0; // expected-note {{pure virtual function}}
+ void g(X2 parm10); // expected-error {{parameter type 'X2<N>' is an abstract class}}
+ void g(X2 parm11[2]); // expected-error {{array of abstract class type 'X2<N>'}}
+ };
+}
+
+namespace test3 {
+ struct A { // expected-note {{not complete until}}
+ A x; // expected-error {{field has incomplete type}}
+ virtual void abstract() = 0;
+ };
+
+ struct B { // expected-note {{not complete until}}
+ virtual void abstract() = 0;
+ B x; // expected-error {{field has incomplete type}}
+ };
+
+ struct C {
+ static C x; // expected-error {{abstract class}}
+ virtual void abstract() = 0; // expected-note {{pure virtual function}}
+ };
+
+ struct D {
+ virtual void abstract() = 0; // expected-note {{pure virtual function}}
+ static D x; // expected-error {{abstract class}}
+ };
+}
+
+namespace test4 {
+ template <class T> struct A {
+ A x; // expected-error {{abstract class}}
+ virtual void abstract() = 0; // expected-note {{pure virtual function}}
+ };
+
+ template <class T> struct B {
+ virtual void abstract() = 0; // expected-note {{pure virtual function}}
+ B x; // expected-error {{abstract class}}
+ };
+
+ template <class T> struct C {
+ static C x; // expected-error {{abstract class}}
+ virtual void abstract() = 0; // expected-note {{pure virtual function}}
+ };
+
+ template <class T> struct D {
+ virtual void abstract() = 0; // expected-note {{pure virtual function}}
+ static D x; // expected-error {{abstract class}}
+ };
+}
diff --git a/test/SemaCXX/access-member-pointer.cpp b/test/SemaCXX/access-member-pointer.cpp
new file mode 100644
index 000000000000..676eb10dcdc9
--- /dev/null
+++ b/test/SemaCXX/access-member-pointer.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// PR7694
+
+class A { };
+class B : private A { public: void foo(); }; // expected-note {{declared private here}}
+void B::foo() {
+ (void)static_cast<void(A::*)()>(&B::foo);
+}
+void bar() {
+ (void)static_cast<void(A::*)()>(&B::foo); // expected-error {{cannot cast 'B' to its private base class 'A'}}
+}
diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp
index f8b00df17314..b581b8a3f649 100644
--- a/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -86,3 +86,13 @@ namespace test0 {
myFunction(bar);
}
}
+
+namespace PR7971 {
+ struct S {
+ void g() {
+ f(&g);
+ }
+ void f(bool (*)(int, char));
+ static bool g(int, char);
+ };
+}
diff --git a/test/SemaCXX/altivec.cpp b/test/SemaCXX/altivec.cpp
new file mode 100644
index 000000000000..cdfc00a5d43a
--- /dev/null
+++ b/test/SemaCXX/altivec.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -faltivec -fno-lax-vector-conversions -triple powerpc-unknown-unknown -verify %s
+
+typedef int V4i __attribute__((vector_size(16)));
+
+void f(V4i a)
+{
+}
+
+void test()
+{
+ V4i vGCC;
+ vector int vAltiVec;
+
+ f(vAltiVec);
+ vGCC = vAltiVec;
+ vGCC = vGCC > vAltiVec;
+ vAltiVec = 0 ? vGCC : vGCC;
+}
diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp
new file mode 100644
index 000000000000..dfa284ae8b52
--- /dev/null
+++ b/test/SemaCXX/anonymous-struct.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct S {
+ S(); // expected-note {{because type 'S' has a user-declared constructor}}
+};
+
+struct E {
+ struct {
+ S x; // expected-error {{anonymous struct member 'x' has a non-trivial constructor}}
+ };
+};
diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp
index 8b381dfe4b25..6f5aa5e78c4c 100644
--- a/test/SemaCXX/attr-unavailable.cpp
+++ b/test/SemaCXX/attr-unavailable.cpp
@@ -12,9 +12,9 @@ void test_foo(short* sp) {
double &dr = foo(1.0);
foo(sp); // expected-error{{call to unavailable function 'foo'}}
- void (*fp)(...) = &bar; // expected-warning{{'bar' is unavailable}}
- void (*fp2)(...) = bar; // expected-warning{{'bar' is unavailable}}
+ void (*fp)(...) = &bar; // expected-error{{'bar' is unavailable}}
+ void (*fp2)(...) = bar; // expected-error{{'bar' is unavailable}}
int &(*fp3)(int) = foo;
- void (*fp4)(...) = foo; // expected-warning{{'foo' is unavailable}}
+ void (*fp4)(...) = foo; // expected-error{{'foo' is unavailable}}
}
diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp
index baa79e7d8971..adbff553e608 100644
--- a/test/SemaCXX/blocks.cpp
+++ b/test/SemaCXX/blocks.cpp
@@ -41,3 +41,30 @@ namespace test2 {
return Power(2).calculate(10);
}
}
+
+// rdar: // 8382559
+namespace radar8382559 {
+ void func(bool& outHasProperty);
+
+ int test3() {
+ __attribute__((__blocks__(byref))) bool hasProperty = false;
+ bool has = true;
+
+ bool (^b)() = ^ {
+ func(hasProperty);
+ if (hasProperty)
+ hasProperty = 0;
+ if (has)
+ hasProperty = 1;
+ return hasProperty;
+ };
+ func(hasProperty);
+ func(has);
+ b();
+ if (hasProperty)
+ hasProperty = 1;
+ if (has)
+ has = 2;
+ return hasProperty = 1;
+ }
+}
diff --git a/test/SemaCXX/borland-extensions.cpp b/test/SemaCXX/borland-extensions.cpp
new file mode 100644
index 000000000000..c33527c7a03b
--- /dev/null
+++ b/test/SemaCXX/borland-extensions.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -fborland-extensions
+
+// Borland extensions
+
+// 1. test -fborland-extensions
+int dummy_function() { return 0; }
+
+// 2. test __pascal
+int _pascal f2();
+
+float __pascal gi2(int, int);
+template<typename T> T g2(T (__pascal * const )(int, int)) { return 0; }
+
+struct M {
+ int __pascal addP();
+ float __pascal subtractP();
+};
+template<typename T> int h2(T (__pascal M::* const )()) { return 0; }
+void m2() {
+ int i; float f;
+ i = f2();
+ f = gi2(2, i);
+ f = g2(gi2);
+ i = h2<int>(&M::addP);
+ f = h2(&M::subtractP);
+}
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index cf309f5597d3..31d53302bf47 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -221,3 +221,17 @@ namespace PR7402 {
S s(3);
}
}
+
+// <rdar://problem/8308215>: don't crash.
+// Lots of questionable recovery here; errors can change.
+namespace test3 {
+ class A : public std::exception {}; // expected-error {{undeclared identifier}} expected-error {{expected class name}} expected-note 3 {{candidate}} expected-note {{passing argument}}
+ class B : public A {
+ public:
+ B(const String& s, int e=0) // expected-error {{unknown type name}}
+ : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}}
+ B(const B& e)
+ : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error {{no viable conversion}} expected-error {{does not name}}
+ }
+ };
+}
diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp
index 3e96d02495fe..07281e16d3f3 100644
--- a/test/SemaCXX/conversion-function.cpp
+++ b/test/SemaCXX/conversion-function.cpp
@@ -97,9 +97,7 @@ void f(Yb& a) {
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)); // expected-note{{explicitly marked}}
+ AutoPtr(AutoPtr &); // expected-note{{declared private here}}
public:
AutoPtr();
@@ -115,7 +113,7 @@ AutoPtr test_auto_ptr(bool Cond) {
AutoPtr p;
if (Cond)
- return p; // expected-error{{call to deleted constructor}}
+ return p; // expected-error{{calling a private constructor}}
return AutoPtr();
}
@@ -125,11 +123,12 @@ struct A1 {
~A1();
private:
- A1(const A1&) __attribute__((unavailable)); // expected-note{{here}}
+ A1(const A1&); // expected-note 2 {{declared private here}}
};
A1 f() {
- return "Hello"; // expected-error{{invokes deleted constructor}}
+ // FIXME: redundant diagnostics!
+ return "Hello"; // expected-error {{calling a private constructor}} expected-warning {{an accessible copy constructor}}
}
namespace source_locations {
@@ -215,3 +214,114 @@ struct Other {
void test_any() {
Any any = Other(); // expected-error{{cannot pass object of non-POD type 'Other' through variadic constructor; call will abort at runtime}}
}
+
+namespace PR7055 {
+ // Make sure that we don't allow too many conversions in an
+ // auto_ptr-like template. In particular, we can't create multiple
+ // temporary objects when binding to a reference.
+ struct auto_ptr {
+ struct auto_ptr_ref { };
+
+ auto_ptr(auto_ptr&);
+ auto_ptr(auto_ptr_ref);
+ explicit auto_ptr(int *);
+
+ operator auto_ptr_ref();
+ };
+
+ struct X {
+ X(auto_ptr);
+ };
+
+ X f() {
+ X x(auto_ptr(new int));
+ return X(auto_ptr(new int));
+ }
+
+ auto_ptr foo();
+
+ X e(foo());
+
+ struct Y {
+ Y(X);
+ };
+
+ Y f2(foo());
+}
+
+namespace PR7934 {
+ typedef unsigned char uint8;
+
+ struct MutablePtr {
+ MutablePtr() : ptr(0) {}
+ void *ptr;
+
+ operator void*() { return ptr; }
+
+ private:
+ operator uint8*() { return reinterpret_cast<uint8*>(ptr); }
+ operator const char*() const { return reinterpret_cast<const char*>(ptr); }
+ };
+
+ void fake_memcpy(const void *);
+
+ void use() {
+ MutablePtr ptr;
+ fake_memcpy(ptr);
+ }
+}
+
+namespace rdar8018274 {
+ struct X { };
+ struct Y {
+ operator const struct X *() const;
+ };
+
+ struct Z : Y {
+ operator struct X * ();
+ };
+
+ void test() {
+ Z x;
+ (void) (x != __null);
+ }
+
+
+ struct Base {
+ operator int();
+ };
+
+ struct Derived1 : Base { };
+
+ struct Derived2 : Base { };
+
+ struct SuperDerived : Derived1, Derived2 {
+ using Derived1::operator int;
+ };
+
+ struct UeberDerived : SuperDerived {
+ operator long();
+ };
+
+ void test2(UeberDerived ud) {
+ int i = ud; // expected-error{{ambiguous conversion from derived class 'rdar8018274::SuperDerived' to base class 'rdar8018274::Base'}}
+ }
+
+ struct Base2 {
+ operator int();
+ };
+
+ struct Base3 {
+ operator int();
+ };
+
+ struct Derived23 : Base2, Base3 {
+ using Base2::operator int;
+ };
+
+ struct ExtraDerived23 : Derived23 { };
+
+ void test3(ExtraDerived23 ed) {
+ int i = ed;
+ }
+}
diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp
index bfe1501df867..5730b2af8f3f 100644
--- a/test/SemaCXX/copy-assignment.cpp
+++ b/test/SemaCXX/copy-assignment.cpp
@@ -97,3 +97,15 @@ void test() {
i = a; // expected-error{{assigning to 'int' from incompatible type 'A'}}
}
+// <rdar://problem/8315440>: Don't crash
+// FIXME: the recovery here is really bad.
+namespace test1 {
+ template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}}
+ A(UndeclaredType n) : X(n) {} // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{undeclared identifier 'n'}} expected-error {{expected ';' at end}} expected-error {{field has incomplete type}}
+ };
+ template<typename T> class B : public A<T> {
+ virtual void foo() {}
+ };
+ extern template class A<char>; // expected-note {{in instantiation}} expected-note {{not complete}}
+ extern template class B<char>;
+}
diff --git a/test/SemaCXX/crash-PR7625.cpp b/test/SemaCXX/crash-PR7625.cpp
new file mode 100644
index 000000000000..3ddf5e5ed249
--- /dev/null
+++ b/test/SemaCXX/crash-PR7625.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+template<typename T> struct a : T {
+ struct x : T {
+ int aa() { return p; } // expected-error{{use of undeclared identifier 'p'}}
+ };
+};
diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp
new file mode 100644
index 000000000000..d4ef7e33a1d1
--- /dev/null
+++ b/test/SemaCXX/decltype.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// PR5290
+int const f0();
+void f0_test() {
+ decltype(0, f0()) i = 0;
+ i = 0;
+}
+
+struct A { int a[1]; A() { } };
+typedef A const AC;
+int &f1(int*);
+float &f2(int const*);
+
+void test_f2() {
+ float &fr = f2(AC().a);
+}
+
diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp
index 757332df0b05..9da85567beda 100644
--- a/test/SemaCXX/default-constructor-initializers.cpp
+++ b/test/SemaCXX/default-constructor-initializers.cpp
@@ -43,7 +43,6 @@ Y4 y4;
// More tests
-
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 here}}
@@ -51,5 +50,12 @@ struct Z1 { // expected-error {{must explicitly initialize the reference member
volatile int v1;
};
+// Test default initialization which *requires* a constructor call for non-POD.
Z1 z1; // expected-note {{first required here}}
+// Ensure that value initialization doesn't use trivial implicit constructors.
+namespace PR7948 {
+ // Note that this is also non-POD to ensure we don't just special case PODs.
+ struct S { const int x; ~S(); };
+ const S arr[2] = { { 42 } };
+}
diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp
index 4f6c76bc90ed..cdcae2e4119e 100644
--- a/test/SemaCXX/destructor.cpp
+++ b/test/SemaCXX/destructor.cpp
@@ -103,5 +103,19 @@ namespace test6 {
};
class B : A<int> { B(); };
- B::B() {}
+ B::B() {} // expected-note {{in instantiation of member function 'test6::A<int>::~A' requested here}}
+}
+
+// Make sure classes are marked invalid when they have invalid
+// members. This avoids a crash-on-invalid.
+namespace test7 {
+ struct A {
+ ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
+ };
+ struct B : A {};
+
+ void test() {
+ B *b;
+ b->~B();
+ }
}
diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp
index 0690ead25085..1dc55e39162b 100644
--- a/test/SemaCXX/enum.cpp
+++ b/test/SemaCXX/enum.cpp
@@ -85,3 +85,8 @@ namespace PR7051 {
// PR7466
enum { }; // expected-warning{{declaration does not declare anything}}
typedef enum { }; // expected-warning{{typedef requires a name}}
+
+// PR7921
+enum PR7921E {
+ PR7921V = (PR7921E)(123) // expected-error {{expression is not an integer constant expression}}
+};
diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp
index 498611ee8599..b4bc78aa9a6d 100644
--- a/test/SemaCXX/exception-spec.cpp
+++ b/test/SemaCXX/exception-spec.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions -fms-extensions %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fexceptions %s
// Straight from the standard:
// Plain function with spec
@@ -43,18 +43,12 @@ void r2() throw(int);
void r2() throw(INT);
// throw-any spec and no spec at all are semantically equivalent
-void r3();
-void r3() throw(...);
-
void r4() throw(int, float);
void r4() throw(float, int);
void r5() throw(int); // expected-note {{previous declaration}}
void r5(); // expected-warning {{missing exception specification}}
-void r6() throw(...); // expected-note {{previous declaration}}
-void r6() throw(int); // expected-error {{exception specification in declaration does not match}}
-
void r7() throw(int); // expected-note {{previous declaration}}
void r7() throw(float); // expected-error {{exception specification in declaration does not match}}
@@ -89,8 +83,6 @@ struct P : private A
struct Base
{
virtual void f1() throw();
- virtual void f2();
- virtual void f3() throw(...);
virtual void f4() throw(int, float);
virtual void f5() throw(int, float);
@@ -107,8 +99,6 @@ struct Base
struct Derived : Base
{
virtual void f1() throw();
- virtual void f2() throw(...);
- virtual void f3();
virtual void f4() throw(float, int);
virtual void f5() throw(float);
diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp
index f3a05c1dbced..b51194acd9c3 100644
--- a/test/SemaCXX/expressions.cpp
+++ b/test/SemaCXX/expressions.cpp
@@ -7,3 +7,10 @@ void test() {
// Result of ! must be type bool.
int i = choice(!1);
}
+
+// rdar://8018252
+void f0() {
+ extern void f0_1(int*);
+ register int x;
+ f0_1(&x);
+}
diff --git a/test/SemaCXX/flexible-array-test.cpp b/test/SemaCXX/flexible-array-test.cpp
index 02e3f83974e2..95d8bb1aa413 100644
--- a/test/SemaCXX/flexible-array-test.cpp
+++ b/test/SemaCXX/flexible-array-test.cpp
@@ -43,3 +43,13 @@ struct X {
int blah;
S strings[]; // expected-error {{flexible array member 'strings' of non-POD element type 'S []'}}
};
+
+class A {
+ int s;
+ char c[];
+};
+
+union B {
+ int s;
+ char c[]; // expected-error {{field has incomplete type 'char []'}}
+};
diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp
index 9672a420dcae..2d08ea9a428f 100644
--- a/test/SemaCXX/i-c-e-cxx.cpp
+++ b/test/SemaCXX/i-c-e-cxx.cpp
@@ -16,7 +16,7 @@ void f() {
}
int a() {
- const int t=t; // expected-note {{subexpression not valid}}
+ const int t=t;
switch(1) { // expected-warning {{no case matching constant switch condition '1'}}
case t:; // expected-error {{not an integer constant expression}}
}
diff --git a/test/SemaCXX/inc-decrement-qualifiers.cpp b/test/SemaCXX/increment-decrement.cpp
index ba837a9c06db..11b7d1e12f4e 100644
--- a/test/SemaCXX/inc-decrement-qualifiers.cpp
+++ b/test/SemaCXX/increment-decrement.cpp
@@ -7,3 +7,8 @@ const int &dec = i--;
const int &incfail = ++i; // expected-error {{drops qualifiers}}
const int &decfail = --i; // expected-error {{drops qualifiers}}
+
+// PR7794
+void f0(int e) {
+ ++(int&)e;
+}
diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp
index 57730a62aae3..86c3d3e87a4c 100644
--- a/test/SemaCXX/linkage-spec.cpp
+++ b/test/SemaCXX/linkage-spec.cpp
@@ -54,3 +54,35 @@ extern "C"
return f2((char *)0);
}
}
+
+// PR6991
+extern "C" typedef int (*PutcFunc_t)(int);
+
+
+// PR7859
+extern "C" void pr7859_a(int) {} // expected-note {{previous definition}}
+extern "C" void pr7859_a(int) {} // expected-error {{redefinition}}
+
+extern "C" void pr7859_b() {} // expected-note {{previous definition}}
+extern "C" void pr7859_b(int) {} // expected-error {{conflicting}}
+
+extern "C" void pr7859_c(short) {} // expected-note {{previous definition}}
+extern "C" void pr7859_c(int) {} // expected-error {{conflicting}}
+
+// <rdar://problem/8318976>
+extern "C" {
+ struct s0 {
+ private:
+ s0();
+ s0(const s0 &);
+ };
+}
+
+//PR7754
+extern "C++" template <class T> int pr7754(T param);
+
+namespace N {
+ int value;
+}
+
+extern "C++" using N::value;
diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp
index 6830c5fdafb7..953ee48aa959 100644
--- a/test/SemaCXX/member-expr.cpp
+++ b/test/SemaCXX/member-expr.cpp
@@ -101,3 +101,17 @@ namespace PR7508 {
a.PopCleanupScope(); // expected-error{{no member named 'PopCleanupScope' in 'PR7508::A'}}
}
}
+
+namespace rdar8231724 {
+ namespace N {
+ template<typename T> struct X1;
+ int i;
+ }
+
+ struct X { };
+ struct Y : X { };
+
+ void f(Y *y) {
+ y->N::X1<int>; // expected-error{{'rdar8231724::N::X1' is not a member of class 'rdar8231724::Y'}}
+ }
+}
diff --git a/test/SemaCXX/member-pointer-ms.cpp b/test/SemaCXX/member-pointer-ms.cpp
new file mode 100644
index 000000000000..3b2d0fceb978
--- /dev/null
+++ b/test/SemaCXX/member-pointer-ms.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -cxx-abi microsoft -fsyntax-only -verify %s
+
+// Test that we reject pointers to members of incomplete classes (for now)
+struct A; //expected-note{{forward declaration of 'A'}}
+int A::*pai1; //expected-error{{incomplete type 'A'}}
+
+// Test that we don't allow reinterpret_casts from pointers of one size to
+// pointers of a different size.
+struct A {};
+struct B {};
+struct C: A, B {};
+
+void (A::*paf)();
+void (C::*pcf)() = reinterpret_cast<void (C::*)()>(paf); //expected-error{{cannot reinterpret_cast from member pointer type}}
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index 9d5cd2fc9273..795c0b95efd6 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -79,7 +79,7 @@ void g() {
void (HasMembers::*pmf)() = &HasMembers::f;
void (*pnf)() = &Fake::f;
- &hm.f; // expected-error {{must explicitly qualify}} expected-warning{{result unused}}
+ &hm.f; // expected-error {{cannot create a non-constant pointer to member function}}
void (HasMembers::*pmgv)() = &HasMembers::g;
void (HasMembers::*pmgi)(int) = &HasMembers::g;
@@ -142,8 +142,8 @@ namespace pr5985 {
void f() {
void (c::*p)();
p = &h; // expected-error {{must explicitly qualify}}
- p = &this->h; // expected-error {{must explicitly qualify}}
- p = &(*this).h; // expected-error {{must explicitly qualify}}
+ p = &this->h; // expected-error {{cannot create a non-constant pointer to member function}}
+ p = &(*this).h; // expected-error {{cannot create a non-constant pointer to member function}}
}
};
}
@@ -174,3 +174,99 @@ namespace PR7176 {
void m()
{ (void)(Condition) &base::Continuous::cond; }
}
+
+namespace rdar8358512 {
+ // We can't call this with an overload set because we're not allowed
+ // to look into overload sets unless the parameter has some kind of
+ // function type.
+ template <class F> void bind(F f); // expected-note 12 {{candidate template ignored}}
+ template <class F, class T> void bindmem(F (T::*f)()); // expected-note 4 {{candidate template ignored}}
+ template <class F> void bindfn(F (*f)()); // expected-note 4 {{candidate template ignored}}
+
+ struct A {
+ void nonstat();
+ void nonstat(int);
+
+ void mixed();
+ static void mixed(int);
+
+ static void stat();
+ static void stat(int);
+
+ template <typename T> struct Test0 {
+ void test() {
+ bind(&nonstat); // expected-error {{no matching function for call}}
+ bind(&A::nonstat); // expected-error {{no matching function for call}}
+
+ bind(&mixed); // expected-error {{no matching function for call}}
+ bind(&A::mixed); // expected-error {{no matching function for call}}
+
+ bind(&stat); // expected-error {{no matching function for call}}
+ bind(&A::stat); // expected-error {{no matching function for call}}
+ }
+ };
+
+ template <typename T> struct Test1 {
+ void test() {
+ bindmem(&nonstat); // expected-error {{no matching function for call}}
+ bindmem(&A::nonstat);
+
+ bindmem(&mixed); // expected-error {{no matching function for call}}
+ bindmem(&A::mixed);
+
+ bindmem(&stat); // expected-error {{no matching function for call}}
+ bindmem(&A::stat); // expected-error {{no matching function for call}}
+ }
+ };
+
+ template <typename T> struct Test2 {
+ void test() {
+ bindfn(&nonstat); // expected-error {{no matching function for call}}
+ bindfn(&A::nonstat); // expected-error {{no matching function for call}}
+
+ bindfn(&mixed); // expected-error {{no matching function for call}}
+ bindfn(&A::mixed); // expected-error {{no matching function for call}}
+
+ bindfn(&stat);
+ bindfn(&A::stat);
+ }
+ };
+ };
+
+ template <class T> class B {
+ void nonstat();
+ void nonstat(int);
+
+ void mixed();
+ static void mixed(int);
+
+ static void stat();
+ static void stat(int);
+
+ // None of these can be diagnosed yet, because the arguments are
+ // still dependent.
+ void test0a() {
+ bind(&nonstat);
+ bind(&B::nonstat);
+
+ bind(&mixed);
+ bind(&B::mixed);
+
+ bind(&stat);
+ bind(&B::stat);
+ }
+
+ void test0b() {
+ bind(&nonstat); // expected-error {{no matching function for call}}
+ bind(&B::nonstat); // expected-error {{no matching function for call}}
+
+ bind(&mixed); // expected-error {{no matching function for call}}
+ bind(&B::mixed); // expected-error {{no matching function for call}}
+
+ bind(&stat); // expected-error {{no matching function for call}}
+ bind(&B::stat); // expected-error {{no matching function for call}}
+ }
+ };
+
+ template void B<int>::test0b(); // expected-note {{in instantiation}}
+}
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 25bf823b2555..9a64e4c01d7e 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -310,3 +310,47 @@ namespace rdar8018245 {
template int *f<X1>(); // expected-note{{in instantiation of}}
}
+
+// <rdar://problem/8248780>
+namespace Instantiate {
+ template<typename T> struct X {
+ operator T*();
+ };
+
+ void f(X<int> &xi) {
+ delete xi;
+ }
+}
+
+namespace PR7810 {
+ struct X {
+ // cv is ignored in arguments
+ static void operator delete(void *const);
+ };
+ struct Y {
+ // cv is ignored in arguments
+ static void operator delete(void *volatile);
+ };
+}
+
+// Don't crash on template delete operators
+namespace TemplateDestructors {
+ struct S {
+ virtual ~S() {}
+
+ void* operator new(const size_t size);
+ template<class T> void* operator new(const size_t, const int, T*);
+ void operator delete(void*, const size_t);
+ template<class T> void operator delete(void*, const size_t, const int, T*);
+ };
+}
+
+namespace DeleteParam {
+ struct X {
+ void operator delete(X*); // expected-error{{first parameter of 'operator delete' must have type 'void *'}}
+ };
+
+ struct Y {
+ void operator delete(void* const);
+ };
+}
diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp
index 639d7faa8e96..17cee62d16fc 100644
--- a/test/SemaCXX/offsetof.cpp
+++ b/test/SemaCXX/offsetof.cpp
@@ -53,3 +53,16 @@ struct Derived2 : public Base1, public Base2 {
int derived1[__builtin_offsetof(Derived2, x) == 0? 1 : -1];
int derived2[__builtin_offsetof(Derived2, y) == 4? 1 : -1];
int derived3[__builtin_offsetof(Derived2, z) == 8? 1 : -1];
+
+// offsetof referring to anonymous struct in base.
+// PR7769
+struct foo {
+ struct {
+ int x;
+ };
+};
+
+struct bar : public foo {
+};
+
+int anonstruct[__builtin_offsetof(bar, x) == 0 ? 1 : -1];
diff --git a/test/SemaCXX/overload-call-copycon.cpp b/test/SemaCXX/overload-call-copycon.cpp
index f57484e5069a..6720cb695338 100644
--- a/test/SemaCXX/overload-call-copycon.cpp
+++ b/test/SemaCXX/overload-call-copycon.cpp
@@ -1,40 +1,44 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -Wnon-pod-varargs
-class X { };
+class X { }; // expected-note {{the implicit copy constructor}} \
+ // expected-note{{the implicit default constructor}}
-int& copycon(X x);
+int& copycon(X x); // expected-note{{passing argument to parameter}}
float& copycon(...);
void test_copycon(X x, X const xc, X volatile xv) {
int& i1 = copycon(x);
int& i2 = copycon(xc);
- float& f1 = copycon(xv);
+ copycon(xv); // expected-error{{no matching constructor}}
}
class A {
public:
- A(A&);
+ A(A&); // expected-note{{would lose const qualifier}} \
+ // expected-note{{no known conversion}}
};
-class B : public A { };
+class B : public A { }; // expected-note{{would lose const qualifier}} \
+// expected-note{{would lose volatile qualifier}} \
+// expected-note 2{{requires 0 arguments}}
-short& copycon2(A a);
-int& copycon2(B b);
+short& copycon2(A a); // expected-note{{passing argument to parameter}}
+int& copycon2(B b); // expected-note 2{{passing argument to parameter}}
float& copycon2(...);
void test_copycon2(A a, const A ac, B b, B const bc, B volatile bv) {
int& i1 = copycon2(b);
- float& f1 = copycon2(bc); // expected-warning {{cannot pass object of non-POD type}}
- float& f2 = copycon2(bv); // expected-warning {{cannot pass object of non-POD type}}
+ copycon2(bc); // expected-error{{no matching constructor}}
+ copycon2(bv); // expected-error{{no matching constructor}}
short& s1 = copycon2(a);
- float& f3 = copycon2(ac); // expected-warning {{cannot pass object of non-POD type}}
+ copycon2(ac); // expected-error{{no matching constructor}}
}
-int& copycon3(A a);
+int& copycon3(A a); // expected-note{{passing argument to parameter 'a' here}}
float& copycon3(...);
void test_copycon3(B b, const B bc) {
int& i1 = copycon3(b);
- float& f1 = copycon3(bc); // expected-warning {{cannot pass object of non-POD type}}
+ copycon3(bc); // expected-error{{no matching constructor}}
}
class C : public B { };
diff --git a/test/SemaCXX/qualified-member-enum.cpp b/test/SemaCXX/qualified-member-enum.cpp
new file mode 100644
index 000000000000..83b0a5911d43
--- /dev/null
+++ b/test/SemaCXX/qualified-member-enum.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// Check that this doesn't crash.
+struct A {
+ enum {LABEL};
+};
+int f() {
+ return A().A::LABEL;
+}
+
diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp
index 9242d1240ab6..dfd548732150 100644
--- a/test/SemaCXX/return-noreturn.cpp
+++ b/test/SemaCXX/return-noreturn.cpp
@@ -7,9 +7,12 @@ namespace PR6884 {
~abort_struct() __attribute__((noreturn));
};
+ // FIXME: Should either of these actually warn, since the destructor is
+ // marked noreturn?
+
int f() {
abort_struct();
- }
+ } // expected-warning{{control reaches end of non-void function}}
int f2() {
abort_struct s;
diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp
index ba6476560360..7d4cb964029b 100644
--- a/test/SemaCXX/return-stack-addr.cpp
+++ b/test/SemaCXX/return-stack-addr.cpp
@@ -108,5 +108,16 @@ int* ret_cpp_const_cast(const int x) {
return const_cast<int*>(&x); // expected-warning {{address of stack memory}}
}
+// PR 7999 - handle the case where a field is itself a reference.
+template <typename T> struct PR7999 {
+ PR7999(T& t) : value(t) {}
+ T& value;
+};
+
+struct PR7999_X {};
+
+PR7999_X& PR7999_f(PR7999<PR7999_X> s) { return s.value; } // no-warning
+void test_PR7999(PR7999_X& x) { (void)PR7999_f(x); } // no-warning
+
// TODO: test case for dynamic_cast. clang does not yet have
// support for C++ classes to write such a test case.
diff --git a/test/SemaCXX/scope-check.cpp b/test/SemaCXX/scope-check.cpp
index cef64f6322c5..cdc3868a7be0 100644
--- a/test/SemaCXX/scope-check.cpp
+++ b/test/SemaCXX/scope-check.cpp
@@ -121,3 +121,33 @@ namespace test6 {
}
}
+// C++0x says it's okay to skip non-trivial initializers on static
+// locals, and we implement that in '03 as well.
+namespace test7 {
+ struct C { C(); };
+
+ void test() {
+ goto foo;
+ static C c;
+ foo:
+ return;
+ }
+}
+
+// PR7789
+namespace test8 {
+ void test1(int c) {
+ switch (c) {
+ case 0:
+ int x = 56; // expected-note {{jump bypasses variable initialization}}
+ case 1: // expected-error {{switch case is in protected scope}}
+ x = 10;
+ }
+ }
+
+ void test2() {
+ goto l2; // expected-error {{goto into protected scope}}
+ l1: int x = 5; // expected-note {{jump bypasses variable initialization}}
+ l2: x++;
+ }
+}
diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp
index 54240dcc305f..fc13630bbf12 100644
--- a/test/SemaCXX/switch.cpp
+++ b/test/SemaCXX/switch.cpp
@@ -8,8 +8,7 @@ void test() {
}
int n = 3;
- switch (n && 1) { // expected-warning {{bool}} \
- // expected-warning {{use of logical && with constant operand}}
+ switch (n && 1) { // expected-warning {{bool}}
case 1:
break;
}
diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp
index 85bd59612688..b05dd07ec2ec 100644
--- a/test/SemaCXX/type-traits.cpp
+++ b/test/SemaCXX/type-traits.cpp
@@ -34,6 +34,37 @@ typedef Derives NonPODAr[10];
typedef HasVirt VirtAr[10];
union NonPODUnion { int i; Derives n; };
+struct HasNoThrowCopyAssign {
+ void operator =(const HasNoThrowCopyAssign&) throw();
+};
+struct HasMultipleCopyAssign {
+ void operator =(const HasMultipleCopyAssign&) throw();
+ void operator =(volatile HasMultipleCopyAssign&);
+};
+struct HasMultipleNoThrowCopyAssign {
+ void operator =(const HasMultipleNoThrowCopyAssign&) throw();
+ void operator =(volatile HasMultipleNoThrowCopyAssign&) throw();
+};
+
+struct HasNoThrowConstructor { HasNoThrowConstructor() throw(); };
+struct HasNoThrowConstructorWithArgs {
+ HasNoThrowConstructorWithArgs(HasCons i = HasCons(0)) throw();
+};
+
+struct HasNoThrowCopy { HasNoThrowCopy(const HasNoThrowCopy&) throw(); };
+struct HasMultipleCopy {
+ HasMultipleCopy(const HasMultipleCopy&) throw();
+ HasMultipleCopy(volatile HasMultipleCopy&);
+};
+struct HasMultipleNoThrowCopy {
+ HasMultipleNoThrowCopy(const HasMultipleNoThrowCopy&) throw();
+ HasMultipleNoThrowCopy(volatile HasMultipleNoThrowCopy&) throw();
+};
+
+struct HasVirtDest { virtual ~HasVirtDest(); };
+struct DerivedVirtDest : HasVirtDest {};
+typedef HasVirtDest VirtDestAr[1];
+
void is_pod()
{
int t01[T(__is_pod(int))];
@@ -258,3 +289,102 @@ void f() {
int t01[T(!__has_trivial_destructor(A))];
int t02[T(!__has_trivial_destructor(B<int>))];
}
+
+void has_nothrow_assign() {
+ int t01[T(__has_nothrow_assign(Int))];
+ int t02[T(__has_nothrow_assign(IntAr))];
+ int t03[T(__has_nothrow_assign(Union))];
+ int t04[T(__has_nothrow_assign(UnionAr))];
+ int t05[T(__has_nothrow_assign(POD))];
+ int t06[T(__has_nothrow_assign(Derives))];
+ int t07[F(__has_nothrow_assign(ConstIntAr))];
+ int t08[F(__has_nothrow_assign(ConstIntArAr))];
+ int t09[T(__has_nothrow_assign(HasDest))];
+ int t10[T(__has_nothrow_assign(HasPriv))];
+ int t11[T(__has_nothrow_assign(HasCons))];
+ int t12[T(__has_nothrow_assign(HasRef))];
+ int t13[T(__has_nothrow_assign(HasCopy))];
+ int t14[F(__has_nothrow_assign(IntRef))];
+ int t15[F(__has_nothrow_assign(HasCopyAssign))];
+ int t16[F(__has_nothrow_assign(const Int))];
+ int t17[F(__has_nothrow_assign(NonPODAr))];
+ int t18[F(__has_nothrow_assign(VirtAr))];
+
+ int t19[T(__has_nothrow_assign(HasNoThrowCopyAssign))];
+ int t20[F(__has_nothrow_assign(HasMultipleCopyAssign))];
+ int t21[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))];
+}
+
+void has_nothrow_copy() {
+ int t01[T(__has_nothrow_copy(Int))];
+ int t02[T(__has_nothrow_copy(IntAr))];
+ int t03[T(__has_nothrow_copy(Union))];
+ int t04[T(__has_nothrow_copy(UnionAr))];
+ int t05[T(__has_nothrow_copy(POD))];
+ int t06[T(__has_nothrow_copy(Derives))];
+ int t07[T(__has_nothrow_copy(ConstIntAr))];
+ int t08[T(__has_nothrow_copy(ConstIntArAr))];
+ int t09[T(__has_nothrow_copy(HasDest))];
+ int t10[T(__has_nothrow_copy(HasPriv))];
+ int t11[T(__has_nothrow_copy(HasCons))];
+ int t12[T(__has_nothrow_copy(HasRef))];
+ int t13[F(__has_nothrow_copy(HasCopy))];
+ int t14[T(__has_nothrow_copy(IntRef))];
+ int t15[T(__has_nothrow_copy(HasCopyAssign))];
+ int t16[T(__has_nothrow_copy(const Int))];
+ int t17[F(__has_nothrow_copy(NonPODAr))];
+ int t18[F(__has_nothrow_copy(VirtAr))];
+
+ int t19[T(__has_nothrow_copy(HasNoThrowCopy))];
+ int t20[F(__has_nothrow_copy(HasMultipleCopy))];
+ int t21[T(__has_nothrow_copy(HasMultipleNoThrowCopy))];
+}
+
+void has_nothrow_constructor() {
+ int t01[T(__has_nothrow_constructor(Int))];
+ int t02[T(__has_nothrow_constructor(IntAr))];
+ int t03[T(__has_nothrow_constructor(Union))];
+ int t04[T(__has_nothrow_constructor(UnionAr))];
+ int t05[T(__has_nothrow_constructor(POD))];
+ int t06[T(__has_nothrow_constructor(Derives))];
+ int t07[T(__has_nothrow_constructor(ConstIntAr))];
+ int t08[T(__has_nothrow_constructor(ConstIntArAr))];
+ int t09[T(__has_nothrow_constructor(HasDest))];
+ int t10[T(__has_nothrow_constructor(HasPriv))];
+ int t11[F(__has_nothrow_constructor(HasCons))];
+ int t12[F(__has_nothrow_constructor(HasRef))];
+ int t13[F(__has_nothrow_constructor(HasCopy))];
+ int t14[F(__has_nothrow_constructor(IntRef))];
+ int t15[T(__has_nothrow_constructor(HasCopyAssign))];
+ int t16[T(__has_nothrow_constructor(const Int))];
+ int t17[T(__has_nothrow_constructor(NonPODAr))];
+ // int t18[T(__has_nothrow_constructor(VirtAr))]; // not implemented
+
+ int t19[T(__has_nothrow_constructor(HasNoThrowConstructor))];
+ int t20[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))];
+}
+
+void has_virtual_destructor() {
+ int t01[F(__has_virtual_destructor(Int))];
+ int t02[F(__has_virtual_destructor(IntAr))];
+ int t03[F(__has_virtual_destructor(Union))];
+ int t04[F(__has_virtual_destructor(UnionAr))];
+ int t05[F(__has_virtual_destructor(POD))];
+ int t06[F(__has_virtual_destructor(Derives))];
+ int t07[F(__has_virtual_destructor(ConstIntAr))];
+ int t08[F(__has_virtual_destructor(ConstIntArAr))];
+ int t09[F(__has_virtual_destructor(HasDest))];
+ int t10[F(__has_virtual_destructor(HasPriv))];
+ int t11[F(__has_virtual_destructor(HasCons))];
+ int t12[F(__has_virtual_destructor(HasRef))];
+ int t13[F(__has_virtual_destructor(HasCopy))];
+ int t14[F(__has_virtual_destructor(IntRef))];
+ int t15[F(__has_virtual_destructor(HasCopyAssign))];
+ int t16[F(__has_virtual_destructor(const Int))];
+ int t17[F(__has_virtual_destructor(NonPODAr))];
+ int t18[F(__has_virtual_destructor(VirtAr))];
+
+ int t19[T(__has_virtual_destructor(HasVirtDest))];
+ int t20[T(__has_virtual_destructor(DerivedVirtDest))];
+ int t21[F(__has_virtual_destructor(VirtDestAr))];
+}
diff --git a/test/SemaCXX/unary-real-imag.cpp b/test/SemaCXX/unary-real-imag.cpp
new file mode 100644
index 000000000000..91b63e37b9a4
--- /dev/null
+++ b/test/SemaCXX/unary-real-imag.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct A {};
+int i = __real__ A(); // expected-error {{invalid type 'A' to __real operator}}
+int j = __imag__ A(); // expected-error {{invalid type 'A' to __imag operator}}
+
diff --git a/test/SemaCXX/unreachable-code.cpp b/test/SemaCXX/unreachable-code.cpp
index 528bba7d5e15..40d0c00b9390 100644
--- a/test/SemaCXX/unreachable-code.cpp
+++ b/test/SemaCXX/unreachable-code.cpp
@@ -39,3 +39,20 @@ void test3() {
bar(); // expected-warning {{will never be executed}}
}
}
+
+// PR 6130 - Don't warn about bogus unreachable code with throw's and
+// temporary objects.
+class PR6130 {
+public:
+ PR6130();
+ ~PR6130();
+};
+
+int pr6130(unsigned i) {
+ switch(i) {
+ case 0: return 1;
+ case 1: return 2;
+ default:
+ throw PR6130(); // no-warning
+ }
+}
diff --git a/test/SemaCXX/vector-no-lax.cpp b/test/SemaCXX/vector-no-lax.cpp
new file mode 100644
index 000000000000..32dcacfb45d8
--- /dev/null
+++ b/test/SemaCXX/vector-no-lax.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -fno-lax-vector-conversions -verify %s
+typedef unsigned int __attribute__((vector_size (16))) vUInt32;
+typedef int __attribute__((vector_size (16))) vSInt32;
+
+vSInt32 foo (vUInt32 a) {
+ vSInt32 b = { 0, 0, 0, 0 };
+ b += a; // expected-error{{can't convert between vector values}}
+ return b;
+}
diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp
index 66b2d680d21a..9ae2c82fc530 100644
--- a/test/SemaCXX/vector.cpp
+++ b/test/SemaCXX/vector.cpp
@@ -51,10 +51,10 @@ void conditional(bool Cond, char16 c16, longlong16 ll16, char16_e c16e,
__typeof__(Cond? ll16 : ll16e) *ll16ep2 = &ll16e;
__typeof__(Cond? ll16e : ll16) *ll16ep3 = &ll16e;
- // Conditional operators with incompatible types.
- (void)(Cond? c16 : ll16); // expected-error{{can't convert between vector values}}
- (void)(Cond? ll16e : c16e); // expected-error{{can't convert between vector values}}
- (void)(Cond? ll16e : c16); // expected-error{{can't convert between vector values}}
+ // Conditional operators with compatible types under -flax-vector-conversions (default)
+ (void)(Cond? c16 : ll16);
+ (void)(Cond? ll16e : c16e);
+ (void)(Cond? ll16e : c16);
}
// Test C++ cast'ing of vector types.
@@ -183,8 +183,10 @@ void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16,
(void)(Cond? to_c16 : to_c16e);
(void)(Cond? to_ll16e : to_ll16);
- (void)(Cond? to_c16 : to_ll16); // expected-error{{can't convert between vector values of different size}}
- (void)(Cond? to_c16e : to_ll16e); // expected-error{{can't convert between vector values of different size}}
+
+ // These 2 are convertable with -flax-vector-conversions (default)
+ (void)(Cond? to_c16 : to_ll16);
+ (void)(Cond? to_c16e : to_ll16e);
}
typedef float fltx2 __attribute__((__vector_size__(8)));
diff --git a/test/SemaCXX/virtual-base-used.cpp b/test/SemaCXX/virtual-base-used.cpp
new file mode 100644
index 000000000000..d147b13f04fd
--- /dev/null
+++ b/test/SemaCXX/virtual-base-used.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// PR7800
+
+class NoDestroy { ~NoDestroy(); }; // expected-note 3 {{declared private here}}
+struct A {
+ virtual ~A();
+};
+
+struct B : public virtual A {
+ NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}}
+};
+struct D : public virtual B {
+ virtual void foo();
+ ~D();
+};
+void D::foo() { // expected-note {{implicit default destructor for 'B' first required here}}
+}
+
+struct E : public virtual A {
+ NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}}
+};
+struct F : public E { // expected-note {{implicit default destructor for 'E' first required here}}
+};
+struct G : public virtual F {
+ virtual void foo();
+ ~G();
+};
+void G::foo() { // expected-note {{implicit default destructor for 'F' first required here}}
+}
+
+struct H : public virtual A {
+ NoDestroy x; // expected-error {{field of type 'NoDestroy' has private destructor}}
+};
+struct I : public virtual H {
+ ~I();
+};
+struct J : public I {
+ virtual void foo();
+ ~J();
+};
+void J::foo() { // expected-note {{implicit default destructor for 'H' first required here}}
+}
diff --git a/test/SemaCXX/warn-cast-align.cpp b/test/SemaCXX/warn-cast-align.cpp
new file mode 100644
index 000000000000..68acbdd4eaa3
--- /dev/null
+++ b/test/SemaCXX/warn-cast-align.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -Wcast-align -verify %s
+
+// Simple casts.
+void test0(char *P) {
+ char *a; short *b; int *c;
+
+ a = (char*) P;
+ a = static_cast<char*>(P);
+ a = reinterpret_cast<char*>(P);
+ typedef char *CharPtr;
+ a = CharPtr(P);
+
+ b = (short*) P; // expected-warning {{cast from 'char *' to 'short *' increases required alignment from 1 to 2}}
+ b = reinterpret_cast<short*>(P);
+ typedef short *ShortPtr;
+ b = ShortPtr(P); // expected-warning {{cast from 'char *' to 'ShortPtr' (aka 'short *') increases required alignment from 1 to 2}}
+
+ c = (int*) P; // expected-warning {{cast from 'char *' to 'int *' increases required alignment from 1 to 4}}
+ c = reinterpret_cast<int*>(P);
+ typedef int *IntPtr;
+ c = IntPtr(P); // expected-warning {{cast from 'char *' to 'IntPtr' (aka 'int *') increases required alignment from 1 to 4}}
+}
+
+// Casts from void* are a special case.
+void test1(void *P) {
+ char *a; short *b; int *c;
+
+ a = (char*) P;
+ a = static_cast<char*>(P);
+ a = reinterpret_cast<char*>(P);
+ typedef char *CharPtr;
+ a = CharPtr(P);
+
+ b = (short*) P;
+ b = static_cast<short*>(P);
+ b = reinterpret_cast<short*>(P);
+ typedef short *ShortPtr;
+ b = ShortPtr(P);
+
+ c = (int*) P;
+ c = static_cast<int*>(P);
+ c = reinterpret_cast<int*>(P);
+ typedef int *IntPtr;
+ c = IntPtr(P);
+}
diff --git a/test/SemaCXX/warn-for-var-in-else.cpp b/test/SemaCXX/warn-for-var-in-else.cpp
deleted file mode 100644
index 1307c43bc20a..000000000000
--- a/test/SemaCXX/warn-for-var-in-else.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// rdar://6425550
-int bar();
-void do_something(int);
-int *get_ptr();
-
-int foo() {
- if (int X = bar()) {
- return X;
- } else {
- do_something(X); // expected-warning{{'X' is always zero in this context}}
- return 0;
- }
-}
-
-bool foo2() {
- if (bool B = bar()) {
- if (int Y = bar()) {
- return B;
- } else {
- do_something(Y); // expected-warning{{'Y' is always zero in this context}}
- return B;
- }
- } else {
- if (bool B2 = B) { // expected-warning{{'B' is always false in this context}}
- 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-global-constructors.cpp b/test/SemaCXX/warn-global-constructors.cpp
new file mode 100644
index 000000000000..107bbe129f67
--- /dev/null
+++ b/test/SemaCXX/warn-global-constructors.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -fsyntax-only -Wglobal-constructors %s -verify
+
+int opaque_int();
+
+namespace test0 {
+ // These should never require global constructors.
+ int a;
+ int b = 20;
+ float c = 5.0f;
+
+ // This global constructor is avoidable based on initialization order.
+ int d = b; // expected-warning {{global constructor}}
+
+ // These global constructors are unavoidable.
+ int e = opaque_int(); // expected-warning {{global constructor}}
+ int f = b; // expected-warning {{global constructor}}
+}
+
+namespace test1 {
+ struct A { int x; };
+ A a;
+ A b = A();
+ A c = { 10 };
+ A d = { opaque_int() }; // expected-warning {{global constructor}}
+ A e = A(A());
+ A f = A(a); // expected-warning {{global constructor}}
+ A g(a); // expected-warning {{global constructor}}
+ A h((A())); // expected-warning {{global constructor}}
+ A i((A(A()))); // expected-warning {{global constructor}}
+}
+
+namespace test2 {
+ struct A { A(); };
+ A a; // expected-warning {{global constructor}}
+ A b[10]; // expected-warning {{global constructor}}
+ A c[10][10]; // expected-warning {{global constructor}}
+
+ A &d = a;
+ A &e = b[5];
+ A &f = c[5][7];
+}
+
+namespace test3 {
+ struct A { ~A(); };
+ A a; // expected-warning {{global destructor}}
+ A b[10]; // expected-warning {{global destructor}}
+ A c[10][10]; // expected-warning {{global destructor}}
+
+ A &d = a;
+ A &e = b[5];
+ A &f = c[5][7];
+}
+
+namespace test4 {
+ char a[] = "hello";
+ char b[5] = "hello";
+ char c[][5] = { "hello" };
+}
+
+namespace test5 {
+ struct A { A(); };
+
+ void f1() {
+ static A a;
+ }
+ void f2() {
+ static A& a = *new A;
+ }
+}
+
+namespace test6 {
+ struct A { ~A(); };
+
+ void f1() {
+ static A a; // expected-warning {{global destructor}}
+ }
+ void f2() {
+ static A& a = *new A;
+ }
+
+} \ No newline at end of file
diff --git a/test/SemaCXX/warn-unused-filescoped.cpp b/test/SemaCXX/warn-unused-filescoped.cpp
new file mode 100644
index 000000000000..75fc6a4da0ba
--- /dev/null
+++ b/test/SemaCXX/warn-unused-filescoped.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function %s
+
+static void f1(); // expected-warning{{unused}}
+
+namespace {
+ void f2(); // expected-warning{{unused}}
+
+ void f3() { } // expected-warning{{unused}}
+
+ struct S {
+ void m1() { } // expected-warning{{unused}}
+ void m2(); // expected-warning{{unused}}
+ void m3();
+ S(const S&);
+ void operator=(const S&);
+ };
+
+ template <typename T>
+ struct TS {
+ void m();
+ };
+ template <> void TS<int>::m() { } // expected-warning{{unused}}
+
+ template <typename T>
+ void tf() { }
+ template <> void tf<int>() { } // expected-warning{{unused}}
+
+ struct VS {
+ virtual void vm() { }
+ };
+
+ struct SVS : public VS {
+ void vm() { }
+ };
+}
+
+void S::m3() { } // expected-warning{{unused}}
+
+static inline void f4() { }
+const unsigned int cx = 0;
+
+static int x1; // expected-warning{{unused}}
+
+namespace {
+ int x2; // expected-warning{{unused}}
+
+ struct S2 {
+ static int x; // expected-warning{{unused}}
+ };
+
+ template <typename T>
+ struct TS2 {
+ static int x;
+ };
+ template <> int TS2<int>::x; // expected-warning{{unused}}
+}
diff --git a/test/SemaObjC/block-type-safety.m b/test/SemaObjC/block-type-safety.m
index 402a658f3e35..c13e80618d51 100644
--- a/test/SemaObjC/block-type-safety.m
+++ b/test/SemaObjC/block-type-safety.m
@@ -104,3 +104,20 @@ void test3() {
f4(^(NSArray<P2>* a) { }); // expected-error {{incompatible block pointer types passing 'void (^)(NSArray<P2> *)' to parameter of type 'void (^)(id<P>)'}}
}
+// rdar : //8302845
+@protocol Foo @end
+
+@interface Baz @end
+
+@interface Baz(FooConformance) <Foo>
+@end
+
+@implementation Baz @end
+
+int test4 () {
+ id <Foo> (^b)() = ^{ // Doesn't work
+ return (Baz *)0;
+ };
+ return 0;
+}
+
diff --git a/test/SemaObjC/compare-qualified-class.m b/test/SemaObjC/compare-qualified-class.m
new file mode 100644
index 000000000000..cb2b26a4f70f
--- /dev/null
+++ b/test/SemaObjC/compare-qualified-class.m
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar:// 8191774
+
+@protocol SomeProtocol
+@end
+
+@protocol SomeProtocol1
+@end
+
+@interface SomeObject <SomeProtocol>
+@end
+
+int main () {
+ Class <SomeProtocol> classA;
+ Class <SomeProtocol> classB;
+ Class <SomeProtocol, SomeProtocol1> classC;
+ Class <SomeProtocol1> classD;
+ void * pv = 0;
+ Class c = (Class)0;;
+ if (pv)
+ return classA == pv;
+
+ if (c)
+ return classA == c;
+
+ return classA == classB || classA == classC ||
+ classC == classA ||
+ classA == classD; // expected-warning {{comparison of distinct pointer types ('Class<SomeProtocol> *' and 'Class<SomeProtocol1> *')}}
+}
+
diff --git a/test/SemaObjC/comptypes-5.m b/test/SemaObjC/comptypes-5.m
index aaf64462b186..46300e3a5309 100644
--- a/test/SemaObjC/comptypes-5.m
+++ b/test/SemaObjC/comptypes-5.m
@@ -26,8 +26,8 @@ int main()
MyOtherClass<MyProtocol> *obj_c_super_p_q = nil;
MyClass<MyProtocol> *obj_c_cat_p_q = nil;
- obj_c_cat_p = obj_id_p;
- obj_c_super_p = obj_id_p;
+ obj_c_cat_p = obj_id_p;
+ obj_c_super_p = obj_id_p;
obj_id_p = obj_c_cat_p; /* Ok */
obj_id_p = obj_c_super_p; /* Ok */
diff --git a/test/SemaObjC/conflict-nonfragile-abi2.m b/test/SemaObjC/conflict-nonfragile-abi2.m
new file mode 100644
index 000000000000..e4b513f75312
--- /dev/null
+++ b/test/SemaObjC/conflict-nonfragile-abi2.m
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fobjc-nonfragile-abi -verify -fsyntax-only %s
+// rdar : // 8225011
+
+int glob; // expected-note {{global variable declared here}}
+
+@interface I
+@property int glob; // expected-note {{property declared here}}
+@property int p;
+@property int le;
+@property int l;
+@property int ls;
+@property int r;
+@end
+
+@implementation I
+- (int) Meth { return glob; } // expected-warning {{when default property synthesis is on, 'glob' lookup will access}}
+@synthesize glob;
+// rdar: // 8248681
+- (int) Meth1: (int) p {
+ extern int le;
+ int l = 1;
+ static int ls;
+ register int r;
+ p = le + ls + r;
+ return l;
+}
+@dynamic p;
+@dynamic le;
+@dynamic l;
+@dynamic ls;
+@dynamic r;
+@end
+
+
diff --git a/test/SemaObjC/crash-label.m b/test/SemaObjC/crash-label.m
index d0a5ae40c7f5..ffcb46344e24 100644
--- a/test/SemaObjC/crash-label.m
+++ b/test/SemaObjC/crash-label.m
@@ -2,8 +2,9 @@
- (NSDictionary*) _executeScript:(NSString *)source { // expected-error 2 {{expected a type}} \
// expected-error {{missing context for method declaration}}
- Exit: [nilArgs release]; // expected-error {{use of undeclared identifier}}
- }
- - (NSDictionary *) _setupKernelStandardMode:(NSString *)source { // expected-error 2 {{expected a type}} \
-expected-error {{missing context for method declaration}}
- Exit: if(_ciKernel && !success ) { // expected-error {{use of undeclared identifier}} // expected-error 2 {{expected}}
+Exit: [nilArgs release]; // expected-error {{use of undeclared identifier}}
+}
+- (NSDictionary *) _setupKernelStandardMode:(NSString *)source { // expected-error 2 {{expected a type}} \
+expected-error {{missing context for method declaration}} \
+expected-note{{to match this '{'}}
+ Exit: if(_ciKernel && !success ) { // expected-error {{use of undeclared identifier}} // expected-error 2 {{expected}} expected-note{{to match this '{'}}
diff --git a/test/SemaObjC/default-synthesize-1.m b/test/SemaObjC/default-synthesize-1.m
new file mode 100644
index 000000000000..374fa8314bfd
--- /dev/null
+++ b/test/SemaObjC/default-synthesize-1.m
@@ -0,0 +1,116 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s
+
+@interface NSObject
+- (void) release;
+- (id) retain;
+@end
+@class NSString;
+
+@interface SynthItAll : NSObject
+@property int howMany;
+@property (retain) NSString* what;
+@end
+
+@implementation SynthItAll
+//@synthesize howMany, what;
+@end
+
+
+@interface SynthSetter : NSObject
+@property (nonatomic) int howMany; // REM: nonatomic to avoid warnings about only implementing one of the pair
+@property (nonatomic, retain) NSString* what;
+@end
+
+@implementation SynthSetter
+//@synthesize howMany, what;
+
+- (int) howMany {
+ return howMany;
+}
+// - (void) setHowMany: (int) value
+
+- (NSString*) what {
+ return what;
+}
+// - (void) setWhat: (NSString*) value
+@end
+
+
+@interface SynthGetter : NSObject
+@property (nonatomic) int howMany; // REM: nonatomic to avoid warnings about only implementing one of the pair
+@property (nonatomic, retain) NSString* what;
+@end
+
+@implementation SynthGetter
+//@synthesize howMany, what;
+
+// - (int) howMany
+- (void) setHowMany: (int) value {
+ howMany = value;
+}
+
+// - (NSString*) what
+- (void) setWhat: (NSString*) value {
+ if (what != value) {
+ [what release];
+ what = [value retain];
+ }
+}
+@end
+
+
+@interface SynthNone : NSObject
+@property int howMany;
+@property (retain) NSString* what;
+@end
+
+@implementation SynthNone
+//@synthesize howMany, what; // REM: Redundant anyway
+
+- (int) howMany {
+ return howMany;
+}
+- (void) setHowMany: (int) value {
+ howMany = value;
+}
+
+- (NSString*) what {
+ return what;
+}
+- (void) setWhat: (NSString*) value {
+ if (what != value) {
+ [what release];
+ what = [value retain];
+ }
+}
+@end
+
+// rdar://8349319
+// No default synthesis if implementation has getter (readonly) and setter(readwrite) methods.
+@interface DSATextSearchResult
+@property(assign,readonly) float relevance;
+@property(assign,readonly) char isTitleMatch;
+@end
+
+@interface DSANodeSearchResult : DSATextSearchResult {}
+@end
+
+
+@implementation DSATextSearchResult
+-(char)isTitleMatch {
+ return (char)0;
+}
+
+-(float)relevance {
+ return 0.0;
+}
+@end
+
+@implementation DSANodeSearchResult
+-(id)initWithNode:(id )node relevance:(float)relevance isTitleMatch:(char)isTitleMatch {
+ relevance = 0.0;
+ isTitleMatch = 'a';
+ return self;
+}
+@end
+
diff --git a/test/SemaObjC/deref-interface.m b/test/SemaObjC/deref-interface.m
index c7096bd59a04..255e1d079814 100644
--- a/test/SemaObjC/deref-interface.m
+++ b/test/SemaObjC/deref-interface.m
@@ -6,7 +6,7 @@
@implementation NSView
- (id)initWithView:(id)realView {
- *(NSView *)self = *(NSView *)realView; // expected-error {{indirection cannot be to an interface in non-fragile ABI}}
+ *(NSView *)self = *(NSView *)realView; // expected-error {{cannot assign to class object in non-fragile ABI}}
}
@end
diff --git a/test/SemaObjC/iboutletcollection-attr.m b/test/SemaObjC/iboutletcollection-attr.m
new file mode 100644
index 000000000000..fb64e3a9f534
--- /dev/null
+++ b/test/SemaObjC/iboutletcollection-attr.m
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify %s
+// rdar: // 8308053
+
+@interface I {
+ __attribute__((iboutletcollection(I))) id ivar1;
+ __attribute__((iboutletcollection(id))) id ivar2;
+ __attribute__((iboutletcollection())) id ivar3;
+ __attribute__((iboutletcollection)) id ivar4;
+}
+@property (nonatomic, retain) __attribute__((iboutletcollection(I))) id prop1;
+@property (nonatomic, retain) __attribute__((iboutletcollection(id))) id prop2;
+@property (nonatomic, retain) __attribute__((iboutletcollection())) id prop3;
+@property (nonatomic, retain) __attribute__((iboutletcollection)) id prop4;
+@end
+
+typedef void *PV;
+@interface BAD {
+ __attribute__((iboutletcollection(I, 1))) id ivar1; // expected-error {{attribute requires 1 argument(s)}}
+ __attribute__((iboutletcollection(B))) id ivar2; // expected-error {{invalid type 'B' as argument of iboutletcollection attribute}}
+ __attribute__((iboutletcollection(PV))) id ivar3; // expected-error {{invalid type 'PV' as argument of iboutletcollection attribute}}
+ __attribute__((iboutletcollection(PV))) void *ivar4; // expected-error {{ivar with iboutletcollection attribute must have object type (invalid 'void *')}}
+ __attribute__((iboutletcollection(int))) id ivar5; // expected-error {{type argument of iboutletcollection attribute cannot be a builtin type}}
+}
+@property (nonatomic, retain) __attribute__((iboutletcollection(I,2,3))) id prop1; // expected-error {{attribute requires 1 argument(s)}}
+@property (nonatomic, retain) __attribute__((iboutletcollection(B))) id prop2; // expected-error {{invalid type 'B' as argument of iboutletcollection attribute}}
+
+@property __attribute__((iboutletcollection(BAD))) int prop3; // expected-error {{property with iboutletcollection attribute must have object type (invalid 'int')}}
+@end
+
diff --git a/test/SemaObjC/method-lookup-3.m b/test/SemaObjC/method-lookup-3.m
index 18a9982840bd..882b3d1d2123 100644
--- a/test/SemaObjC/method-lookup-3.m
+++ b/test/SemaObjC/method-lookup-3.m
@@ -50,3 +50,8 @@ void f4(id a0, Abstract *a1) {
void f5(id a0, Abstract *a1) {
[ a0 setZ: a1];
}
+
+// pr7861
+void f6(id<A> a0) {
+ Abstract *l = [a0 x];
+}
diff --git a/test/SemaObjC/method-no-context.m b/test/SemaObjC/method-no-context.m
index c88205dfd28f..3c45beef0426 100644
--- a/test/SemaObjC/method-no-context.m
+++ b/test/SemaObjC/method-no-context.m
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-- im0 { int a; return 0; // expected-error{{missing context for method declaration}}
+- im0 { // expected-note{{to match this '{'}} expected-error{{missing context for method declaration}}
+ int a; return 0;
// expected-error{{expected '}'}}
diff --git a/test/SemaObjC/nonnull.m b/test/SemaObjC/nonnull.m
index 642f50f9e4d6..15fee74a3b5f 100644
--- a/test/SemaObjC/nonnull.m
+++ b/test/SemaObjC/nonnull.m
@@ -43,3 +43,5 @@ foo (int i1, int i2, int i3, void (^cp1)(), void (^cp2)(), void (^cp3)())
func6((NSObject*) 0); // no-warning
func7((NSObject*) 0); // no-warning
}
+
+void func5(int) __attribute__((nonnull)); // expected-warning{{'nonnull' attribute applied to function with no pointer arguments}}
diff --git a/test/SemaObjC/property-and-ivar-use.m b/test/SemaObjC/property-and-ivar-use.m
new file mode 100644
index 000000000000..b9235c1dd3d4
--- /dev/null
+++ b/test/SemaObjC/property-and-ivar-use.m
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s
+// Do not issue error if 'ivar' used previously belongs to the inherited class
+// and has same name as @dynalic property in current class.
+
+typedef signed char BOOL;
+
+@protocol IDEBuildable
+@property (readonly) BOOL hasRecursiveDependencyCycle;
+@end
+
+@protocol IDEBuildableProduct <IDEBuildable>
+@end
+
+@interface IDEBuildableSupportMixIn
+@property (readonly) BOOL hasRecursiveDependencyCycle;
+@end
+
+@interface Xcode3TargetBuildable <IDEBuildable>
+{
+ IDEBuildableSupportMixIn *_buildableMixIn;
+}
+@end
+
+@interface Xcode3TargetProduct : Xcode3TargetBuildable <IDEBuildableProduct>
+@end
+
+@implementation Xcode3TargetBuildable
+- (BOOL)hasRecursiveDependencyCycle
+{
+ return [_buildableMixIn hasRecursiveDependencyCycle];
+}
+@end
+
+@implementation Xcode3TargetProduct
+@dynamic hasRecursiveDependencyCycle;
+@end
diff --git a/test/SemaObjC/property-not-lvalue.m b/test/SemaObjC/property-not-lvalue.m
index 55eec3e45397..3d95d2607f8e 100644
--- a/test/SemaObjC/property-not-lvalue.m
+++ b/test/SemaObjC/property-not-lvalue.m
@@ -15,8 +15,8 @@ typedef struct NSSize {
void foo() {
Foo *f;
- f.size.width = 2.2; // expected-error {{expression is not assignable using property assignment syntax}}
- f.size.inner.dim = 200; // expected-error {{expression is not assignable using property assignment syntax}}
+ f.size.width = 2.2; // expected-error {{expression is not assignable}}
+ f.size.inner.dim = 200; // expected-error {{expression is not assignable}}
}
// radar 7628953
@@ -28,7 +28,7 @@ void foo() {
@implementation Gorf
- (void)MyView_sharedInit {
- self.size.width = 2.2; // expected-error {{expression is not assignable using property assignment syntax}}
+ self.size.width = 2.2; // expected-error {{expression is not assignable}}
}
- (NSSize)size {}
@end
diff --git a/test/SemaObjC/protocol-attribute.m b/test/SemaObjC/protocol-attribute.m
index e04a39bda6ca..52c980396eda 100644
--- a/test/SemaObjC/protocol-attribute.m
+++ b/test/SemaObjC/protocol-attribute.m
@@ -3,7 +3,7 @@
__attribute ((unavailable))
@protocol FwProto; // expected-note{{marked unavailable}}
-Class <FwProto> cFw = 0; // expected-warning {{'FwProto' is unavailable}}
+Class <FwProto> cFw = 0; // expected-error {{'FwProto' is unavailable}}
__attribute ((deprecated)) @protocol MyProto1
@@ -35,12 +35,12 @@ Class <MyProto1> clsP1 = 0; // expected-warning {{'MyProto1' is deprecated}}
@protocol FwProto @end // expected-note{{marked unavailable}}
-@interface MyClass2 <FwProto> // expected-warning {{'FwProto' is unavailable}}
+@interface MyClass2 <FwProto> // expected-error {{'FwProto' is unavailable}}
@end
__attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto; // expected-note{{marked unavailable}}
-id <XProto> idX = 0; // expected-warning {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}}
+id <XProto> idX = 0; // expected-error {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}}
int main ()
{
diff --git a/test/SemaObjC/protocols.m b/test/SemaObjC/protocols.m
index 8447fe2aad2f..ca38f20fbd01 100644
--- a/test/SemaObjC/protocols.m
+++ b/test/SemaObjC/protocols.m
@@ -61,3 +61,7 @@
@protocol B < A > // expected-error{{protocol has circular dependency}}
@end
+@protocol P
+- (int)test:(int)param, ..; // expected-warning{{type specifier missing}} \
+ // expected-error{{expected ';' after method prototype}}
+@end
diff --git a/test/SemaObjC/static-ivar-ref-1.m b/test/SemaObjC/static-ivar-ref-1.m
index cd5e05558c35..d9f99f513da7 100644
--- a/test/SemaObjC/static-ivar-ref-1.m
+++ b/test/SemaObjC/static-ivar-ref-1.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -ast-print %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -ast-print %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -ast-print %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -ast-print %s 2>&1 | FileCheck %s
@interface current
{
@@ -14,5 +14,17 @@ current *pc;
int foo()
{
- return pc->ivar2 + (*pc).ivar + pc->ivar1;
+ return pc->ivar2 + (*pc).ivar + pc->ivar1;
}
+
+// CHECK: @interface current{
+// CHECK: int ivar;
+// CHECK: int ivar1;
+// CHECK: int ivar2;
+// CHECK: }
+// CHECK: @end
+// CHECK: current *pc;
+// CHECK: int foo() {
+// CHECK: return pc->ivar2 + (*pc).ivar + pc->ivar1;
+// CHECK: }
+
diff --git a/test/SemaObjC/synth-provisional-ivars.m b/test/SemaObjC/synth-provisional-ivars.m
new file mode 100644
index 000000000000..973c771ad779
--- /dev/null
+++ b/test/SemaObjC/synth-provisional-ivars.m
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s
+
+int bar;
+
+@interface I
+{
+ int _bar;
+}
+@property int PROP;
+@property int PROP1;
+@property int PROP2;
+@property int PROP3;
+@property int PROP4;
+
+@property int bar;
+@property int bar1;
+
+@end
+
+@implementation I
+- (int) Meth { return PROP; } // expected-note {{'PROP' declared here}}
+
+@dynamic PROP1;
+- (int) Meth1 { return PROP1; } // expected-error {{use of undeclared identifier 'PROP1'}}
+
+- (int) Meth2 { return PROP2; } // expected-error {{use of undeclared identifier 'PROP2'}}
+@dynamic PROP2;
+
+- (int) Meth3 { return PROP3; } // expected-error {{use of undeclared identifier 'PROP3'}}
+@synthesize PROP3=IVAR;
+
+- (int) Meth4 { return PROP4; }
+@synthesize PROP4=PROP4;
+
+- (int) Meth5 { return bar; } // expected-error {{use of undeclared identifier 'bar'}}
+@synthesize bar = _bar;
+
+- (int) Meth6 { return bar1; }
+
+@end
+
+@implementation I(CAT)
+- (int) Meth { return PROP1; } // expected-error {{use of undeclared identifier 'PROP1'}}
+@end
+
+@implementation I(r8251648)
+- (int) Meth1: (int) bar {
+ return bar; // expected-warning {{local declaration of 'bar' hides instance variable}}
+}
+@end
diff --git a/test/SemaObjC/warn-strict-selector-match.m b/test/SemaObjC/warn-strict-selector-match.m
new file mode 100644
index 000000000000..8ac0ca46ac43
--- /dev/null
+++ b/test/SemaObjC/warn-strict-selector-match.m
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -Wstrict-selector-match -fsyntax-only -verify %s
+
+@interface Foo
+-(int) method; // expected-note {{using}}
+@end
+
+@interface Bar
+-(float) method; // expected-note {{also found}}
+@end
+
+int main() { [(id)0 method]; } // expected-warning {{multiple methods named 'method' found [-Wstrict-selector-match]}}
+
+@interface Object @end
+
+@interface Class1
+- (void)setWindow:(Object *)wdw; // expected-note {{using}}
+@end
+
+@interface Class2
+- (void)setWindow:(Class1 *)window; // expected-note {{also found}}
+@end
+
+id foo(void) {
+ Object *obj = 0;
+ id obj2 = obj;
+ [obj setWindow:0]; // expected-warning {{Object' may not respond to 'setWindow:'}}
+ [obj2 setWindow:0]; // expected-warning {{multiple methods named 'setWindow:' found [-Wstrict-selector-match]}}
+ return obj;
+}
+
+@protocol MyObject
+- (id)initWithData:(Object *)data; // expected-note {{using}} \
+ // expected-note {{passing argument to parameter 'data' here}}
+@end
+
+@protocol SomeOther
+- (id)initWithData:(int)data; // expected-note {{also found}}
+@end
+
+@protocol MyCoding
+- (id)initWithData:(id<MyObject, MyCoding>)data; // expected-note {{also found}}
+@end
+
+@interface NTGridDataObject: Object <MyCoding>
+{
+ Object<MyCoding> *_data;
+}
++ (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data;
+@end
+
+@implementation NTGridDataObject
+- (id)initWithData:(id<MyObject, MyCoding>)data {
+ return data;
+}
++ (NTGridDataObject*)dataObject:(id<MyObject, MyCoding>)data
+{
+ NTGridDataObject *result = [(id)0 initWithData:data]; // expected-warning {{multiple methods named 'initWithData:' found [-Wstrict-selector-match]}} \
+ expected-warning {{sending 'id<MyObject,MyCoding>' to parameter of incompatible type 'Object *'}}
+ return result;
+}
+@end
+
+@interface Base
+- (unsigned)port;
+@end
+
+@interface Derived: Base
+- (Object *)port;
++ (Protocol *)port;
+@end
+
+void foo1(void) {
+ [(Class)0 port]; // OK - gcc issues warning but there is only one Class method so no ambiguity to warn
+}
+
diff --git a/test/SemaObjCXX/conversion-to-objc-pointer-2.mm b/test/SemaObjCXX/conversion-to-objc-pointer-2.mm
index 5277d101f588..b03d4d89e920 100644
--- a/test/SemaObjCXX/conversion-to-objc-pointer-2.mm
+++ b/test/SemaObjCXX/conversion-to-objc-pointer-2.mm
@@ -82,6 +82,7 @@ int main (int argc, const char * argv[]) {
TNSAutoRef<NSObject*> object2([[NSObject alloc] init]);
TNSAutoRef<TBar*> bar([[TBar alloc] init]);
[bar setBlah: object1]; // <== Does not compile. It should.
- [bar setBlah: object2]; // <== Does not compile. It should.
+ if (object1 == object2)
+ [bar setBlah: object2]; // <== Does not compile. It should.
return 0;
}
diff --git a/test/SemaObjCXX/cxxoperator-selector.mm b/test/SemaObjCXX/cxxoperator-selector.mm
new file mode 100644
index 000000000000..6dd36a8c100e
--- /dev/null
+++ b/test/SemaObjCXX/cxxoperator-selector.mm
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar:// 8328250
+
+@class NSDate;
+
+@interface XSGraphDataSet
+- and;
+- xor;
+- or;
+
+- ||; // expected-error {{expected selector for Objective-C method}}
+
+- &&; // expected-error {{expected selector for Objective-C method}}
+
+- (void)dataSetForValuesBetween:(NSDate *)startDate and:(NSDate *)endDate;
+@end
+
+@implementation XSGraphDataSet
+- (id) and{return 0; };
+- (id) xor{return 0; };
+- (id) or{return 0; };
+
+- (void)dataSetForValuesBetween:(NSDate *)startDate and:(NSDate *)endDate { return; }
+@end
diff --git a/test/SemaObjCXX/deduction.mm b/test/SemaObjCXX/deduction.mm
index 6dd449d6ea75..220f36863bab 100644
--- a/test/SemaObjCXX/deduction.mm
+++ b/test/SemaObjCXX/deduction.mm
@@ -56,3 +56,10 @@ namespace test1 {
template struct tester<Test1Class>; // expected-note {{in instantiation}}
template struct tester<Test1Class<Test1Protocol> >; // expected-note {{in instantiation}}
}
+
+namespace test2 {
+ template <typename T> void foo(const T* t) {}
+ void test(id x) {
+ foo(x);
+ }
+}
diff --git a/test/SemaObjCXX/exceptions-fragile.mm b/test/SemaObjCXX/exceptions-fragile.mm
new file mode 100644
index 000000000000..11dd8e94c1de
--- /dev/null
+++ b/test/SemaObjCXX/exceptions-fragile.mm
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+@interface NSException @end
+void opaque();
+
+namespace test0 {
+ void test() {
+ try {
+ } catch (NSException *e) { // expected-error {{can't catch Objective C exceptions in C++ in the non-unified exception model}}
+ }
+ }
+}
diff --git a/test/SemaObjCXX/expr-objcxx.mm b/test/SemaObjCXX/expr-objcxx.mm
new file mode 100644
index 000000000000..e70a001b7041
--- /dev/null
+++ b/test/SemaObjCXX/expr-objcxx.mm
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
+
+// rdar://8366474
+void *P = @selector(foo::bar::);
diff --git a/test/SemaObjCXX/foreach-block.mm b/test/SemaObjCXX/foreach-block.mm
new file mode 100644
index 000000000000..91bd0c83b31b
--- /dev/null
+++ b/test/SemaObjCXX/foreach-block.mm
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
+// rdar://8295106
+
+int main() {
+id array;
+
+ for (int (^b)(void) in array) {
+ if (b() == 10000) {
+ return 1;
+ }
+ }
+
+ int (^b)(void) in array; // expected-error {{expected ';' at end of declaration}}
+}
diff --git a/test/SemaObjCXX/instantiate-stmt.mm b/test/SemaObjCXX/instantiate-stmt.mm
index e92f8e8d4f0c..5e8ec61573d4 100644
--- a/test/SemaObjCXX/instantiate-stmt.mm
+++ b/test/SemaObjCXX/instantiate-stmt.mm
@@ -25,6 +25,7 @@ template void synchronized_test(int); // expected-note{{in instantiation of}}
// fast enumeration
@interface NSArray
+- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount;
@end
@interface NSString
diff --git a/test/SemaObjCXX/message.mm b/test/SemaObjCXX/message.mm
index 76bde6f57cab..f92518ad48c1 100644
--- a/test/SemaObjCXX/message.mm
+++ b/test/SemaObjCXX/message.mm
@@ -38,7 +38,7 @@ I2 *operator+(I2_holder, int);
return 0;
}
+ (void)method {
- [ivar method]; // expected-error{{receiver type 'ivar' (aka 'ivar') is not an Objective-C class}}
+ [ivar method]; // expected-error{{receiver type 'ivar' is not an Objective-C class}}
}
@end
diff --git a/test/SemaObjCXX/objc-decls-inside-namespace.mm b/test/SemaObjCXX/objc-decls-inside-namespace.mm
index 9953ec366e16..f68078b6779d 100644
--- a/test/SemaObjCXX/objc-decls-inside-namespace.mm
+++ b/test/SemaObjCXX/objc-decls-inside-namespace.mm
@@ -23,5 +23,10 @@ namespace C {
@implementation A(C) //expected-error{{Objective-C declarations may only appear in global scope}}
@end
+@interface B @end //expected-error{{Objective-C declarations may only appear in global scope}}
+@implementation B //expected-error{{Objective-C declarations may only appear in global scope}}
++ (void) foo {}
+@end
+
}
diff --git a/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm b/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm
index 80383ebfd8a9..d0f8404b6027 100644
--- a/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm
+++ b/test/SemaObjCXX/pointer-to-objc-pointer-conv.mm
@@ -19,3 +19,31 @@ void a() {
}
+
+// pr7936
+@interface I1 @end
+
+class Wrapper {
+public:
+ operator id() const { return (id)_value; }
+ operator Class() const { return (Class)_value; }
+ operator I1*() const { return (I1*)_value; }
+
+ bool Compare(id obj) { return *this == obj; }
+ bool CompareClass(Class obj) { return *this == obj; }
+ bool CompareI1(I1* obj) { return *this == obj; }
+
+ Wrapper &operator*();
+ Wrapper &operator[](int);
+ Wrapper& operator->*(int);
+
+private:
+ long _value;
+};
+
+void f() {
+ Wrapper w;
+ w[0];
+ *w;
+ w->*(0);
+}
diff --git a/test/SemaObjCXX/references.mm b/test/SemaObjCXX/references.mm
index 70ce8278e8f0..15033f6bde8d 100644
--- a/test/SemaObjCXX/references.mm
+++ b/test/SemaObjCXX/references.mm
@@ -24,3 +24,39 @@ int f2(A *a) {
return f0(a.p1); // expected-error {{property 'p1' not found on object of type 'A *'}}
}
+// PR7740
+@class NSString;
+
+void f3(id);
+void f4(NSString &tmpstr) {
+ f3(&tmpstr);
+}
+
+// PR7741
+@protocol P1 @end
+@protocol P2 @end
+@protocol P3 @end
+@interface foo<P1> {} @end
+@interface bar : foo <P1, P2> {} @end
+typedef bar baz;
+
+struct ToBar {
+ operator bar&() const;
+};
+
+void f5(foo&);
+void f5b(foo<P1>&);
+void f5c(foo<P2>&);
+void f5d(foo<P3>&);
+void f6(baz* x) {
+ f5(*x);
+ f5b(*x);
+ f5c(*x);
+ f5d(*x);
+ (void)((foo&)*x);
+ f5(ToBar());
+ f5b(ToBar());
+ f5c(ToBar());
+ f5d(ToBar());
+ (void)((foo&)ToBar());
+}
diff --git a/test/SemaObjCXX/warn-strict-selector-match.mm b/test/SemaObjCXX/warn-strict-selector-match.mm
new file mode 100644
index 000000000000..6d315db27cba
--- /dev/null
+++ b/test/SemaObjCXX/warn-strict-selector-match.mm
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -Wstrict-selector-match -fsyntax-only -verify %s
+
+@interface Base
+- (id) meth1: (Base *)arg1; // expected-note {{using}}
+- (id) window; // expected-note {{using}}
+@end
+
+@interface Derived: Base
+- (id) meth1: (Derived *)arg1; // expected-note {{also found}}
+- (Base *) window; // expected-note {{also found}}
+@end
+
+void foo(void) {
+ id r;
+
+ [r meth1:r]; // expected-warning {{multiple methods named 'meth1:' found [-Wstrict-selector-match]}}
+ [r window]; // expected-warning {{multiple methods named 'window' found [-Wstrict-selector-match]}}
+}
diff --git a/test/SemaTemplate/class-template-id.cpp b/test/SemaTemplate/class-template-id.cpp
index df5ef554f7aa..50e0b00c1a32 100644
--- a/test/SemaTemplate/class-template-id.cpp
+++ b/test/SemaTemplate/class-template-id.cpp
@@ -41,3 +41,7 @@ typedef N::C<float> c2;
template<typename T> struct Foo { }; // expected-note{{template is declared here}}
void f(void) { Foo bar; } // expected-error{{without a template argument list}}
+
+// rdar://problem/8254267
+template <typename T> class Party;
+template <> class Party<T> { friend struct Party<>; }; // expected-error {{use of undeclared identifier 'T'}}
diff --git a/test/SemaTemplate/crash-8204126.cpp b/test/SemaTemplate/crash-8204126.cpp
new file mode 100644
index 000000000000..eb96560b8da5
--- /dev/null
+++ b/test/SemaTemplate/crash-8204126.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+struct A
+{
+ template<int> template<typename T> friend void foo(T) {} // expected-error{{extraneous template parameter list}}
+ void bar() { foo(0); } // expected-error{{use of undeclared identifier 'foo'}}
+};
diff --git a/test/SemaTemplate/current-instantiation.cpp b/test/SemaTemplate/current-instantiation.cpp
index c631dd71d174..8caac9399a87 100644
--- a/test/SemaTemplate/current-instantiation.cpp
+++ b/test/SemaTemplate/current-instantiation.cpp
@@ -164,3 +164,38 @@ namespace ConstantInCurrentInstantiation {
template<typename T>
int X<T>::array[X<T>::value] = { 1, 2 };
}
+
+namespace Expressions {
+ template <bool b>
+ struct Bool {
+ enum anonymous_enum { value = b };
+ };
+ struct True : public Bool<true> {};
+ struct False : public Bool<false> {};
+
+ template <typename T1, typename T2>
+ struct Is_Same : public False {};
+ template <typename T>
+ struct Is_Same<T, T> : public True {};
+
+ template <bool b, typename T = void>
+ struct Enable_If {};
+ template <typename T>
+ struct Enable_If<true, T> {
+ typedef T type;
+ };
+
+ template <typename T>
+ class Class {
+ public:
+ template <typename U>
+ typename Enable_If<Is_Same<U, Class>::value, void>::type
+ foo();
+ };
+
+
+ template <typename T>
+ template <typename U>
+ typename Enable_If<Is_Same<U, Class<T> >::value, void>::type
+ Class<T>::foo() {}
+}
diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp
index 1860c7577c79..8f4b7281818d 100644
--- a/test/SemaTemplate/deduction-crash.cpp
+++ b/test/SemaTemplate/deduction-crash.cpp
@@ -4,7 +4,7 @@
// Note that the error count below doesn't matter. We just want to
// make sure that the parser doesn't crash.
-// CHECK: 16 errors
+// CHECK: 15 errors
template<a>
struct int_;
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
index e8ff8d3a6d24..9400a0aba96b 100644
--- a/test/SemaTemplate/deduction.cpp
+++ b/test/SemaTemplate/deduction.cpp
@@ -105,3 +105,32 @@ namespace PR7463 {
template <typename T_> void g (T_&); // expected-note{{T_ = int}}
void h (void) { g(f()); } // expected-error{{no matching function for call}}
}
+
+namespace test0 {
+ template <class T> void make(const T *(*fn)()); // expected-note {{candidate template ignored: can't deduce a type for 'T' which would make 'T const' equal 'char'}}
+ char *char_maker();
+ void test() {
+ make(char_maker); // expected-error {{no matching function for call to 'make'}}
+ }
+}
+
+namespace test1 {
+ template<typename T> void foo(const T a[3][3]);
+ void test() {
+ int a[3][3];
+ foo(a);
+ }
+}
+
+// PR7708
+namespace test2 {
+ template<typename T> struct Const { typedef void const type; };
+
+ template<typename T> void f(T, typename Const<T>::type*);
+ template<typename T> void f(T, void const *);
+
+ void test() {
+ void *p = 0;
+ f(0, p);
+ }
+}
diff --git a/test/SemaTemplate/dependent-base-member-init.cpp b/test/SemaTemplate/dependent-base-member-init.cpp
index 1f131491e621..1d4fed3e1d26 100644
--- a/test/SemaTemplate/dependent-base-member-init.cpp
+++ b/test/SemaTemplate/dependent-base-member-init.cpp
@@ -57,3 +57,12 @@ template<typename T, typename U>
struct X0 : T::template apply<U> {
X0(int i) : T::template apply<U>(i) { }
};
+
+// PR7698
+namespace PR7698 {
+ template<typename Type>
+ class A {
+ char mA[sizeof(Type *)];
+ A(): mA() {}
+ };
+}
diff --git a/test/SemaTemplate/dependent-class-member-operator.cpp b/test/SemaTemplate/dependent-class-member-operator.cpp
new file mode 100644
index 000000000000..d70a60cfdfa1
--- /dev/null
+++ b/test/SemaTemplate/dependent-class-member-operator.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// PR7837
+
+template<class T> struct C1 { void operator()(T); };
+template<class T> struct C2; // expected-note {{template is declared here}}
+template<class T> void foo(T);
+void wrap() {
+ foo(&C1<int>::operator());
+ foo(&C1<int>::operator+); // expected-error {{no member named 'operator+' in 'C1<int>'}}
+ foo(&C2<int>::operator+); // expected-error {{implicit instantiation of undefined template 'C2<int>'}}
+}
diff --git a/test/SemaTemplate/dependent-expr.cpp b/test/SemaTemplate/dependent-expr.cpp
index 9fa757107bdb..e25afce77a6b 100644
--- a/test/SemaTemplate/dependent-expr.cpp
+++ b/test/SemaTemplate/dependent-expr.cpp
@@ -40,3 +40,8 @@ namespace PR7198 {
}
};
}
+
+namespace PR7724 {
+ template<typename OT> int myMethod()
+ { return 2 && sizeof(OT); }
+}
diff --git a/test/SemaTemplate/inject-templated-friend-post.cpp b/test/SemaTemplate/inject-templated-friend-post.cpp
new file mode 100644
index 000000000000..98ac38edfac0
--- /dev/null
+++ b/test/SemaTemplate/inject-templated-friend-post.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang %s -S -emit-llvm -o - | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
+// RUN: %clang %s -S -emit-llvm -o - -DPROTOTYPE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
+// RUN: %clang %s -S -emit-llvm -o - -DINSTANTIATE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
+// RUN: %clang %s -S -emit-llvm -o - -DPROTOTYPE -DINSTANTIATE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
+// RUN: %clang -cc1 %s -DREDEFINE -verify
+// RUN: %clang -cc1 %s -DPROTOTYPE -DREDEFINE -verify
+// PR8007: friend function not instantiated, reordered version.
+// Corresponds to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38392
+
+struct std_ostream
+{
+ int dummy;
+};
+
+std_ostream cout;
+
+template <typename STRUCT_TYPE>
+struct Streamer;
+
+typedef struct Foo {} Foo;
+
+std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+
+void test(const Streamer<Foo>& foo)
+{
+ cout << foo;
+}
+
+template <typename STRUCT_TYPE>
+struct Streamer
+{
+ friend std_ostream& operator << (std_ostream& o, const Streamer& f) // expected-error{{redefinition of 'operator<<'}}
+ {
+ Streamer s(f);
+ s(o);
+ return o;
+ }
+
+ Streamer(const STRUCT_TYPE& s) : s(s) {}
+
+ const STRUCT_TYPE& s;
+ void operator () (std_ostream&) const;
+};
+
+#ifdef PROTOTYPE
+std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+#endif
+
+#ifdef INSTANTIATE
+template struct Streamer<Foo>;
+#endif
+
+#ifdef REDEFINE
+std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
+{
+ return o;
+}
+#endif
+
+#ifndef INSTANTIATE
+template <>
+void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}}
+{
+}
+#endif
+
+int main(void)
+{
+ Foo foo;
+ test(foo);
+}
+
diff --git a/test/SemaTemplate/inject-templated-friend.cpp b/test/SemaTemplate/inject-templated-friend.cpp
new file mode 100644
index 000000000000..fbe86d96389e
--- /dev/null
+++ b/test/SemaTemplate/inject-templated-friend.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang %s -S -emit-llvm -o - | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
+// RUN: %clang -cc1 %s -DREDEFINE -verify
+// PR8007: friend function not instantiated.
+
+struct std_ostream
+{
+ int dummy;
+};
+
+std_ostream cout;
+
+template <typename STRUCT_TYPE>
+struct Streamer
+{
+ friend std_ostream& operator << (std_ostream& o, const Streamer& f) // expected-error{{redefinition of 'operator<<'}}
+ {
+ Streamer s(f);
+ s(o);
+ return o;
+ }
+
+ Streamer(const STRUCT_TYPE& s) : s(s) {}
+
+ const STRUCT_TYPE& s;
+ void operator () (std_ostream&) const;
+};
+
+typedef struct Foo {} Foo;
+
+std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+#ifdef REDEFINE
+std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
+{
+ // Sema should flag this as a redefinition
+ return o;
+}
+#endif
+
+template <>
+void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}}
+{
+}
+
+int main(void)
+{
+ Foo foo;
+ cout << foo;
+}
diff --git a/test/SemaTemplate/instantiate-anonymous-union.cpp b/test/SemaTemplate/instantiate-anonymous-union.cpp
index 255454b2ebf2..f2862db6bb7f 100644
--- a/test/SemaTemplate/instantiate-anonymous-union.cpp
+++ b/test/SemaTemplate/instantiate-anonymous-union.cpp
@@ -47,3 +47,22 @@ namespace PR7088 {
template void f<double>();
}
+
+// Check for problems related to PR7402 that occur when template instantiation
+// instantiates implicit initializers.
+namespace PR7402 {
+ struct X {
+ union {
+ struct {
+ int x;
+ int y;
+ };
+ int v[2];
+ };
+
+ // Check that this requirement survives instantiation.
+ template <typename T> X(const T& t) : x(t), y(t) {}
+ };
+
+ X x(42.0);
+}
diff --git a/test/SemaTemplate/instantiate-attr.cpp b/test/SemaTemplate/instantiate-attr.cpp
index e8291ed00d20..bbadb6375b5b 100644
--- a/test/SemaTemplate/instantiate-attr.cpp
+++ b/test/SemaTemplate/instantiate-attr.cpp
@@ -11,3 +11,16 @@ struct A {
int a[sizeof(A<int>) == 16 ? 1 : -1];
int a2[sizeof(A<int>::B) == 16 ? 1 : -1];
+// rdar://problem/8243419
+namespace test1 {
+ template <typename T> struct A {
+ int a;
+ T b[0];
+ } __attribute__((packed));
+
+ typedef A<unsigned long> type;
+
+ int test0[sizeof(type) == 4 ? 1 : -1];
+ int test1[__builtin_offsetof(type, a) == 0 ? 1 : -1];
+ int test2[__builtin_offsetof(type, b) == 4 ? 1 : -1];
+}
diff --git a/test/SemaTemplate/instantiate-clang.cpp b/test/SemaTemplate/instantiate-clang.cpp
index cef2b7090bf2..34d68c4e59fd 100644
--- a/test/SemaTemplate/instantiate-clang.cpp
+++ b/test/SemaTemplate/instantiate-clang.cpp
@@ -24,7 +24,7 @@ template<typename T, typename U, int N, int M>
struct ShuffleVector0 {
void f(T t, U u, double2 a, double2 b) {
(void)__builtin_shufflevector(t, u, N, M); // expected-error{{index}}
- (void)__builtin_shufflevector(a, b, N, M);
+ (void)__builtin_shufflevector(a, b, N, M); // expected-error{{index}}
(void)__builtin_shufflevector(a, b, 2, 1);
}
};
diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp
index 2d27075bd41f..ced56dfc6abc 100644
--- a/test/SemaTemplate/instantiate-declref.cpp
+++ b/test/SemaTemplate/instantiate-declref.cpp
@@ -95,3 +95,13 @@ namespace test0 {
};
void g() { X<2>(); }
}
+
+// <rdar://problem/8302161>
+namespace test1 {
+ template <typename T> void f(T const &t) {
+ union { char c; T t_; };
+ c = 'a'; // <- this shouldn't silently fail to instantiate
+ T::foo(); // expected-error {{has no members}}
+ }
+ template void f(int const &); // expected-note {{requested here}}
+}
diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp
index d506b19a7a97..ca88b00300dc 100644
--- a/test/SemaTemplate/instantiate-expr-3.cpp
+++ b/test/SemaTemplate/instantiate-expr-3.cpp
@@ -63,7 +63,11 @@ template struct Conditional0<int, int, int>;
template<typename T>
struct StatementExpr0 {
void f(T t) {
- (void)({ if (t) t = t + 17; t + 12;}); // expected-error{{contextually convertible}}
+ (void)({
+ if (t) // expected-error{{contextually convertible}}
+ t = t + 17;
+ t + 12; // expected-error{{invalid operands}}
+ });
}
};
@@ -106,8 +110,8 @@ struct VaArg1 {
VaList va;
__builtin_va_start(va, n); // expected-error{{int}}
for (int i = 0; i != n; ++i)
- (void)__builtin_va_arg(va, ArgType);
- __builtin_va_end(va);
+ (void)__builtin_va_arg(va, ArgType); // expected-error{{int}}
+ __builtin_va_end(va); // expected-error{{int}}
}
};
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
index 8cd7342e98eb..adae1da26aaf 100644
--- a/test/SemaTemplate/instantiate-expr-4.cpp
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -115,7 +115,7 @@ template<typename T>
struct Delete0 {
void f(T t) {
delete t; // expected-error{{cannot delete}}
- ::delete [] t;
+ ::delete [] t; // expected-error{{cannot delete}}
}
};
diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp
index a293e9a788de..651c02c6cdcf 100644
--- a/test/SemaTemplate/instantiate-function-1.cpp
+++ b/test/SemaTemplate/instantiate-function-1.cpp
@@ -72,7 +72,7 @@ template<typename T, typename U, typename V> struct X6 {
if (T x = t) {
t = x;
}
- return v;
+ return v; // expected-error{{cannot initialize return object of type}}
}
};
@@ -178,10 +178,10 @@ template<typename T> struct IndirectGoto0 {
prior:
T prior_label;
- prior_label = &&prior;
+ prior_label = &&prior; // expected-error{{assigning to 'int'}}
T later_label;
- later_label = &&later;
+ later_label = &&later; // expected-error{{assigning to 'int'}}
later:
(void)(1+1);
diff --git a/test/SemaTemplate/instantiate-member-template.cpp b/test/SemaTemplate/instantiate-member-template.cpp
index 24a3f317e636..8f4063bc71cb 100644
--- a/test/SemaTemplate/instantiate-member-template.cpp
+++ b/test/SemaTemplate/instantiate-member-template.cpp
@@ -189,3 +189,17 @@ namespace PR7587 {
};
}
+
+namespace PR7669 {
+ template<class> struct X {
+ template<class> struct Y {
+ template<int,class> struct Z;
+ template<int Dummy> struct Z<Dummy,int> {};
+ };
+ };
+
+ void a()
+ {
+ X<int>::Y<int>::Z<0,int>();
+ }
+}
diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp
index 24db791e0115..16b9515a15dc 100644
--- a/test/SemaTemplate/member-access-expr.cpp
+++ b/test/SemaTemplate/member-access-expr.cpp
@@ -121,3 +121,14 @@ namespace test4 {
}
};
}
+
+namespace test5 {
+ template<typename T>
+ struct X {
+ using T::value;
+
+ T &getValue() {
+ return &value;
+ }
+ };
+}
diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp
index ea17cdbb5864..dbd27c456c51 100644
--- a/test/SemaTemplate/member-template-access-expr.cpp
+++ b/test/SemaTemplate/member-template-access-expr.cpp
@@ -123,3 +123,22 @@ namespace PR6021 {
};
};
}
+
+namespace rdar8198511 {
+ template<int, typename U>
+ struct Base {
+ void f();
+ };
+
+ template<typename T>
+ struct X0 : Base<1, T> { };
+
+ template<typename T>
+ struct X1 {
+ X0<int> x0;
+
+ void f() {
+ this->x0.Base<1, int>::f();
+ }
+ };
+}
diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp
index 12ab48680915..9c72845fb6a6 100644
--- a/test/SemaTemplate/nested-name-spec-template.cpp
+++ b/test/SemaTemplate/nested-name-spec-template.cpp
@@ -88,3 +88,14 @@ namespace PR7385 {
has_xxx0<int>::type t; // expected-note{{instantiation of}}
}
+
+namespace PR7725 {
+ template<class ignored> struct TypedefProvider;
+ template<typename T>
+ struct TemplateClass : public TypedefProvider<T>
+ {
+ void PrintSelf() {
+ TemplateClass::Test::PrintSelf();
+ }
+ };
+}
diff --git a/test/SemaTemplate/recovery-crash.cpp b/test/SemaTemplate/recovery-crash.cpp
new file mode 100644
index 000000000000..0ed3258b683b
--- /dev/null
+++ b/test/SemaTemplate/recovery-crash.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// We don't expect a fix-it to be applied in this case. Clang used to crash
+// trying to recover while adding 'this->' before Work(x);
+
+template <typename> struct A {
+ static void Work(int); // expected-note{{must qualify identifier}}
+};
+
+template <typename T> struct B : public A<T> {
+ template <typename T2> B(T2 x) {
+ Work(x); // expected-error{{use of undeclared identifier}}
+ }
+};
+
+void Test() {
+ B<int> b(0); // expected-note{{in instantiation of function template}}
+}
+
diff --git a/test/SemaTemplate/temp.cpp b/test/SemaTemplate/temp.cpp
index 961b9c873ab8..e037f0f0713a 100644
--- a/test/SemaTemplate/temp.cpp
+++ b/test/SemaTemplate/temp.cpp
@@ -1,5 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-// p3
-template<typename T> int foo(T), bar(T, T); // expected-error{{single entity}}
+namespace test0 {
+ // p3
+ template<typename T> int foo(T), bar(T, T); // expected-error{{single entity}}
+}
+
+// PR7252
+namespace test1 {
+ namespace A { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}}
+ namespace B { template<typename T> struct Base { typedef T t; }; } // expected-note {{member found}}
+
+ template<typename T> struct Derived : A::Base<char>, B::Base<int> {
+ // FIXME: the syntax error here is unfortunate
+ typename Derived::Base<float>::t x; // expected-error {{found in multiple base classes of different types}} \
+ // expected-error {{expected member name or ';'}}
+ };
+}
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index d351eb458838..6f515916e45f 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -203,3 +203,43 @@ namespace PR6964 {
struct as_nview<Sequence, I0> // expected-note{{while checking a default template argument used here}}
{ };
}
+
+// rdar://problem/8302138
+namespace test8 {
+ template <int* ip> struct A {
+ int* p;
+ A() : p(ip) {}
+ };
+
+ void test0() {
+ extern int i00;
+ A<&i00> a00;
+ }
+
+ extern int i01;
+ void test1() {
+ A<&i01> a01;
+ }
+
+
+ struct C {
+ int x;
+ char y;
+ double z;
+ };
+
+ template <C* cp> struct B {
+ C* p;
+ B() : p(cp) {}
+ };
+
+ void test2() {
+ extern C c02;
+ B<&c02> b02;
+ }
+
+ extern C c03;
+ void test3() {
+ B<&c03> b03;
+ }
+}
diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp
index 667122583fda..944acacd8441 100644
--- a/test/SemaTemplate/temp_arg_template.cpp
+++ b/test/SemaTemplate/temp_arg_template.cpp
@@ -33,3 +33,21 @@ 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.
// A<::N::Z> *a10;
+
+// PR7807
+namespace N {
+ template <typename, typename = int>
+ struct X
+ { };
+
+ template <typename ,int>
+ struct Y
+ { X<int> const_ref(); };
+
+ template <template<typename,int> class TT, typename T, int N>
+ int operator<<(int, TT<T, N> a) { // expected-note{{candidate template ignored}}
+ 0 << a.const_ref(); // expected-error{{invalid operands to binary expression ('int' and 'X<int>')}}
+ }
+
+ void f0( Y<int,1> y){ 1 << y; } // expected-note{{in instantiation of function template specialization 'N::operator<<<Y, int, 1>' requested here}}
+}
diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp
index 3876c256455d..397094218af8 100644
--- a/test/SemaTemplate/temp_arg_type.cpp
+++ b/test/SemaTemplate/temp_arg_type.cpp
@@ -24,11 +24,11 @@ A<ns::B> a8; // expected-error{{use of class template ns::B requires template ar
// [temp.arg.type]p2
void f() {
class X { };
- A<X> * a = 0; // expected-error{{template argument uses local type 'X'}}
+ A<X> * a = 0; // expected-warning{{template argument uses local type 'X'}}
}
struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}}
-A<__typeof__(Unnamed)> *a9; // expected-error{{template argument uses unnamed type}}
+A<__typeof__(Unnamed)> *a9; // expected-warning{{template argument uses unnamed type}}
template<typename T, unsigned N>
struct Array {
diff --git a/test/lit.cfg b/test/lit.cfg
index 42de5cbc5f92..80f8d5a544af 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -146,3 +146,9 @@ config.substitutions.append(
config.substitutions.append(
(' %clang-cc1 ',
"""*** invalid substitution, use '%clang_cc1'. ***""") )
+
+###
+
+# Set available features we allow tests to conditionalize on.
+if platform.system() != 'Windows':
+ config.available_features.add('crash-recovery')
diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt
index d965fd2b51e2..5cf2cd6ebf34 100644
--- a/tools/c-index-test/CMakeLists.txt
+++ b/tools/c-index-test/CMakeLists.txt
@@ -5,10 +5,11 @@ set( LLVM_USED_LIBS
clangIndex
clangFrontend
clangDriver
+ clangSerialization
+ clangParse
clangSema
clangAnalysis
clangAST
- clangParse
clangLex
clangBasic
)
diff --git a/tools/c-index-test/Makefile b/tools/c-index-test/Makefile
index d168df553651..f41aa8098155 100644
--- a/tools/c-index-test/Makefile
+++ b/tools/c-index-test/Makefile
@@ -14,7 +14,8 @@ TOOLNAME = c-index-test
TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := bitreader mc core
-USEDLIBS = clang.a clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
- clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
+USEDLIBS = clang.a clangIndex.a clangFrontend.a clangDriver.a \
+ clangSerialization.a clangParse.a clangSema.a clangAnalysis.a \
+ clangAST.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 4ed24b15c9d3..58eff97ef8f8 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1,6 +1,7 @@
/* c-index-test.c */
#include "clang-c/Index.h"
+#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -28,6 +29,18 @@ char *basename(const char* path)
extern char *basename(const char *);
#endif
+/** \brief Return the default parsing options. */
+static unsigned getDefaultParsingOptions() {
+ unsigned options = CXTranslationUnit_DetailedPreprocessingRecord;
+
+ if (getenv("CINDEXTEST_EDITING"))
+ options |= clang_defaultEditingTranslationUnitOptions();
+ if (getenv("CINDEXTEST_COMPLETION_CACHING"))
+ options |= CXTranslationUnit_CacheCompletionResults;
+
+ return options;
+}
+
static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,
unsigned end_line, unsigned end_column) {
fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,
@@ -38,7 +51,7 @@ static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
CXTranslationUnit *TU) {
*TU = clang_createTranslationUnit(Idx, file);
- if (!TU) {
+ if (!*TU) {
fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
return 0;
}
@@ -52,6 +65,7 @@ void free_remapped_files(struct CXUnsavedFile *unsaved_files,
free((char *)unsaved_files[i].Filename);
free((char *)unsaved_files[i].Contents);
}
+ free(unsaved_files);
}
int parse_remapped_files(int argc, const char **argv, int start_arg,
@@ -75,8 +89,8 @@ int parse_remapped_files(int argc, const char **argv, int start_arg,
return 0;
*unsaved_files
- = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
- *num_unsaved_files);
+ = (struct CXUnsavedFile *)malloc(sizeof(struct CXUnsavedFile) *
+ *num_unsaved_files);
for (arg = start_arg, i = 0; i != *num_unsaved_files; ++i, ++arg) {
struct CXUnsavedFile *unsaved = *unsaved_files + i;
const char *arg_string = argv[arg] + prefix_len;
@@ -152,7 +166,8 @@ static void PrintCursor(CXCursor Cursor) {
CXString string, ks;
CXCursor Referenced;
unsigned line, column;
-
+ CXCursor SpecializationOf;
+
ks = clang_getCursorKindSpelling(Cursor.kind);
string = clang_getCursorSpelling(Cursor);
printf("%s=%s", clang_getCString(ks),
@@ -169,6 +184,57 @@ static void PrintCursor(CXCursor Cursor) {
if (clang_isCursorDefinition(Cursor))
printf(" (Definition)");
+
+ switch (clang_getCursorAvailability(Cursor)) {
+ case CXAvailability_Available:
+ break;
+
+ case CXAvailability_Deprecated:
+ printf(" (deprecated)");
+ break;
+
+ case CXAvailability_NotAvailable:
+ printf(" (unavailable)");
+ break;
+ }
+
+ if (Cursor.kind == CXCursor_IBOutletCollectionAttr) {
+ CXType T =
+ clang_getCanonicalType(clang_getIBOutletCollectionType(Cursor));
+ CXString S = clang_getTypeKindSpelling(T.kind);
+ printf(" [IBOutletCollection=%s]", clang_getCString(S));
+ clang_disposeString(S);
+ }
+
+ if (Cursor.kind == CXCursor_CXXBaseSpecifier) {
+ enum CX_CXXAccessSpecifier access = clang_getCXXAccessSpecifier(Cursor);
+ unsigned isVirtual = clang_isVirtualBase(Cursor);
+ const char *accessStr = 0;
+
+ switch (access) {
+ case CX_CXXInvalidAccessSpecifier:
+ accessStr = "invalid"; break;
+ case CX_CXXPublic:
+ accessStr = "public"; break;
+ case CX_CXXProtected:
+ accessStr = "protected"; break;
+ case CX_CXXPrivate:
+ accessStr = "private"; break;
+ }
+
+ printf(" [access=%s isVirtual=%s]", accessStr,
+ isVirtual ? "true" : "false");
+ }
+
+ SpecializationOf = clang_getSpecializedCursorTemplate(Cursor);
+ if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) {
+ CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf);
+ CXString Name = clang_getCursorSpelling(SpecializationOf);
+ clang_getInstantiationLocation(Loc, 0, &line, &column, 0);
+ printf(" [Specialization of %s:%d:%d]",
+ clang_getCString(Name), line, column);
+ clang_disposeString(Name);
+ }
}
}
@@ -477,6 +543,8 @@ static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
clang_disposeString(RS);
}
}
+ /* Print if this is a non-POD type. */
+ printf(" [isPOD=%d]", clang_isPODType(T));
printf("\n");
}
@@ -558,7 +626,7 @@ int perform_test_load_source(int argc, const char **argv,
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
int result;
-
+
Idx = clang_createIndex(/* excludeDeclsFromPCH */
!strcmp(filter, "local") ? 1 : 0,
/* displayDiagnosics=*/1);
@@ -578,6 +646,7 @@ int perform_test_load_source(int argc, const char **argv,
unsaved_files);
if (!TU) {
fprintf(stderr, "Unable to load translation unit!\n");
+ free_remapped_files(unsaved_files, num_unsaved_files);
clang_disposeIndex(Idx);
return 1;
}
@@ -588,6 +657,60 @@ int perform_test_load_source(int argc, const char **argv,
return result;
}
+int perform_test_reparse_source(int argc, const char **argv, int trials,
+ const char *filter, CXCursorVisitor Visitor,
+ PostVisitTU PV) {
+ const char *UseExternalASTs =
+ getenv("CINDEXTEST_USE_EXTERNAL_AST_GENERATION");
+ CXIndex Idx;
+ CXTranslationUnit TU;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
+ int result;
+ int trial;
+
+ Idx = clang_createIndex(/* excludeDeclsFromPCH */
+ !strcmp(filter, "local") ? 1 : 0,
+ /* displayDiagnosics=*/1);
+
+ if (UseExternalASTs && strlen(UseExternalASTs))
+ clang_setUseExternalASTGeneration(Idx, 1);
+
+ if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
+ clang_disposeIndex(Idx);
+ return -1;
+ }
+
+ /* Load the initial translation unit -- we do this without honoring remapped
+ * files, so that we have a way to test results after changing the source. */
+ TU = clang_parseTranslationUnit(Idx, 0,
+ argv + num_unsaved_files,
+ argc - num_unsaved_files,
+ 0, 0, getDefaultParsingOptions());
+ if (!TU) {
+ fprintf(stderr, "Unable to load translation unit!\n");
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ clang_disposeIndex(Idx);
+ return 1;
+ }
+
+ for (trial = 0; trial < trials; ++trial) {
+ if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU))) {
+ fprintf(stderr, "Unable to reparse translation unit!\n");
+ clang_disposeTranslationUnit(TU);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ clang_disposeIndex(Idx);
+ return -1;
+ }
+ }
+
+ result = perform_test_load(Idx, TU, filter, NULL, Visitor, PV);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ clang_disposeIndex(Idx);
+ return result;
+}
+
/******************************************************************************/
/* Logic for testing clang_getCursor(). */
/******************************************************************************/
@@ -795,8 +918,40 @@ void print_completion_result(CXCompletionResult *completion_result,
clang_disposeString(ks);
print_completion_string(completion_result->CompletionString, file);
- fprintf(file, " (%u)\n",
+ fprintf(file, " (%u)",
clang_getCompletionPriority(completion_result->CompletionString));
+ switch (clang_getCompletionAvailability(completion_result->CompletionString)){
+ case CXAvailability_Available:
+ break;
+
+ case CXAvailability_Deprecated:
+ fprintf(file, " (deprecated)");
+ break;
+
+ case CXAvailability_NotAvailable:
+ fprintf(file, " (unavailable)");
+ break;
+ }
+ fprintf(file, "\n");
+}
+
+int my_stricmp(const char *s1, const char *s2) {
+ while (*s1 && *s2) {
+ int c1 = tolower(*s1), c2 = tolower(*s2);
+ if (c1 < c2)
+ return -1;
+ else if (c1 > c2)
+ return 1;
+
+ ++s1;
+ ++s2;
+ }
+
+ if (*s1)
+ return 1;
+ else if (*s2)
+ return -1;
+ return 0;
}
int perform_code_completion(int argc, const char **argv, int timing_only) {
@@ -809,7 +964,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
CXCodeCompleteResults *results = 0;
-
+ CXTranslationUnit *TU = 0;
+
if (timing_only)
input += strlen("-code-completion-timing=");
else
@@ -823,17 +979,43 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
return -1;
CIdx = clang_createIndex(0, 1);
- results = clang_codeComplete(CIdx,
- argv[argc - 1], argc - num_unsaved_files - 3,
- argv + num_unsaved_files + 2,
- num_unsaved_files, unsaved_files,
- filename, line, column);
+ if (getenv("CINDEXTEST_EDITING")) {
+ unsigned I, Repeats = 5;
+ TU = clang_parseTranslationUnit(CIdx, 0,
+ argv + num_unsaved_files + 2,
+ argc - num_unsaved_files - 2,
+ 0, 0, getDefaultParsingOptions());
+ if (!TU) {
+ fprintf(stderr, "Unable to load translation unit!\n");
+ return 1;
+ }
+ for (I = 0; I != Repeats; ++I) {
+ results = clang_codeCompleteAt(TU, filename, line, column,
+ unsaved_files, num_unsaved_files,
+ clang_defaultCodeCompleteOptions());
+ if (!results) {
+ fprintf(stderr, "Unable to perform code completion!\n");
+ return 1;
+ }
+ if (I != Repeats-1)
+ clang_disposeCodeCompleteResults(results);
+ }
+ } else
+ results = clang_codeComplete(CIdx,
+ argv[argc - 1], argc - num_unsaved_files - 3,
+ argv + num_unsaved_files + 2,
+ num_unsaved_files, unsaved_files,
+ filename, line, column);
if (results) {
unsigned i, n = results->NumResults;
- if (!timing_only)
+ if (!timing_only) {
+ /* Sort the code-completion results based on the typed text. */
+ clang_sortCodeCompletionResults(results->Results, results->NumResults);
+
for (i = 0; i != n; ++i)
print_completion_result(results->Results + i, stdout);
+ }
n = clang_codeCompleteGetNumDiagnostics(results);
for (i = 0; i != n; ++i) {
CXDiagnostic diag = clang_codeCompleteGetDiagnostic(results, i);
@@ -842,7 +1024,7 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
}
clang_disposeCodeCompleteResults(results);
}
-
+ clang_disposeTranslationUnit(TU);
clang_disposeIndex(CIdx);
free(filename);
@@ -1197,6 +1379,43 @@ int print_usrs_file(const char *file_name) {
/******************************************************************************/
/* Command line processing. */
/******************************************************************************/
+int write_pch_file(const char *filename, int argc, const char *argv[]) {
+ CXIndex Idx;
+ CXTranslationUnit TU;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
+
+ Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnosics=*/1);
+
+ if (parse_remapped_files(argc, argv, 0, &unsaved_files, &num_unsaved_files)) {
+ clang_disposeIndex(Idx);
+ return -1;
+ }
+
+ TU = clang_parseTranslationUnit(Idx, 0,
+ argv + num_unsaved_files,
+ argc - num_unsaved_files,
+ unsaved_files,
+ num_unsaved_files,
+ CXTranslationUnit_Incomplete);
+ if (!TU) {
+ fprintf(stderr, "Unable to load translation unit!\n");
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ clang_disposeIndex(Idx);
+ return 1;
+ }
+
+ if (clang_saveTranslationUnit(TU, filename, clang_defaultSaveOptions(TU)))
+ fprintf(stderr, "Unable to write PCH file %s\n", filename);
+ clang_disposeTranslationUnit(TU);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ clang_disposeIndex(Idx);
+ return 0;
+}
+
+/******************************************************************************/
+/* Command line processing. */
+/******************************************************************************/
static CXCursorVisitor GetVisitor(const char *s) {
if (s[0] == '\0')
@@ -1219,14 +1438,19 @@ static void print_usage(void) {
"[FileCheck prefix]\n"
" c-index-test -test-load-source <symbol filter> {<args>}*\n");
fprintf(stderr,
+ " c-index-test -test-load-source-reparse <trials> <symbol filter> "
+ " {<args>}*\n"
" c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
" c-index-test -test-annotate-tokens=<range> {<args>}*\n"
" c-index-test -test-inclusion-stack-source {<args>}*\n"
" c-index-test -test-inclusion-stack-tu <AST file>\n"
" c-index-test -test-print-linkage-source {<args>}*\n"
" c-index-test -test-print-typekind {<args>}*\n"
- " c-index-test -print-usr [<CursorKind> {<args>}]*\n"
- " c-index-test -print-usr-file <file>\n\n"
+ " c-index-test -print-usr [<CursorKind> {<args>}]*\n");
+ fprintf(stderr,
+ " c-index-test -print-usr-file <file>\n"
+ " c-index-test -write-pch <file> <compiler arguments>\n\n");
+ fprintf(stderr,
" <symbol filter> values:\n%s",
" all - load all symbols, including those from PCH\n"
" local - load all symbols except those in PCH\n"
@@ -1252,6 +1476,14 @@ int main(int argc, const char **argv) {
return perform_test_load_tu(argv[2], argv[3], argc >= 5 ? argv[4] : 0, I,
NULL);
}
+ else if (argc >= 5 && strncmp(argv[1], "-test-load-source-reparse", 25) == 0){
+ CXCursorVisitor I = GetVisitor(argv[1] + 25);
+ if (I) {
+ int trials = atoi(argv[2]);
+ return perform_test_reparse_source(argc - 4, argv + 4, trials, argv[3], I,
+ NULL);
+ }
+ }
else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
CXCursorVisitor I = GetVisitor(argv[1] + 17);
if (I)
@@ -1284,7 +1516,9 @@ int main(int argc, const char **argv) {
}
else if (argc > 2 && strcmp(argv[1], "-print-usr-file") == 0)
return print_usrs_file(argv[2]);
-
+ else if (argc > 2 && strcmp(argv[1], "-write-pch") == 0)
+ return write_pch_file(argv[2], argc - 3, argv + 3);
+
print_usage();
return 1;
}
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 0eaddba4739d..ec6e9c6e8026 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -1,15 +1,18 @@
set(LLVM_NO_RTTI 1)
set( LLVM_USED_LIBS
+ clangFrontendTool
clangFrontend
clangDriver
+ clangSerialization
clangCodeGen
+ clangParse
clangSema
clangChecker
clangAnalysis
+ clangIndex
clangRewrite
clangAST
- clangParse
clangLex
clangBasic
)
diff --git a/tools/driver/Info.plist.in b/tools/driver/Info.plist.in
new file mode 100644
index 000000000000..c938fb053d92
--- /dev/null
+++ b/tools/driver/Info.plist.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleIdentifier</key>
+ <string>@TOOL_INFO_UTI@</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>@TOOL_INFO_NAME</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@TOOL_INFO_VERSION@</string>
+ <key>CFBundleVersion</key>
+ <string>@TOOL_INFO_BUILD_VERSION@</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+</dict>
+</plist>
diff --git a/tools/driver/Makefile b/tools/driver/Makefile
index b049af64bbf4..447f0e4eb06b 100644
--- a/tools/driver/Makefile
+++ b/tools/driver/Makefile
@@ -17,6 +17,9 @@ else
endif
endif
+# Include tool version information on OS X.
+TOOL_INFO_PLIST := Info.plist
+
# Include this here so we can get the configuration of the targets that have
# been configured for construction. We have to do this early so we can set up
# LINK_COMPONENTS before including Makefile.rules
@@ -24,12 +27,36 @@ include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader bitwriter codegen \
ipo selectiondag
-USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
- clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
- clangParse.a clangLex.a clangBasic.a
+USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \
+ clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \
+ clangChecker.a clangAnalysis.a clangIndex.a clangRewrite.a \
+ clangAST.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
+# Set the tool version information values.
+ifeq ($(HOST_OS),Darwin)
+ifdef CLANG_VENDOR
+TOOL_INFO_NAME := $(CLANG_VENDOR) clang
+else
+TOOL_INFO_NAME := clang
+endif
+
+ifdef CLANG_VENDOR_UTI
+TOOL_INFO_UTI := $(CLANG_VENDOR_UTI)
+else
+TOOL_INFO_UTI := org.llvm.clang
+endif
+
+TOOL_INFO_VERSION := $(word 3,$(shell grep "CLANG_VERSION " \
+ $(PROJ_OBJ_DIR)/$(CLANG_LEVEL)/include/clang/Basic/Version.inc))
+ifdef LLVM_SUBMIT_VERSION
+TOOL_INFO_BUILD_VERSION := $(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION)
+else
+TOOL_INFO_BUILD_VERSION :=
+endif
+endif
+
# Translate make variable to define when building a "production" clang.
ifdef CLANG_IS_PRODUCTION
CPP.Defines += -DCLANG_IS_PRODUCTION
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index 841e40abfc75..de5e8bf043bf 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -13,9 +13,6 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Checker/FrontendActions.h"
-#include "clang/CodeGen/CodeGenAction.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/CC1Options.h"
@@ -23,20 +20,16 @@
#include "clang/Driver/OptTable.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/TextDiagnosticBuffer.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Rewrite/FrontendActions.h"
+#include "clang/FrontendTool/Utils.h"
#include "llvm/LLVMContext.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/DynamicLibrary.h"
#include "llvm/Target/TargetSelect.h"
#include <cstdio>
using namespace clang;
@@ -54,78 +47,6 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) {
exit(1);
}
-static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
- using namespace clang::frontend;
-
- switch (CI.getFrontendOpts().ProgramAction) {
- default:
- 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 BoostCon: return new BoostConAction();
- case DumpRawTokens: return new DumpRawTokensAction();
- 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 EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
- case EmitObj: return new EmitObjAction();
- case FixIt: return new FixItAction();
- case GeneratePCH: return new GeneratePCHAction();
- case GeneratePTH: return new GeneratePTHAction();
- case InheritanceView: return new InheritanceViewAction();
- case InitOnly: return new InitOnlyAction();
- case ParseNoop: return new ParseOnlyAction();
- case ParsePrintCallbacks: return new PrintParseAction();
- case ParseSyntaxOnly: return new SyntaxOnlyAction();
-
- case PluginAction: {
-
- for (FrontendPluginRegistry::iterator it =
- FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
- it != ie; ++it) {
- if (it->getName() == CI.getFrontendOpts().ActionName) {
- PluginASTAction* plugin = it->instantiate();
- plugin->ParseArgs(CI.getFrontendOpts().PluginArgs);
- return plugin;
- }
- }
-
- CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
- << CI.getFrontendOpts().ActionName;
- return 0;
- }
-
- case PrintDeclContext: return new DeclContextPrintAction();
- case PrintPreprocessedInput: return new PrintPreprocessedAction();
- 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();
- }
-}
-
-static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
- // Create the underlying action.
- FrontendAction *Act = CreateFrontendBaseAction(CI);
- if (!Act)
- return 0;
-
- // If there are any AST files to merge, create a frontend action
- // adaptor to perform the merge.
- if (!CI.getFrontendOpts().ASTMergeFiles.empty())
- Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
- CI.getFrontendOpts().ASTMergeFiles.size());
-
- return Act;
-}
-
// FIXME: Define the need for this testing away.
static int cc1_test(Diagnostic &Diags,
const char **ArgBegin, const char **ArgEnd) {
@@ -200,8 +121,8 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// Run clang -cc1 test.
if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
- TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
- Diagnostic Diags(&DiagClient);
+ Diagnostic Diags(new TextDiagnosticPrinter(llvm::errs(),
+ DiagnosticOptions()));
return cc1_test(Diags, ArgBegin + 1, ArgEnd);
}
@@ -212,8 +133,8 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// Buffer diagnostics from argument parsing so that we can output them using a
// well formed diagnostic object.
- TextDiagnosticBuffer DiagsBuffer;
- Diagnostic Diags(&DiagsBuffer);
+ TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
+ Diagnostic Diags(DiagsBuffer);
CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd,
Diags);
@@ -223,35 +144,6 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
Clang->getHeaderSearchOpts().ResourceDir =
CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
- // Honor -help.
- if (Clang->getFrontendOpts().ShowHelp) {
- llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
- Opts->PrintHelp(llvm::outs(), "clang -cc1",
- "LLVM 'Clang' Compiler: http://clang.llvm.org");
- return 0;
- }
-
- // Honor -version.
- //
- // FIXME: Use a better -version message?
- if (Clang->getFrontendOpts().ShowVersion) {
- llvm::cl::PrintVersionMessage();
- return 0;
- }
-
- // Honor -mllvm.
- //
- // FIXME: Remove this, one day.
- if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
- unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
- const char **Args = new const char*[NumArgs + 2];
- Args[0] = "clang (LLVM option parsing)";
- for (unsigned i = 0; i != NumArgs; ++i)
- Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
- Args[NumArgs + 1] = 0;
- llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
- }
-
// Create the actual diagnostics engine.
Clang->createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
if (!Clang->hasDiagnostics())
@@ -262,33 +154,20 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
llvm::install_fatal_error_handler(LLVMErrorHandler,
static_cast<void*>(&Clang->getDiagnostics()));
- DiagsBuffer.FlushDiagnostics(Clang->getDiagnostics());
+ DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
- // Load any requested plugins.
- for (unsigned i = 0,
- e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) {
- const std::string &Path = Clang->getFrontendOpts().Plugins[i];
- std::string Error;
- if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
- Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
- }
-
- // If there were errors in processing arguments, don't do anything else.
- bool Success = false;
- if (!Clang->getDiagnostics().getNumErrors()) {
- // Create and execute the frontend action.
- llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(*Clang));
- if (Act) {
- Success = Clang->ExecuteAction(*Act);
- if (Clang->getFrontendOpts().DisableFree)
- Act.take();
- }
- }
+ // Execute the frontend actions.
+ bool Success = ExecuteCompilerInvocation(Clang.get());
// If any timers were active but haven't been destroyed yet, print their
// results now. This happens in -disable-free mode.
llvm::TimerGroup::printAll(llvm::errs());
-
+
+ // Our error handler depends on the Diagnostics object, which we're
+ // potentially about to delete. Uninstall the handler now so that any
+ // later errors use the default handling behavior instead.
+ llvm::remove_fatal_error_handler();
+
// When running with -disable-free, don't do any destruction or shutdown.
if (Clang->getFrontendOpts().DisableFree) {
if (Clang->getFrontendOpts().ShowStats)
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 3c5ca9213f67..5bce70cb2a1b 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -24,7 +24,9 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/MC/MCParser/AsmParser.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
@@ -141,7 +143,7 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
// Construct the invocation.
// Target Options
- Opts.Triple = Args->getLastArgValue(OPT_triple);
+ Opts.Triple = Triple::normalize(Args->getLastArgValue(OPT_triple));
if (Opts.Triple.empty()) // Use the host triple if unspecified.
Opts.Triple = sys::getHostTriple();
@@ -253,38 +255,38 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, Diagnostic &Diags) {
return false;
}
- OwningPtr<MCCodeEmitter> CE;
OwningPtr<MCStreamer> Str;
- OwningPtr<TargetAsmBackend> TAB;
if (Opts.OutputType == AssemblerInvocation::FT_Asm) {
MCInstPrinter *IP =
TheTarget->createMCInstPrinter(Opts.OutputAsmVariant, *MAI);
+ MCCodeEmitter *CE = 0;
if (Opts.ShowEncoding)
- CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
+ CE = TheTarget->createCodeEmitter(*TM, Ctx);
Str.reset(createAsmStreamer(Ctx, *Out,TM->getTargetData()->isLittleEndian(),
- /*asmverbose*/true, IP, CE.get(),
- Opts.ShowInst));
+ /*asmverbose*/true, IP, CE, Opts.ShowInst));
} else if (Opts.OutputType == AssemblerInvocation::FT_Null) {
Str.reset(createNullStreamer(Ctx));
} else {
assert(Opts.OutputType == AssemblerInvocation::FT_Obj &&
"Invalid file type!");
- CE.reset(TheTarget->createCodeEmitter(*TM, Ctx));
- TAB.reset(TheTarget->createAsmBackend(Opts.Triple));
- Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), Opts.RelaxAll));
+ MCCodeEmitter *CE = TheTarget->createCodeEmitter(*TM, Ctx);
+ TargetAsmBackend *TAB = TheTarget->createAsmBackend(Opts.Triple);
+ Str.reset(TheTarget->createObjectStreamer(Opts.Triple, Ctx, *TAB, *Out,
+ CE, Opts.RelaxAll));
}
- AsmParser Parser(*TheTarget, SrcMgr, Ctx, *Str.get(), *MAI);
- OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(Parser));
+ OwningPtr<MCAsmParser> Parser(createMCAsmParser(*TheTarget, SrcMgr, Ctx,
+ *Str.get(), *MAI));
+ OwningPtr<TargetAsmParser> TAP(TheTarget->createAsmParser(*Parser, *TM));
if (!TAP) {
Diags.Report(diag::err_target_unknown_triple) << Opts.Triple;
return false;
}
- Parser.setTargetParser(*TAP.get());
+ Parser->setTargetParser(*TAP.get());
- bool Success = !Parser.Run(Opts.NoInitialTextSection);
+ bool Success = !Parser->Run(Opts.NoInitialTextSection);
// Close the output.
delete Out;
@@ -320,14 +322,15 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd,
InitializeAllAsmParsers();
// Construct our diagnostic client.
- TextDiagnosticPrinter DiagClient(errs(), DiagnosticOptions());
- DiagClient.setPrefix("clang -cc1as");
- Diagnostic Diags(&DiagClient);
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(errs(), DiagnosticOptions());
+ DiagClient->setPrefix("clang -cc1as");
+ Diagnostic Diags(DiagClient);
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
- install_fatal_error_handler(LLVMErrorHandler,
- static_cast<void*>(&Diags));
+ ScopedFatalErrorHandler FatalErrorHandler
+ (LLVMErrorHandler, static_cast<void*>(&Diags));
// Parse the arguments.
AssemblerInvocation Asm;
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index c4b12cba0f7a..c058ece0dc9b 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -19,15 +19,19 @@
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.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"
using namespace clang;
using namespace clang::driver;
@@ -75,7 +79,7 @@ static const char *SaveStringInSet(std::set<std::string> &SavedStrings,
/// \param Edit - The override command to perform.
/// \param SavedStrings - Set to use for storing string representations.
static void ApplyOneQAOverride(llvm::raw_ostream &OS,
- std::vector<const char*> &Args,
+ llvm::SmallVectorImpl<const char*> &Args,
llvm::StringRef Edit,
std::set<std::string> &SavedStrings) {
// This does not need to be efficient.
@@ -141,7 +145,7 @@ static void ApplyOneQAOverride(llvm::raw_ostream &OS,
/// ApplyQAOverride - Apply a comma separate list of edits to the
/// input argument lists. See ApplyOneQAOverride.
-static void ApplyQAOverride(std::vector<const char*> &Args,
+static void ApplyQAOverride(llvm::SmallVectorImpl<const char*> &Args,
const char *OverrideStr,
std::set<std::string> &SavedStrings) {
llvm::raw_ostream *OS = &llvm::errs();
@@ -173,19 +177,97 @@ extern int cc1_main(const char **ArgBegin, const char **ArgEnd,
extern int cc1as_main(const char **ArgBegin, const char **ArgEnd,
const char *Argv0, void *MainAddr);
-int main(int argc, const char **argv) {
+static void ExpandArgsFromBuf(const char *Arg,
+ llvm::SmallVectorImpl<const char*> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ const char *FName = Arg + 1;
+ llvm::MemoryBuffer *MemBuf = llvm::MemoryBuffer::getFile(FName);
+ if (!MemBuf) {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, Arg));
+ return;
+ }
+
+ const char *Buf = MemBuf->getBufferStart();
+ char InQuote = ' ';
+ std::string CurArg;
+
+ for (const char *P = Buf; ; ++P) {
+ if (*P == '\0' || (isspace(*P) && InQuote == ' ')) {
+ if (!CurArg.empty()) {
+
+ if (CurArg[0] != '@') {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, CurArg));
+ } else {
+ ExpandArgsFromBuf(CurArg.c_str(), ArgVector, SavedStrings);
+ }
+
+ CurArg = "";
+ }
+ if (*P == '\0')
+ break;
+ else
+ continue;
+ }
+
+ if (isspace(*P)) {
+ if (InQuote != ' ')
+ CurArg.push_back(*P);
+ continue;
+ }
+
+ if (*P == '"' || *P == '\'') {
+ if (InQuote == *P)
+ InQuote = ' ';
+ else if (InQuote == ' ')
+ InQuote = *P;
+ else
+ CurArg.push_back(*P);
+ continue;
+ }
+
+ if (*P == '\\') {
+ ++P;
+ if (*P != '\0')
+ CurArg.push_back(*P);
+ continue;
+ }
+ CurArg.push_back(*P);
+ }
+ delete MemBuf;
+}
+
+static void ExpandArgv(int argc, const char **argv,
+ llvm::SmallVectorImpl<const char*> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ for (int i = 0; i < argc; ++i) {
+ const char *Arg = argv[i];
+ if (Arg[0] != '@') {
+ ArgVector.push_back(SaveStringInSet(SavedStrings, std::string(Arg)));
+ continue;
+ }
+
+ ExpandArgsFromBuf(Arg, ArgVector, SavedStrings);
+ }
+}
+
+int main(int argc_, const char **argv_) {
llvm::sys::PrintStackTraceOnErrorSignal();
- llvm::PrettyStackTraceProgram X(argc, argv);
+ llvm::PrettyStackTraceProgram X(argc_, argv_);
+
+ std::set<std::string> SavedStrings;
+ llvm::SmallVector<const char*, 256> argv;
+
+ ExpandArgv(argc_, argv_, argv, SavedStrings);
// Handle -cc1 integrated tools.
- if (argc > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
+ if (argv.size() > 1 && llvm::StringRef(argv[1]).startswith("-cc1")) {
llvm::StringRef Tool = argv[1] + 4;
if (Tool == "")
- return cc1_main(argv+2, argv+argc, argv[0],
+ return cc1_main(argv.data()+2, argv.data()+argv.size(), argv[0],
(void*) (intptr_t) GetExecutablePath);
if (Tool == "as")
- return cc1as_main(argv+2, argv+argc, argv[0],
+ return cc1as_main(argv.data()+2, argv.data()+argv.size(), argv[0],
(void*) (intptr_t) GetExecutablePath);
// Reject unknown tools.
@@ -194,7 +276,7 @@ int main(int argc, const char **argv) {
}
bool CanonicalPrefixes = true;
- for (int i = 1; i < argc; ++i) {
+ for (int i = 1, size = argv.size(); i < size; ++i) {
if (llvm::StringRef(argv[i]) == "-no-canonical-prefixes") {
CanonicalPrefixes = false;
break;
@@ -203,10 +285,10 @@ int main(int argc, const char **argv) {
llvm::sys::Path Path = GetExecutablePath(argv[0], CanonicalPrefixes);
- TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
- DiagClient.setPrefix(Path.getBasename());
-
- Diagnostic Diags(&DiagClient);
+ TextDiagnosticPrinter *DiagClient
+ = new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
+ DiagClient->setPrefix(Path.getBasename());
+ Diagnostic Diags(DiagClient);
#ifdef CLANG_IS_PRODUCTION
const bool IsProduction = true;
@@ -219,11 +301,27 @@ int main(int argc, const char **argv) {
const bool IsProduction = false;
const bool CXXIsProduction = false;
#endif
- Driver TheDriver(Path.getBasename(), Path.getDirname(),
- llvm::sys::getHostTriple(),
+ Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
"a.out", IsProduction, CXXIsProduction,
Diags);
+ // Attempt to find the original path used to invoke the driver, to determine
+ // the installed path. We do this manually, because we want to support that
+ // path being a symlink.
+ llvm::sys::Path InstalledPath(argv[0]);
+
+ // Do a PATH lookup, if there are no directory components.
+ if (InstalledPath.getLast() == InstalledPath.str()) {
+ llvm::sys::Path Tmp =
+ llvm::sys::Program::FindProgramByName(InstalledPath.getLast());
+ if (!Tmp.empty())
+ InstalledPath = Tmp;
+ }
+ InstalledPath.makeAbsolute();
+ InstalledPath.eraseComponent();
+ if (InstalledPath.exists())
+ TheDriver.setInstalledDir(InstalledPath.str());
+
// Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
// compiler. This matches things like "c++", "clang++", and "clang++-1.1".
//
@@ -231,15 +329,14 @@ int main(int argc, const char **argv) {
// being a symlink.
//
// We use *argv instead of argv[0] to work around a bogus g++ warning.
- std::string ProgName(llvm::sys::Path(*argv).getBasename());
+ const char *progname = argv_[0];
+ std::string ProgName(llvm::sys::Path(progname).getBasename());
if (llvm::StringRef(ProgName).endswith("++") ||
llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
TheDriver.CCCIsCXX = true;
TheDriver.CCCGenericGCCName = "g++";
}
- llvm::OwningPtr<Compilation> C;
-
// Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
if (TheDriver.CCPrintOptions)
@@ -247,46 +344,35 @@ int main(int argc, const char **argv) {
// Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a
// command line behind the scenes.
- std::set<std::string> SavedStrings;
if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) {
// FIXME: Driver shouldn't take extra initial argument.
- std::vector<const char*> StringPointers(argv, argv + argc);
-
- ApplyQAOverride(StringPointers, OverrideStr, SavedStrings);
-
- C.reset(TheDriver.BuildCompilation(StringPointers.size(),
- &StringPointers[0]));
+ ApplyQAOverride(argv, OverrideStr, SavedStrings);
} else if (const char *Cur = ::getenv("CCC_ADD_ARGS")) {
- std::vector<const char*> StringPointers;
-
// FIXME: Driver shouldn't take extra initial argument.
- StringPointers.push_back(argv[0]);
+ std::vector<const char*> ExtraArgs;
for (;;) {
const char *Next = strchr(Cur, ',');
if (Next) {
- StringPointers.push_back(SaveStringInSet(SavedStrings,
- std::string(Cur, Next)));
+ ExtraArgs.push_back(SaveStringInSet(SavedStrings,
+ std::string(Cur, Next)));
Cur = Next + 1;
} else {
if (*Cur != '\0')
- StringPointers.push_back(SaveStringInSet(SavedStrings, Cur));
+ ExtraArgs.push_back(SaveStringInSet(SavedStrings, Cur));
break;
}
}
- StringPointers.insert(StringPointers.end(), argv + 1, argv + argc);
-
- C.reset(TheDriver.BuildCompilation(StringPointers.size(),
- &StringPointers[0]));
- } else
- C.reset(TheDriver.BuildCompilation(argc, argv));
+ argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end());
+ }
+ llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(),
+ &argv[0]));
int Res = 0;
if (C.get())
Res = TheDriver.ExecuteCompilation(*C);
-
// If any timers were active but haven't been destroyed yet, print their
// results now. This happens in -disable-free mode.
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 7f32a1c148dd..5117f2c16424 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -14,6 +14,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
+#include "CXType.h"
#include "CXSourceLocation.h"
#include "CIndexDiagnostic.h"
@@ -29,7 +30,9 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
@@ -143,10 +146,10 @@ static RangeComparisonResult RangeCompare(SourceManager &SM,
SourceRange R2) {
assert(R1.isValid() && "First range is invalid?");
assert(R2.isValid() && "Second range is invalid?");
- if (R1.getEnd() == R2.getBegin() ||
+ if (R1.getEnd() != R2.getBegin() &&
SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
return RangeBefore;
- if (R2.getEnd() == R1.getBegin() ||
+ if (R2.getEnd() != R1.getBegin() &&
SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
return RangeAfter;
return RangeOverlap;
@@ -158,10 +161,8 @@ static RangeComparisonResult LocationCompare(SourceManager &SM,
SourceLocation L, SourceRange R) {
assert(R.isValid() && "First range is invalid?");
assert(L.isValid() && "Second range is invalid?");
- if (L == R.getBegin())
+ if (L == R.getBegin() || L == R.getEnd())
return RangeOverlap;
- if (L == R.getEnd())
- return RangeAfter;
if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
return RangeBefore;
if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
@@ -284,15 +285,24 @@ public:
// Declaration visitors
bool VisitAttributes(Decl *D);
bool VisitBlockDecl(BlockDecl *B);
+ bool VisitCXXRecordDecl(CXXRecordDecl *D);
bool VisitDeclContext(DeclContext *DC);
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitTypedefDecl(TypedefDecl *D);
bool VisitTagDecl(TagDecl *D);
+ bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
+ bool VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
bool VisitEnumConstantDecl(EnumConstantDecl *D);
bool VisitDeclaratorDecl(DeclaratorDecl *DD);
bool VisitFunctionDecl(FunctionDecl *ND);
bool VisitFieldDecl(FieldDecl *D);
bool VisitVarDecl(VarDecl *);
+ bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ bool VisitClassTemplateDecl(ClassTemplateDecl *D);
+ bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
@@ -309,14 +319,28 @@ public:
bool VisitObjCClassDecl(ObjCClassDecl *D);
bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
bool VisitNamespaceDecl(NamespaceDecl *D);
-
+ bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ bool VisitUsingDecl(UsingDecl *D);
+ bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+ // Name visitor
+ bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
+ bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
+
+ // Template visitors
+ bool VisitTemplateParameters(const TemplateParameterList *Params);
+ bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
+ bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
+
// Type visitors
- // FIXME: QualifiedTypeLoc doesn't provide any location information
+ bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
bool VisitTagTypeLoc(TagTypeLoc TL);
- // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL);
bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
@@ -325,9 +349,9 @@ public:
bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
- bool VisitFunctionTypeLoc(FunctionTypeLoc TL);
+ bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
bool VisitArrayTypeLoc(ArrayTypeLoc TL);
- // FIXME: Implement for TemplateSpecializationTypeLoc
+ bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL);
// FIXME: Implement visitors here when the unimplemented TypeLocs get
// implemented
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
@@ -345,6 +369,8 @@ public:
// bool VisitSwitchCase(SwitchCase *S);
// Expression visitors
+ bool VisitDeclRefExpr(DeclRefExpr *E);
+ bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
bool VisitBlockExpr(BlockExpr *B);
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
bool VisitExplicitCastExpr(ExplicitCastExpr *E);
@@ -352,10 +378,30 @@ public:
bool VisitObjCEncodeExpr(ObjCEncodeExpr *E);
bool VisitOffsetOfExpr(OffsetOfExpr *E);
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ bool VisitMemberExpr(MemberExpr *E);
+ // FIXME: AddrLabelExpr (once we have cursors for labels)
+ bool VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
+ bool VisitVAArgExpr(VAArgExpr *E);
+ // FIXME: InitListExpr (for the designators)
+ // FIXME: DesignatedInitExpr
+ bool VisitCXXTypeidExpr(CXXTypeidExpr *E);
+ bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { return false; }
+ // FIXME: CXXTemporaryObjectExpr has poor source-location information.
+ // FIXME: CXXScalarValueInitExpr has poor source-location information.
+ // FIXME: CXXNewExpr has poor source-location information
+ bool VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
+ // FIXME: UnaryTypeTraitExpr has poor source-location information.
+ bool VisitOverloadExpr(OverloadExpr *E);
+ bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ // FIXME: CXXUnresolvedConstructExpr has poor source-location information.
+ bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ bool VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
};
} // end anonymous namespace
+static SourceRange getRawCursorExtent(CXCursor C);
+
RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
return RangeCompare(TU->getSourceManager(), R, RegionOfInterest);
}
@@ -387,8 +433,7 @@ bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
// If we have a range of interest, and this cursor doesn't intersect with it,
// we're done.
if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
- SourceRange Range =
- cxloc::translateCXSourceRange(clang_getCursorExtent(Cursor));
+ SourceRange Range = getRawCursorExtent(Cursor);
if (Range.isInvalid() || CompareRegionOfInterest(Range))
return false;
}
@@ -478,10 +523,10 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
RegionOfInterest.isInvalid()) {
- const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
- for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
- ie = TLDs.end(); it != ie; ++it) {
- if (Visit(MakeCXCursor(*it, CXXUnit), true))
+ for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
+ TLEnd = CXXUnit->top_level_end();
+ TL != TLEnd; ++TL) {
+ if (Visit(MakeCXCursor(*TL, CXXUnit), true))
return true;
}
} else if (VisitDeclContext(
@@ -520,7 +565,10 @@ bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
if (Visit(B->getSignatureAsWritten()->getTypeLoc()))
return true;
- return Visit(MakeCXCursor(B->getBody(), StmtParent, TU));
+ if (Stmt *Body = B->getBody())
+ return Visit(MakeCXCursor(Body, StmtParent, TU));
+
+ return false;
}
bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
@@ -534,8 +582,7 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
CXCursor Cursor = MakeCXCursor(D, TU);
if (RegionOfInterest.isValid()) {
- SourceRange Range =
- cxloc::translateCXSourceRange(clang_getCursorExtent(Cursor));
+ SourceRange Range = getRawCursorExtent(Cursor);
if (Range.isInvalid())
continue;
@@ -577,6 +624,67 @@ bool CursorVisitor::VisitTagDecl(TagDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ bool ShouldVisitBody = false;
+ switch (D->getSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // Nothing to visit
+ return false;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ ShouldVisitBody = true;
+ break;
+ }
+
+ // Visit the template arguments used in the specialization.
+ if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
+ TypeLoc TL = SpecType->getTypeLoc();
+ if (TemplateSpecializationTypeLoc *TSTLoc
+ = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) {
+ for (unsigned I = 0, N = TSTLoc->getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TSTLoc->getArgLoc(I)))
+ return true;
+ }
+ }
+
+ if (ShouldVisitBody && VisitCXXRecordDecl(D))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ // Visit the partial specialization arguments.
+ const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten();
+ for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TemplateArgs[I]))
+ return true;
+
+ return VisitCXXRecordDecl(D);
+}
+
+bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ // Visit the default argument.
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
+ if (Visit(DefArg->getTypeLoc()))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
if (Expr *Init = D->getInitExpr())
return Visit(MakeCXCursor(Init, StmtParent, TU));
@@ -592,9 +700,37 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
}
bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- if (VisitDeclaratorDecl(ND))
- return true;
-
+ if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
+ // Visit the function declaration's syntactic components in the order
+ // written. This requires a bit of work.
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);
+
+ // If we have a function declared directly (without the use of a typedef),
+ // visit just the return type. Otherwise, just visit the function's type
+ // now.
+ if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||
+ (!FTL && Visit(TL)))
+ return true;
+
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifier *Qualifier = ND->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, ND->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(ND->getNameInfo()))
+ return true;
+
+ // FIXME: Visit explicitly-specified template arguments!
+
+ // Visit the function parameters, if we have a function type.
+ if (FTL && VisitFunctionTypeLoc(*FTL, true))
+ return true;
+
+ // FIXME: Attributes?
+ }
+
if (ND->isThisDeclarationADefinition() &&
Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return true;
@@ -622,6 +758,46 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) {
return false;
}
+bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (Expr *DefArg = D->getDefaultArgument())
+ return Visit(MakeCXCursor(DefArg, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitFunctionDecl(D->getTemplatedDecl());
+}
+
+bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitCXXRecordDecl(D->getTemplatedDecl());
+}
+
+bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
+ VisitTemplateArgumentLoc(D->getDefaultArgument()))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
if (Visit(TSInfo->getTypeLoc()))
@@ -773,10 +949,207 @@ bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getQualifierRange()))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
+ D->getTargetNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameDecl())
+ if (VisitNestedNameSpecifier(Qualifier, D->getNestedNameRange()))
+ return true;
+
+ // FIXME: Provide a multi-reference of some kind for all of the declarations
+ // that the using declaration refers to. We don't have this kind of cursor
+ // yet.
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getQualifierRange()))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
+ D->getIdentLocation(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange()))
+ return true;
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
+ switch (Name.getName().getNameKind()) {
+ case clang::DeclarationName::Identifier:
+ case clang::DeclarationName::CXXLiteralOperatorName:
+ case clang::DeclarationName::CXXOperatorName:
+ case clang::DeclarationName::CXXUsingDirective:
+ return false;
+
+ case clang::DeclarationName::CXXConstructorName:
+ case clang::DeclarationName::CXXDestructorName:
+ case clang::DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case clang::DeclarationName::ObjCZeroArgSelector:
+ case clang::DeclarationName::ObjCOneArgSelector:
+ case clang::DeclarationName::ObjCMultiArgSelector:
+ // FIXME: Per-identifier location info?
+ return false;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range) {
+ // FIXME: This whole routine is a hack to work around the lack of proper
+ // source information in nested-name-specifiers (PR5791). Since we do have
+ // a beginning source location, we can visit the first component of the
+ // nested-name-specifier, if it's a single-token component.
+ if (!NNS)
+ return false;
+
+ // Get the first component in the nested-name-specifier.
+ while (NestedNameSpecifier *Prefix = NNS->getPrefix())
+ NNS = Prefix;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Namespace:
+ // FIXME: The token at this source location might actually have been a
+ // namespace alias, but we don't model that. Lame!
+ return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(),
+ TU));
+
+ case NestedNameSpecifier::TypeSpec: {
+ // If the type has a form where we know that the beginning of the source
+ // range matches up with a reference cursor. Visit the appropriate reference
+ // cursor.
+ Type *T = NNS->getAsType();
+ if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
+ if (const TagType *Tag = dyn_cast<TagType>(T))
+ return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(T))
+ return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Identifier:
+ break;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateParameters(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return false;
+
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
+ switch (Name.getKind()) {
+ case TemplateName::Template:
+ return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
+
+ case TemplateName::OverloadedTemplate:
+ // FIXME: We need a way to return multiple lookup results in a single
+ // cursor.
+ return false;
+
+ case TemplateName::DependentTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return false;
+
+ case TemplateName::QualifiedTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsQualifiedTemplateName()->getDecl(),
+ Loc, TU));
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
+ switch (TAL.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ return false;
+
+ case TemplateArgument::Pack:
+ // FIXME: Implement when variadic templates come along.
+ return false;
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case TemplateArgument::Declaration:
+ if (Expr *E = TAL.getSourceDeclExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+ return false;
+
+ case TemplateArgument::Expression:
+ if (Expr *E = TAL.getSourceExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+ return false;
+
+ case TemplateArgument::Template:
+ return VisitTemplateName(TAL.getArgument().getAsTemplate(),
+ TAL.getTemplateNameLoc());
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return Visit(TL.getUnqualifiedLoc());
+}
+
bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
ASTContext &Context = TU->getASTContext();
@@ -848,6 +1221,13 @@ bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
+bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ // FIXME: We can't visit the template template parameter, but there's
+ // no context information with which we can match up the depth/index in the
+ // type to the appropriate
+ return false;
+}
+
bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
return true;
@@ -892,8 +1272,9 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
return Visit(TL.getPointeeLoc());
}
-bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- if (Visit(TL.getResultLoc()))
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
+ bool SkipResultType) {
+ if (!SkipResultType && Visit(TL.getResultLoc()))
return true;
for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
@@ -914,6 +1295,21 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
return false;
}
+bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ // Visit the template name.
+ if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
+ TL.getTemplateNameLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
}
@@ -1054,6 +1450,56 @@ bool CursorVisitor::VisitForStmt(ForStmt *S) {
return false;
}
+bool CursorVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
+ // Visit nested-name-specifier, if present.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit declaration name.
+ if (VisitDeclarationNameInfo(E->getNameInfo()))
+ return true;
+
+ // Visit explicitly-specified template arguments.
+ if (E->hasExplicitTemplateArgs()) {
+ ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
+ for (TemplateArgumentLoc *Arg = Args.getTemplateArgs(),
+ *ArgEnd = Arg + Args.NumTemplateArgs;
+ Arg != ArgEnd; ++Arg)
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ if (Visit(MakeCXCursor(E->getArg(0), StmtParent, TU)))
+ return true;
+
+ if (Visit(MakeCXCursor(E->getCallee(), StmtParent, TU)))
+ return true;
+
+ for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I)
+ if (Visit(MakeCXCursor(E->getArg(I), StmtParent, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ if (D->isDefinition()) {
+ for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
+ E = D->bases_end(); I != E; ++I) {
+ if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
+ return true;
+ }
+ }
+
+ return VisitTagDecl(D);
+}
+
+
bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
return Visit(B->getBlockDecl());
}
@@ -1077,6 +1523,34 @@ bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
return VisitExpr(E);
}
+bool CursorVisitor::VisitMemberExpr(MemberExpr *E) {
+ // Visit the base expression.
+ if (Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ // Visit the nested-name-specifier
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getMemberNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments, if any.
+ if (E->hasExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = E->getTemplateArgs(),
+ *ArgEnd = Arg + E->getNumTemplateArgs();
+ Arg != ArgEnd;
+ ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
if (TypeSourceInfo *TSInfo = E->getTypeInfoAsWritten())
if (Visit(TSInfo->getTypeLoc()))
@@ -1093,6 +1567,143 @@ bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return VisitExpr(E);
}
+bool CursorVisitor::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
+ return Visit(E->getArgTInfo1()->getTypeLoc()) ||
+ Visit(E->getArgTInfo2()->getTypeLoc());
+}
+
+bool CursorVisitor::VisitVAArgExpr(VAArgExpr *E) {
+ if (Visit(E->getWrittenTypeInfo()->getTypeLoc()))
+ return true;
+
+ return Visit(MakeCXCursor(E->getSubExpr(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ if (E->isTypeOperand()) {
+ if (TypeSourceInfo *TSInfo = E->getTypeOperandSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+ }
+
+ return VisitExpr(E);
+}
+
+bool CursorVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ // Visit base expression.
+ if (Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the scope type that looks disturbingly like the nested-name-specifier
+ // but isn't.
+ if (TypeSourceInfo *TSInfo = E->getScopeTypeInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ // Visit the name of the type being destroyed.
+ if (TypeSourceInfo *TSInfo = E->getDestroyedTypeInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) {
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments.
+ if (const ExplicitTemplateArgumentList *ArgList
+ = E->getOptionalExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ // FIXME: We don't have a way to visit all of the declarations referenced
+ // here.
+ return false;
+}
+
+bool CursorVisitor::VisitDependentScopeDeclRefExpr(
+ DependentScopeDeclRefExpr *E) {
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments.
+ if (const ExplicitTemplateArgumentList *ArgList
+ = E->getOptionalExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *E) {
+ // Visit the base expression, if there is one.
+ if (!E->isImplicitAccess() &&
+ Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getMemberNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments.
+ if (const ExplicitTemplateArgumentList *ArgList
+ = E->getOptionalExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+ // Visit the base expression, if there is one.
+ if (!E->isImplicitAccess() &&
+ Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ return VisitOverloadExpr(E);
+}
+
bool CursorVisitor::VisitObjCMessageExpr(ObjCMessageExpr *E) {
if (TypeSourceInfo *TSInfo = E->getClassReceiverTypeInfo())
if (Visit(TSInfo->getTypeLoc()))
@@ -1107,8 +1718,9 @@ bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
bool CursorVisitor::VisitAttributes(Decl *D) {
- for (const Attr *A = D->getAttrs(); A; A = A->getNext())
- if (Visit(MakeCXCursor(A, D, TU)))
+ for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
+ i != e; ++i)
+ if (Visit(MakeCXCursor(*i, D, TU)))
return true;
return false;
@@ -1117,6 +1729,10 @@ bool CursorVisitor::VisitAttributes(Decl *D) {
extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics) {
+ // We use crash recovery to make some of our APIs more reliable, implicitly
+ // enable it.
+ llvm::CrashRecoveryContext::Enable();
+
CIndexer *CIdxr = new CIndexer();
if (excludeDeclarationsFromPCH)
CIdxr->setOnlyLocalDecls();
@@ -1128,6 +1744,8 @@ CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
void clang_disposeIndex(CXIndex CIdx) {
if (CIdx)
delete static_cast<CIndexer *>(CIdx);
+ if (getenv("LIBCLANG_TIMING"))
+ llvm::TimerGroup::printAll(llvm::errs());
}
void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) {
@@ -1145,23 +1763,61 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
- return ASTUnit::LoadFromPCHFile(ast_filename, Diags,
+ return ASTUnit::LoadFromASTFile(ast_filename, Diags,
CXXIdx->getOnlyLocalDecls(),
0, 0, true);
}
+unsigned clang_defaultEditingTranslationUnitOptions() {
+ return CXTranslationUnit_PrecompiledPreamble;
+}
+
CXTranslationUnit
clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
- const char **command_line_args,
+ const char * const *command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files) {
+ return clang_parseTranslationUnit(CIdx, source_filename,
+ command_line_args, num_command_line_args,
+ unsaved_files, num_unsaved_files,
+ CXTranslationUnit_DetailedPreprocessingRecord);
+}
+
+struct ParseTranslationUnitInfo {
+ CXIndex CIdx;
+ const char *source_filename;
+ const char *const *command_line_args;
+ int num_command_line_args;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned num_unsaved_files;
+ unsigned options;
+ CXTranslationUnit result;
+};
+static void clang_parseTranslationUnit_Impl(void *UserData) {
+ ParseTranslationUnitInfo *PTUI =
+ static_cast<ParseTranslationUnitInfo*>(UserData);
+ CXIndex CIdx = PTUI->CIdx;
+ const char *source_filename = PTUI->source_filename;
+ const char * const *command_line_args = PTUI->command_line_args;
+ int num_command_line_args = PTUI->num_command_line_args;
+ struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;
+ unsigned num_unsaved_files = PTUI->num_unsaved_files;
+ unsigned options = PTUI->options;
+ PTUI->result = 0;
+
if (!CIdx)
- return 0;
+ return;
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
+ bool CompleteTranslationUnit
+ = ((options & CXTranslationUnit_Incomplete) == 0);
+ bool CacheCodeCompetionResults
+ = options & CXTranslationUnit_CacheCompletionResults;
+
// Configure the diagnostics.
DiagnosticOptions DiagOpts;
llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
@@ -1195,8 +1851,13 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
Args.insert(Args.end(), command_line_args,
command_line_args + num_command_line_args);
- Args.push_back("-Xclang");
- Args.push_back("-detailed-preprocessing-record");
+
+ // Do we need the detailed preprocessing record?
+ if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ Args.push_back("-Xclang");
+ Args.push_back("-detailed-preprocessing-record");
+ }
+
unsigned NumErrors = Diags->getNumErrors();
#ifdef USE_CRASHTRACER
@@ -1210,7 +1871,10 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
CXXIdx->getOnlyLocalDecls(),
RemappedFiles.data(),
RemappedFiles.size(),
- /*CaptureDiagnostics=*/true));
+ /*CaptureDiagnostics=*/true,
+ PrecompilePreamble,
+ CompleteTranslationUnit,
+ CacheCodeCompetionResults));
if (NumErrors != Diags->getNumErrors()) {
// Make sure to check that 'Unit' is non-NULL.
@@ -1233,7 +1897,8 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
}
}
- return Unit.take();
+ PTUI->result = Unit.take();
+ return;
}
// Build up the arguments for invoking 'clang'.
@@ -1269,7 +1934,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
std::vector<llvm::sys::Path> TemporaryFiles;
std::vector<std::string> RemapArgs;
if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
- return 0;
+ return;
// The pointers into the elements of RemapArgs are stable because we
// won't be adding anything to RemapArgs after this point.
@@ -1300,9 +1965,12 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
TemporaryFiles.push_back(DiagnosticsFile);
argv.push_back("-fdiagnostics-binary");
- argv.push_back("-Xclang");
- argv.push_back("-detailed-preprocessing-record");
-
+ // Do we need the detailed preprocessing record?
+ if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ argv.push_back("-Xclang");
+ argv.push_back("-detailed-preprocessing-record");
+ }
+
// Add the null terminator.
argv.push_back(NULL);
@@ -1328,7 +1996,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
}
- ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, Diags,
+ ASTUnit *ATU = ASTUnit::LoadFromASTFile(astTmpFile, Diags,
CXXIdx->getOnlyLocalDecls(),
RemappedFiles.data(),
RemappedFiles.size(),
@@ -1373,7 +2041,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
// Make the translation unit responsible for destroying all temporary files.
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
ATU->addTemporaryFile(TemporaryFiles[i]);
- ATU->addTemporaryFile(llvm::sys::Path(ATU->getPCHFileName()));
+ ATU->addTemporaryFile(llvm::sys::Path(ATU->getASTFileName()));
} else {
// Destroy all of the temporary files now; they can't be referenced any
// longer.
@@ -1382,13 +2050,124 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
TemporaryFiles[i].eraseFromDisk();
}
- return ATU;
+ PTUI->result = ATU;
+}
+CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options) {
+ ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,
+ num_command_line_args, unsaved_files, num_unsaved_files,
+ options, 0 };
+ llvm::CrashRecoveryContext CRC;
+
+ if (!CRC.RunSafely(clang_parseTranslationUnit_Impl, &PTUI)) {
+ fprintf(stderr, "libclang: crash detected during parsing: {\n");
+ fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
+ fprintf(stderr, " 'command_line_args' : [");
+ for (int i = 0; i != num_command_line_args; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "'%s'", command_line_args[i]);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'unsaved_files' : [");
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
+ unsaved_files[i].Length);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'options' : %d,\n", options);
+ fprintf(stderr, "}\n");
+
+ return 0;
+ }
+
+ return PTUI.result;
+}
+
+unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
+ return CXSaveTranslationUnit_None;
+}
+
+int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
+ unsigned options) {
+ if (!TU)
+ return 1;
+
+ return static_cast<ASTUnit *>(TU)->Save(FileName);
}
void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
- if (CTUnit)
+ if (CTUnit) {
+ // If the translation unit has been marked as unsafe to free, just discard
+ // it.
+ if (static_cast<ASTUnit *>(CTUnit)->isUnsafeToFree())
+ return;
+
delete static_cast<ASTUnit *>(CTUnit);
+ }
+}
+
+unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
+ return CXReparse_None;
+}
+
+struct ReparseTranslationUnitInfo {
+ CXTranslationUnit TU;
+ unsigned num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned options;
+ int result;
+};
+static void clang_reparseTranslationUnit_Impl(void *UserData) {
+ ReparseTranslationUnitInfo *RTUI =
+ static_cast<ReparseTranslationUnitInfo*>(UserData);
+ CXTranslationUnit TU = RTUI->TU;
+ unsigned num_unsaved_files = RTUI->num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
+ unsigned options = RTUI->options;
+ (void) options;
+ RTUI->result = 1;
+
+ if (!TU)
+ return;
+
+ llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
+ RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
+ if (!static_cast<ASTUnit *>(TU)->Reparse(RemappedFiles.data(),
+ RemappedFiles.size()))
+ RTUI->result = 0;
}
+int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options) {
+ ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,
+ options, 0 };
+ llvm::CrashRecoveryContext CRC;
+
+ if (!CRC.RunSafely(clang_reparseTranslationUnit_Impl, &RTUI)) {
+ fprintf(stderr, "libclang: crash detected during reparsing\n");
+ static_cast<ASTUnit *>(TU)->setUnsafeToFree(true);
+ return 1;
+ }
+
+ return RTUI.result;
+}
+
CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
if (!CTUnit)
@@ -1574,18 +2353,8 @@ unsigned clang_visitChildren(CXCursor parent,
CXClientData client_data) {
ASTUnit *CXXUnit = getCursorASTUnit(parent);
- unsigned PCHLevel = Decl::MaxPCHLevel;
-
- // Set the PCHLevel to filter out unwanted decls if requested.
- if (CXXUnit->getOnlyLocalDecls()) {
- PCHLevel = 0;
-
- // If the main input was an AST, bump the level.
- if (CXXUnit->isMainFileAST())
- ++PCHLevel;
- }
-
- CursorVisitor CursorVis(CXXUnit, visitor, client_data, PCHLevel);
+ CursorVisitor CursorVis(CXXUnit, visitor, client_data,
+ CXXUnit->getMaxPCHLevel());
return CursorVis.VisitChildren(parent);
}
@@ -1603,6 +2372,9 @@ static CXString getDeclSpelling(Decl *D) {
// ObjCCategoryImplDecl returns the category name.
return createCXString(CIMP->getIdentifier()->getNameStart());
+ if (isa<UsingDirectiveDecl>(D))
+ return createCXString("");
+
llvm::SmallString<1024> S;
llvm::raw_svector_ostream os(S);
ND->printName(os);
@@ -1629,6 +2401,10 @@ CXString clang_getCursorSpelling(CXCursor C) {
assert(OID && "getCursorSpelling(): Missing protocol decl");
return createCXString(OID->getIdentifier()->getNameStart());
}
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ return createCXString(B->getType().getAsString());
+ }
case CXCursor_TypeRef: {
TypeDecl *Type = getCursorTypeRef(C).first;
assert(Type && "Missing type decl");
@@ -1636,6 +2412,19 @@ CXString clang_getCursorSpelling(CXCursor C) {
return createCXString(getCursorContext(C).getTypeDeclType(Type).
getAsString());
}
+ case CXCursor_TemplateRef: {
+ TemplateDecl *Template = getCursorTemplateRef(C).first;
+ assert(Template && "Missing template decl");
+
+ return createCXString(Template->getNameAsString());
+ }
+
+ case CXCursor_NamespaceRef: {
+ NamedDecl *NS = getCursorNamespaceRef(C).first;
+ assert(NS && "Missing namespace decl");
+
+ return createCXString(NS->getNameAsString());
+ }
default:
return createCXString("<not implemented>");
@@ -1715,6 +2504,10 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("ObjCClassRef");
case CXCursor_TypeRef:
return createCXString("TypeRef");
+ case CXCursor_TemplateRef:
+ return createCXString("TemplateRef");
+ case CXCursor_NamespaceRef:
+ return createCXString("NamespaceRef");
case CXCursor_UnexposedExpr:
return createCXString("UnexposedExpr");
case CXCursor_BlockExpr:
@@ -1757,6 +2550,32 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("Namespace");
case CXCursor_LinkageSpec:
return createCXString("LinkageSpec");
+ case CXCursor_CXXBaseSpecifier:
+ return createCXString("C++ base class specifier");
+ case CXCursor_Constructor:
+ return createCXString("CXXConstructor");
+ case CXCursor_Destructor:
+ return createCXString("CXXDestructor");
+ case CXCursor_ConversionFunction:
+ return createCXString("CXXConversion");
+ case CXCursor_TemplateTypeParameter:
+ return createCXString("TemplateTypeParameter");
+ case CXCursor_NonTypeTemplateParameter:
+ return createCXString("NonTypeTemplateParameter");
+ case CXCursor_TemplateTemplateParameter:
+ return createCXString("TemplateTemplateParameter");
+ case CXCursor_FunctionTemplate:
+ return createCXString("FunctionTemplate");
+ case CXCursor_ClassTemplate:
+ return createCXString("ClassTemplate");
+ case CXCursor_ClassTemplatePartialSpecialization:
+ return createCXString("ClassTemplatePartialSpecialization");
+ case CXCursor_NamespaceAlias:
+ return createCXString("NamespaceAlias");
+ case CXCursor_UsingDirective:
+ return createCXString("UsingDirective");
+ case CXCursor_UsingDeclaration:
+ return createCXString("UsingDeclaration");
}
llvm_unreachable("Unhandled CXCursorKind");
@@ -1776,20 +2595,28 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
return clang_getNullCursor();
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
-
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+ // Translate the given source location to make it point at the beginning of
+ // the token under the cursor.
SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
+
+ // Guard against an invalid SourceLocation, or we may assert in one
+ // of the following calls.
+ if (SLoc.isInvalid())
+ return clang_getNullCursor();
+
+ SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
+ CXXUnit->getASTContext().getLangOptions());
+
CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
if (SLoc.isValid()) {
- SourceRange RegionOfInterest(SLoc, SLoc.getFileLocWithOffset(1));
-
// FIXME: Would be great to have a "hint" cursor, then walk from that
// hint cursor upward until we find a cursor whose source range encloses
// the region of interest, rather than starting from the translation unit.
CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
CursorVisitor CursorVis(CXXUnit, GetCursorVisitor, &Result,
- Decl::MaxPCHLevel, RegionOfInterest);
+ Decl::MaxPCHLevel, SourceLocation(SLoc));
CursorVis.VisitChildren(Parent);
}
return Result;
@@ -1873,6 +2700,21 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
}
+ case CXCursor_TemplateRef: {
+ std::pair<TemplateDecl *, SourceLocation> P = getCursorTemplateRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_NamespaceRef: {
+ std::pair<NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_CXXBaseSpecifier: {
+ // FIXME: Figure out what location to return for a CXXBaseSpecifier.
+ return clang_getNullLocation();
+ }
+
default:
// FIXME: Need a way to enumerate all non-reference cases.
llvm_unreachable("Missed a reference kind");
@@ -1909,67 +2751,68 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
return cxloc::translateSourceLocation(getCursorContext(C), Loc);
}
-CXSourceRange clang_getCursorExtent(CXCursor C) {
+} // end extern "C"
+
+static SourceRange getRawCursorExtent(CXCursor C) {
if (clang_isReference(C.kind)) {
switch (C.kind) {
- case CXCursor_ObjCSuperClassRef: {
- std::pair<ObjCInterfaceDecl *, SourceLocation> P
- = getCursorObjCSuperClassRef(C);
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_ObjCSuperClassRef:
+ return getCursorObjCSuperClassRef(C).second;
- case CXCursor_ObjCProtocolRef: {
- std::pair<ObjCProtocolDecl *, SourceLocation> P
- = getCursorObjCProtocolRef(C);
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_ObjCProtocolRef:
+ return getCursorObjCProtocolRef(C).second;
- case CXCursor_ObjCClassRef: {
- std::pair<ObjCInterfaceDecl *, SourceLocation> P
- = getCursorObjCClassRef(C);
+ case CXCursor_ObjCClassRef:
+ return getCursorObjCClassRef(C).second;
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_TypeRef:
+ return getCursorTypeRef(C).second;
- case CXCursor_TypeRef: {
- std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_TemplateRef:
+ return getCursorTemplateRef(C).second;
+
+ case CXCursor_NamespaceRef:
+ return getCursorNamespaceRef(C).second;
+
+ case CXCursor_CXXBaseSpecifier:
+ // FIXME: Figure out what source range to use for a CXBaseSpecifier.
+ return SourceRange();
- default:
- // FIXME: Need a way to enumerate all non-reference cases.
- llvm_unreachable("Missed a reference kind");
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
}
}
if (clang_isExpression(C.kind))
- return cxloc::translateSourceRange(getCursorContext(C),
- getCursorExpr(C)->getSourceRange());
+ return getCursorExpr(C)->getSourceRange();
if (clang_isStatement(C.kind))
- return cxloc::translateSourceRange(getCursorContext(C),
- getCursorStmt(C)->getSourceRange());
+ return getCursorStmt(C)->getSourceRange();
- if (C.kind == CXCursor_PreprocessingDirective) {
- SourceRange R = cxcursor::getCursorPreprocessingDirective(C);
- return cxloc::translateSourceRange(getCursorContext(C), R);
- }
+ if (C.kind == CXCursor_PreprocessingDirective)
+ return cxcursor::getCursorPreprocessingDirective(C);
- if (C.kind == CXCursor_MacroInstantiation) {
- SourceRange R = cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
- return cxloc::translateSourceRange(getCursorContext(C), R);
- }
+ if (C.kind == CXCursor_MacroInstantiation)
+ return cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
- if (C.kind == CXCursor_MacroDefinition) {
- SourceRange R = cxcursor::getCursorMacroDefinition(C)->getSourceRange();
- return cxloc::translateSourceRange(getCursorContext(C), R);
- }
+ if (C.kind == CXCursor_MacroDefinition)
+ return cxcursor::getCursorMacroDefinition(C)->getSourceRange();
- if (C.kind < CXCursor_FirstDecl || C.kind > CXCursor_LastDecl)
+ if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl)
+ return getCursorDecl(C)->getSourceRange();
+
+ return SourceRange();
+}
+
+extern "C" {
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ SourceRange R = getRawCursorExtent(C);
+ if (R.isInvalid())
return clang_getNullRange();
- Decl *D = getCursorDecl(C);
- return cxloc::translateSourceRange(getCursorContext(C), D->getSourceRange());
+ return cxloc::translateSourceRange(getCursorContext(C), R);
}
CXCursor clang_getCursorReferenced(CXCursor C) {
@@ -2008,6 +2851,18 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
case CXCursor_TypeRef:
return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
+ case CXCursor_TemplateRef:
+ return MakeCXCursor(getCursorTemplateRef(C).first, CXXUnit);
+
+ case CXCursor_NamespaceRef:
+ return MakeCXCursor(getCursorNamespaceRef(C).first, CXXUnit);
+
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
+ return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
+ CXXUnit));
+ }
+
default:
// We would prefer to enumerate all non-reference cursor kinds here.
llvm_unreachable("Unhandled reference cursor kind");
@@ -2118,8 +2973,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::ClassTemplate: {
if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
->getDefinition())
- return MakeCXCursor(
- cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
+ return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
CXXUnit);
return clang_getNullCursor();
}
@@ -2530,8 +3384,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
return CXChildVisit_Recurse;
}
- CXSourceRange cursorExtent = clang_getCursorExtent(cursor);
- SourceRange cursorRange = cxloc::translateCXSourceRange(cursorExtent);
+ SourceRange cursorRange = getRawCursorExtent(cursor);
if (cursorRange.isInvalid())
return CXChildVisit_Continue;
@@ -2559,11 +3412,27 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
}
}
+ // If the location of the cursor occurs within a macro instantiation, record
+ // the spelling location of the cursor in our annotation map. We can then
+ // paper over the token labelings during a post-processing step to try and
+ // get cursor mappings for tokens that are the *arguments* of a macro
+ // instantiation.
+ if (L.isMacroID()) {
+ unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();
+ // Only invalidate the old annotation if it isn't part of a preprocessing
+ // directive. Here we assume that the default construction of CXCursor
+ // results in CXCursor.kind being an initialized value (i.e., 0). If
+ // this isn't the case, we can fix by doing lookup + insertion.
+
+ CXCursor &oldC = Annotated[rawEncoding];
+ if (!clang_isPreprocessing(oldC.kind))
+ oldC = cursor;
+ }
+
const enum CXCursorKind K = clang_getCursorKind(parent);
const CXCursor updateC =
- (clang_isInvalid(K) || K == CXCursor_TranslationUnit ||
- L.isMacroID())
- ? clang_getNullCursor() : parent;
+ (clang_isInvalid(K) || K == CXCursor_TranslationUnit)
+ ? clang_getNullCursor() : parent;
while (MoreTokens()) {
const unsigned I = NextToken();
@@ -2574,7 +3443,6 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
AdvanceToken();
continue;
case RangeAfter:
- return CXChildVisit_Continue;
case RangeOverlap:
break;
}
@@ -2658,11 +3526,9 @@ void clang_annotateTokens(CXTranslationUnit TU,
SourceRange RegionOfInterest;
RegionOfInterest.setBegin(cxloc::translateSourceLocation(
clang_getTokenLocation(TU, Tokens[0])));
-
- SourceLocation End
- = cxloc::translateSourceLocation(clang_getTokenLocation(TU,
- Tokens[NumTokens - 1]));
- RegionOfInterest.setEnd(CXXUnit->getPreprocessor().getLocForEndOfToken(End));
+ RegionOfInterest.setEnd(cxloc::translateSourceLocation(
+ clang_getTokenLocation(TU,
+ Tokens[NumTokens - 1])));
// A mapping from the source locations found when re-lexing or traversing the
// region of interest to the corresponding cursors.
@@ -2811,6 +3677,21 @@ static CXLanguageKind getDeclLanguage(const Decl *D) {
}
extern "C" {
+
+enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ if (Decl *D = cxcursor::getCursorDecl(cursor)) {
+ if (D->hasAttr<UnavailableAttr>() ||
+ (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()))
+ return CXAvailability_Available;
+
+ if (D->hasAttr<DeprecatedAttr>())
+ return CXAvailability_Deprecated;
+ }
+
+ return CXAvailability_Available;
+}
+
CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
if (clang_isDeclaration(cursor.kind))
return getDeclLanguage(cxcursor::getCursorDecl(cursor));
@@ -2828,13 +3709,35 @@ extern "C" {
unsigned clang_CXXMethod_isStatic(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return 0;
- CXXMethodDecl *D = dyn_cast<CXXMethodDecl>(cxcursor::getCursorDecl(C));
- return (D && D->isStatic()) ? 1 : 0;
+
+ CXXMethodDecl *Method = 0;
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = dyn_cast_or_null<CXXMethodDecl>(D);
+ return (Method && Method->isStatic()) ? 1 : 0;
}
} // end: extern "C"
//===----------------------------------------------------------------------===//
+// Attribute introspection.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXType clang_getIBOutletCollectionType(CXCursor C) {
+ if (C.kind != CXCursor_IBOutletCollectionAttr)
+ return cxtype::MakeCXType(QualType(), cxcursor::getCursorASTUnit(C));
+
+ IBOutletCollectionAttr *A =
+ cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
+
+ return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorASTUnit(C));
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
// CXString Operations.
//===----------------------------------------------------------------------===//
diff --git a/tools/libclang/CIndexCXX.cpp b/tools/libclang/CIndexCXX.cpp
new file mode 100644
index 000000000000..3ade5195d8f8
--- /dev/null
+++ b/tools/libclang/CIndexCXX.cpp
@@ -0,0 +1,124 @@
+//===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
+//
+// 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 libclang support for C++ cursors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "CXType.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+
+using namespace clang;
+using namespace clang::cxstring;
+using namespace clang::cxcursor;
+
+extern "C" {
+
+unsigned clang_isVirtualBase(CXCursor C) {
+ if (C.kind != CXCursor_CXXBaseSpecifier)
+ return 0;
+
+ CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ return B->isVirtual();
+}
+
+enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
+ if (C.kind != CXCursor_CXXBaseSpecifier)
+ return CX_CXXInvalidAccessSpecifier;
+
+ CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ switch (B->getAccessSpecifier()) {
+ case AS_public: return CX_CXXPublic;
+ case AS_protected: return CX_CXXProtected;
+ case AS_private: return CX_CXXPrivate;
+ case AS_none: return CX_CXXInvalidAccessSpecifier;
+ }
+
+ // FIXME: Clang currently thinks this is reachable.
+ return CX_CXXInvalidAccessSpecifier;
+}
+
+enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
+ using namespace clang::cxcursor;
+
+ switch (C.kind) {
+ case CXCursor_ClassTemplate:
+ case CXCursor_FunctionTemplate:
+ if (TemplateDecl *Template
+ = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
+ return MakeCXCursor(Template->getTemplatedDecl(),
+ getCursorASTUnit(C)).kind;
+ break;
+
+ case CXCursor_ClassTemplatePartialSpecialization:
+ if (ClassTemplateSpecializationDecl *PartialSpec
+ = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
+ getCursorDecl(C))) {
+ switch (PartialSpec->getTagKind()) {
+ case TTK_Class: return CXCursor_ClassDecl;
+ case TTK_Struct: return CXCursor_StructDecl;
+ case TTK_Union: return CXCursor_UnionDecl;
+ case TTK_Enum: return CXCursor_NoDeclFound;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return CXCursor_NoDeclFound;
+}
+
+CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullCursor();
+
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+
+ Decl *Template = 0;
+ if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
+ if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
+ Template = PartialSpec->getSpecializedTemplate();
+ else if (ClassTemplateSpecializationDecl *ClassSpec
+ = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *> Result
+ = ClassSpec->getSpecializedTemplateOrPartial();
+ if (Result.is<ClassTemplateDecl *>())
+ Template = Result.get<ClassTemplateDecl *>();
+ else
+ Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
+
+ } else
+ Template = CXXRecord->getInstantiatedFromMemberClass();
+ } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
+ Template = Function->getPrimaryTemplate();
+ if (!Template)
+ Template = Function->getInstantiatedFromMemberFunction();
+ } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ if (Var->isStaticDataMember())
+ Template = Var->getInstantiatedFromStaticDataMember();
+ } else if (RedeclarableTemplateDecl *Tmpl
+ = dyn_cast<RedeclarableTemplateDecl>(D))
+ Template = Tmpl->getInstantiatedFromMemberTemplate();
+
+ if (!Template)
+ return clang_getNullCursor();
+
+ return MakeCXCursor(Template, getCursorASTUnit(C));
+}
+
+} // end extern "C"
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 277fadf683bc..d591c5defb2e 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -16,18 +16,23 @@
#include "CIndexDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Program.h"
+#include <cstdlib>
+#include <cstdio>
+
#ifdef UDP_CODE_COMPLETION_LOGGER
#include "clang/Basic/Version.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -43,11 +48,15 @@ namespace {
/// This is the representation behind a CXCompletionString.
class CXStoredCodeCompletionString : public CodeCompletionString {
unsigned Priority;
+ CXAvailabilityKind Availability;
public:
- CXStoredCodeCompletionString(unsigned Priority) : Priority(Priority) { }
+ CXStoredCodeCompletionString(unsigned Priority,
+ CXAvailabilityKind Availability)
+ : Priority(Priority), Availability(Availability) { }
unsigned getPriority() const { return Priority; }
+ CXAvailabilityKind getAvailability() const { return Availability; }
};
}
@@ -205,6 +214,13 @@ unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
}
+enum CXAvailabilityKind
+clang_getCompletionAvailability(CXCompletionString completion_string) {
+ CXStoredCodeCompletionString *CCStr
+ = (CXStoredCodeCompletionString *)completion_string;
+ return CCStr? CCStr->getAvailability() : CXAvailability_Available;
+}
+
static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
unsigned &Value) {
if (Memory + sizeof(unsigned) > MemoryEnd)
@@ -221,15 +237,11 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
AllocatedCXCodeCompleteResults();
~AllocatedCXCodeCompleteResults();
- /// \brief The memory buffer from which we parsed the results. We
- /// retain this buffer because the completion strings point into it.
- llvm::MemoryBuffer *Buffer;
-
/// \brief Diagnostics produced while performing code completion.
llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
/// \brief Diag object
- Diagnostic Diag;
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diag;
/// \brief Language options used to adjust source locations.
LangOptions LangOpts;
@@ -243,25 +255,29 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// \brief Temporary files that should be removed once we have finished
/// with the code-completion results.
std::vector<llvm::sys::Path> TemporaryFiles;
+
+ /// \brief Temporary buffers that will be deleted once we have finished with the code-completion results.
+ llvm::SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
};
AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
- : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
+ : CXCodeCompleteResults(), Diag(new Diagnostic), SourceMgr(*Diag) { }
AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
for (unsigned I = 0, N = NumResults; I != N; ++I)
delete (CXStoredCodeCompletionString *)Results[I].CompletionString;
delete [] Results;
- delete Buffer;
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
TemporaryFiles[I].eraseFromDisk();
+ for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
+ delete TemporaryBuffers[I];
}
CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
- const char **command_line_args,
+ const char * const *command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
const char *complete_filename,
@@ -273,6 +289,17 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
#endif
#endif
+ bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0;
+
+ llvm::OwningPtr<llvm::NamedRegionTimer> CCTimer;
+ if (getenv("LIBCLANG_TIMING")) {
+ llvm::SmallString<128> TimerName;
+ llvm::raw_svector_ostream TimerNameOut(TimerName);
+ TimerNameOut << "Code completion (out-of-process) @ " << complete_filename
+ << ":" << complete_line << ":" << complete_column;
+ CCTimer.reset(new llvm::NamedRegionTimer(TimerNameOut.str()));
+ }
+
// The indexer, which is mainly used to determine where diagnostics go.
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
@@ -348,6 +375,15 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
argv.push_back(arg);
}
+ if (EnableLogging) {
+ std::string Log = ClangPath.str();
+ for (unsigned I = 0, N = argv.size(); I != N; ++I) {
+ Log += ' ';
+ Log += argv[I];
+ }
+ fprintf(stderr, "libclang (Code Completion): %s\n", Log.c_str());
+ }
+
// Add the null terminator.
argv.push_back(NULL);
@@ -363,6 +399,8 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
TemporaryFiles.push_back(DiagnosticsFile);
+
+
// Invoke 'clang'.
llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
// on Unix or NUL (Windows).
@@ -392,7 +430,6 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
Results->Results = 0;
Results->NumResults = 0;
- Results->Buffer = 0;
// FIXME: Set Results->LangOpts!
if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
@@ -407,8 +444,13 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
if (ReadUnsigned(Str, StrEnd, Priority))
break;
+ unsigned Availability;
+ if (ReadUnsigned(Str, StrEnd, Availability))
+ break;
+
CXStoredCodeCompletionString *CCStr
- = new CXStoredCodeCompletionString(Priority);
+ = new CXStoredCodeCompletionString(Priority,
+ (CXAvailabilityKind)Availability);
if (!CCStr->Deserialize(Str, StrEnd)) {
delete CCStr;
continue;
@@ -428,7 +470,7 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
Results->NumResults = CompletionResults.size();
memcpy(Results->Results, CompletionResults.data(),
CompletionResults.size() * sizeof(CXCompletionResult));
- Results->Buffer = F;
+ Results->TemporaryBuffers.push_back(F);
}
LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
@@ -511,9 +553,208 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
}
#endif
#endif
+ clang_sortCodeCompletionResults(Results->Results, Results->NumResults);
return Results;
}
+} // end extern "C"
+
+namespace {
+ class CaptureCompletionResults : public CodeCompleteConsumer {
+ AllocatedCXCodeCompleteResults &AllocatedResults;
+
+ public:
+ explicit CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
+ : CodeCompleteConsumer(true, false, true, false),
+ AllocatedResults(Results) { }
+
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {
+ AllocatedResults.Results = new CXCompletionResult [NumResults];
+ AllocatedResults.NumResults = NumResults;
+ for (unsigned I = 0; I != NumResults; ++I) {
+ CXStoredCodeCompletionString *StoredCompletion
+ = new CXStoredCodeCompletionString(Results[I].Priority,
+ Results[I].Availability);
+ (void)Results[I].CreateCodeCompletionString(S, StoredCompletion);
+ AllocatedResults.Results[I].CursorKind = Results[I].CursorKind;
+ AllocatedResults.Results[I].CompletionString = StoredCompletion;
+ }
+ }
+
+ // FIXME: Add ProcessOverloadCandidates?
+ };
+}
+
+extern "C" {
+struct CodeCompleteAtInfo {
+ CXTranslationUnit TU;
+ const char *complete_filename;
+ unsigned complete_line;
+ unsigned complete_column;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned num_unsaved_files;
+ unsigned options;
+ CXCodeCompleteResults *result;
+};
+void clang_codeCompleteAt_Impl(void *UserData) {
+ CodeCompleteAtInfo *CCAI = static_cast<CodeCompleteAtInfo*>(UserData);
+ CXTranslationUnit TU = CCAI->TU;
+ const char *complete_filename = CCAI->complete_filename;
+ unsigned complete_line = CCAI->complete_line;
+ unsigned complete_column = CCAI->complete_column;
+ struct CXUnsavedFile *unsaved_files = CCAI->unsaved_files;
+ unsigned num_unsaved_files = CCAI->num_unsaved_files;
+ unsigned options = CCAI->options;
+ CCAI->result = 0;
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
+#endif
+#endif
+
+ bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != 0;
+
+ ASTUnit *AST = static_cast<ASTUnit *>(TU);
+ if (!AST)
+ return;
+
+ // Perform the remapping of source files.
+ llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
+ RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
+ if (EnableLogging) {
+ // FIXME: Add logging.
+ }
+
+ // Parse the resulting source file to find code-completion results.
+ AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
+ Results->Results = 0;
+ Results->NumResults = 0;
+
+ // Create a code-completion consumer to capture the results.
+ CaptureCompletionResults Capture(*Results);
+
+ // Perform completion.
+ AST->CodeComplete(complete_filename, complete_line, complete_column,
+ RemappedFiles.data(), RemappedFiles.size(),
+ (options & CXCodeComplete_IncludeMacros),
+ (options & CXCodeComplete_IncludeCodePatterns),
+ Capture,
+ *Results->Diag, Results->LangOpts, Results->SourceMgr,
+ Results->FileMgr, Results->Diagnostics,
+ Results->TemporaryBuffers);
+
+
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
+ llvm::SmallString<256> LogResult;
+ llvm::raw_svector_ostream os(LogResult);
+
+ // Figure out the language and whether or not it uses PCH.
+ const char *lang = 0;
+ bool usesPCH = false;
+
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I != E; ++I) {
+ if (*I == 0)
+ continue;
+ if (strcmp(*I, "-x") == 0) {
+ if (I + 1 != E) {
+ lang = *(++I);
+ continue;
+ }
+ }
+ else if (strcmp(*I, "-include") == 0) {
+ if (I+1 != E) {
+ const char *arg = *(++I);
+ llvm::SmallString<512> pchName;
+ {
+ llvm::raw_svector_ostream os(pchName);
+ os << arg << ".pth";
+ }
+ pchName.push_back('\0');
+ struct stat stat_results;
+ if (stat(pchName.data(), &stat_results) == 0)
+ usesPCH = true;
+ continue;
+ }
+ }
+ }
+
+ os << "{ ";
+ os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
+ os << ", \"numRes\": " << Results->NumResults;
+ os << ", \"diags\": " << Results->Diagnostics.size();
+ os << ", \"pch\": " << (usesPCH ? "true" : "false");
+ os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
+ const char *name = getlogin();
+ os << ", \"user\": \"" << (name ? name : "unknown") << '"';
+ os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
+ os << " }";
+
+ llvm::StringRef res = os.str();
+ if (res.size() > 0) {
+ do {
+ // Setup the UDP socket.
+ struct sockaddr_in servaddr;
+ bzero(&servaddr, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
+ if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
+ &servaddr.sin_addr) <= 0)
+ break;
+
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ break;
+
+ sendto(sockfd, res.data(), res.size(), 0,
+ (struct sockaddr *)&servaddr, sizeof(servaddr));
+ close(sockfd);
+ }
+ while (false);
+ }
+#endif
+#endif
+ CCAI->result = Results;
+}
+CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options) {
+ CodeCompleteAtInfo CCAI = { TU, complete_filename, complete_line,
+ complete_column, unsaved_files, num_unsaved_files,
+ options, 0 };
+ llvm::CrashRecoveryContext CRC;
+
+ if (!CRC.RunSafely(clang_codeCompleteAt_Impl, &CCAI)) {
+ fprintf(stderr, "libclang: crash detected in code completion\n");
+ static_cast<ASTUnit *>(TU)->setUnsafeToFree(true);
+ return 0;
+ }
+
+ return CCAI.result;
+}
+
+unsigned clang_defaultCodeCompleteOptions(void) {
+ return CXCodeComplete_IncludeMacros;
+}
+
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
if (!ResultsIn)
return;
@@ -522,7 +763,7 @@ void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
= static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
delete Results;
}
-
+
unsigned
clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
AllocatedCXCodeCompleteResults *Results
@@ -546,3 +787,36 @@ clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
} // end extern "C"
+
+namespace {
+ struct OrderCompletionResults {
+ bool operator()(const CXCompletionResult &XR,
+ const CXCompletionResult &YR) const {
+ CXStoredCodeCompletionString *X
+ = (CXStoredCodeCompletionString *)XR.CompletionString;
+ CXStoredCodeCompletionString *Y
+ = (CXStoredCodeCompletionString *)YR.CompletionString;
+
+ const char *XText = X->getTypedText();
+ const char *YText = Y->getTypedText();
+ if (!XText || !YText)
+ return XText != 0;
+
+ int result = llvm::StringRef(XText).compare_lower(YText);
+ if (result < 0)
+ return true;
+ if (result > 0)
+ return false;
+
+ result = llvm::StringRef(XText).compare(YText);
+ return result;
+ }
+ };
+}
+
+extern "C" {
+ void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+ unsigned NumResults) {
+ std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
+ }
+}
diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp
index 3db37b97da14..531992efebce 100644
--- a/tools/libclang/CIndexDiagnostic.cpp
+++ b/tools/libclang/CIndexDiagnostic.cpp
@@ -204,26 +204,13 @@ CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
if (ReplacementRange) {
- if (Hint.RemoveRange.isInvalid()) {
- // Create an empty range that refers to a single source
- // location (which is the insertion point).
- CXSourceRange Range = {
- { (void *)&StoredDiag->Diag.getLocation().getManager(),
- (void *)&StoredDiag->LangOpts },
- Hint.InsertionLoc.getRawEncoding(),
- Hint.InsertionLoc.getRawEncoding()
- };
-
- *ReplacementRange = Range;
- } else {
- // Create a range that covers the entire replacement (or
- // removal) range, adjusting the end of the range to point to
- // the end of the token.
- *ReplacementRange
- = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
- StoredDiag->LangOpts,
- Hint.RemoveRange);
- }
+ // Create a range that covers the entire replacement (or
+ // removal) range, adjusting the end of the range to point to
+ // the end of the token.
+ *ReplacementRange
+ = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ Hint.RemoveRange);
}
return createCXString(Hint.CodeToInsert);
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index e98fd262a712..8f3dacfad218 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -13,6 +13,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Lex/PreprocessingRecord.h"
@@ -64,6 +65,9 @@ public:
void VisitFunctionDecl(FunctionDecl *D);
void VisitNamedDecl(NamedDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitObjCClassDecl(ObjCClassDecl *CD);
void VisitObjCContainerDecl(ObjCContainerDecl *CD);
void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P);
@@ -72,12 +76,26 @@ public:
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitTagDecl(TagDecl *D);
void VisitTypedefDecl(TypedefDecl *D);
+ void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
void VisitVarDecl(VarDecl *D);
+ void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
void VisitLinkageSpecDecl(LinkageSpecDecl *D) {
IgnoreResults = true;
- return;
}
-
+ void VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUsingDecl(UsingDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ IgnoreResults = true;
+ }
+ void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+ IgnoreResults = true;
+ }
+
/// Generate the string component containing the location of the
/// declaration.
bool GenLoc(const Decl *D);
@@ -104,7 +122,10 @@ public:
void GenObjCProtocol(llvm::StringRef prot);
void VisitType(QualType T);
-
+ void VisitTemplateParameterList(const TemplateParameterList *Params);
+ void VisitTemplateName(TemplateName Name);
+ void VisitTemplateArgument(const TemplateArgument &Arg);
+
/// Emit a Decl's name using NamedDecl::printName() and return true if
/// the decl had no name.
bool EmitDeclName(const NamedDecl *D);
@@ -155,7 +176,11 @@ void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
return;
VisitDeclContext(D->getDeclContext());
- Out << "@F@";
+ if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) {
+ Out << "@FT@";
+ VisitTemplateParameterList(FunTmpl->getTemplateParameters());
+ } else
+ Out << "@F@";
D->printName(Out);
ASTContext &Ctx = AU->getASTContext();
@@ -207,7 +232,7 @@ void USRGenerator::VisitVarDecl(VarDecl *D) {
// The string can be empty if the declaration has no name; e.g., it is
// the ParmDecl with no name for declaration of a function pointer type, e.g.:
- // void (*f)(void *);
+ // void (*f)(void *);
// In this case, don't generate a USR.
if (s.empty())
IgnoreResults = true;
@@ -215,6 +240,16 @@ void USRGenerator::VisitVarDecl(VarDecl *D) {
Out << '@' << s;
}
+void USRGenerator::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
+void USRGenerator::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
if (D->isAnonymousNamespace()) {
Out << "@aN";
@@ -226,8 +261,35 @@ void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
Out << "@N@" << D->getName();
}
+void USRGenerator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ VisitFunctionDecl(D->getTemplatedDecl());
+}
+
+void USRGenerator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ VisitTagDecl(D->getTemplatedDecl());
+}
+
+void USRGenerator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ if (!IgnoreResults)
+ Out << "@NA@" << D->getName();
+}
+
void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
- Visit(cast<Decl>(D->getDeclContext()));
+ Decl *container = cast<Decl>(D->getDeclContext());
+
+ // The USR for a method declared in a class extension is based on
+ // the ObjCInterfaceDecl, not the ObjCCategoryDecl.
+ do {
+ if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(container))
+ if (CD->IsClassExtension()) {
+ Visit(CD->getClassInterface());
+ break;
+ }
+ Visit(cast<Decl>(D->getDeclContext()));
+ }
+ while (false);
+
// Ideally we would use 'GenObjCMethod', but this is such a hot path
// for Objective-C code that we don't want to use
// DeclarationName::getAsString().
@@ -267,7 +329,15 @@ void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
IgnoreResults = true;
return;
}
- GenObjCCategory(ID->getName(), CD->getName());
+ // Specially handle class extensions, which are anonymous categories.
+ // We want to mangle in the location to uniquely distinguish them.
+ if (CD->IsClassExtension()) {
+ Out << "objc(ext)" << ID->getName() << '@';
+ GenLoc(CD);
+ }
+ else
+ GenObjCCategory(ID->getName(), CD->getName());
+
break;
}
case Decl::ObjCCategoryImpl: {
@@ -313,13 +383,41 @@ void USRGenerator::VisitTagDecl(TagDecl *D) {
D = D->getCanonicalDecl();
VisitDeclContext(D->getDeclContext());
- switch (D->getTagKind()) {
- case TTK_Struct: Out << "@S"; break;
- case TTK_Class: Out << "@C"; break;
- case TTK_Union: Out << "@U"; break;
- case TTK_Enum: Out << "@E"; break;
+ bool AlreadyStarted = false;
+ if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
+ if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) {
+ AlreadyStarted = true;
+
+ switch (D->getTagKind()) {
+ case TTK_Struct: Out << "@ST"; break;
+ case TTK_Class: Out << "@CT"; break;
+ case TTK_Union: Out << "@UT"; break;
+ case TTK_Enum: llvm_unreachable("enum template"); break;
+ }
+ VisitTemplateParameterList(ClassTmpl->getTemplateParameters());
+ } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) {
+ AlreadyStarted = true;
+
+ switch (D->getTagKind()) {
+ case TTK_Struct: Out << "@SP"; break;
+ case TTK_Class: Out << "@CP"; break;
+ case TTK_Union: Out << "@UP"; break;
+ case TTK_Enum: llvm_unreachable("enum partial specialization"); break;
+ }
+ VisitTemplateParameterList(PartialSpec->getTemplateParameters());
+ }
}
-
+
+ if (!AlreadyStarted) {
+ switch (D->getTagKind()) {
+ case TTK_Struct: Out << "@S"; break;
+ case TTK_Class: Out << "@C"; break;
+ case TTK_Union: Out << "@U"; break;
+ case TTK_Enum: Out << "@E"; break;
+ }
+ }
+
Out << '@';
Out.flush();
assert(Buf.size() > 0);
@@ -333,6 +431,17 @@ void USRGenerator::VisitTagDecl(TagDecl *D) {
else
Buf[off] = 'a';
}
+
+ // For a class template specialization, mangle the template arguments.
+ if (ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs();
+ Out << '>';
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ Out << '#';
+ VisitTemplateArgument(Args.get(I));
+ }
+ }
}
void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
@@ -345,6 +454,11 @@ void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
Out << D->getName();
}
+void USRGenerator::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ GenLoc(D);
+ return;
+}
+
bool USRGenerator::GenLoc(const Decl *D) {
if (generatedLoc)
return IgnoreResults;
@@ -368,10 +482,10 @@ bool USRGenerator::GenLoc(const Decl *D) {
IgnoreResults = true;
return true;
}
- Out << '@'
- << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':'
- << SM.getColumnNumber(Decomposed.first, Decomposed.second);
-
+ // Use the offest into the FileID to represent the location. Using
+ // a line/column can cause us to look back at the original source file,
+ // which is expensive.
+ Out << '@' << Decomposed.second;
return IgnoreResults;
}
@@ -494,13 +608,100 @@ void USRGenerator::VisitType(QualType T) {
VisitTagDecl(TT->getDecl());
return;
}
-
+ if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+ if (const TemplateSpecializationType *Spec
+ = T->getAs<TemplateSpecializationType>()) {
+ Out << '>';
+ VisitTemplateName(Spec->getTemplateName());
+ Out << Spec->getNumArgs();
+ for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I)
+ VisitTemplateArgument(Spec->getArg(I));
+ return;
+ }
+
// Unhandled type.
Out << ' ';
break;
} while (true);
}
+void USRGenerator::VisitTemplateParameterList(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return;
+ Out << '>' << Params->size();
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ Out << '#';
+ if (isa<TemplateTypeParmDecl>(*P)) {
+ Out << 'T';
+ continue;
+ }
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
+ Out << 'N';
+ VisitType(NTTP->getType());
+ continue;
+ }
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
+ Out << 't';
+ VisitTemplateParameterList(TTP->getTemplateParameters());
+ }
+}
+
+void USRGenerator::VisitTemplateName(TemplateName Name) {
+ if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+ if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Template)) {
+ Out << 't' << TTP->getDepth() << '.' << TTP->getIndex();
+ return;
+ }
+
+ Visit(Template);
+ return;
+ }
+
+ // FIXME: Visit dependent template names.
+}
+
+void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ break;
+
+ case TemplateArgument::Declaration:
+ Visit(Arg.getAsDecl());
+ break;
+
+ case TemplateArgument::Template:
+ VisitTemplateName(Arg.getAsTemplate());
+ break;
+
+ case TemplateArgument::Expression:
+ // FIXME: Visit expressions.
+ break;
+
+ case TemplateArgument::Pack:
+ // FIXME: Variadic templates
+ break;
+
+ case TemplateArgument::Type:
+ VisitType(Arg.getAsType());
+ break;
+
+ case TemplateArgument::Integral:
+ Out << 'V';
+ VisitType(Arg.getIntegralType());
+ Out << *Arg.getAsIntegral();
+ break;
+ }
+}
+
//===----------------------------------------------------------------------===//
// General purpose USR generation methods.
//===----------------------------------------------------------------------===//
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index ab4accae5e27..29ef574fff6a 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -5,10 +5,11 @@ set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangFrontend
clangDriver
+ clangSerialization
+ clangParse
clangSema
clangAnalysis
clangAST
- clangParse
clangLex
clangBasic)
@@ -20,28 +21,34 @@ set( LLVM_LINK_COMPONENTS
add_clang_library(libclang
CIndex.cpp
+ CIndexCXX.cpp
CIndexCodeCompletion.cpp
CIndexDiagnostic.cpp
CIndexInclusionStack.cpp
CIndexUSRs.cpp
CIndexer.cpp
CXCursor.cpp
- CXTypes.cpp
+ CXType.cpp
../../include/clang-c/Index.h
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- # FIXME: Deal with LLVM_SUBMIT_VERSION?
+ # dylib versioning information
+ # FIXME: Is there a more CMake-ish way to handle this?
+ set(LIBCLANG_VERSION 1
+ CACHE STRING "Version number of the libclang library")
+ set(LIBCLANG_SUBVERSION 0
+ CACHE STRING "Minor version number of the libclang library")
+ set(LIBCLANG_LINK_FLAGS
+ "-Wl,-current_version -Wl,${LIBCLANG_VERSION}.${LIBCLANG_SUBVERSION} -Wl,-compatibility_version -Wl,1")
+
+ set(LIBCLANG_LINK_FLAGS
+ "${LIBCLANG_LINK_FLAGS} -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000")
- # FIXME: This uses a special darwin-specific exports file in order to
- # get underscore-prefixed names. It would be better to have build rules
- # which know how to produce a darwin-suitable exports file from the
- # regular exports file.
set_target_properties(libclang
PROPERTIES
- LINK_FLAGS "-avoid-version -Wl,-exported_symbols_list -Wl,${CMAKE_CURRENT_SOURCE_DIR}/libclang.darwin.exports -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000"
- INSTALL_NAME_DIR "@executable_path/../lib"
- )
+ LINK_FLAGS "${LIBCLANG_LINK_FLAGS}"
+ INSTALL_NAME_DIR "@executable_path/../lib")
endif()
if(MSVC)
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index be3623f6e9e2..a8fd049c9965 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -16,6 +16,7 @@
#include "CXCursor.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "llvm/Support/ErrorHandling.h"
@@ -28,52 +29,6 @@ CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
return C;
}
-static CXCursorKind GetCursorKind(Decl *D) {
- assert(D && "Invalid arguments!");
- switch (D->getKind()) {
- case Decl::Enum: return CXCursor_EnumDecl;
- case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
- case Decl::Field: return CXCursor_FieldDecl;
- case Decl::Function:
- return CXCursor_FunctionDecl;
- case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
- case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
- case Decl::ObjCClass:
- // FIXME
- return CXCursor_UnexposedDecl;
- case Decl::ObjCForwardProtocol:
- // FIXME
- return CXCursor_UnexposedDecl;
- case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
- case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
- case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
- case Decl::ObjCMethod:
- return cast<ObjCMethodDecl>(D)->isInstanceMethod()
- ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
- case Decl::CXXMethod: return CXCursor_CXXMethod;
- case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
- case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
- case Decl::ParmVar: return CXCursor_ParmDecl;
- case Decl::Typedef: return CXCursor_TypedefDecl;
- case Decl::Var: return CXCursor_VarDecl;
- case Decl::Namespace: return CXCursor_Namespace;
- default:
- if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- switch (TD->getTagKind()) {
- case TTK_Struct: return CXCursor_StructDecl;
- case TTK_Class: return CXCursor_ClassDecl;
- case TTK_Union: return CXCursor_UnionDecl;
- case TTK_Enum: return CXCursor_EnumDecl;
- }
- }
-
- return CXCursor_UnexposedDecl;
- }
-
- llvm_unreachable("Invalid Decl");
- return CXCursor_NotImplemented;
-}
-
static CXCursorKind GetCursorKind(const Attr *A) {
assert(A && "Invalid arguments!");
switch (A->getKind()) {
@@ -94,7 +49,7 @@ CXCursor cxcursor::MakeCXCursor(const Attr *A, Decl *Parent, ASTUnit *TU) {
CXCursor cxcursor::MakeCXCursor(Decl *D, ASTUnit *TU) {
assert(D && TU && "Invalid arguments!");
- CXCursor C = { GetCursorKind(D), { D, 0, TU } };
+ CXCursor C = { getCursorKindForDecl(D), { D, 0, TU } };
return C;
}
@@ -182,7 +137,6 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, ASTUnit *TU) {
case Stmt::UnaryTypeTraitExprClass:
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::CXXBindTemporaryExprClass:
- case Stmt::CXXBindReferenceExprClass:
case Stmt::CXXExprWithTemporariesClass:
case Stmt::CXXUnresolvedConstructExprClass:
case Stmt::CXXDependentScopeMemberExprClass:
@@ -302,6 +256,50 @@ cxcursor::getCursorTypeRef(CXCursor C) {
reinterpret_cast<uintptr_t>(C.data[1])));
}
+CXCursor cxcursor::MakeCursorTemplateRef(TemplateDecl *Template,
+ SourceLocation Loc, ASTUnit *TU) {
+ assert(Template && TU && "Invalid arguments!");
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_TemplateRef, { Template, RawLoc, TU } };
+ return C;
+}
+
+std::pair<TemplateDecl *, SourceLocation>
+cxcursor::getCursorTemplateRef(CXCursor C) {
+ assert(C.kind == CXCursor_TemplateRef);
+ return std::make_pair(static_cast<TemplateDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc,
+ ASTUnit *TU) {
+
+ assert(NS && (isa<NamespaceDecl>(NS) || isa<NamespaceAliasDecl>(NS)) && TU &&
+ "Invalid arguments!");
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_NamespaceRef, { NS, RawLoc, TU } };
+ return C;
+}
+
+std::pair<NamedDecl *, SourceLocation>
+cxcursor::getCursorNamespaceRef(CXCursor C) {
+ assert(C.kind == CXCursor_NamespaceRef);
+ return std::make_pair(static_cast<NamedDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU){
+ CXCursor C = { CXCursor_CXXBaseSpecifier, { B, 0, TU } };
+ return C;
+}
+
+CXXBaseSpecifier *cxcursor::getCursorCXXBaseSpecifier(CXCursor C) {
+ assert(C.kind == CXCursor_CXXBaseSpecifier);
+ return static_cast<CXXBaseSpecifier*>(C.data[0]);
+}
+
CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range,
ASTUnit *TU) {
CXCursor C = { CXCursor_PreprocessingDirective,
@@ -358,6 +356,10 @@ Stmt *cxcursor::getCursorStmt(CXCursor Cursor) {
return (Stmt *)Cursor.data[1];
}
+Attr *cxcursor::getCursorAttr(CXCursor Cursor) {
+ return (Attr *)Cursor.data[1];
+}
+
ASTContext &cxcursor::getCursorContext(CXCursor Cursor) {
return getCursorASTUnit(Cursor)->getASTContext();
}
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index 1664f5a9ced2..a5f111edc1d8 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -23,6 +23,7 @@ namespace clang {
class ASTContext;
class ASTUnit;
class Attr;
+class CXXBaseSpecifier;
class Decl;
class Expr;
class MacroDefinition;
@@ -31,6 +32,7 @@ class NamedDecl;
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class Stmt;
+class TemplateDecl;
class TypeDecl;
namespace cxcursor {
@@ -70,11 +72,33 @@ std::pair<ObjCInterfaceDecl *, SourceLocation>
/// \brief Create a type reference at the given location.
CXCursor MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, ASTUnit *TU);
-
+
/// \brief Unpack a TypeRef cursor into the class it references
/// and optionally the location where the reference occurred.
std::pair<TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
+/// \brief Create a reference to a template at the given location.
+CXCursor MakeCursorTemplateRef(TemplateDecl *Template, SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack a TemplateRef cursor into the template it references and
+/// the location where the reference occurred.
+std::pair<TemplateDecl *, SourceLocation> getCursorTemplateRef(CXCursor C);
+
+/// \brief Create a reference to a namespace or namespace alias at the given
+/// location.
+CXCursor MakeCursorNamespaceRef(NamedDecl *NS, SourceLocation Loc, ASTUnit *TU);
+
+/// \brief Unpack a NamespaceRef cursor into the namespace or namespace alias
+/// it references and the location where the reference occurred.
+std::pair<NamedDecl *, SourceLocation> getCursorNamespaceRef(CXCursor C);
+
+/// \brief Create a CXX base specifier cursor.
+CXCursor MakeCursorCXXBaseSpecifier(CXXBaseSpecifier *B, ASTUnit *TU);
+
+/// \brief Unpack a CXXBaseSpecifier cursor into a CXXBaseSpecifier.
+CXXBaseSpecifier *getCursorCXXBaseSpecifier(CXCursor C);
+
/// \brief Create a preprocessing directive cursor.
CXCursor MakePreprocessingDirectiveCursor(SourceRange Range, ASTUnit *TU);
@@ -98,6 +122,8 @@ MacroInstantiation *getCursorMacroInstantiation(CXCursor C);
Decl *getCursorDecl(CXCursor Cursor);
Expr *getCursorExpr(CXCursor Cursor);
Stmt *getCursorStmt(CXCursor Cursor);
+Attr *getCursorAttr(CXCursor Cursor);
+
ASTContext &getCursorContext(CXCursor Cursor);
ASTUnit *getCursorASTUnit(CXCursor Cursor);
diff --git a/tools/libclang/CXTypes.cpp b/tools/libclang/CXType.cpp
index d5c9f452100b..aa173cae32c0 100644
--- a/tools/libclang/CXTypes.cpp
+++ b/tools/libclang/CXType.cpp
@@ -13,6 +13,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
+#include "CXType.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
@@ -85,12 +86,15 @@ static CXTypeKind GetTypeKind(QualType T) {
#undef TKCASE
}
-static CXType MakeCXType(QualType T, ASTUnit *TU) {
+
+CXType cxtype::MakeCXType(QualType T, ASTUnit *TU) {
CXTypeKind TK = GetTypeKind(T);
CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
return CT;
}
+using cxtype::MakeCXType;
+
static inline QualType GetQualType(CXType CT) {
return QualType::getFromOpaquePtr(CT.data[0]);
}
@@ -283,4 +287,11 @@ CXType clang_getCursorResultType(CXCursor C) {
return MakeCXType(QualType(), cxcursor::getCursorASTUnit(C));
}
+unsigned clang_isPODType(CXType X) {
+ QualType T = GetQualType(X);
+ if (!T.getTypePtr())
+ return 0;
+ return T->isPODType() ? 1 : 0;
+}
+
} // end: extern "C"
diff --git a/tools/libclang/CXType.h b/tools/libclang/CXType.h
new file mode 100644
index 000000000000..94151ed6b98b
--- /dev/null
+++ b/tools/libclang/CXType.h
@@ -0,0 +1,29 @@
+//===- CXTypes.h - Routines for manipulating CXTypes ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CXTYPES_H
+#define LLVM_CLANG_CXTYPES_H
+
+#include "clang-c/Index.h"
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+class ASTUnit;
+
+namespace cxtype {
+
+CXType MakeCXType(QualType T, ASTUnit *TU);
+
+}} // end namespace clang::cxtype
+#endif
diff --git a/tools/libclang/Makefile b/tools/libclang/Makefile
index 253ea38c7b94..6d2a13cfc0b4 100644
--- a/tools/libclang/Makefile
+++ b/tools/libclang/Makefile
@@ -16,8 +16,8 @@ LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := bitreader mc core
-USEDLIBS = clangFrontend.a clangDriver.a clangSema.a \
- clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
+USEDLIBS = clangFrontend.a clangDriver.a clangSerialization.a clangParse.a \
+ clangSema.a clangAnalysis.a clangAST.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
@@ -26,23 +26,21 @@ include $(CLANG_LEVEL)/Makefile
##===----------------------------------------------------------------------===##
ifeq ($(HOST_OS),Darwin)
- # set dylib internal version number to llvmCore submission number
+ LLVMLibsOptions += -Wl,-compatibility_version,1
+
+ # Set dylib internal version number to submission number.
ifdef LLVM_SUBMIT_VERSION
- LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \
- -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
- -Wl,-compatibility_version -Wl,1
+ LLVMLibsOptions += -Wl,-current_version \
+ -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION)
endif
- # extra options to override libtool defaults
- LLVMLibsOptions := $(LLVMLibsOptions) \
- -avoid-version \
- -Wl,-dead_strip \
- -Wl,-seg1addr -Wl,0xE0000000
+
+ # Extra options to override libtool defaults.
+ LLVMLibsOptions += -Wl,-dead_strip -Wl,-seg1addr,0xE0000000
# Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
ifneq ($(DARWIN_VERS),8)
- LLVMLibsOptions := $(LLVMLibsOptions) \
- -no-undefined -Wl,-install_name \
- -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)"
+ LLVMLibsOptions += -Wl,-install_name \
+ -Wl,"@rpath/lib$(LIBRARYNAME)$(SHLIBEXT)"
endif
endif
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index f21fec63f48a..d1b45a248674 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -1,6 +1,7 @@
_clang_CXXMethod_isStatic
_clang_annotateTokens
_clang_codeComplete
+_clang_codeCompleteAt
_clang_codeCompleteGetDiagnostic
_clang_codeCompleteGetNumDiagnostics
_clang_constructUSR_ObjCCategory
@@ -12,7 +13,11 @@ _clang_constructUSR_ObjCProtocol
_clang_createIndex
_clang_createTranslationUnit
_clang_createTranslationUnitFromSourceFile
+_clang_defaultCodeCompleteOptions
_clang_defaultDiagnosticDisplayOptions
+_clang_defaultEditingTranslationUnitOptions
+_clang_defaultReparseOptions
+_clang_defaultSaveOptions
_clang_disposeCodeCompleteResults
_clang_disposeDiagnostic
_clang_disposeIndex
@@ -25,13 +30,16 @@ _clang_equalLocations
_clang_equalTypes
_clang_formatDiagnostic
_clang_getCString
+_clang_getCXXAccessSpecifier
_clang_getCanonicalType
_clang_getClangVersion
+_clang_getCompletionAvailability
_clang_getCompletionChunkCompletionString
_clang_getCompletionChunkKind
_clang_getCompletionChunkText
_clang_getCompletionPriority
_clang_getCursor
+_clang_getCursorAvailability
_clang_getCursorDefinition
_clang_getCursorExtent
_clang_getCursorKind
@@ -40,8 +48,8 @@ _clang_getCursorLanguage
_clang_getCursorLinkage
_clang_getCursorLocation
_clang_getCursorReferenced
-_clang_getCursorSpelling
_clang_getCursorResultType
+_clang_getCursorSpelling
_clang_getCursorType
_clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent
@@ -56,6 +64,7 @@ _clang_getDiagnosticSpelling
_clang_getFile
_clang_getFileName
_clang_getFileTime
+_clang_getIBOutletCollectionType
_clang_getInclusions
_clang_getInstantiationLocation
_clang_getLocation
@@ -69,6 +78,8 @@ _clang_getRange
_clang_getRangeEnd
_clang_getRangeStart
_clang_getResultType
+_clang_getSpecializedCursorTemplate
+_clang_getTemplateCursorKind
_clang_getTokenExtent
_clang_getTokenKind
_clang_getTokenLocation
@@ -81,11 +92,17 @@ _clang_isCursorDefinition
_clang_isDeclaration
_clang_isExpression
_clang_isInvalid
+_clang_isPODType
_clang_isPreprocessing
_clang_isReference
_clang_isStatement
_clang_isTranslationUnit
_clang_isUnexposed
+_clang_isVirtualBase
+_clang_parseTranslationUnit
+_clang_reparseTranslationUnit
+_clang_saveTranslationUnit
_clang_setUseExternalASTGeneration
+_clang_sortCodeCompletionResults
_clang_tokenize
_clang_visitChildren
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index dcb40d413ca9..0ea6993b218c 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -1,6 +1,7 @@
clang_CXXMethod_isStatic
clang_annotateTokens
clang_codeComplete
+clang_codeCompleteAt
clang_codeCompleteGetDiagnostic
clang_codeCompleteGetNumDiagnostics
clang_constructUSR_ObjCCategory
@@ -12,7 +13,11 @@ clang_constructUSR_ObjCProtocol
clang_createIndex
clang_createTranslationUnit
clang_createTranslationUnitFromSourceFile
+clang_defaultCodeCompleteOptions
clang_defaultDiagnosticDisplayOptions
+clang_defaultEditingTranslationUnitOptions
+clang_defaultReparseOptions
+clang_defaultSaveOptions
clang_disposeCodeCompleteResults
clang_disposeDiagnostic
clang_disposeIndex
@@ -25,13 +30,16 @@ clang_equalLocations
clang_equalTypes
clang_formatDiagnostic
clang_getCString
+clang_getCXXAccessSpecifier
clang_getCanonicalType
clang_getClangVersion
+clang_getCompletionAvailability
clang_getCompletionChunkCompletionString
clang_getCompletionChunkKind
clang_getCompletionChunkText
clang_getCompletionPriority
clang_getCursor
+clang_getCursorAvailability
clang_getCursorDefinition
clang_getCursorExtent
clang_getCursorKind
@@ -40,8 +48,8 @@ clang_getCursorLanguage
clang_getCursorLinkage
clang_getCursorLocation
clang_getCursorReferenced
-clang_getCursorSpelling
clang_getCursorResultType
+clang_getCursorSpelling
clang_getCursorType
clang_getCursorUSR
clang_getDefinitionSpellingAndExtent
@@ -56,6 +64,7 @@ clang_getDiagnosticSpelling
clang_getFile
clang_getFileName
clang_getFileTime
+clang_getIBOutletCollectionType
clang_getInclusions
clang_getInstantiationLocation
clang_getLocation
@@ -69,6 +78,8 @@ clang_getRange
clang_getRangeEnd
clang_getRangeStart
clang_getResultType
+clang_getSpecializedCursorTemplate
+clang_getTemplateCursorKind
clang_getTokenExtent
clang_getTokenKind
clang_getTokenLocation
@@ -81,11 +92,17 @@ clang_isCursorDefinition
clang_isDeclaration
clang_isExpression
clang_isInvalid
+clang_isPODType
clang_isPreprocessing
clang_isReference
clang_isStatement
clang_isTranslationUnit
clang_isUnexposed
+clang_isVirtualBase
+clang_parseTranslationUnit
+clang_reparseTranslationUnit
+clang_saveTranslationUnit
clang_setUseExternalASTGeneration
+clang_sortCodeCompletionResults
clang_tokenize
clang_visitChildren
diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl
index 5f37473a1f97..76e569d92aca 100644
--- a/www/analyzer/latest_checker.html.incl
+++ b/www/analyzer/latest_checker.html.incl
@@ -1 +1 @@
-<b><a href="/checker/checker-244.tar.bz2">checker-244.tar.bz2</a></b> (built July 8, 2010)
+<b><a href="/checker/checker-247.tar.bz2">checker-247.tar.bz2</a></b> (built July 30, 2010)
diff --git a/www/compatibility.html b/www/compatibility.html
index 0f8409b953a5..cf0d96e2f4ff 100644
--- a/www/compatibility.html
+++ b/www/compatibility.html
@@ -33,6 +33,7 @@
<ul>
<li><a href="#inline">C99 inline functions</a></li>
<li><a href="#lvalue-cast">Lvalue casts</a></li>
+ <li><a href="#blocks-in-protected-scope">Jumps to within <tt>__block</tt> variable scope</a></li>
</ul>
</li>
<li><a href="#objective-c">Objective-C compatibility</a>
@@ -58,6 +59,9 @@
<ul>
<li><a href="#implicit-downcasts">Implicit downcasts</a></li>
</ul>
+ <ul>
+ <li><a href="#Use of class as method name">Use of class as method name</a></li>
+ </ul>
</li>
</ul>
@@ -132,6 +136,55 @@ example, one could use:</p>
</pre>
<!-- ======================================================================= -->
+<h3 id="blocks-in-protected-scope">Jumps to within <tt>__block</tt> variable scope</h3>
+<!-- ======================================================================= -->
+
+<p>Clang disallows jumps into the scope of a <tt>__block</tt> variable, similar
+to the manner in which both GCC and Clang disallow jumps into the scope of
+variables which have user defined constructors (in C++).</p>
+
+<p>Variables marked with <tt>__block</tt> require special runtime initialization
+before they can be used. A jump into the scope of a <tt>__block</tt> variable
+would bypass this initialization and therefore the variable cannot safely be
+used.</p>
+
+<p>For example, consider the following code fragment:</p>
+
+<pre>
+int f0(int c) {
+ if (c)
+ goto error;
+
+ __block int x;
+ x = 1;
+ return x;
+
+ error:
+ x = 0;
+ return x;
+}
+</pre>
+
+<p>GCC accepts this code, but it will crash at runtime along the error path,
+because the runtime setup for the storage backing the <tt>x</tt> variable will
+not have been initialized. Clang rejects this code with a hard error:</p>
+
+<pre>
+t.c:3:5: error: goto into protected scope
+ goto error;
+ ^
+t.c:5:15: note: jump bypasses setup of __block variable
+ __block int x;
+ ^
+</pre>
+
+<p>Some instances of this construct may be safe if the variable is never used
+after the jump target, however the protected scope checker does not check the
+uses of the variable, only the scopes in which it is visible. You should rewrite
+your code to put the <tt>__block</tt> variables in a scope which is only visible
+where they are used.</p>
+
+<!-- ======================================================================= -->
<h2 id="objective-c">Objective-C compatibility</h3>
<!-- ======================================================================= -->
@@ -604,6 +657,28 @@ explicit cast:</p>
f((Derived *)base);
</pre>
+<!-- ======================================================================= -->
+<h3 id="Use of class as method name">Use of class as method name</h3>
+<!-- ======================================================================= -->
+
+<p>Use of 'class' name to declare a method is allowed in objective-c++ mode to
+be compatible with GCC. However, use of property dot syntax notation to call
+this method is not allowed in clang++, as [I class] is a suitable syntax that
+will work. So, this test will fail in clang++.
+
+<pre>
+@interface I {
+int cls;
+}
++ (int)class;
+@end
+
+@implementation I
+- (int) Meth { return I.class; }
+@end
+<pre>
+
+
</div>
</body>
</html>
diff --git a/www/cxx_status.html b/www/cxx_status.html
index 8fccc2a34137..7312c16b3bd9 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -24,7 +24,7 @@
<!--*************************************************************************-->
<h1>C++ and C++'0x Support in Clang</h1>
<!--*************************************************************************-->
-<p>Last updated: $Date: 2010-05-21 23:16:21 +0200 (Fri, 21 May 2010) $</p>
+<p>Last updated: $Date: 2010-08-26 16:20:18 +0200 (Thu, 26 Aug 2010) $</p>
<ul>
<li><a href="#projects">Projects Building with Clang</a></li>
@@ -70,7 +70,7 @@
<td><a href="http://blog.llvm.org/2010/05/clang-builds-boost.html">Compiles
and passes regression tests</a> on Darwin/X86-64.</td>
<td>May 20, 2010</td>
- <td><a href="http://llvm.org/bugs/show_bug.cgi?id=6023">PR6023</a></td>
+ <td><a href="http://llvm.org/bugs/show_bug.cgi?id=6023"><del>PR6023</del></a></td>
</tr>
<tr>
<td><a href="http://qt.nokia.com">Qt</a></td>
diff --git a/www/get_started.html b/www/get_started.html
index 96979af32d06..b64a5f285fb0 100644
--- a/www/get_started.html
+++ b/www/get_started.html
@@ -76,7 +76,7 @@ follows:</p>
hard-coded paths" in <tt>clang/lib/Frontend/InitHeaderSearch.cpp</tt> and
change the lines below to include that path.</li>
</ul>
- <li>Try it out (assuming you add llvm/Debug/bin to your path):</li>
+ <li>Try it out (assuming you add llvm/Debug+Asserts/bin to your path):</li>
<ul>
<li><tt>clang --help</tt></li>
<li><tt>clang file.c -fsyntax-only</tt> (check for correctness)</li>
diff --git a/www/hacking.html b/www/hacking.html
index 07a0d6c85bf5..7bd718ba3abc 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -26,6 +26,7 @@
<ul>
<li><a href="#testingNonWindows">Testing on Unix-like Systems</a></li>
<li><a href="#testingWindows">Testing using Visual Studio on Windows</a></li>
+ <li><a href="#testingCommands">Testing on the Command Line</a></li>
</ul>
<li><a href="#patches">Creating Patch Files</a></li>
<li><a href="#irgen">LLVM IR Generation</a></li>
@@ -172,6 +173,10 @@
run the test from Visual Studio, right-click the clang-test project
and select "Build".</p>
+ <!--=====================================================================-->
+ <h3 id="testingCommands">Testing on the Command Line</h3>
+ <!--=====================================================================-->
+
<p>To run all the tests from the command line, execute a command like
the following:</p>
diff --git a/www/menu.html.incl b/www/menu.html.incl
index d115088f2ed3..d828449ca256 100644
--- a/www/menu.html.incl
+++ b/www/menu.html.incl
@@ -8,7 +8,7 @@
<a href="/index.html">About</a>
<a href="/features.html">Features</a>
<a href="/comparison.html">Comparisons</a>
- <a href="/docs/UsersManual.html">Users Manual</a>
+ <a href="/docs/UsersManual.html">User's Manual</a>
<a href="/compatibility.html">Language&nbsp;Compatibility</a>
<a href="/docs/LanguageExtensions.html">Language&nbsp;Extensions</a>
<a href="/cxx_status.html">C++ Status</a>