aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-04-14 14:01:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-04-14 14:01:31 +0000
commitdbe13110f59f48b4dbb7552b3ac2935acdeece7f (patch)
treebe1815eb79b42ff482a8562b13c2dcbf0c5dcbee /lib
parent9da628931ebf2609493570f87824ca22402cc65f (diff)
downloadsrc-dbe13110f59f48b4dbb7552b3ac2935acdeece7f.tar.gz
src-dbe13110f59f48b4dbb7552b3ac2935acdeece7f.zip
Vendor import of clang trunk r154661:vendor/clang/clang-trunk-r154661
Notes
Notes: svn path=/vendor/clang/dist/; revision=234287 svn path=/vendor/clang/clang-trunk-r154661/; revision=234288; tag=vendor/clang/clang-trunk-r154661
Diffstat (limited to 'lib')
-rw-r--r--lib/ARCMigrate/ARCMT.cpp165
-rw-r--r--lib/ARCMigrate/ARCMTActions.cpp17
-rw-r--r--lib/ARCMigrate/CMakeLists.txt3
-rw-r--r--lib/ARCMigrate/FileRemapper.cpp44
-rw-r--r--lib/ARCMigrate/Internals.h19
-rw-r--r--lib/ARCMigrate/ObjCMT.cpp226
-rw-r--r--lib/ARCMigrate/TransARCAssign.cpp3
-rw-r--r--lib/ARCMigrate/TransAutoreleasePool.cpp4
-rw-r--r--lib/ARCMigrate/TransBlockObjCVariable.cpp66
-rw-r--r--lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp43
-rw-r--r--lib/ARCMigrate/TransGCAttrs.cpp358
-rw-r--r--lib/ARCMigrate/TransGCCalls.cpp84
-rw-r--r--lib/ARCMigrate/TransProperties.cpp328
-rw-r--r--lib/ARCMigrate/TransRetainReleaseDealloc.cpp112
-rw-r--r--lib/ARCMigrate/TransUnbridgedCasts.cpp30
-rw-r--r--lib/ARCMigrate/TransUnusedInitDelegate.cpp6
-rw-r--r--lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp75
-rw-r--r--lib/ARCMigrate/TransformActions.cpp33
-rw-r--r--lib/ARCMigrate/Transforms.cpp344
-rw-r--r--lib/ARCMigrate/Transforms.h118
-rw-r--r--lib/AST/APValue.cpp573
-rw-r--r--lib/AST/ASTConsumer.cpp6
-rw-r--r--lib/AST/ASTContext.cpp530
-rw-r--r--lib/AST/ASTDiagnostic.cpp26
-rw-r--r--lib/AST/ASTImporter.cpp773
-rw-r--r--lib/AST/AttrImpl.cpp4
-rw-r--r--lib/AST/CMakeLists.txt2
-rw-r--r--lib/AST/CXXInheritance.cpp15
-rw-r--r--lib/AST/Decl.cpp919
-rw-r--r--lib/AST/DeclBase.cpp418
-rw-r--r--lib/AST/DeclCXX.cpp467
-rw-r--r--lib/AST/DeclFriend.cpp7
-rw-r--r--lib/AST/DeclObjC.cpp442
-rw-r--r--lib/AST/DeclPrinter.cpp91
-rw-r--r--lib/AST/DeclTemplate.cpp198
-rw-r--r--lib/AST/DeclarationName.cpp16
-rw-r--r--lib/AST/DumpXML.cpp50
-rw-r--r--lib/AST/Expr.cpp1003
-rw-r--r--lib/AST/ExprCXX.cpp536
-rw-r--r--lib/AST/ExprClassification.cpp90
-rw-r--r--lib/AST/ExprConstant.cpp5717
-rw-r--r--lib/AST/ItaniumMangle.cpp387
-rw-r--r--lib/AST/LambdaMangleContext.cpp30
-rw-r--r--lib/AST/Mangle.cpp12
-rw-r--r--lib/AST/MicrosoftMangle.cpp33
-rw-r--r--lib/AST/NSAPI.cpp312
-rw-r--r--lib/AST/NestedNameSpecifier.cpp28
-rw-r--r--lib/AST/ParentMap.cpp4
-rw-r--r--lib/AST/RecordLayout.cpp4
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp766
-rw-r--r--lib/AST/Stmt.cpp102
-rw-r--r--lib/AST/StmtDumper.cpp69
-rw-r--r--lib/AST/StmtPrinter.cpp412
-rw-r--r--lib/AST/StmtProfile.cpp99
-rw-r--r--lib/AST/TemplateBase.cpp114
-rw-r--r--lib/AST/TemplateName.cpp2
-rw-r--r--lib/AST/Type.cpp277
-rw-r--r--lib/AST/TypeLoc.cpp113
-rw-r--r--lib/AST/TypePrinter.cpp109
-rw-r--r--lib/AST/VTableBuilder.cpp17
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp (renamed from lib/Analysis/AnalysisContext.cpp)137
-rw-r--r--lib/Analysis/CFG.cpp405
-rw-r--r--lib/Analysis/CMakeLists.txt5
-rw-r--r--lib/Analysis/CallGraph.cpp184
-rw-r--r--lib/Analysis/CocoaConventions.cpp49
-rw-r--r--lib/Analysis/Dominators.cpp14
-rw-r--r--lib/Analysis/FormatString.cpp251
-rw-r--r--lib/Analysis/FormatStringParsing.h6
-rw-r--r--lib/Analysis/LiveVariables.cpp171
-rw-r--r--lib/Analysis/PostOrderCFGView.cpp49
-rw-r--r--lib/Analysis/PrintfFormatString.cpp167
-rw-r--r--lib/Analysis/ProgramPoint.cpp2
-rw-r--r--lib/Analysis/PseudoConstantAnalysis.cpp17
-rw-r--r--lib/Analysis/ReachableCode.cpp6
-rw-r--r--lib/Analysis/ScanfFormatString.cpp290
-rw-r--r--lib/Analysis/ThreadSafety.cpp1533
-rw-r--r--lib/Analysis/UninitializedValues.cpp10
-rw-r--r--lib/Basic/Builtins.cpp1
-rw-r--r--lib/Basic/CMakeLists.txt2
-rw-r--r--lib/Basic/ConvertUTF.c143
-rw-r--r--lib/Basic/Diagnostic.cpp126
-rw-r--r--lib/Basic/DiagnosticIDs.cpp229
-rw-r--r--lib/Basic/FileManager.cpp27
-rw-r--r--lib/Basic/FileSystemStatCache.cpp2
-rw-r--r--lib/Basic/IdentifierTable.cpp43
-rw-r--r--lib/Basic/LangOptions.cpp2
-rw-r--r--lib/Basic/Makefile21
-rw-r--r--lib/Basic/Module.cpp274
-rw-r--r--lib/Basic/SourceLocation.cpp4
-rw-r--r--lib/Basic/SourceManager.cpp144
-rw-r--r--lib/Basic/TargetInfo.cpp5
-rw-r--r--lib/Basic/Targets.cpp1008
-rw-r--r--lib/Basic/Version.cpp58
-rw-r--r--lib/CMakeLists.txt2
-rw-r--r--lib/CodeGen/ABIInfo.h21
-rw-r--r--lib/CodeGen/BackendUtil.cpp143
-rw-r--r--lib/CodeGen/CGBlocks.cpp387
-rw-r--r--lib/CodeGen/CGBlocks.h47
-rw-r--r--lib/CodeGen/CGBuiltin.cpp2692
-rw-r--r--lib/CodeGen/CGCXX.cpp29
-rw-r--r--lib/CodeGen/CGCXXABI.cpp43
-rw-r--r--lib/CodeGen/CGCXXABI.h34
-rw-r--r--lib/CodeGen/CGCall.cpp621
-rw-r--r--lib/CodeGen/CGCall.h154
-rw-r--r--lib/CodeGen/CGClass.cpp362
-rw-r--r--lib/CodeGen/CGCleanup.cpp74
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp946
-rw-r--r--lib/CodeGen/CGDebugInfo.h42
-rw-r--r--lib/CodeGen/CGDecl.cpp243
-rw-r--r--lib/CodeGen/CGDeclCXX.cpp220
-rw-r--r--lib/CodeGen/CGException.cpp145
-rw-r--r--lib/CodeGen/CGException.h56
-rw-r--r--lib/CodeGen/CGExpr.cpp1017
-rw-r--r--lib/CodeGen/CGExprAgg.cpp580
-rw-r--r--lib/CodeGen/CGExprCXX.cpp296
-rw-r--r--lib/CodeGen/CGExprComplex.cpp66
-rw-r--r--lib/CodeGen/CGExprConstant.cpp879
-rw-r--r--lib/CodeGen/CGExprScalar.cpp335
-rw-r--r--lib/CodeGen/CGObjC.cpp836
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp296
-rw-r--r--lib/CodeGen/CGObjCMac.cpp851
-rw-r--r--lib/CodeGen/CGObjCRuntime.cpp74
-rw-r--r--lib/CodeGen/CGObjCRuntime.h28
-rw-r--r--lib/CodeGen/CGRTTI.cpp59
-rw-r--r--lib/CodeGen/CGRecordLayoutBuilder.cpp183
-rw-r--r--lib/CodeGen/CGStmt.cpp62
-rw-r--r--lib/CodeGen/CGTemporaries.cpp49
-rw-r--r--lib/CodeGen/CGVTT.cpp21
-rw-r--r--lib/CodeGen/CGVTables.cpp40
-rw-r--r--lib/CodeGen/CGValue.h84
-rw-r--r--lib/CodeGen/CMakeLists.txt3
-rw-r--r--lib/CodeGen/CodeGenAction.cpp107
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp180
-rw-r--r--lib/CodeGen/CodeGenFunction.h407
-rw-r--r--lib/CodeGen/CodeGenModule.cpp617
-rw-r--r--lib/CodeGen/CodeGenModule.h115
-rw-r--r--lib/CodeGen/CodeGenTBAA.cpp6
-rw-r--r--lib/CodeGen/CodeGenTBAA.h4
-rw-r--r--lib/CodeGen/CodeGenTypes.cpp44
-rw-r--r--lib/CodeGen/CodeGenTypes.h109
-rw-r--r--lib/CodeGen/ItaniumCXXABI.cpp334
-rw-r--r--lib/CodeGen/MicrosoftCXXABI.cpp7
-rw-r--r--lib/CodeGen/ModuleBuilder.cpp17
-rw-r--r--lib/CodeGen/TargetInfo.cpp882
-rw-r--r--lib/CodeGen/TargetInfo.h5
-rw-r--r--lib/Driver/Action.cpp31
-rw-r--r--lib/Driver/Arg.cpp4
-rw-r--r--lib/Driver/ArgList.cpp30
-rw-r--r--lib/Driver/CC1AsOptions.cpp2
-rw-r--r--lib/Driver/CC1Options.cpp2
-rw-r--r--lib/Driver/CMakeLists.txt2
-rw-r--r--lib/Driver/Compilation.cpp8
-rw-r--r--lib/Driver/Driver.cpp370
-rw-r--r--lib/Driver/DriverOptions.cpp2
-rw-r--r--lib/Driver/HostInfo.cpp731
-rw-r--r--lib/Driver/Job.cpp2
-rw-r--r--lib/Driver/Option.cpp2
-rw-r--r--lib/Driver/ToolChain.cpp187
-rw-r--r--lib/Driver/ToolChains.cpp1513
-rw-r--r--lib/Driver/ToolChains.h337
-rw-r--r--lib/Driver/Tools.cpp1596
-rw-r--r--lib/Driver/Tools.h97
-rw-r--r--lib/Driver/Types.cpp1
-rw-r--r--lib/Driver/WindowsToolChain.cpp368
-rw-r--r--lib/Edit/CMakeLists.txt7
-rw-r--r--lib/Edit/Commit.cpp345
-rw-r--r--lib/Edit/EditedSource.cpp329
-rw-r--r--lib/Edit/Makefile14
-rw-r--r--lib/Edit/RewriteObjCFoundationAPI.cpp587
-rw-r--r--lib/Frontend/ASTConsumers.cpp3
-rw-r--r--lib/Frontend/ASTMerge.cpp13
-rw-r--r--lib/Frontend/ASTUnit.cpp746
-rw-r--r--lib/Frontend/CMakeLists.txt8
-rw-r--r--lib/Frontend/CacheTokens.cpp4
-rw-r--r--lib/Frontend/ChainedDiagnosticConsumer.cpp14
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp (renamed from lib/Serialization/ChainedIncludesSource.cpp)40
-rw-r--r--lib/Frontend/CompilerInstance.cpp813
-rw-r--r--lib/Frontend/CompilerInvocation.cpp818
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp17
-rw-r--r--lib/Frontend/DependencyFile.cpp64
-rw-r--r--lib/Frontend/DependencyGraph.cpp140
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp386
-rw-r--r--lib/Frontend/FrontendAction.cpp137
-rw-r--r--lib/Frontend/FrontendActions.cpp314
-rw-r--r--lib/Frontend/HeaderIncludeGen.cpp5
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp46
-rw-r--r--lib/Frontend/InitPreprocessor.cpp128
-rw-r--r--lib/Frontend/LangStandards.cpp3
-rw-r--r--lib/Frontend/LayoutOverrideSource.cpp206
-rw-r--r--lib/Frontend/LogDiagnosticPrinter.cpp8
-rw-r--r--lib/Frontend/MultiplexConsumer.cpp50
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp8
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp592
-rw-r--r--lib/Frontend/TextDiagnostic.cpp881
-rw-r--r--lib/Frontend/TextDiagnosticBuffer.cpp2
-rw-r--r--lib/Frontend/TextDiagnosticPrinter.cpp1148
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp38
-rw-r--r--lib/Frontend/Warnings.cpp190
-rw-r--r--lib/FrontendTool/ExecuteCompilerInvocation.cpp43
-rw-r--r--lib/Headers/CMakeLists.txt9
-rw-r--r--lib/Headers/Makefile14
-rw-r--r--lib/Headers/avx2intrin.h961
-rw-r--r--lib/Headers/avxintrin.h331
-rw-r--r--lib/Headers/bmi2intrin.h75
-rw-r--r--lib/Headers/bmiintrin.h115
-rw-r--r--lib/Headers/cpuid.h33
-rw-r--r--lib/Headers/emmintrin.h56
-rw-r--r--lib/Headers/float.h11
-rw-r--r--lib/Headers/fma4intrin.h231
-rw-r--r--lib/Headers/immintrin.h18
-rw-r--r--lib/Headers/lzcntintrin.h55
-rw-r--r--lib/Headers/mm3dnow.h2
-rw-r--r--lib/Headers/module.map108
-rw-r--r--lib/Headers/popcntintrin.h45
-rw-r--r--lib/Headers/smmintrin.h127
-rw-r--r--lib/Headers/tgmath.h23
-rw-r--r--lib/Headers/tmmintrin.h11
-rw-r--r--lib/Headers/unwind.h124
-rw-r--r--lib/Headers/wmmintrin.h2
-rw-r--r--lib/Headers/x86intrin.h26
-rw-r--r--lib/Headers/xmmintrin.h21
-rw-r--r--lib/Index/ASTLocation.cpp12
-rw-r--r--lib/Index/Analyzer.cpp4
-rw-r--r--lib/Index/CMakeLists.txt2
-rw-r--r--lib/Index/GlobalCallGraph.cpp (renamed from lib/Index/CallGraph.cpp)10
-rw-r--r--lib/Lex/CMakeLists.txt2
-rw-r--r--lib/Lex/HeaderMap.cpp4
-rw-r--r--lib/Lex/HeaderSearch.cpp516
-rw-r--r--lib/Lex/Lexer.cpp438
-rw-r--r--lib/Lex/LiteralSupport.cpp464
-rw-r--r--lib/Lex/MacroArgs.cpp9
-rw-r--r--lib/Lex/MacroInfo.cpp5
-rw-r--r--lib/Lex/ModuleMap.cpp1437
-rw-r--r--lib/Lex/PPCaching.cpp22
-rw-r--r--lib/Lex/PPCallbacks.cpp14
-rw-r--r--lib/Lex/PPDirectives.cpp354
-rw-r--r--lib/Lex/PPExpressions.cpp22
-rw-r--r--lib/Lex/PPLexerChange.cpp88
-rw-r--r--lib/Lex/PPMacroExpansion.cpp134
-rw-r--r--lib/Lex/PTHLexer.cpp6
-rw-r--r--lib/Lex/Pragma.cpp211
-rw-r--r--lib/Lex/PreprocessingRecord.cpp265
-rw-r--r--lib/Lex/Preprocessor.cpp149
-rw-r--r--lib/Lex/PreprocessorLexer.cpp2
-rw-r--r--lib/Lex/TokenConcatenation.cpp49
-rw-r--r--lib/Lex/TokenLexer.cpp12
-rwxr-xr-xlib/Makefile4
-rw-r--r--lib/Parse/ParseAST.cpp35
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp120
-rw-r--r--lib/Parse/ParseDecl.cpp1544
-rw-r--r--lib/Parse/ParseDeclCXX.cpp685
-rw-r--r--lib/Parse/ParseExpr.cpp365
-rw-r--r--lib/Parse/ParseExprCXX.cpp610
-rw-r--r--lib/Parse/ParseInit.cpp179
-rw-r--r--lib/Parse/ParseObjc.cpp526
-rw-r--r--lib/Parse/ParsePragma.cpp118
-rw-r--r--lib/Parse/ParsePragma.h10
-rw-r--r--lib/Parse/ParseStmt.cpp252
-rw-r--r--lib/Parse/ParseTemplate.cpp184
-rw-r--r--lib/Parse/ParseTentative.cpp331
-rw-r--r--lib/Parse/Parser.cpp454
-rw-r--r--lib/Rewrite/CMakeLists.txt1
-rw-r--r--lib/Rewrite/FixItRewriter.cpp115
-rw-r--r--lib/Rewrite/FrontendActions.cpp75
-rw-r--r--lib/Rewrite/HTMLPrint.cpp2
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp10
-rw-r--r--lib/Rewrite/RewriteMacros.cpp6
-rw-r--r--lib/Rewrite/RewriteModernObjC.cpp7275
-rw-r--r--lib/Rewrite/RewriteObjC.cpp3197
-rw-r--r--lib/Rewrite/RewriteTest.cpp2
-rw-r--r--lib/Rewrite/Rewriter.cpp3
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp250
-rw-r--r--lib/Sema/AttributeList.cpp133
-rw-r--r--lib/Sema/CMakeLists.txt18
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp186
-rw-r--r--lib/Sema/DeclSpec.cpp33
-rw-r--r--lib/Sema/DelayedDiagnostic.cpp6
-rw-r--r--lib/Sema/IdentifierResolver.cpp158
-rw-r--r--lib/Sema/JumpDiagnostics.cpp124
-rw-r--r--lib/Sema/MultiInitializer.cpp92
-rw-r--r--lib/Sema/Scope.cpp28
-rw-r--r--lib/Sema/Sema.cpp269
-rw-r--r--lib/Sema/SemaAccess.cpp326
-rw-r--r--lib/Sema/SemaAttr.cpp54
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp167
-rw-r--r--lib/Sema/SemaCast.cpp271
-rw-r--r--lib/Sema/SemaChecking.cpp2118
-rw-r--r--lib/Sema/SemaCodeComplete.cpp1135
-rw-r--r--lib/Sema/SemaConsumer.cpp14
-rw-r--r--lib/Sema/SemaDecl.cpp2340
-rw-r--r--lib/Sema/SemaDeclAttr.cpp267
-rw-r--r--lib/Sema/SemaDeclCXX.cpp3141
-rw-r--r--lib/Sema/SemaDeclObjC.cpp779
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp21
-rw-r--r--lib/Sema/SemaExpr.cpp3464
-rw-r--r--lib/Sema/SemaExprCXX.cpp1341
-rw-r--r--lib/Sema/SemaExprMember.cpp346
-rw-r--r--lib/Sema/SemaExprObjC.cpp1491
-rw-r--r--lib/Sema/SemaFixItUtils.cpp44
-rw-r--r--lib/Sema/SemaInit.cpp2136
-rw-r--r--lib/Sema/SemaLambda.cpp820
-rw-r--r--lib/Sema/SemaLookup.cpp825
-rw-r--r--lib/Sema/SemaObjCProperty.cpp382
-rw-r--r--lib/Sema/SemaOverload.cpp2109
-rw-r--r--lib/Sema/SemaPseudoObject.cpp1351
-rw-r--r--lib/Sema/SemaStmt.cpp532
-rw-r--r--lib/Sema/SemaTemplate.cpp1265
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp763
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp305
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp654
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp117
-rw-r--r--lib/Sema/SemaType.cpp837
-rw-r--r--lib/Sema/TargetAttributesSema.cpp2
-rw-r--r--lib/Sema/TreeTransform.h1141
-rw-r--r--lib/Serialization/ASTCommon.cpp3
-rw-r--r--lib/Serialization/ASTCommon.h1
-rw-r--r--lib/Serialization/ASTReader.cpp1607
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp1529
-rw-r--r--lib/Serialization/ASTReaderInternals.h25
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp377
-rw-r--r--lib/Serialization/ASTWriter.cpp930
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp435
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp295
-rw-r--r--lib/Serialization/CMakeLists.txt6
-rw-r--r--lib/Serialization/GeneratePCH.cpp13
-rw-r--r--lib/Serialization/Module.cpp18
-rw-r--r--lib/Serialization/ModuleManager.cpp51
-rw-r--r--lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp74
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp63
-rw-r--r--lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp13
-rw-r--r--lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp70
-rw-r--r--lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp157
-rw-r--r--lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/CMakeLists.txt12
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp481
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringSyntaxChecker.cpp191
-rw-r--r--lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp128
-rw-r--r--lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp6
-rw-r--r--lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp232
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp233
-rw-r--r--lib/StaticAnalyzer/Checkers/Checkers.td148
-rw-r--r--lib/StaticAnalyzer/Checkers/ChrootChecker.cpp22
-rw-r--r--lib/StaticAnalyzer/Checkers/ClangSACheckers.h2
-rw-r--r--lib/StaticAnalyzer/Checkers/CommonBugCategories.cpp18
-rw-r--r--lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp56
-rw-r--r--lib/StaticAnalyzer/Checkers/DebugCheckers.cpp70
-rw-r--r--lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp60
-rw-r--r--lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp45
-rw-r--r--lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp9
-rw-r--r--lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp740
-rw-r--r--lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp34
-rw-r--r--lib/StaticAnalyzer/Checkers/InterCheckerAPI.h22
-rw-r--r--lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp46
-rw-r--r--lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp15
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp229
-rw-r--r--lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp34
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp1341
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocOverflowSecurityChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp211
-rw-r--r--lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp31
-rw-r--r--lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp14
-rw-r--r--lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp4
-rw-r--r--lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp96
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersASTChecker.cpp174
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp159
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp82
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp11
-rw-r--r--lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp44
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp900
-rw-r--r--lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp10
-rw-r--r--lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp64
-rw-r--r--lib/StaticAnalyzer/Checkers/StreamChecker.cpp109
-rw-r--r--lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp62
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp37
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp20
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp20
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp7
-rw-r--r--lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp8
-rw-r--r--lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp204
-rw-r--r--lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp34
-rw-r--r--lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp87
-rw-r--r--lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp241
-rw-r--r--lib/StaticAnalyzer/Core/AggExprVisitor.cpp69
-rw-r--r--lib/StaticAnalyzer/Core/AnalysisManager.cpp38
-rw-r--r--lib/StaticAnalyzer/Core/BasicConstraintManager.cpp66
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp750
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp237
-rw-r--r--lib/StaticAnalyzer/Core/CMakeLists.txt3
-rw-r--r--lib/StaticAnalyzer/Core/Checker.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/CheckerContext.cpp76
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp174
-rw-r--r--lib/StaticAnalyzer/Core/CheckerRegistry.cpp5
-rw-r--r--lib/StaticAnalyzer/Core/CoreEngine.cpp592
-rw-r--r--lib/StaticAnalyzer/Core/Environment.cpp147
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp174
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp1215
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp611
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp237
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp357
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineObjC.cpp92
-rw-r--r--lib/StaticAnalyzer/Core/FunctionSummary.cpp38
-rw-r--r--lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp127
-rw-r--r--lib/StaticAnalyzer/Core/MemRegion.cpp170
-rw-r--r--lib/StaticAnalyzer/Core/ObjCMessage.cpp118
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp466
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp298
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp350
-rw-r--r--lib/StaticAnalyzer/Core/RangeConstraintManager.cpp64
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp388
-rw-r--r--lib/StaticAnalyzer/Core/SValBuilder.cpp152
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp89
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp178
-rw-r--r--lib/StaticAnalyzer/Core/SimpleConstraintManager.h36
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp341
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp46
-rw-r--r--lib/StaticAnalyzer/Core/SubEngine.cpp14
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp128
-rw-r--r--lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp31
-rw-r--r--lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp414
-rw-r--r--lib/StaticAnalyzer/Frontend/CMakeLists.txt3
-rw-r--r--lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp2
-rw-r--r--lib/Tooling/CMakeLists.txt7
-rw-r--r--lib/Tooling/CompilationDatabase.cpp230
-rw-r--r--lib/Tooling/Makefile13
-rw-r--r--lib/Tooling/Tooling.cpp296
435 files changed, 91609 insertions, 34948 deletions
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index 6e1b0e535bbb..9354dc38b8c6 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -10,6 +10,7 @@
#include "Internals.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/AST/ASTConsumer.h"
@@ -98,7 +99,7 @@ public:
virtual void HandleDiagnostic(DiagnosticsEngine::Level level,
const Diagnostic &Info) {
- if (arcmt::isARCDiagnostic(Info.getID(), Diags) ||
+ if (DiagnosticIDs::isARCDiagnostic(Info.getID()) ||
level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
CapturedDiags.push_back(StoredDiagnostic(level, Info));
return;
@@ -184,18 +185,19 @@ static bool HasARCRuntime(CompilerInvocation &origCI) {
static CompilerInvocation *
createInvocationForMigration(CompilerInvocation &origCI) {
- llvm::OwningPtr<CompilerInvocation> CInvok;
+ OwningPtr<CompilerInvocation> CInvok;
CInvok.reset(new CompilerInvocation(origCI));
CInvok->getPreprocessorOpts().ImplicitPCHInclude = std::string();
CInvok->getPreprocessorOpts().ImplicitPTHInclude = std::string();
std::string define = getARCMTMacroName();
define += '=';
CInvok->getPreprocessorOpts().addMacroDef(define);
- CInvok->getLangOpts().ObjCAutoRefCount = true;
+ CInvok->getLangOpts()->ObjCAutoRefCount = true;
+ CInvok->getLangOpts()->setGC(LangOptions::NonGC);
CInvok->getDiagnosticOpts().ErrorLimit = 0;
CInvok->getDiagnosticOpts().Warnings.push_back(
"error=arc-unsafe-retained-assign");
- CInvok->getLangOpts().ObjCRuntimeHasWeak = HasARCRuntime(origCI);
+ CInvok->getLangOpts()->ObjCRuntimeHasWeak = HasARCRuntime(origCI);
return CInvok.take();
}
@@ -204,12 +206,12 @@ static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
const DiagnosticOptions &diagOpts,
Preprocessor &PP) {
TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, &printer, /*ShouldOwnClient=*/false));
Diags->setSourceManager(&PP.getSourceManager());
- printer.BeginSourceFile(PP.getLangOptions(), &PP);
+ printer.BeginSourceFile(PP.getLangOpts(), &PP);
arcDiags.reportDiagnostics(*Diags);
printer.EndSourceFile();
}
@@ -219,33 +221,38 @@ static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
//===----------------------------------------------------------------------===//
bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
- StringRef Filename, InputKind Kind,
+ const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient,
bool emitPremigrationARCErrors,
StringRef plistOut) {
- if (!origCI.getLangOpts().ObjC1)
+ if (!origCI.getLangOpts()->ObjC1)
return false;
- std::vector<TransformFn> transforms = arcmt::getAllTransformations();
+ LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
+ bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError;
+ bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
+
+ std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
+ NoFinalizeRemoval);
assert(!transforms.empty());
- llvm::OwningPtr<CompilerInvocation> CInvok;
+ OwningPtr<CompilerInvocation> CInvok;
CInvok.reset(createInvocationForMigration(origCI));
CInvok->getFrontendOpts().Inputs.clear();
- CInvok->getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename));
+ CInvok->getFrontendOpts().Inputs.push_back(Input);
CapturedDiagList capturedDiags;
assert(DiagClient);
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
// Filter of all diagnostics.
CaptureDiagnosticConsumer errRec(*Diags, capturedDiags);
Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
- llvm::OwningPtr<ASTUnit> Unit(
+ OwningPtr<ASTUnit> Unit(
ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags));
if (!Unit)
return true;
@@ -257,7 +264,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
if (Diags->hasFatalErrorOccurred()) {
Diags->Reset();
- DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
+ DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
capturedDiags.reportDiagnostics(*Diags);
DiagClient->EndSourceFile();
return true;
@@ -272,7 +279,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
arcDiags.push_back(*I);
writeARCDiagsToPlist(plistOut, arcDiags,
- Ctx.getSourceManager(), Ctx.getLangOptions());
+ Ctx.getSourceManager(), Ctx.getLangOpts());
}
// After parsing of source files ended, we want to reuse the
@@ -280,14 +287,16 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
// We call BeginSourceFile because DiagnosticConsumer requires that
// diagnostics with source range information are emitted only in between
// BeginSourceFile() and EndSourceFile().
- DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
+ DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
// No macros will be added since we are just checking and we won't modify
// source code.
std::vector<SourceLocation> ARCMTMacroLocs;
TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
- MigrationPass pass(Ctx, Unit->getSema(), testAct, ARCMTMacroLocs);
+ MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, ARCMTMacroLocs);
+ pass.setNSAllocReallocError(NoNSAllocReallocError);
+ pass.setNoFinalizeRemoval(NoFinalizeRemoval);
for (unsigned i=0, e = transforms.size(); i != e; ++i)
transforms[i](pass);
@@ -298,7 +307,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
// If we are migrating code that gets the '-fobjc-arc' flag, make sure
// to remove it so that we don't get errors from normal compilation.
- origCI.getLangOpts().ObjCAutoRefCount = false;
+ origCI.getLangOpts()->ObjCAutoRefCount = false;
return capturedDiags.hasErrors() || testAct.hasReportedErrors();
}
@@ -308,27 +317,31 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
//===----------------------------------------------------------------------===//
static bool applyTransforms(CompilerInvocation &origCI,
- StringRef Filename, InputKind Kind,
+ const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient,
StringRef outputDir,
bool emitPremigrationARCErrors,
StringRef plistOut) {
- if (!origCI.getLangOpts().ObjC1)
+ if (!origCI.getLangOpts()->ObjC1)
return false;
+ LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC();
+
// Make sure checking is successful first.
CompilerInvocation CInvokForCheck(origCI);
- if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient,
+ if (arcmt::checkForManualIssues(CInvokForCheck, Input, DiagClient,
emitPremigrationARCErrors, plistOut))
return true;
CompilerInvocation CInvok(origCI);
CInvok.getFrontendOpts().Inputs.clear();
- CInvok.getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename));
+ CInvok.getFrontendOpts().Inputs.push_back(Input);
MigrationProcess migration(CInvok, DiagClient, outputDir);
+ bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval;
- std::vector<TransformFn> transforms = arcmt::getAllTransformations();
+ std::vector<TransformFn> transforms = arcmt::getAllTransformations(OrigGCMode,
+ NoFinalizeRemoval);
assert(!transforms.empty());
for (unsigned i=0, e = transforms.size(); i != e; ++i) {
@@ -336,36 +349,36 @@ static bool applyTransforms(CompilerInvocation &origCI,
if (err) return true;
}
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
if (outputDir.empty()) {
- origCI.getLangOpts().ObjCAutoRefCount = true;
+ origCI.getLangOpts()->ObjCAutoRefCount = true;
return migration.getRemapper().overwriteOriginal(*Diags);
} else {
// If we are migrating code that gets the '-fobjc-arc' flag, make sure
// to remove it so that we don't get errors from normal compilation.
- origCI.getLangOpts().ObjCAutoRefCount = false;
+ origCI.getLangOpts()->ObjCAutoRefCount = false;
return migration.getRemapper().flushToDisk(outputDir, *Diags);
}
}
bool arcmt::applyTransformations(CompilerInvocation &origCI,
- StringRef Filename, InputKind Kind,
+ const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient) {
- return applyTransforms(origCI, Filename, Kind, DiagClient,
+ return applyTransforms(origCI, Input, DiagClient,
StringRef(), false, StringRef());
}
bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI,
- StringRef Filename, InputKind Kind,
+ const FrontendInputFile &Input,
DiagnosticConsumer *DiagClient,
StringRef outputDir,
bool emitPremigrationARCErrors,
StringRef plistOut) {
assert(!outputDir.empty() && "Expected output directory path");
- return applyTransforms(origCI, Filename, Kind, DiagClient,
+ return applyTransforms(origCI, Input, DiagClient,
outputDir, emitPremigrationARCErrors, plistOut);
}
@@ -375,8 +388,8 @@ bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
DiagnosticConsumer *DiagClient) {
assert(!outputDir.empty());
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
FileRemapper remapper;
@@ -385,13 +398,51 @@ bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
if (err)
return true;
- CompilerInvocation CI;
- remapper.applyMappings(CI);
- remap = CI.getPreprocessorOpts().RemappedFiles;
+ PreprocessorOptions PPOpts;
+ remapper.applyMappings(PPOpts);
+ remap = PPOpts.RemappedFiles;
return false;
}
+bool arcmt::getFileRemappingsFromFileList(
+ std::vector<std::pair<std::string,std::string> > &remap,
+ ArrayRef<StringRef> remapFiles,
+ DiagnosticConsumer *DiagClient) {
+ bool hasErrorOccurred = false;
+ llvm::StringMap<bool> Uniquer;
+
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
+
+ for (ArrayRef<StringRef>::iterator
+ I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
+ StringRef file = *I;
+
+ FileRemapper remapper;
+ bool err = remapper.initFromFile(file, *Diags,
+ /*ignoreIfFilesChanged=*/true);
+ hasErrorOccurred = hasErrorOccurred || err;
+ if (err)
+ continue;
+
+ PreprocessorOptions PPOpts;
+ remapper.applyMappings(PPOpts);
+ for (PreprocessorOptions::remapped_file_iterator
+ RI = PPOpts.remapped_file_begin(), RE = PPOpts.remapped_file_end();
+ RI != RE; ++RI) {
+ bool &inserted = Uniquer[RI->first];
+ if (inserted)
+ continue;
+ inserted = true;
+ remap.push_back(*RI);
+ }
+ }
+
+ return hasErrorOccurred;
+}
+
//===----------------------------------------------------------------------===//
// CollectTransformActions.
//===----------------------------------------------------------------------===//
@@ -478,8 +529,8 @@ MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
StringRef outputDir)
: OrigCI(CI), DiagClient(diagClient) {
if (!outputDir.empty()) {
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true);
}
@@ -487,28 +538,28 @@ MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
bool MigrationProcess::applyTransform(TransformFn trans,
RewriteListener *listener) {
- llvm::OwningPtr<CompilerInvocation> CInvok;
+ OwningPtr<CompilerInvocation> CInvok;
CInvok.reset(createInvocationForMigration(OrigCI));
CInvok->getDiagnosticOpts().IgnoreWarnings = true;
- Remapper.applyMappings(*CInvok);
+ Remapper.applyMappings(CInvok->getPreprocessorOpts());
CapturedDiagList capturedDiags;
std::vector<SourceLocation> ARCMTMacroLocs;
assert(DiagClient);
- llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
// Filter of all diagnostics.
CaptureDiagnosticConsumer errRec(*Diags, capturedDiags);
Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
- llvm::OwningPtr<ARCMTMacroTrackerAction> ASTAction;
+ OwningPtr<ARCMTMacroTrackerAction> ASTAction;
ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs));
- llvm::OwningPtr<ASTUnit> Unit(
+ OwningPtr<ASTUnit> Unit(
ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags,
ASTAction.get()));
if (!Unit)
@@ -522,7 +573,7 @@ bool MigrationProcess::applyTransform(TransformFn trans,
if (Diags->hasFatalErrorOccurred()) {
Diags->Reset();
- DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
+ DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
capturedDiags.reportDiagnostics(*Diags);
DiagClient->EndSourceFile();
return true;
@@ -533,11 +584,12 @@ bool MigrationProcess::applyTransform(TransformFn trans,
// We call BeginSourceFile because DiagnosticConsumer requires that
// diagnostics with source range information are emitted only in between
// BeginSourceFile() and EndSourceFile().
- DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
+ DiagClient->BeginSourceFile(Ctx.getLangOpts(), &Unit->getPreprocessor());
- Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOptions());
+ Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
TransformActions TA(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
- MigrationPass pass(Ctx, Unit->getSema(), TA, ARCMTMacroLocs);
+ MigrationPass pass(Ctx, OrigCI.getLangOpts()->getGC(),
+ Unit->getSema(), TA, ARCMTMacroLocs);
trans(pass);
@@ -559,25 +611,16 @@ bool MigrationProcess::applyTransform(TransformFn trans,
assert(file);
std::string newFname = file->getName();
newFname += "-trans";
- llvm::SmallString<512> newText;
+ SmallString<512> newText;
llvm::raw_svector_ostream vecOS(newText);
buf.write(vecOS);
vecOS.flush();
llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
StringRef(newText.data(), newText.size()), newFname);
- llvm::SmallString<64> filePath(file->getName());
+ SmallString<64> filePath(file->getName());
Unit->getFileManager().FixupRelativePath(filePath);
Remapper.remap(filePath.str(), memBuf);
}
return false;
}
-
-//===----------------------------------------------------------------------===//
-// isARCDiagnostic.
-//===----------------------------------------------------------------------===//
-
-bool arcmt::isARCDiagnostic(unsigned diagID, DiagnosticsEngine &Diag) {
- return Diag.getDiagnosticIDs()->getCategoryNumberForDiag(diagID) ==
- diag::DiagCat_Automatic_Reference_Counting_Issue;
-}
diff --git a/lib/ARCMigrate/ARCMTActions.cpp b/lib/ARCMigrate/ARCMTActions.cpp
index dea867af659d..0ed36ddf68c8 100644
--- a/lib/ARCMigrate/ARCMTActions.cpp
+++ b/lib/ARCMigrate/ARCMTActions.cpp
@@ -15,8 +15,7 @@ using namespace clang;
using namespace arcmt;
bool CheckAction::BeginInvocation(CompilerInstance &CI) {
- if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentFile(),
- getCurrentFileKind(),
+ if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentInput(),
CI.getDiagnostics().getClient()))
return false; // errors, stop the action.
@@ -29,8 +28,7 @@ CheckAction::CheckAction(FrontendAction *WrappedAction)
: WrapperFrontendAction(WrappedAction) {}
bool ModifyAction::BeginInvocation(CompilerInstance &CI) {
- return !arcmt::applyTransformations(CI.getInvocation(),
- getCurrentFile(), getCurrentFileKind(),
+ return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(),
CI.getDiagnostics().getClient());
}
@@ -39,12 +37,11 @@ ModifyAction::ModifyAction(FrontendAction *WrappedAction)
bool MigrateAction::BeginInvocation(CompilerInstance &CI) {
if (arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
- getCurrentFile(),
- getCurrentFileKind(),
- CI.getDiagnostics().getClient(),
- MigrateDir,
- EmitPremigrationARCErros,
- PlistOut))
+ getCurrentInput(),
+ CI.getDiagnostics().getClient(),
+ MigrateDir,
+ EmitPremigrationARCErros,
+ PlistOut))
return false; // errors, stop the action.
// We only want to see diagnostics emitted by migrateWithTemporaryFiles.
diff --git a/lib/ARCMigrate/CMakeLists.txt b/lib/ARCMigrate/CMakeLists.txt
index f6d404ee1354..fcb7f72ee21d 100644
--- a/lib/ARCMigrate/CMakeLists.txt
+++ b/lib/ARCMigrate/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_library(clangARCMigrate
ARCMT.cpp
ARCMTActions.cpp
FileRemapper.cpp
+ ObjCMT.cpp
PlistReporter.cpp
TransAPIUses.cpp
TransARCAssign.cpp
@@ -12,6 +13,8 @@ add_clang_library(clangARCMigrate
TransEmptyStatementsAndDealloc.cpp
TransformActions.cpp
Transforms.cpp
+ TransGCAttrs.cpp
+ TransGCCalls.cpp
TransProperties.cpp
TransRetainReleaseDealloc.cpp
TransUnbridgedCasts.cpp
diff --git a/lib/ARCMigrate/FileRemapper.cpp b/lib/ARCMigrate/FileRemapper.cpp
index c6e6ce46d173..474ce7dcbaf8 100644
--- a/lib/ARCMigrate/FileRemapper.cpp
+++ b/lib/ARCMigrate/FileRemapper.cpp
@@ -8,8 +8,9 @@
//===----------------------------------------------------------------------===//
#include "clang/ARCMigrate/FileRemapper.h"
-#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/FileSystem.h"
@@ -50,9 +51,15 @@ std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
bool FileRemapper::initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged) {
+ std::string infoFile = getRemapInfoFile(outputDir);
+ return initFromFile(infoFile, Diag, ignoreIfFilesChanged);
+}
+
+bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag,
+ bool ignoreIfFilesChanged) {
assert(FromToMappings.empty() &&
"initFromDisk should be called before any remap calls");
- std::string infoFile = getRemapInfoFile(outputDir);
+ std::string infoFile = filePath;
bool fileExists = false;
llvm::sys::fs::exists(infoFile, fileExists);
if (!fileExists)
@@ -60,9 +67,8 @@ bool FileRemapper::initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
- llvm::OwningPtr<llvm::MemoryBuffer> fileBuf;
- if (llvm::error_code ec = llvm::MemoryBuffer::getFile(infoFile.c_str(),
- fileBuf))
+ OwningPtr<llvm::MemoryBuffer> fileBuf;
+ if (llvm::MemoryBuffer::getFile(infoFile.c_str(), fileBuf))
return report("Error opening file: " + infoFile, Diag);
SmallVector<StringRef, 64> lines;
@@ -109,8 +115,15 @@ bool FileRemapper::flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag) {
if (fs::create_directory(outputDir, existed) != llvm::errc::success)
return report("Could not create directory: " + outputDir, Diag);
- std::string errMsg;
std::string infoFile = getRemapInfoFile(outputDir);
+ return flushToFile(infoFile, Diag);
+}
+
+bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) {
+ using namespace llvm::sys;
+
+ std::string errMsg;
+ std::string infoFile = outputPath;
llvm::raw_fd_ostream infoOut(infoFile.c_str(), errMsg,
llvm::raw_fd_ostream::F_Binary);
if (!errMsg.empty())
@@ -120,18 +133,18 @@ bool FileRemapper::flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag) {
I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
const FileEntry *origFE = I->first;
- llvm::SmallString<200> origPath = StringRef(origFE->getName());
+ SmallString<200> origPath = StringRef(origFE->getName());
fs::make_absolute(origPath);
infoOut << origPath << '\n';
infoOut << (uint64_t)origFE->getModificationTime() << '\n';
if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
- llvm::SmallString<200> newPath = StringRef(FE->getName());
+ SmallString<200> newPath = StringRef(FE->getName());
fs::make_absolute(newPath);
infoOut << newPath << '\n';
} else {
- llvm::SmallString<64> tempPath;
+ SmallString<64> tempPath;
tempPath = path::filename(origFE->getName());
tempPath += "-%%%%%%%%";
tempPath += path::extension(origFE->getName());
@@ -190,8 +203,7 @@ bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag,
return false;
}
-void FileRemapper::applyMappings(CompilerInvocation &CI) const {
- PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const {
for (MappingsTy::const_iterator
I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
@@ -205,8 +217,7 @@ void FileRemapper::applyMappings(CompilerInvocation &CI) const {
PPOpts.RetainRemappedFileBuffers = true;
}
-void FileRemapper::transferMappingsAndClear(CompilerInvocation &CI) {
- PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
+void FileRemapper::transferMappingsAndClear(PreprocessorOptions &PPOpts) {
for (MappingsTy::iterator
I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
@@ -269,15 +280,12 @@ void FileRemapper::resetTarget(Target &targ) {
delete oldmem;
} else {
const FileEntry *toFE = targ.get<const FileEntry *>();
- llvm::DenseMap<const FileEntry *, const FileEntry *>::iterator
- I = ToFromMappings.find(toFE);
- if (I != ToFromMappings.end())
- ToFromMappings.erase(I);
+ ToFromMappings.erase(toFE);
}
}
bool FileRemapper::report(const Twine &err, DiagnosticsEngine &Diag) {
- llvm::SmallString<128> buf;
+ SmallString<128> buf;
unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error,
err.toStringRef(buf));
Diag.Report(ID);
diff --git a/lib/ARCMigrate/Internals.h b/lib/ARCMigrate/Internals.h
index 46f3bb626f2f..59177c483ea0 100644
--- a/lib/ARCMigrate/Internals.h
+++ b/lib/ARCMigrate/Internals.h
@@ -94,6 +94,8 @@ public:
void reportError(StringRef error, SourceLocation loc,
SourceRange range = SourceRange());
+ void reportWarning(StringRef warning, SourceLocation loc,
+ SourceRange range = SourceRange());
void reportNote(StringRef note, SourceLocation loc,
SourceRange range = SourceRange());
@@ -137,17 +139,26 @@ public:
class MigrationPass {
public:
ASTContext &Ctx;
+ LangOptions::GCMode OrigGCMode;
+ MigratorOptions MigOptions;
Sema &SemaRef;
TransformActions &TA;
std::vector<SourceLocation> &ARCMTMacroLocs;
- MigrationPass(ASTContext &Ctx, Sema &sema, TransformActions &TA,
+ MigrationPass(ASTContext &Ctx, LangOptions::GCMode OrigGCMode,
+ Sema &sema, TransformActions &TA,
std::vector<SourceLocation> &ARCMTMacroLocs)
- : Ctx(Ctx), SemaRef(sema), TA(TA), ARCMTMacroLocs(ARCMTMacroLocs) { }
+ : Ctx(Ctx), OrigGCMode(OrigGCMode), MigOptions(),
+ SemaRef(sema), TA(TA),
+ ARCMTMacroLocs(ARCMTMacroLocs) { }
+
+ bool isGCMigration() const { return OrigGCMode != LangOptions::NonGC; }
+ bool noNSAllocReallocError() const { return MigOptions.NoNSAllocReallocError; }
+ void setNSAllocReallocError(bool val) { MigOptions.NoNSAllocReallocError = val; }
+ bool noFinalizeRemoval() const { return MigOptions.NoFinalizeRemoval; }
+ void setNoFinalizeRemoval(bool val) {MigOptions.NoFinalizeRemoval = val; }
};
-bool isARCDiagnostic(unsigned diagID, DiagnosticsEngine &Diag);
-
static inline StringRef getARCMTMacroName() {
return "__IMPL_ARCMT_REMOVED_EXPR__";
}
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
new file mode 100644
index 000000000000..e63527447633
--- /dev/null
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -0,0 +1,226 @@
+//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ARCMigrate/ARCMTActions.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/NSAPI.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Edit/Rewriters.h"
+#include "clang/Edit/EditedSource.h"
+#include "clang/Edit/Commit.h"
+#include "clang/Edit/EditsReceiver.h"
+#include "clang/Rewrite/Rewriter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Basic/FileManager.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang;
+using namespace arcmt;
+
+namespace {
+
+class ObjCMigrateASTConsumer : public ASTConsumer {
+ void migrateDecl(Decl *D);
+
+public:
+ std::string MigrateDir;
+ bool MigrateLiterals;
+ bool MigrateSubscripting;
+ llvm::OwningPtr<NSAPI> NSAPIObj;
+ llvm::OwningPtr<edit::EditedSource> Editor;
+ FileRemapper &Remapper;
+ FileManager &FileMgr;
+ const PreprocessingRecord *PPRec;
+ bool IsOutputFile;
+
+ ObjCMigrateASTConsumer(StringRef migrateDir,
+ bool migrateLiterals,
+ bool migrateSubscripting,
+ FileRemapper &remapper,
+ FileManager &fileMgr,
+ const PreprocessingRecord *PPRec,
+ bool isOutputFile = false)
+ : MigrateDir(migrateDir),
+ MigrateLiterals(migrateLiterals),
+ MigrateSubscripting(migrateSubscripting),
+ Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec),
+ IsOutputFile(isOutputFile) { }
+
+protected:
+ virtual void Initialize(ASTContext &Context) {
+ NSAPIObj.reset(new NSAPI(Context));
+ Editor.reset(new edit::EditedSource(Context.getSourceManager(),
+ Context.getLangOpts(),
+ PPRec));
+ }
+
+ virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
+ for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
+ migrateDecl(*I);
+ return true;
+ }
+ virtual void HandleInterestingDecl(DeclGroupRef DG) {
+ // Ignore decls from the PCH.
+ }
+ virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
+ ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
+ }
+
+ virtual void HandleTranslationUnit(ASTContext &Ctx);
+};
+
+}
+
+ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
+ StringRef migrateDir,
+ bool migrateLiterals,
+ bool migrateSubscripting)
+ : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
+ MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting),
+ CompInst(0) {
+ if (MigrateDir.empty())
+ MigrateDir = "."; // user current directory if none is given.
+}
+
+ASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ ASTConsumer *
+ WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+ ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir,
+ MigrateLiterals,
+ MigrateSubscripting,
+ Remapper,
+ CompInst->getFileManager(),
+ CompInst->getPreprocessor().getPreprocessingRecord());
+ ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer };
+ return new MultiplexConsumer(Consumers);
+}
+
+bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
+ Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
+ /*ignoreIfFilesChanges=*/true);
+ CompInst = &CI;
+ CI.getDiagnostics().setIgnoreAllWarnings(true);
+ CI.getPreprocessorOpts().DetailedRecord = true;
+ CI.getPreprocessorOpts().DetailedRecordConditionalDirectives = true;
+ return true;
+}
+
+namespace {
+class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
+ ObjCMigrateASTConsumer &Consumer;
+
+public:
+ ObjCMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
+
+ bool shouldVisitTemplateInstantiations() const { return false; }
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ if (Consumer.MigrateLiterals) {
+ edit::Commit commit(*Consumer.Editor);
+ edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit);
+ Consumer.Editor->commit(commit);
+ }
+
+ if (Consumer.MigrateSubscripting) {
+ edit::Commit commit(*Consumer.Editor);
+ edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
+ Consumer.Editor->commit(commit);
+ }
+
+ return true;
+ }
+
+ bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
+ // Do depth first; we want to rewrite the subexpressions first so that if
+ // we have to move expressions we will move them already rewritten.
+ for (Stmt::child_range range = E->children(); range; ++range)
+ if (!TraverseStmt(*range))
+ return false;
+
+ return WalkUpFromObjCMessageExpr(E);
+ }
+};
+}
+
+void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
+ if (!D)
+ return;
+ if (isa<ObjCMethodDecl>(D))
+ return; // Wait for the ObjC container declaration.
+
+ ObjCMigrator(*this).TraverseDecl(D);
+}
+
+namespace {
+
+class RewritesReceiver : public edit::EditsReceiver {
+ Rewriter &Rewrite;
+
+public:
+ RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
+
+ virtual void insert(SourceLocation loc, StringRef text) {
+ Rewrite.InsertText(loc, text);
+ }
+ virtual void replace(CharSourceRange range, StringRef text) {
+ Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
+ }
+};
+
+}
+
+void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
+ Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
+ RewritesReceiver Rec(rewriter);
+ Editor->applyRewrites(Rec);
+
+ for (Rewriter::buffer_iterator
+ I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
+ FileID FID = I->first;
+ RewriteBuffer &buf = I->second;
+ const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
+ assert(file);
+ llvm::SmallString<512> newText;
+ llvm::raw_svector_ostream vecOS(newText);
+ buf.write(vecOS);
+ vecOS.flush();
+ llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
+ StringRef(newText.data(), newText.size()), file->getName());
+ llvm::SmallString<64> filePath(file->getName());
+ FileMgr.FixupRelativePath(filePath);
+ Remapper.remap(filePath.str(), memBuf);
+ }
+
+ if (IsOutputFile) {
+ Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
+ } else {
+ Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
+ }
+}
+
+bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
+ CI.getPreprocessorOpts().DetailedRecord = true;
+ CI.getPreprocessorOpts().DetailedRecordConditionalDirectives = true;
+ return true;
+}
+
+ASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile,
+ /*MigrateLiterals=*/true,
+ /*MigrateSubscripting=*/true,
+ Remapper,
+ CI.getFileManager(),
+ CI.getPreprocessor().getPreprocessingRecord(),
+ /*isOutputFile=*/true);
+}
diff --git a/lib/ARCMigrate/TransARCAssign.cpp b/lib/ARCMigrate/TransARCAssign.cpp
index 1f10196f9daa..cfa6da1f99f9 100644
--- a/lib/ARCMigrate/TransARCAssign.cpp
+++ b/lib/ARCMigrate/TransARCAssign.cpp
@@ -39,6 +39,9 @@ public:
ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
bool VisitBinaryOperator(BinaryOperator *Exp) {
+ if (Exp->getType()->isDependentType())
+ return true;
+
Expr *E = Exp->getLHS();
SourceLocation OrigLoc = E->getExprLoc();
SourceLocation Loc = OrigLoc;
diff --git a/lib/ARCMigrate/TransAutoreleasePool.cpp b/lib/ARCMigrate/TransAutoreleasePool.cpp
index 08561f97f962..87877242a124 100644
--- a/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -263,10 +263,6 @@ private:
return checkRef(E->getLocation(), E->getDecl()->getLocation());
}
- bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
- return checkRef(E->getLocation(), E->getDecl()->getLocation());
- }
-
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
return checkRef(TL.getBeginLoc(), TL.getTypedefNameDecl()->getLocation());
}
diff --git a/lib/ARCMigrate/TransBlockObjCVariable.cpp b/lib/ARCMigrate/TransBlockObjCVariable.cpp
index 48c0ca9cefe5..3be8132e3b7e 100644
--- a/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ b/lib/ARCMigrate/TransBlockObjCVariable.cpp
@@ -38,7 +38,7 @@ namespace {
class RootBlockObjCVarRewriter :
public RecursiveASTVisitor<RootBlockObjCVarRewriter> {
MigrationPass &Pass;
- llvm::DenseSet<VarDecl *> CheckedVars;
+ llvm::DenseSet<VarDecl *> &VarsToChange;
class BlockVarChecker : public RecursiveASTVisitor<BlockVarChecker> {
VarDecl *Var;
@@ -48,13 +48,13 @@ class RootBlockObjCVarRewriter :
BlockVarChecker(VarDecl *var) : Var(var) { }
bool TraverseImplicitCastExpr(ImplicitCastExpr *castE) {
- if (BlockDeclRefExpr *
- ref = dyn_cast<BlockDeclRefExpr>(castE->getSubExpr())) {
+ if (DeclRefExpr *
+ ref = dyn_cast<DeclRefExpr>(castE->getSubExpr())) {
if (ref->getDecl() == Var) {
if (castE->getCastKind() == CK_LValueToRValue)
return true; // Using the value of the variable.
if (castE->getCastKind() == CK_NoOp && castE->isLValue() &&
- Var->getASTContext().getLangOptions().CPlusPlus)
+ Var->getASTContext().getLangOpts().CPlusPlus)
return true; // Binding to const C++ reference.
}
}
@@ -62,7 +62,7 @@ class RootBlockObjCVarRewriter :
return base::TraverseImplicitCastExpr(castE);
}
- bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
if (E->getDecl() == Var)
return false; // The reference of the variable, and not just its value,
// is needed.
@@ -71,7 +71,9 @@ class RootBlockObjCVarRewriter :
};
public:
- RootBlockObjCVarRewriter(MigrationPass &pass) : Pass(pass) { }
+ RootBlockObjCVarRewriter(MigrationPass &pass,
+ llvm::DenseSet<VarDecl *> &VarsToChange)
+ : Pass(pass), VarsToChange(VarsToChange) { }
bool VisitBlockDecl(BlockDecl *block) {
SmallVector<VarDecl *, 4> BlockVars;
@@ -80,7 +82,6 @@ public:
I = block->capture_begin(), E = block->capture_end(); I != E; ++I) {
VarDecl *var = I->getVariable();
if (I->isByRef() &&
- !isAlreadyChecked(var) &&
var->getType()->isObjCObjectPointerType() &&
isImplicitStrong(var->getType())) {
BlockVars.push_back(var);
@@ -89,32 +90,19 @@ public:
for (unsigned i = 0, e = BlockVars.size(); i != e; ++i) {
VarDecl *var = BlockVars[i];
- CheckedVars.insert(var);
BlockVarChecker checker(var);
bool onlyValueOfVarIsNeeded = checker.TraverseStmt(block->getBody());
- if (onlyValueOfVarIsNeeded) {
- BlocksAttr *attr = var->getAttr<BlocksAttr>();
- if(!attr)
- continue;
- bool useWeak = canApplyWeak(Pass.Ctx, var->getType());
- SourceManager &SM = Pass.Ctx.getSourceManager();
- Transaction Trans(Pass.TA);
- Pass.TA.replaceText(SM.getExpansionLoc(attr->getLocation()),
- "__block",
- useWeak ? "__weak" : "__unsafe_unretained");
- }
-
+ if (onlyValueOfVarIsNeeded)
+ VarsToChange.insert(var);
+ else
+ VarsToChange.erase(var);
}
return true;
}
private:
- bool isAlreadyChecked(VarDecl *VD) {
- return CheckedVars.count(VD);
- }
-
bool isImplicitStrong(QualType ty) {
if (isa<AttributedType>(ty.getTypePtr()))
return false;
@@ -124,19 +112,39 @@ private:
class BlockObjCVarRewriter : public RecursiveASTVisitor<BlockObjCVarRewriter> {
MigrationPass &Pass;
+ llvm::DenseSet<VarDecl *> &VarsToChange;
public:
- BlockObjCVarRewriter(MigrationPass &pass) : Pass(pass) { }
+ BlockObjCVarRewriter(MigrationPass &pass,
+ llvm::DenseSet<VarDecl *> &VarsToChange)
+ : Pass(pass), VarsToChange(VarsToChange) { }
bool TraverseBlockDecl(BlockDecl *block) {
- RootBlockObjCVarRewriter(Pass).TraverseDecl(block);
+ RootBlockObjCVarRewriter(Pass, VarsToChange).TraverseDecl(block);
return true;
}
};
} // anonymous namespace
-void trans::rewriteBlockObjCVariable(MigrationPass &pass) {
- BlockObjCVarRewriter trans(pass);
- trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+void BlockObjCVariableTraverser::traverseBody(BodyContext &BodyCtx) {
+ MigrationPass &Pass = BodyCtx.getMigrationContext().Pass;
+ llvm::DenseSet<VarDecl *> VarsToChange;
+
+ BlockObjCVarRewriter trans(Pass, VarsToChange);
+ trans.TraverseStmt(BodyCtx.getTopStmt());
+
+ for (llvm::DenseSet<VarDecl *>::iterator
+ I = VarsToChange.begin(), E = VarsToChange.end(); I != E; ++I) {
+ VarDecl *var = *I;
+ BlocksAttr *attr = var->getAttr<BlocksAttr>();
+ if(!attr)
+ continue;
+ bool useWeak = canApplyWeak(Pass.Ctx, var->getType());
+ SourceManager &SM = Pass.Ctx.getSourceManager();
+ Transaction Trans(Pass.TA);
+ Pass.TA.replaceText(SM.getExpansionLoc(attr->getLocation()),
+ "__block",
+ useWeak ? "__weak" : "__unsafe_unretained");
+ }
}
diff --git a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index 3ad05e683c78..0fb7141544aa 100644
--- a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -196,35 +196,60 @@ static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
return true;
}
-static void removeDeallocMethod(MigrationPass &pass) {
+static void cleanupDeallocOrFinalize(MigrationPass &pass) {
ASTContext &Ctx = pass.Ctx;
TransformActions &TA = pass.TA;
DeclContext *DC = Ctx.getTranslationUnitDecl();
+ Selector FinalizeSel =
+ Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
impl_iterator;
for (impl_iterator I = impl_iterator(DC->decls_begin()),
E = impl_iterator(DC->decls_end()); I != E; ++I) {
+ ObjCMethodDecl *DeallocM = 0;
+ ObjCMethodDecl *FinalizeM = 0;
for (ObjCImplementationDecl::instmeth_iterator
MI = (*I)->instmeth_begin(),
ME = (*I)->instmeth_end(); MI != ME; ++MI) {
ObjCMethodDecl *MD = *MI;
+ if (!MD->hasBody())
+ continue;
+
if (MD->getMethodFamily() == OMF_dealloc) {
- if (MD->hasBody() &&
- isBodyEmpty(MD->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
- Transaction Trans(TA);
- TA.remove(MD->getSourceRange());
- }
- break;
+ DeallocM = MD;
+ } else if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
+ FinalizeM = MD;
+ }
+ }
+
+ if (DeallocM) {
+ if (isBodyEmpty(DeallocM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
+ Transaction Trans(TA);
+ TA.remove(DeallocM->getSourceRange());
+ }
+
+ if (FinalizeM) {
+ Transaction Trans(TA);
+ TA.remove(FinalizeM->getSourceRange());
+ }
+
+ } else if (FinalizeM) {
+ if (isBodyEmpty(FinalizeM->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
+ Transaction Trans(TA);
+ TA.remove(FinalizeM->getSourceRange());
+ } else {
+ Transaction Trans(TA);
+ TA.replaceText(FinalizeM->getSelectorStartLoc(), "finalize", "dealloc");
}
}
}
}
-void trans::removeEmptyStatementsAndDealloc(MigrationPass &pass) {
+void trans::removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass) {
EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
- removeDeallocMethod(pass);
+ cleanupDeallocOrFinalize(pass);
for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
Transaction Trans(pass.TA);
diff --git a/lib/ARCMigrate/TransGCAttrs.cpp b/lib/ARCMigrate/TransGCAttrs.cpp
new file mode 100644
index 000000000000..9f6066ef77da
--- /dev/null
+++ b/lib/ARCMigrate/TransGCAttrs.cpp
@@ -0,0 +1,358 @@
+//===--- TransGCAttrs.cpp - Transformations to ARC mode --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/TinyPtrVector.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+
+namespace {
+
+/// \brief Collects all the places where GC attributes __strong/__weak occur.
+class GCAttrsCollector : public RecursiveASTVisitor<GCAttrsCollector> {
+ MigrationContext &MigrateCtx;
+ bool FullyMigratable;
+ std::vector<ObjCPropertyDecl *> &AllProps;
+
+ typedef RecursiveASTVisitor<GCAttrsCollector> base;
+public:
+ GCAttrsCollector(MigrationContext &ctx,
+ std::vector<ObjCPropertyDecl *> &AllProps)
+ : MigrateCtx(ctx), FullyMigratable(false),
+ AllProps(AllProps) { }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+ handleAttr(TL);
+ return true;
+ }
+
+ bool TraverseDecl(Decl *D) {
+ if (!D || D->isImplicit())
+ return true;
+
+ SaveAndRestore<bool> Save(FullyMigratable, isMigratable(D));
+
+ if (ObjCPropertyDecl *PropD = dyn_cast<ObjCPropertyDecl>(D)) {
+ lookForAttribute(PropD, PropD->getTypeSourceInfo());
+ AllProps.push_back(PropD);
+ } else if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+ lookForAttribute(DD, DD->getTypeSourceInfo());
+ }
+ return base::TraverseDecl(D);
+ }
+
+ void lookForAttribute(Decl *D, TypeSourceInfo *TInfo) {
+ if (!TInfo)
+ return;
+ TypeLoc TL = TInfo->getTypeLoc();
+ while (TL) {
+ if (const QualifiedTypeLoc *QL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+ TL = QL->getUnqualifiedLoc();
+ } else if (const AttributedTypeLoc *
+ Attr = dyn_cast<AttributedTypeLoc>(&TL)) {
+ if (handleAttr(*Attr, D))
+ break;
+ TL = Attr->getModifiedLoc();
+ } else if (const ArrayTypeLoc *Arr = dyn_cast<ArrayTypeLoc>(&TL)) {
+ TL = Arr->getElementLoc();
+ } else if (const PointerTypeLoc *PT = dyn_cast<PointerTypeLoc>(&TL)) {
+ TL = PT->getPointeeLoc();
+ } else if (const ReferenceTypeLoc *RT = dyn_cast<ReferenceTypeLoc>(&TL))
+ TL = RT->getPointeeLoc();
+ else
+ break;
+ }
+ }
+
+ bool handleAttr(AttributedTypeLoc TL, Decl *D = 0) {
+ if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
+ return false;
+
+ SourceLocation Loc = TL.getAttrNameLoc();
+ unsigned RawLoc = Loc.getRawEncoding();
+ if (MigrateCtx.AttrSet.count(RawLoc))
+ return true;
+
+ ASTContext &Ctx = MigrateCtx.Pass.Ctx;
+ SourceManager &SM = Ctx.getSourceManager();
+ if (Loc.isMacroID())
+ Loc = SM.getImmediateExpansionRange(Loc).first;
+ SmallString<32> Buf;
+ bool Invalid = false;
+ StringRef Spell = Lexer::getSpelling(
+ SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
+ Buf, SM, Ctx.getLangOpts(), &Invalid);
+ if (Invalid)
+ return false;
+ MigrationContext::GCAttrOccurrence::AttrKind Kind;
+ if (Spell == "strong")
+ Kind = MigrationContext::GCAttrOccurrence::Strong;
+ else if (Spell == "weak")
+ Kind = MigrationContext::GCAttrOccurrence::Weak;
+ else
+ return false;
+
+ MigrateCtx.AttrSet.insert(RawLoc);
+ MigrateCtx.GCAttrs.push_back(MigrationContext::GCAttrOccurrence());
+ MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs.back();
+
+ Attr.Kind = Kind;
+ Attr.Loc = Loc;
+ Attr.ModifiedType = TL.getModifiedLoc().getType();
+ Attr.Dcl = D;
+ Attr.FullyMigratable = FullyMigratable;
+ return true;
+ }
+
+ bool isMigratable(Decl *D) {
+ if (isa<TranslationUnitDecl>(D))
+ return false;
+
+ if (isInMainFile(D))
+ return true;
+
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->hasBody();
+
+ if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D))
+ return hasObjCImpl(ContD);
+
+ if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ for (CXXRecordDecl::method_iterator
+ MI = RD->method_begin(), ME = RD->method_end(); MI != ME; ++MI) {
+ if ((*MI)->isOutOfLine())
+ return true;
+ }
+ return false;
+ }
+
+ return isMigratable(cast<Decl>(D->getDeclContext()));
+ }
+
+ static bool hasObjCImpl(Decl *D) {
+ if (!D)
+ return false;
+ if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) {
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD))
+ return ID->getImplementation() != 0;
+ if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD))
+ return CD->getImplementation() != 0;
+ if (isa<ObjCImplDecl>(ContD))
+ return true;
+ return false;
+ }
+ return false;
+ }
+
+ bool isInMainFile(Decl *D) {
+ if (!D)
+ return false;
+
+ for (Decl::redecl_iterator
+ I = D->redecls_begin(), E = D->redecls_end(); I != E; ++I)
+ if (!isInMainFile((*I)->getLocation()))
+ return false;
+
+ return true;
+ }
+
+ bool isInMainFile(SourceLocation Loc) {
+ if (Loc.isInvalid())
+ return false;
+
+ SourceManager &SM = MigrateCtx.Pass.Ctx.getSourceManager();
+ return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID());
+ }
+};
+
+} // anonymous namespace
+
+static void errorForGCAttrsOnNonObjC(MigrationContext &MigrateCtx) {
+ TransformActions &TA = MigrateCtx.Pass.TA;
+
+ for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
+ MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
+ if (Attr.FullyMigratable && Attr.Dcl) {
+ if (Attr.ModifiedType.isNull())
+ continue;
+ if (!Attr.ModifiedType->isObjCRetainableType()) {
+ TA.reportError("GC managed memory will become unmanaged in ARC",
+ Attr.Loc);
+ }
+ }
+ }
+}
+
+static void checkWeakGCAttrs(MigrationContext &MigrateCtx) {
+ TransformActions &TA = MigrateCtx.Pass.TA;
+
+ for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {
+ MigrationContext::GCAttrOccurrence &Attr = MigrateCtx.GCAttrs[i];
+ if (Attr.Kind == MigrationContext::GCAttrOccurrence::Weak) {
+ if (Attr.ModifiedType.isNull() ||
+ !Attr.ModifiedType->isObjCRetainableType())
+ continue;
+ if (!canApplyWeak(MigrateCtx.Pass.Ctx, Attr.ModifiedType,
+ /*AllowOnUnknownClass=*/true)) {
+ Transaction Trans(TA);
+ if (!MigrateCtx.RemovedAttrSet.count(Attr.Loc.getRawEncoding()))
+ TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained");
+ TA.clearDiagnostic(diag::err_arc_weak_no_runtime,
+ diag::err_arc_unsupported_weak_class,
+ Attr.Loc);
+ }
+ }
+ }
+}
+
+typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
+
+static void checkAllAtProps(MigrationContext &MigrateCtx,
+ SourceLocation AtLoc,
+ IndivPropsTy &IndProps) {
+ if (IndProps.empty())
+ return;
+
+ for (IndivPropsTy::iterator
+ PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
+ QualType T = (*PI)->getType();
+ if (T.isNull() || !T->isObjCRetainableType())
+ return;
+ }
+
+ SmallVector<std::pair<AttributedTypeLoc, ObjCPropertyDecl *>, 4> ATLs;
+ bool hasWeak = false, hasStrong = false;
+ ObjCPropertyDecl::PropertyAttributeKind
+ Attrs = ObjCPropertyDecl::OBJC_PR_noattr;
+ for (IndivPropsTy::iterator
+ PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {
+ ObjCPropertyDecl *PD = *PI;
+ Attrs = PD->getPropertyAttributesAsWritten();
+ TypeSourceInfo *TInfo = PD->getTypeSourceInfo();
+ if (!TInfo)
+ return;
+ TypeLoc TL = TInfo->getTypeLoc();
+ if (AttributedTypeLoc *ATL = dyn_cast<AttributedTypeLoc>(&TL)) {
+ ATLs.push_back(std::make_pair(*ATL, PD));
+ if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+ hasWeak = true;
+ } else if (TInfo->getType().getObjCLifetime() == Qualifiers::OCL_Strong)
+ hasStrong = true;
+ else
+ return;
+ }
+ }
+ if (ATLs.empty())
+ return;
+ if (hasWeak && hasStrong)
+ return;
+
+ TransformActions &TA = MigrateCtx.Pass.TA;
+ Transaction Trans(TA);
+
+ if (GCAttrsCollector::hasObjCImpl(
+ cast<Decl>(IndProps.front()->getDeclContext()))) {
+ if (hasWeak)
+ MigrateCtx.AtPropsWeak.insert(AtLoc.getRawEncoding());
+
+ } else {
+ StringRef toAttr = "strong";
+ if (hasWeak) {
+ if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(),
+ /*AllowOnUnkwownClass=*/true))
+ toAttr = "weak";
+ else
+ toAttr = "unsafe_unretained";
+ }
+ if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
+ MigrateCtx.rewritePropertyAttribute("assign", toAttr, AtLoc);
+ else
+ MigrateCtx.addPropertyAttribute(toAttr, AtLoc);
+ }
+
+ for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
+ SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
+ if (Loc.isMacroID())
+ Loc = MigrateCtx.Pass.Ctx.getSourceManager()
+ .getImmediateExpansionRange(Loc).first;
+ TA.remove(Loc);
+ TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);
+ TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,
+ ATLs[i].second->getLocation());
+ MigrateCtx.RemovedAttrSet.insert(Loc.getRawEncoding());
+ }
+}
+
+static void checkAllProps(MigrationContext &MigrateCtx,
+ std::vector<ObjCPropertyDecl *> &AllProps) {
+ typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;
+ llvm::DenseMap<unsigned, IndivPropsTy> AtProps;
+
+ for (unsigned i = 0, e = AllProps.size(); i != e; ++i) {
+ ObjCPropertyDecl *PD = AllProps[i];
+ if (PD->getPropertyAttributesAsWritten() &
+ (ObjCPropertyDecl::OBJC_PR_assign |
+ ObjCPropertyDecl::OBJC_PR_readonly)) {
+ SourceLocation AtLoc = PD->getAtLoc();
+ if (AtLoc.isInvalid())
+ continue;
+ unsigned RawAt = AtLoc.getRawEncoding();
+ AtProps[RawAt].push_back(PD);
+ }
+ }
+
+ for (llvm::DenseMap<unsigned, IndivPropsTy>::iterator
+ I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
+ SourceLocation AtLoc = SourceLocation::getFromRawEncoding(I->first);
+ IndivPropsTy &IndProps = I->second;
+ checkAllAtProps(MigrateCtx, AtLoc, IndProps);
+ }
+}
+
+void GCAttrsTraverser::traverseTU(MigrationContext &MigrateCtx) {
+ std::vector<ObjCPropertyDecl *> AllProps;
+ GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl(
+ MigrateCtx.Pass.Ctx.getTranslationUnitDecl());
+
+ errorForGCAttrsOnNonObjC(MigrateCtx);
+ checkAllProps(MigrateCtx, AllProps);
+ checkWeakGCAttrs(MigrateCtx);
+}
+
+void MigrationContext::dumpGCAttrs() {
+ llvm::errs() << "\n################\n";
+ for (unsigned i = 0, e = GCAttrs.size(); i != e; ++i) {
+ GCAttrOccurrence &Attr = GCAttrs[i];
+ llvm::errs() << "KIND: "
+ << (Attr.Kind == GCAttrOccurrence::Strong ? "strong" : "weak");
+ llvm::errs() << "\nLOC: ";
+ Attr.Loc.dump(Pass.Ctx.getSourceManager());
+ llvm::errs() << "\nTYPE: ";
+ Attr.ModifiedType.dump();
+ if (Attr.Dcl) {
+ llvm::errs() << "DECL:\n";
+ Attr.Dcl->dump();
+ } else {
+ llvm::errs() << "DECL: NONE";
+ }
+ llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable;
+ llvm::errs() << "\n----------------\n";
+ }
+ llvm::errs() << "\n################\n";
+}
diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp
new file mode 100644
index 000000000000..1be902088c62
--- /dev/null
+++ b/lib/ARCMigrate/TransGCCalls.cpp
@@ -0,0 +1,84 @@
+//===--- TransGCCalls.cpp - Tranformations to ARC mode --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+
+namespace {
+
+class GCCollectableCallsChecker :
+ public RecursiveASTVisitor<GCCollectableCallsChecker> {
+ MigrationContext &MigrateCtx;
+ ParentMap &PMap;
+ IdentifierInfo *NSMakeCollectableII;
+ IdentifierInfo *CFMakeCollectableII;
+
+public:
+ GCCollectableCallsChecker(MigrationContext &ctx, ParentMap &map)
+ : MigrateCtx(ctx), PMap(map) {
+ IdentifierTable &Ids = MigrateCtx.Pass.Ctx.Idents;
+ NSMakeCollectableII = &Ids.get("NSMakeCollectable");
+ CFMakeCollectableII = &Ids.get("CFMakeCollectable");
+ }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool VisitCallExpr(CallExpr *E) {
+ TransformActions &TA = MigrateCtx.Pass.TA;
+
+ if (MigrateCtx.isGCOwnedNonObjC(E->getType())) {
+ if (MigrateCtx.Pass.noNSAllocReallocError())
+ TA.reportWarning("call returns pointer to GC managed memory; "
+ "it will become unmanaged in ARC",
+ E->getLocStart(), E->getSourceRange());
+ else
+ TA.reportError("call returns pointer to GC managed memory; "
+ "it will become unmanaged in ARC",
+ E->getLocStart(), E->getSourceRange());
+ return true;
+ }
+
+ Expr *CEE = E->getCallee()->IgnoreParenImpCasts();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
+ if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) {
+ if (!FD->getDeclContext()->getRedeclContext()->isFileContext())
+ return true;
+
+ if (FD->getIdentifier() == NSMakeCollectableII) {
+ Transaction Trans(TA);
+ TA.clearDiagnostic(diag::err_unavailable,
+ diag::err_unavailable_message,
+ diag::err_ovl_deleted_call, // ObjC++
+ DRE->getSourceRange());
+ TA.replace(DRE->getSourceRange(), "CFBridgingRelease");
+
+ } else if (FD->getIdentifier() == CFMakeCollectableII) {
+ TA.reportError("CFMakeCollectable will leak the object that it "
+ "receives in ARC", DRE->getLocation(),
+ DRE->getSourceRange());
+ }
+ }
+ }
+
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void GCCollectableCallsTraverser::traverseBody(BodyContext &BodyCtx) {
+ GCCollectableCallsChecker(BodyCtx.getMigrationContext(),
+ BodyCtx.getParentMap())
+ .TraverseStmt(BodyCtx.getTopStmt());
+}
diff --git a/lib/ARCMigrate/TransProperties.cpp b/lib/ARCMigrate/TransProperties.cpp
index ca845b6b330d..cc85fe25cca9 100644
--- a/lib/ARCMigrate/TransProperties.cpp
+++ b/lib/ARCMigrate/TransProperties.cpp
@@ -44,8 +44,17 @@ using namespace trans;
namespace {
class PropertiesRewriter {
+ MigrationContext &MigrateCtx;
MigrationPass &Pass;
ObjCImplementationDecl *CurImplD;
+
+ enum PropActionKind {
+ PropAction_None,
+ PropAction_RetainReplacedWithStrong,
+ PropAction_AssignRemoved,
+ PropAction_AssignRewritten,
+ PropAction_MaybeAddWeakOrUnsafe
+ };
struct PropData {
ObjCPropertyDecl *PropD;
@@ -58,9 +67,27 @@ class PropertiesRewriter {
typedef SmallVector<PropData, 2> PropsTy;
typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
AtPropDeclsTy AtProps;
+ llvm::DenseMap<IdentifierInfo *, PropActionKind> ActionOnProp;
public:
- PropertiesRewriter(MigrationPass &pass) : Pass(pass) { }
+ explicit PropertiesRewriter(MigrationContext &MigrateCtx)
+ : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { }
+
+ static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps,
+ AtPropDeclsTy *PrevAtProps = 0) {
+ for (ObjCInterfaceDecl::prop_iterator
+ propI = D->prop_begin(),
+ propE = D->prop_end(); propI != propE; ++propI) {
+ if (propI->getAtLoc().isInvalid())
+ continue;
+ unsigned RawLoc = propI->getAtLoc().getRawEncoding();
+ if (PrevAtProps)
+ if (PrevAtProps->find(RawLoc) != PrevAtProps->end())
+ continue;
+ PropsTy &props = AtProps[RawLoc];
+ props.push_back(*propI);
+ }
+ }
void doTransform(ObjCImplementationDecl *D) {
CurImplD = D;
@@ -68,14 +95,7 @@ public:
if (!iface)
return;
- for (ObjCInterfaceDecl::prop_iterator
- propI = iface->prop_begin(),
- propE = iface->prop_end(); propI != propE; ++propI) {
- if (propI->getAtLoc().isInvalid())
- continue;
- PropsTy &props = AtProps[propI->getAtLoc().getRawEncoding()];
- props.push_back(*propI);
- }
+ collectProperties(iface, AtProps);
typedef DeclContext::specific_decl_iterator<ObjCPropertyImplDecl>
prop_impl_iterator;
@@ -110,19 +130,66 @@ public:
I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {
SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
PropsTy &props = I->second;
- QualType ty = getPropertyType(props);
- if (!ty->isObjCRetainableType())
+ if (!getPropertyType(props)->isObjCRetainableType())
continue;
- if (hasIvarWithExplicitOwnership(props))
+ if (hasIvarWithExplicitARCOwnership(props))
continue;
Transaction Trans(Pass.TA);
rewriteProperty(props, atLoc);
}
+
+ AtPropDeclsTy AtExtProps;
+ // Look through extensions.
+ for (ObjCCategoryDecl *Cat = iface->getCategoryList();
+ Cat; Cat = Cat->getNextClassCategory())
+ if (Cat->IsClassExtension())
+ collectProperties(Cat, AtExtProps, &AtProps);
+
+ for (AtPropDeclsTy::iterator
+ I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) {
+ SourceLocation atLoc = SourceLocation::getFromRawEncoding(I->first);
+ PropsTy &props = I->second;
+ Transaction Trans(Pass.TA);
+ doActionForExtensionProp(props, atLoc);
+ }
}
private:
- void rewriteProperty(PropsTy &props, SourceLocation atLoc) const {
+ void doPropAction(PropActionKind kind,
+ PropsTy &props, SourceLocation atLoc,
+ bool markAction = true) {
+ if (markAction)
+ for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
+ ActionOnProp[I->PropD->getIdentifier()] = kind;
+
+ switch (kind) {
+ case PropAction_None:
+ return;
+ case PropAction_RetainReplacedWithStrong: {
+ StringRef toAttr = "strong";
+ MigrateCtx.rewritePropertyAttribute("retain", toAttr, atLoc);
+ return;
+ }
+ case PropAction_AssignRemoved:
+ return removeAssignForDefaultStrong(props, atLoc);
+ case PropAction_AssignRewritten:
+ return rewriteAssign(props, atLoc);
+ case PropAction_MaybeAddWeakOrUnsafe:
+ return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
+ }
+ }
+
+ void doActionForExtensionProp(PropsTy &props, SourceLocation atLoc) {
+ llvm::DenseMap<IdentifierInfo *, PropActionKind>::iterator I;
+ I = ActionOnProp.find(props[0].PropD->getIdentifier());
+ if (I == ActionOnProp.end())
+ return;
+
+ doPropAction(I->second, props, atLoc, false);
+ }
+
+ void rewriteProperty(PropsTy &props, SourceLocation atLoc) {
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
if (propAttrs & (ObjCPropertyDecl::OBJC_PR_copy |
@@ -132,79 +199,82 @@ private:
return;
if (propAttrs & ObjCPropertyDecl::OBJC_PR_retain) {
- rewriteAttribute("retain", "strong", atLoc);
- return;
+ // strong is the default.
+ return doPropAction(PropAction_RetainReplacedWithStrong, props, atLoc);
}
+ bool HasIvarAssignedAPlusOneObject = hasIvarAssignedAPlusOneObject(props);
+
if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
- if (hasIvarAssignedAPlusOneObject(props)) {
- rewriteAttribute("assign", "strong", atLoc);
- return;
- }
- return rewriteAssign(props, atLoc);
+ if (HasIvarAssignedAPlusOneObject)
+ return doPropAction(PropAction_AssignRemoved, props, atLoc);
+ return doPropAction(PropAction_AssignRewritten, props, atLoc);
}
- if (hasIvarAssignedAPlusOneObject(props))
- return maybeAddStrongAttr(props, atLoc);
+ if (HasIvarAssignedAPlusOneObject ||
+ (Pass.isGCMigration() && !hasGCWeak(props, atLoc)))
+ return; // 'strong' by default.
- return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
+ return doPropAction(PropAction_MaybeAddWeakOrUnsafe, props, atLoc);
}
- void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
- bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
-
- bool rewroteAttr = rewriteAttribute("assign",
- canUseWeak ? "weak" : "unsafe_unretained",
- atLoc);
- if (!rewroteAttr)
- canUseWeak = false;
+ void removeAssignForDefaultStrong(PropsTy &props,
+ SourceLocation atLoc) const {
+ removeAttribute("retain", atLoc);
+ if (!removeAttribute("assign", atLoc))
+ return;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD))
- Pass.TA.insert(I->IvarD->getLocation(),
- canUseWeak ? "__weak " : "__unsafe_unretained ");
if (I->ImplD)
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
I->ImplD->getLocation());
}
}
- void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
- SourceLocation atLoc) const {
- ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
+ void rewriteAssign(PropsTy &props, SourceLocation atLoc) const {
+ bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
+ /*AllowOnUnknownClass=*/Pass.isGCMigration());
+ const char *toWhich =
+ (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "strong" :
+ (canUseWeak ? "weak" : "unsafe_unretained");
- bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
- if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
- !hasAllIvarsBacked(props)) {
- bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
- atLoc);
- if (!addedAttr)
- canUseWeak = false;
- }
+ bool rewroteAttr = rewriteAttribute("assign", toWhich, atLoc);
+ if (!rewroteAttr)
+ canUseWeak = false;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
- if (isUserDeclared(I->IvarD))
- Pass.TA.insert(I->IvarD->getLocation(),
- canUseWeak ? "__weak " : "__unsafe_unretained ");
- if (I->ImplD) {
+ if (isUserDeclared(I->IvarD)) {
+ if (I->IvarD &&
+ I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak) {
+ const char *toWhich =
+ (Pass.isGCMigration() && !hasGCWeak(props, atLoc)) ? "__strong " :
+ (canUseWeak ? "__weak " : "__unsafe_unretained ");
+ Pass.TA.insert(I->IvarD->getLocation(), toWhich);
+ }
+ }
+ if (I->ImplD)
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
I->ImplD->getLocation());
- Pass.TA.clearDiagnostic(
- diag::err_arc_objc_property_default_assign_on_object,
- I->ImplD->getLocation());
- }
}
}
- void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const {
- ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
+ void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
+ SourceLocation atLoc) const {
+ bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props),
+ /*AllowOnUnknownClass=*/Pass.isGCMigration());
- if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
- !hasAllIvarsBacked(props)) {
- addAttribute("strong", atLoc);
- }
+ bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
+ atLoc);
+ if (!addedAttr)
+ canUseWeak = false;
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
+ if (isUserDeclared(I->IvarD)) {
+ if (I->IvarD &&
+ I->IvarD->getType().getObjCLifetime() != Qualifiers::OCL_Weak)
+ Pass.TA.insert(I->IvarD->getLocation(),
+ canUseWeak ? "__weak " : "__unsafe_unretained ");
+ }
if (I->ImplD) {
Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
I->ImplD->getLocation());
@@ -215,108 +285,17 @@ private:
}
}
+ bool removeAttribute(StringRef fromAttr, SourceLocation atLoc) const {
+ return MigrateCtx.removePropertyAttribute(fromAttr, atLoc);
+ }
+
bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
SourceLocation atLoc) const {
- if (atLoc.isMacroID())
- return false;
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Pass.Ctx.getLangOptions(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::at)) return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::raw_identifier)) return false;
- if (StringRef(tok.getRawIdentifierData(), tok.getLength())
- != "property")
- return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::l_paren)) return false;
-
- lexer.LexFromRawLexer(tok);
- if (tok.is(tok::r_paren))
- return false;
-
- while (1) {
- if (tok.isNot(tok::raw_identifier)) return false;
- StringRef ident(tok.getRawIdentifierData(), tok.getLength());
- if (ident == fromAttr) {
- Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
- return true;
- }
-
- do {
- lexer.LexFromRawLexer(tok);
- } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
- if (tok.is(tok::r_paren))
- break;
- lexer.LexFromRawLexer(tok);
- }
-
- return false;
+ return MigrateCtx.rewritePropertyAttribute(fromAttr, toAttr, atLoc);
}
bool addAttribute(StringRef attr, SourceLocation atLoc) const {
- if (atLoc.isMacroID())
- return false;
-
- SourceManager &SM = Pass.Ctx.getSourceManager();
-
- // Break down the source location.
- std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
-
- // Try to load the file buffer.
- bool invalidTemp = false;
- StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
- if (invalidTemp)
- return false;
-
- const char *tokenBegin = file.data() + locInfo.second;
-
- // Lex from the start of the given location.
- Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Pass.Ctx.getLangOptions(),
- file.begin(), tokenBegin, file.end());
- Token tok;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::at)) return false;
- lexer.LexFromRawLexer(tok);
- if (tok.isNot(tok::raw_identifier)) return false;
- if (StringRef(tok.getRawIdentifierData(), tok.getLength())
- != "property")
- return false;
- lexer.LexFromRawLexer(tok);
-
- if (tok.isNot(tok::l_paren)) {
- Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
- return true;
- }
-
- lexer.LexFromRawLexer(tok);
- if (tok.is(tok::r_paren)) {
- Pass.TA.insert(tok.getLocation(), attr);
- return true;
- }
-
- if (tok.isNot(tok::raw_identifier)) return false;
-
- Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
- return true;
+ return MigrateCtx.addPropertyAttribute(attr, atLoc);
}
class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
@@ -358,7 +337,10 @@ private:
return false;
}
- bool hasIvarWithExplicitOwnership(PropsTy &props) const {
+ bool hasIvarWithExplicitARCOwnership(PropsTy &props) const {
+ if (Pass.isGCMigration())
+ return false;
+
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
if (isUserDeclared(I->IvarD)) {
if (isa<AttributedType>(I->IvarD->getType()))
@@ -380,17 +362,26 @@ private:
return true;
}
+ // \brief Returns true if all declarations in the @property have GC __weak.
+ bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const {
+ if (!Pass.isGCMigration())
+ return false;
+ if (props.empty())
+ return false;
+ return MigrateCtx.AtPropsWeak.count(atLoc.getRawEncoding());
+ }
+
bool isUserDeclared(ObjCIvarDecl *ivarD) const {
return ivarD && !ivarD->getSynthesize();
}
QualType getPropertyType(PropsTy &props) const {
assert(!props.empty());
- QualType ty = props[0].PropD->getType();
+ QualType ty = props[0].PropD->getType().getUnqualifiedType();
#ifndef NDEBUG
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
- assert(ty == I->PropD->getType());
+ assert(ty == I->PropD->getType().getUnqualifiedType());
#endif
return ty;
@@ -411,21 +402,10 @@ private:
}
};
-class ImplementationChecker :
- public RecursiveASTVisitor<ImplementationChecker> {
- MigrationPass &Pass;
-
-public:
- ImplementationChecker(MigrationPass &pass) : Pass(pass) { }
-
- bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
- PropertiesRewriter(Pass).doTransform(D);
- return true;
- }
-};
-
} // anonymous namespace
-void trans::rewriteProperties(MigrationPass &pass) {
- ImplementationChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+void PropertyRewriteTraverser::traverseObjCImplementation(
+ ObjCImplementationContext &ImplCtx) {
+ PropertiesRewriter(ImplCtx.getMigrationContext())
+ .doTransform(ImplCtx.getImplementationDecl());
}
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index 394f8480e112..11a655334144 100644
--- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -21,6 +21,8 @@
#include "Internals.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/AST/ParentMap.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Basic/SourceManager.h"
using namespace clang;
using namespace arcmt;
@@ -34,15 +36,17 @@ class RetainReleaseDeallocRemover :
MigrationPass &Pass;
ExprSet Removables;
- llvm::OwningPtr<ParentMap> StmtMap;
+ OwningPtr<ParentMap> StmtMap;
- Selector DelegateSel;
+ Selector DelegateSel, FinalizeSel;
public:
RetainReleaseDeallocRemover(MigrationPass &pass)
: Body(0), Pass(pass) {
DelegateSel =
Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate"));
+ FinalizeSel =
+ Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
}
void transformBody(Stmt *body) {
@@ -55,6 +59,8 @@ public:
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
switch (E->getMethodFamily()) {
default:
+ if (E->isInstanceMessage() && E->getSelector() == FinalizeSel)
+ break;
return true;
case OMF_autorelease:
if (isRemovable(E)) {
@@ -124,27 +130,105 @@ public:
Transaction Trans(Pass.TA);
clearDiagnostics(rec->getExprLoc());
- if (E->getMethodFamily() == OMF_release &&
- isRemovable(E) && isInAtFinally(E)) {
+ ObjCMessageExpr *Msg = E;
+ Expr *RecContainer = Msg;
+ SourceRange RecRange = rec->getSourceRange();
+ checkForGCDOrXPC(Msg, RecContainer, rec, RecRange);
+
+ if (Msg->getMethodFamily() == OMF_release &&
+ isRemovable(RecContainer) && isInAtFinally(RecContainer)) {
// Change the -release to "receiver = nil" in a finally to avoid a leak
// when an exception is thrown.
- Pass.TA.replace(E->getSourceRange(), rec->getSourceRange());
+ Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
std::string str = " = ";
str += getNilString(Pass.Ctx);
- Pass.TA.insertAfterToken(rec->getLocEnd(), str);
+ Pass.TA.insertAfterToken(RecRange.getEnd(), str);
return true;
}
- if (!hasSideEffects(E, Pass.Ctx)) {
- if (tryRemoving(E))
+ if (!hasSideEffects(rec, Pass.Ctx)) {
+ if (tryRemoving(RecContainer))
return true;
}
- Pass.TA.replace(E->getSourceRange(), rec->getSourceRange());
+ Pass.TA.replace(RecContainer->getSourceRange(), RecRange);
return true;
}
private:
+ /// \brief Check if the retain/release is due to a GCD/XPC macro that are
+ /// defined as:
+ ///
+ /// #define dispatch_retain(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); (void)[_o retain]; })
+ /// #define dispatch_release(object) ({ dispatch_object_t _o = (object); _dispatch_object_validate(_o); [_o release]; })
+ /// #define xpc_retain(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o retain]; })
+ /// #define xpc_release(object) ({ xpc_object_t _o = (object); _xpc_object_validate(_o); [_o release]; })
+ ///
+ /// and return the top container which is the StmtExpr and the macro argument
+ /// expression.
+ void checkForGCDOrXPC(ObjCMessageExpr *Msg, Expr *&RecContainer,
+ Expr *&Rec, SourceRange &RecRange) {
+ SourceLocation Loc = Msg->getExprLoc();
+ if (!Loc.isMacroID())
+ return;
+ SourceManager &SM = Pass.Ctx.getSourceManager();
+ StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM,
+ Pass.Ctx.getLangOpts());
+ bool isGCDOrXPC = llvm::StringSwitch<bool>(MacroName)
+ .Case("dispatch_retain", true)
+ .Case("dispatch_release", true)
+ .Case("xpc_retain", true)
+ .Case("xpc_release", true)
+ .Default(false);
+ if (!isGCDOrXPC)
+ return;
+
+ StmtExpr *StmtE = 0;
+ Stmt *S = Msg;
+ while (S) {
+ if (StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
+ StmtE = SE;
+ break;
+ }
+ S = StmtMap->getParent(S);
+ }
+
+ if (!StmtE)
+ return;
+
+ Stmt::child_range StmtExprChild = StmtE->children();
+ if (!StmtExprChild)
+ return;
+ CompoundStmt *CompS = dyn_cast_or_null<CompoundStmt>(*StmtExprChild);
+ if (!CompS)
+ return;
+
+ Stmt::child_range CompStmtChild = CompS->children();
+ if (!CompStmtChild)
+ return;
+ DeclStmt *DeclS = dyn_cast_or_null<DeclStmt>(*CompStmtChild);
+ if (!DeclS)
+ return;
+ if (!DeclS->isSingleDecl())
+ return;
+ VarDecl *VD = dyn_cast_or_null<VarDecl>(DeclS->getSingleDecl());
+ if (!VD)
+ return;
+ Expr *Init = VD->getInit();
+ if (!Init)
+ return;
+
+ RecContainer = StmtE;
+ Rec = Init->IgnoreParenImpCasts();
+ if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Rec))
+ Rec = EWC->getSubExpr()->IgnoreParenImpCasts();
+ RecRange = Rec->getSourceRange();
+ if (SM.isMacroArgExpansion(RecRange.getBegin()))
+ RecRange.setBegin(SM.getImmediateSpellingLoc(RecRange.getBegin()));
+ if (SM.isMacroArgExpansion(RecRange.getEnd()))
+ RecRange.setEnd(SM.getImmediateSpellingLoc(RecRange.getEnd()));
+ }
+
void clearDiagnostics(SourceLocation loc) const {
Pass.TA.clearDiagnostic(diag::err_arc_illegal_explicit_message,
diag::err_unavailable,
@@ -156,12 +240,14 @@ private:
if (!E) return false;
E = E->IgnoreParenCasts();
+
+ // Also look through property-getter sugar.
+ if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E))
+ E = pseudoOp->getResultExpr()->IgnoreImplicit();
+
if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel);
- if (ObjCPropertyRefExpr *propE = dyn_cast<ObjCPropertyRefExpr>(E))
- return propE->getGetterSelector() == DelegateSel;
-
return false;
}
@@ -211,7 +297,7 @@ private:
} // anonymous namespace
-void trans::removeRetainReleaseDealloc(MigrationPass &pass) {
+void trans::removeRetainReleaseDeallocFinalize(MigrationPass &pass) {
BodyTransform<RetainReleaseDeallocRemover> trans(pass);
trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
}
diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 69fb2e8949e4..48437c795fa9 100644
--- a/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -38,6 +38,7 @@
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/SmallString.h"
using namespace clang;
using namespace arcmt;
@@ -48,7 +49,7 @@ namespace {
class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
MigrationPass &Pass;
IdentifierInfo *SelfII;
- llvm::OwningPtr<ParentMap> StmtMap;
+ OwningPtr<ParentMap> StmtMap;
public:
UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass) {
@@ -128,6 +129,21 @@ private:
if (fname.endswith("Retain") ||
fname.find("Create") != StringRef::npos ||
fname.find("Copy") != StringRef::npos) {
+ // Do not migrate to couple of bridge transfer casts which
+ // cancel each other out. Leave it unchanged so error gets user
+ // attention instead.
+ if (FD->getName() == "CFRetain" &&
+ FD->getNumParams() == 1 &&
+ FD->getParent()->isTranslationUnit() &&
+ FD->getLinkage() == ExternalLinkage) {
+ Expr *Arg = callE->getArg(0);
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
+ const Expr *sub = ICE->getSubExpr();
+ QualType T = sub->getType();
+ if (T->isObjCObjectPointerType())
+ return;
+ }
+ }
castToObjCObject(E, /*retained=*/true);
return;
}
@@ -179,7 +195,7 @@ private:
TA.insertAfterToken(CCE->getLParenLoc(), bridge);
} else {
SourceLocation insertLoc = E->getSubExpr()->getLocStart();
- llvm::SmallString<128> newCast;
+ SmallString<128> newCast;
newCast += '(';
newCast += bridge;
newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
@@ -236,7 +252,15 @@ private:
}
}
- if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getSubExpr())){
+ Expr *subExpr = E->getSubExpr();
+
+ // Look through pseudo-object expressions.
+ if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) {
+ subExpr = pseudo->getResultExpr();
+ assert(subExpr && "no result for pseudo-object of non-void type?");
+ }
+
+ if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) {
if (implCE->getCastKind() == CK_ARCConsumeObject)
return rewriteToBridgedCast(E, OBC_BridgeRetained);
if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
diff --git a/lib/ARCMigrate/TransUnusedInitDelegate.cpp b/lib/ARCMigrate/TransUnusedInitDelegate.cpp
index e2aa6ff93cf3..60ed32aef4ce 100644
--- a/lib/ARCMigrate/TransUnusedInitDelegate.cpp
+++ b/lib/ARCMigrate/TransUnusedInitDelegate.cpp
@@ -54,7 +54,11 @@ public:
Transaction Trans(Pass.TA);
Pass.TA.clearDiagnostic(diag::err_arc_unused_init_message,
ME->getExprLoc());
- Pass.TA.insert(ME->getExprLoc(), "self = ");
+ SourceRange ExprRange = ME->getSourceRange();
+ Pass.TA.insert(ExprRange.getBegin(), "if (!(self = ");
+ std::string retStr = ")) return ";
+ retStr += getNilString(Pass.Ctx);
+ Pass.TA.insertAfterToken(ExprRange.getEnd(), retStr);
}
return true;
}
diff --git a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index 1dbe81114947..d1f08aac28c2 100644
--- a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -31,9 +31,13 @@ class ZeroOutInDeallocRemover :
llvm::DenseMap<ObjCPropertyDecl*, ObjCPropertyImplDecl*> SynthesizedProperties;
ImplicitParamDecl *SelfD;
ExprSet Removables;
+ Selector FinalizeSel;
public:
- ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) { }
+ ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) {
+ FinalizeSel =
+ Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize"));
+ }
bool VisitObjCMessageExpr(ObjCMessageExpr *ME) {
ASTContext &Ctx = Pass.Ctx;
@@ -74,6 +78,15 @@ public:
return true;
}
+ bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
+ if (isZeroingPropIvar(POE) && isRemovable(POE)) {
+ Transaction Trans(Pass.TA);
+ Pass.TA.removeStmt(POE);
+ }
+
+ return true;
+ }
+
bool VisitBinaryOperator(BinaryOperator *BOE) {
if (isZeroingPropIvar(BOE) && isRemovable(BOE)) {
Transaction Trans(Pass.TA);
@@ -84,7 +97,8 @@ public:
}
bool TraverseObjCMethodDecl(ObjCMethodDecl *D) {
- if (D->getMethodFamily() != OMF_dealloc)
+ if (D->getMethodFamily() != OMF_dealloc &&
+ !(D->isInstanceMethod() && D->getSelector() == FinalizeSel))
return true;
if (!D->hasBody())
return true;
@@ -137,17 +151,21 @@ private:
}
bool isZeroingPropIvar(Expr *E) {
- BinaryOperator *BOE = dyn_cast_or_null<BinaryOperator>(E);
- if (!BOE) return false;
+ E = E->IgnoreParens();
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E))
+ return isZeroingPropIvar(BO);
+ if (PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(E))
+ return isZeroingPropIvar(PO);
+ return false;
+ }
+ bool isZeroingPropIvar(BinaryOperator *BOE) {
if (BOE->getOpcode() == BO_Comma)
return isZeroingPropIvar(BOE->getLHS()) &&
isZeroingPropIvar(BOE->getRHS());
if (BOE->getOpcode() != BO_Assign)
- return false;
-
- ASTContext &Ctx = Pass.Ctx;
+ return false;
Expr *LHS = BOE->getLHS();
if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) {
@@ -167,31 +185,44 @@ private:
if (!IvarBacksPropertySynthesis)
return false;
}
- else if (ObjCPropertyRefExpr *PropRefExp = dyn_cast<ObjCPropertyRefExpr>(LHS)) {
- // TODO: Using implicit property decl.
- if (PropRefExp->isImplicitProperty())
- return false;
- if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
- if (!SynthesizedProperties.count(PDecl))
- return false;
- }
- }
else
return false;
- Expr *RHS = BOE->getRHS();
- bool RHSIsNull = RHS->isNullPointerConstant(Ctx,
- Expr::NPC_ValueDependentIsNull);
- if (RHSIsNull)
+ return isZero(BOE->getRHS());
+ }
+
+ bool isZeroingPropIvar(PseudoObjectExpr *PO) {
+ BinaryOperator *BO = dyn_cast<BinaryOperator>(PO->getSyntacticForm());
+ if (!BO) return false;
+ if (BO->getOpcode() != BO_Assign) return false;
+
+ ObjCPropertyRefExpr *PropRefExp =
+ dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParens());
+ if (!PropRefExp) return false;
+
+ // TODO: Using implicit property decl.
+ if (PropRefExp->isImplicitProperty())
+ return false;
+
+ if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) {
+ if (!SynthesizedProperties.count(PDecl))
+ return false;
+ }
+
+ return isZero(cast<OpaqueValueExpr>(BO->getRHS())->getSourceExpr());
+ }
+
+ bool isZero(Expr *E) {
+ if (E->isNullPointerConstant(Pass.Ctx, Expr::NPC_ValueDependentIsNull))
return true;
- return isZeroingPropIvar(RHS);
+ return isZeroingPropIvar(E);
}
};
} // anonymous namespace
-void trans::removeZeroOutPropsInDealloc(MigrationPass &pass) {
+void trans::removeZeroOutPropsInDeallocFinalize(MigrationPass &pass) {
ZeroOutInDeallocRemover trans(pass);
trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
}
diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp
index ec676e909a3b..0ecfeb54f85d 100644
--- a/lib/ARCMigrate/TransformActions.cpp
+++ b/lib/ARCMigrate/TransformActions.cpp
@@ -122,6 +122,8 @@ public:
ASTContext &ctx, Preprocessor &PP)
: CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { }
+ ASTContext &getASTContext() { return Ctx; }
+
void startTransaction();
bool commitTransaction();
void abortTransaction();
@@ -674,6 +676,12 @@ void TransformActions::reportError(StringRef error, SourceLocation loc,
SourceRange range) {
assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
"Errors should be emitted out of a transaction");
+
+ SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)->
+ getASTContext().getSourceManager();
+ if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
+ return;
+
// FIXME: Use a custom category name to distinguish rewriter errors.
std::string rewriteErr = "[rewriter] ";
rewriteErr += error;
@@ -684,10 +692,35 @@ void TransformActions::reportError(StringRef error, SourceLocation loc,
ReportedErrors = true;
}
+void TransformActions::reportWarning(StringRef warning, SourceLocation loc,
+ SourceRange range) {
+ assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
+ "Warning should be emitted out of a transaction");
+
+ SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)->
+ getASTContext().getSourceManager();
+ if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
+ return;
+
+ // FIXME: Use a custom category name to distinguish rewriter errors.
+ std::string rewriterWarn = "[rewriter] ";
+ rewriterWarn += warning;
+ unsigned diagID
+ = Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Warning,
+ rewriterWarn);
+ Diags.Report(loc, diagID) << range;
+}
+
void TransformActions::reportNote(StringRef note, SourceLocation loc,
SourceRange range) {
assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
"Errors should be emitted out of a transaction");
+
+ SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)->
+ getASTContext().getSourceManager();
+ if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
+ return;
+
// FIXME: Use a custom category name to distinguish rewriter errors.
std::string rewriteNote = "[rewriter] ";
rewriteNote += note;
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 4244fafe07d4..d342d1aa0477 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -12,8 +12,6 @@
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringSwitch.h"
@@ -24,62 +22,35 @@ using namespace clang;
using namespace arcmt;
using namespace trans;
+ASTTraverser::~ASTTraverser() { }
+
//===----------------------------------------------------------------------===//
// Helpers.
//===----------------------------------------------------------------------===//
-/// \brief True if the class is one that does not support weak.
-static bool isClassInWeakBlacklist(ObjCInterfaceDecl *cls) {
- if (!cls)
+bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
+ bool AllowOnUnknownClass) {
+ if (!Ctx.getLangOpts().ObjCRuntimeHasWeak)
return false;
- bool inList = llvm::StringSwitch<bool>(cls->getName())
- .Case("NSColorSpace", true)
- .Case("NSFont", true)
- .Case("NSFontPanel", true)
- .Case("NSImage", true)
- .Case("NSLazyBrowserCell", true)
- .Case("NSWindow", true)
- .Case("NSWindowController", true)
- .Case("NSMenuView", true)
- .Case("NSPersistentUIWindowInfo", true)
- .Case("NSTableCellView", true)
- .Case("NSATSTypeSetter", true)
- .Case("NSATSGlyphStorage", true)
- .Case("NSLineFragmentRenderingContext", true)
- .Case("NSAttributeDictionary", true)
- .Case("NSParagraphStyle", true)
- .Case("NSTextTab", true)
- .Case("NSSimpleHorizontalTypesetter", true)
- .Case("_NSCachedAttributedString", true)
- .Case("NSStringDrawingTextStorage", true)
- .Case("NSTextView", true)
- .Case("NSSubTextStorage", true)
- .Default(false);
-
- if (inList)
- return true;
-
- return isClassInWeakBlacklist(cls->getSuperClass());
-}
-
-bool trans::canApplyWeak(ASTContext &Ctx, QualType type) {
- if (!Ctx.getLangOptions().ObjCRuntimeHasWeak)
+ QualType T = type;
+ if (T.isNull())
return false;
- QualType T = type;
+ // iOS is always safe to use 'weak'.
+ if (Ctx.getTargetInfo().getTriple().getOS() == llvm::Triple::IOS)
+ AllowOnUnknownClass = true;
+
while (const PointerType *ptr = T->getAs<PointerType>())
T = ptr->getPointeeType();
if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
- if (!Class || Class->getName() == "NSObject")
+ if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject"))
return false; // id/NSObject is not safe for weak.
- if (Class->isForwardDecl())
+ if (!AllowOnUnknownClass && !Class->hasDefinition())
return false; // forward classes are not verifiable, therefore not safe.
if (Class->isArcWeakrefUnavailable())
return false;
- if (isClassInWeakBlacklist(Class))
- return false;
}
return true;
@@ -105,11 +76,10 @@ SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
ASTContext &Ctx) {
SourceManager &SM = Ctx.getSourceManager();
if (loc.isMacroID()) {
- if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
+ if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc))
return SourceLocation();
- loc = SM.getExpansionRange(loc).second;
}
- loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
+ loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts());
// Break down the source location.
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
@@ -124,7 +94,7 @@ SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
// Lex from the start of the given location.
Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
- Ctx.getLangOptions(),
+ Ctx.getLangOpts(),
file.begin(), tokenBegin, file.end());
Token tok;
lexer.LexFromRawLexer(tok);
@@ -189,7 +159,6 @@ class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
public:
ReferenceClear(ExprSet &refs) : Refs(refs) { }
bool VisitDeclRefExpr(DeclRefExpr *E) { Refs.erase(E); return true; }
- bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { Refs.erase(E); return true; }
};
class ReferenceCollector : public RecursiveASTVisitor<ReferenceCollector> {
@@ -205,12 +174,6 @@ public:
Refs.insert(E);
return true;
}
-
- bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
- if (E->getDecl() == Dcl)
- Refs.insert(E);
- return true;
- }
};
class RemovablesCollector : public RecursiveASTVisitor<RemovablesCollector> {
@@ -290,27 +253,290 @@ void trans::collectRemovables(Stmt *S, ExprSet &exprs) {
}
//===----------------------------------------------------------------------===//
+// MigrationContext
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class ASTTransform : public RecursiveASTVisitor<ASTTransform> {
+ MigrationContext &MigrateCtx;
+ typedef RecursiveASTVisitor<ASTTransform> base;
+
+public:
+ ASTTransform(MigrationContext &MigrateCtx) : MigrateCtx(MigrateCtx) { }
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
+ ObjCImplementationContext ImplCtx(MigrateCtx, D);
+ for (MigrationContext::traverser_iterator
+ I = MigrateCtx.traversers_begin(),
+ E = MigrateCtx.traversers_end(); I != E; ++I)
+ (*I)->traverseObjCImplementation(ImplCtx);
+
+ return base::TraverseObjCImplementationDecl(D);
+ }
+
+ bool TraverseStmt(Stmt *rootS) {
+ if (!rootS)
+ return true;
+
+ BodyContext BodyCtx(MigrateCtx, rootS);
+ for (MigrationContext::traverser_iterator
+ I = MigrateCtx.traversers_begin(),
+ E = MigrateCtx.traversers_end(); I != E; ++I)
+ (*I)->traverseBody(BodyCtx);
+
+ return true;
+ }
+};
+
+}
+
+MigrationContext::~MigrationContext() {
+ for (traverser_iterator
+ I = traversers_begin(), E = traversers_end(); I != E; ++I)
+ delete *I;
+}
+
+bool MigrationContext::isGCOwnedNonObjC(QualType T) {
+ while (!T.isNull()) {
+ if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
+ if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
+ return !AttrT->getModifiedType()->isObjCRetainableType();
+ }
+
+ if (T->isArrayType())
+ T = Pass.Ctx.getBaseElementType(T);
+ else if (const PointerType *PT = T->getAs<PointerType>())
+ T = PT->getPointeeType();
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ T = RT->getPointeeType();
+ else
+ break;
+ }
+
+ return false;
+}
+
+bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr,
+ StringRef toAttr,
+ SourceLocation atLoc) {
+ if (atLoc.isMacroID())
+ return false;
+
+ SourceManager &SM = Pass.Ctx.getSourceManager();
+
+ // Break down the source location.
+ std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
+
+ // Try to load the file buffer.
+ bool invalidTemp = false;
+ StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
+ if (invalidTemp)
+ return false;
+
+ const char *tokenBegin = file.data() + locInfo.second;
+
+ // Lex from the start of the given location.
+ Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
+ Pass.Ctx.getLangOpts(),
+ file.begin(), tokenBegin, file.end());
+ Token tok;
+ lexer.LexFromRawLexer(tok);
+ if (tok.isNot(tok::at)) return false;
+ lexer.LexFromRawLexer(tok);
+ if (tok.isNot(tok::raw_identifier)) return false;
+ if (StringRef(tok.getRawIdentifierData(), tok.getLength())
+ != "property")
+ return false;
+ lexer.LexFromRawLexer(tok);
+ if (tok.isNot(tok::l_paren)) return false;
+
+ Token BeforeTok = tok;
+ Token AfterTok;
+ AfterTok.startToken();
+ SourceLocation AttrLoc;
+
+ lexer.LexFromRawLexer(tok);
+ if (tok.is(tok::r_paren))
+ return false;
+
+ while (1) {
+ if (tok.isNot(tok::raw_identifier)) return false;
+ StringRef ident(tok.getRawIdentifierData(), tok.getLength());
+ if (ident == fromAttr) {
+ if (!toAttr.empty()) {
+ Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
+ return true;
+ }
+ // We want to remove the attribute.
+ AttrLoc = tok.getLocation();
+ }
+
+ do {
+ lexer.LexFromRawLexer(tok);
+ if (AttrLoc.isValid() && AfterTok.is(tok::unknown))
+ AfterTok = tok;
+ } while (tok.isNot(tok::comma) && tok.isNot(tok::r_paren));
+ if (tok.is(tok::r_paren))
+ break;
+ if (AttrLoc.isInvalid())
+ BeforeTok = tok;
+ lexer.LexFromRawLexer(tok);
+ }
+
+ if (toAttr.empty() && AttrLoc.isValid() && AfterTok.isNot(tok::unknown)) {
+ // We want to remove the attribute.
+ if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::r_paren)) {
+ Pass.TA.remove(SourceRange(BeforeTok.getLocation(),
+ AfterTok.getLocation()));
+ } else if (BeforeTok.is(tok::l_paren) && AfterTok.is(tok::comma)) {
+ Pass.TA.remove(SourceRange(AttrLoc, AfterTok.getLocation()));
+ } else {
+ Pass.TA.remove(SourceRange(BeforeTok.getLocation(), AttrLoc));
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool MigrationContext::addPropertyAttribute(StringRef attr,
+ SourceLocation atLoc) {
+ if (atLoc.isMacroID())
+ return false;
+
+ SourceManager &SM = Pass.Ctx.getSourceManager();
+
+ // Break down the source location.
+ std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(atLoc);
+
+ // Try to load the file buffer.
+ bool invalidTemp = false;
+ StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
+ if (invalidTemp)
+ return false;
+
+ const char *tokenBegin = file.data() + locInfo.second;
+
+ // Lex from the start of the given location.
+ Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
+ Pass.Ctx.getLangOpts(),
+ file.begin(), tokenBegin, file.end());
+ Token tok;
+ lexer.LexFromRawLexer(tok);
+ if (tok.isNot(tok::at)) return false;
+ lexer.LexFromRawLexer(tok);
+ if (tok.isNot(tok::raw_identifier)) return false;
+ if (StringRef(tok.getRawIdentifierData(), tok.getLength())
+ != "property")
+ return false;
+ lexer.LexFromRawLexer(tok);
+
+ if (tok.isNot(tok::l_paren)) {
+ Pass.TA.insert(tok.getLocation(), std::string("(") + attr.str() + ") ");
+ return true;
+ }
+
+ lexer.LexFromRawLexer(tok);
+ if (tok.is(tok::r_paren)) {
+ Pass.TA.insert(tok.getLocation(), attr);
+ return true;
+ }
+
+ if (tok.isNot(tok::raw_identifier)) return false;
+
+ Pass.TA.insert(tok.getLocation(), std::string(attr) + ", ");
+ return true;
+}
+
+void MigrationContext::traverse(TranslationUnitDecl *TU) {
+ for (traverser_iterator
+ I = traversers_begin(), E = traversers_end(); I != E; ++I)
+ (*I)->traverseTU(*this);
+
+ ASTTransform(*this).TraverseDecl(TU);
+}
+
+static void GCRewriteFinalize(MigrationPass &pass) {
+ ASTContext &Ctx = pass.Ctx;
+ TransformActions &TA = pass.TA;
+ DeclContext *DC = Ctx.getTranslationUnitDecl();
+ Selector FinalizeSel =
+ Ctx.Selectors.getNullarySelector(&pass.Ctx.Idents.get("finalize"));
+
+ typedef DeclContext::specific_decl_iterator<ObjCImplementationDecl>
+ impl_iterator;
+ for (impl_iterator I = impl_iterator(DC->decls_begin()),
+ E = impl_iterator(DC->decls_end()); I != E; ++I) {
+ for (ObjCImplementationDecl::instmeth_iterator
+ MI = (*I)->instmeth_begin(),
+ ME = (*I)->instmeth_end(); MI != ME; ++MI) {
+ ObjCMethodDecl *MD = *MI;
+ if (!MD->hasBody())
+ continue;
+
+ if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) {
+ ObjCMethodDecl *FinalizeM = MD;
+ Transaction Trans(TA);
+ TA.insert(FinalizeM->getSourceRange().getBegin(),
+ "#if !__has_feature(objc_arc)\n");
+ CharSourceRange::getTokenRange(FinalizeM->getSourceRange());
+ const SourceManager &SM = pass.Ctx.getSourceManager();
+ const LangOptions &LangOpts = pass.Ctx.getLangOpts();
+ bool Invalid;
+ std::string str = "\n#endif\n";
+ str += Lexer::getSourceText(
+ CharSourceRange::getTokenRange(FinalizeM->getSourceRange()),
+ SM, LangOpts, &Invalid);
+ TA.insertAfterToken(FinalizeM->getSourceRange().getEnd(), str);
+
+ break;
+ }
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
// getAllTransformations.
//===----------------------------------------------------------------------===//
+static void traverseAST(MigrationPass &pass) {
+ MigrationContext MigrateCtx(pass);
+
+ if (pass.isGCMigration()) {
+ MigrateCtx.addTraverser(new GCCollectableCallsTraverser);
+ MigrateCtx.addTraverser(new GCAttrsTraverser());
+ }
+ MigrateCtx.addTraverser(new PropertyRewriteTraverser());
+ MigrateCtx.addTraverser(new BlockObjCVariableTraverser());
+
+ MigrateCtx.traverse(pass.Ctx.getTranslationUnitDecl());
+}
+
static void independentTransforms(MigrationPass &pass) {
rewriteAutoreleasePool(pass);
- rewriteProperties(pass);
- removeRetainReleaseDealloc(pass);
+ removeRetainReleaseDeallocFinalize(pass);
rewriteUnusedInitDelegate(pass);
- removeZeroOutPropsInDealloc(pass);
+ removeZeroOutPropsInDeallocFinalize(pass);
makeAssignARCSafe(pass);
rewriteUnbridgedCasts(pass);
- rewriteBlockObjCVariable(pass);
checkAPIUses(pass);
+ traverseAST(pass);
}
-std::vector<TransformFn> arcmt::getAllTransformations() {
+std::vector<TransformFn> arcmt::getAllTransformations(
+ LangOptions::GCMode OrigGCMode,
+ bool NoFinalizeRemoval) {
std::vector<TransformFn> transforms;
+ if (OrigGCMode == LangOptions::GCOnly && NoFinalizeRemoval)
+ transforms.push_back(GCRewriteFinalize);
transforms.push_back(independentTransforms);
// This depends on previous transformations removing various expressions.
- transforms.push_back(removeEmptyStatementsAndDealloc);
+ transforms.push_back(removeEmptyStatementsAndDeallocFinalize);
return transforms;
}
diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h
index 5e4db56dc894..445c3e599d65 100644
--- a/lib/ARCMigrate/Transforms.h
+++ b/lib/ARCMigrate/Transforms.h
@@ -11,6 +11,7 @@
#define LLVM_CLANG_LIB_ARCMIGRATE_TRANSFORMS_H
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/ParentMap.h"
#include "llvm/ADT/DenseSet.h"
namespace clang {
@@ -25,6 +26,8 @@ namespace arcmt {
namespace trans {
+ class MigrationContext;
+
//===----------------------------------------------------------------------===//
// Transformations.
//===----------------------------------------------------------------------===//
@@ -32,21 +35,124 @@ namespace trans {
void rewriteAutoreleasePool(MigrationPass &pass);
void rewriteUnbridgedCasts(MigrationPass &pass);
void makeAssignARCSafe(MigrationPass &pass);
-void removeRetainReleaseDealloc(MigrationPass &pass);
-void removeZeroOutPropsInDealloc(MigrationPass &pass);
-void rewriteProperties(MigrationPass &pass);
-void rewriteBlockObjCVariable(MigrationPass &pass);
+void removeRetainReleaseDeallocFinalize(MigrationPass &pass);
+void removeZeroOutPropsInDeallocFinalize(MigrationPass &pass);
void rewriteUnusedInitDelegate(MigrationPass &pass);
void checkAPIUses(MigrationPass &pass);
-void removeEmptyStatementsAndDealloc(MigrationPass &pass);
+void removeEmptyStatementsAndDeallocFinalize(MigrationPass &pass);
+
+class BodyContext {
+ MigrationContext &MigrateCtx;
+ ParentMap PMap;
+ Stmt *TopStmt;
+
+public:
+ BodyContext(MigrationContext &MigrateCtx, Stmt *S)
+ : MigrateCtx(MigrateCtx), PMap(S), TopStmt(S) {}
+
+ MigrationContext &getMigrationContext() { return MigrateCtx; }
+ ParentMap &getParentMap() { return PMap; }
+ Stmt *getTopStmt() { return TopStmt; }
+};
+
+class ObjCImplementationContext {
+ MigrationContext &MigrateCtx;
+ ObjCImplementationDecl *ImpD;
+
+public:
+ ObjCImplementationContext(MigrationContext &MigrateCtx,
+ ObjCImplementationDecl *D)
+ : MigrateCtx(MigrateCtx), ImpD(D) {}
+
+ MigrationContext &getMigrationContext() { return MigrateCtx; }
+ ObjCImplementationDecl *getImplementationDecl() { return ImpD; }
+};
+
+class ASTTraverser {
+public:
+ virtual ~ASTTraverser();
+ virtual void traverseTU(MigrationContext &MigrateCtx) { }
+ virtual void traverseBody(BodyContext &BodyCtx) { }
+ virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) {}
+};
+
+class MigrationContext {
+ std::vector<ASTTraverser *> Traversers;
+
+public:
+ MigrationPass &Pass;
+
+ struct GCAttrOccurrence {
+ enum AttrKind { Weak, Strong } Kind;
+ SourceLocation Loc;
+ QualType ModifiedType;
+ Decl *Dcl;
+ /// \brief true if the attribute is owned, e.g. it is in a body and not just
+ /// in an interface.
+ bool FullyMigratable;
+ };
+ std::vector<GCAttrOccurrence> GCAttrs;
+ llvm::DenseSet<unsigned> AttrSet;
+ llvm::DenseSet<unsigned> RemovedAttrSet;
+
+ /// \brief Set of raw '@' locations for 'assign' properties group that contain
+ /// GC __weak.
+ llvm::DenseSet<unsigned> AtPropsWeak;
+
+ explicit MigrationContext(MigrationPass &pass) : Pass(pass) {}
+ ~MigrationContext();
+
+ typedef std::vector<ASTTraverser *>::iterator traverser_iterator;
+ traverser_iterator traversers_begin() { return Traversers.begin(); }
+ traverser_iterator traversers_end() { return Traversers.end(); }
+
+ void addTraverser(ASTTraverser *traverser) {
+ Traversers.push_back(traverser);
+ }
+
+ bool isGCOwnedNonObjC(QualType T);
+ bool removePropertyAttribute(StringRef fromAttr, SourceLocation atLoc) {
+ return rewritePropertyAttribute(fromAttr, StringRef(), atLoc);
+ }
+ bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr,
+ SourceLocation atLoc);
+ bool addPropertyAttribute(StringRef attr, SourceLocation atLoc);
+
+ void traverse(TranslationUnitDecl *TU);
+
+ void dumpGCAttrs();
+};
+
+class PropertyRewriteTraverser : public ASTTraverser {
+public:
+ virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx);
+};
+
+class BlockObjCVariableTraverser : public ASTTraverser {
+public:
+ virtual void traverseBody(BodyContext &BodyCtx);
+};
+
+// GC transformations
+
+class GCAttrsTraverser : public ASTTraverser {
+public:
+ virtual void traverseTU(MigrationContext &MigrateCtx);
+};
+
+class GCCollectableCallsTraverser : public ASTTraverser {
+public:
+ virtual void traverseBody(BodyContext &BodyCtx);
+};
//===----------------------------------------------------------------------===//
// Helpers.
//===----------------------------------------------------------------------===//
/// \brief Determine whether we can add weak to the given type.
-bool canApplyWeak(ASTContext &Ctx, QualType type);
+bool canApplyWeak(ASTContext &Ctx, QualType type,
+ bool AllowOnUnknownClass = false);
/// \brief 'Loc' is the end of a statement range. This returns the location
/// immediately after the semicolon following the statement.
diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp
index 6f63a32dd2ed..a31b3c5bfb37 100644
--- a/lib/AST/APValue.cpp
+++ b/lib/AST/APValue.cpp
@@ -12,7 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/APValue.h"
+#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
@@ -20,49 +24,169 @@
using namespace clang;
namespace {
- struct LV {
- const Expr* Base;
+ struct LVBase {
+ llvm::PointerIntPair<APValue::LValueBase, 1, bool> BaseAndIsOnePastTheEnd;
CharUnits Offset;
+ unsigned PathLength;
+ unsigned CallIndex;
};
}
-APValue::APValue(const Expr* B) : Kind(Uninitialized) {
- MakeLValue(); setLValue(B, CharUnits::Zero());
-}
-
-const APValue &APValue::operator=(const APValue &RHS) {
- if (Kind != RHS.Kind) {
- MakeUninit();
- if (RHS.isInt())
- MakeInt();
- else if (RHS.isFloat())
- MakeFloat();
- else if (RHS.isVector())
- MakeVector();
- else if (RHS.isComplexInt())
- MakeComplexInt();
- else if (RHS.isComplexFloat())
- MakeComplexFloat();
- else if (RHS.isLValue())
- MakeLValue();
+struct APValue::LV : LVBase {
+ static const unsigned InlinePathSpace =
+ (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
+
+ /// Path - The sequence of base classes, fields and array indices to follow to
+ /// walk from Base to the subobject. When performing GCC-style folding, there
+ /// may not be such a path.
+ union {
+ LValuePathEntry Path[InlinePathSpace];
+ LValuePathEntry *PathPtr;
+ };
+
+ LV() { PathLength = (unsigned)-1; }
+ ~LV() { resizePath(0); }
+
+ void resizePath(unsigned Length) {
+ if (Length == PathLength)
+ return;
+ if (hasPathPtr())
+ delete [] PathPtr;
+ PathLength = Length;
+ if (hasPathPtr())
+ PathPtr = new LValuePathEntry[Length];
+ }
+
+ bool hasPath() const { return PathLength != (unsigned)-1; }
+ bool hasPathPtr() const { return hasPath() && PathLength > InlinePathSpace; }
+
+ LValuePathEntry *getPath() { return hasPathPtr() ? PathPtr : Path; }
+ const LValuePathEntry *getPath() const {
+ return hasPathPtr() ? PathPtr : Path;
+ }
+};
+
+namespace {
+ struct MemberPointerBase {
+ llvm::PointerIntPair<const ValueDecl*, 1, bool> MemberAndIsDerivedMember;
+ unsigned PathLength;
+ };
+}
+
+struct APValue::MemberPointerData : MemberPointerBase {
+ static const unsigned InlinePathSpace =
+ (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*);
+ typedef const CXXRecordDecl *PathElem;
+ union {
+ PathElem Path[InlinePathSpace];
+ PathElem *PathPtr;
+ };
+
+ MemberPointerData() { PathLength = 0; }
+ ~MemberPointerData() { resizePath(0); }
+
+ void resizePath(unsigned Length) {
+ if (Length == PathLength)
+ return;
+ if (hasPathPtr())
+ delete [] PathPtr;
+ PathLength = Length;
+ if (hasPathPtr())
+ PathPtr = new PathElem[Length];
}
- if (isInt())
+
+ bool hasPathPtr() const { return PathLength > InlinePathSpace; }
+
+ PathElem *getPath() { return hasPathPtr() ? PathPtr : Path; }
+ const PathElem *getPath() const {
+ return hasPathPtr() ? PathPtr : Path;
+ }
+};
+
+// FIXME: Reduce the malloc traffic here.
+
+APValue::Arr::Arr(unsigned NumElts, unsigned Size) :
+ Elts(new APValue[NumElts + (NumElts != Size ? 1 : 0)]),
+ NumElts(NumElts), ArrSize(Size) {}
+APValue::Arr::~Arr() { delete [] Elts; }
+
+APValue::StructData::StructData(unsigned NumBases, unsigned NumFields) :
+ Elts(new APValue[NumBases+NumFields]),
+ NumBases(NumBases), NumFields(NumFields) {}
+APValue::StructData::~StructData() {
+ delete [] Elts;
+}
+
+APValue::UnionData::UnionData() : Field(0), Value(new APValue) {}
+APValue::UnionData::~UnionData () {
+ delete Value;
+}
+
+APValue::APValue(const APValue &RHS) : Kind(Uninitialized) {
+ switch (RHS.getKind()) {
+ case Uninitialized:
+ break;
+ case Int:
+ MakeInt();
setInt(RHS.getInt());
- else if (isFloat())
+ break;
+ case Float:
+ MakeFloat();
setFloat(RHS.getFloat());
- else if (isVector())
+ break;
+ case Vector:
+ MakeVector();
setVector(((const Vec *)(const char *)RHS.Data)->Elts,
RHS.getVectorLength());
- else if (isComplexInt())
+ break;
+ case ComplexInt:
+ MakeComplexInt();
setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
- else if (isComplexFloat())
+ break;
+ case ComplexFloat:
+ MakeComplexFloat();
setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
- else if (isLValue())
- setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
- return *this;
+ break;
+ case LValue:
+ MakeLValue();
+ if (RHS.hasLValuePath())
+ setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), RHS.getLValuePath(),
+ RHS.isLValueOnePastTheEnd(), RHS.getLValueCallIndex());
+ else
+ setLValue(RHS.getLValueBase(), RHS.getLValueOffset(), NoLValuePath(),
+ RHS.getLValueCallIndex());
+ break;
+ case Array:
+ MakeArray(RHS.getArrayInitializedElts(), RHS.getArraySize());
+ for (unsigned I = 0, N = RHS.getArrayInitializedElts(); I != N; ++I)
+ getArrayInitializedElt(I) = RHS.getArrayInitializedElt(I);
+ if (RHS.hasArrayFiller())
+ getArrayFiller() = RHS.getArrayFiller();
+ break;
+ case Struct:
+ MakeStruct(RHS.getStructNumBases(), RHS.getStructNumFields());
+ for (unsigned I = 0, N = RHS.getStructNumBases(); I != N; ++I)
+ getStructBase(I) = RHS.getStructBase(I);
+ for (unsigned I = 0, N = RHS.getStructNumFields(); I != N; ++I)
+ getStructField(I) = RHS.getStructField(I);
+ break;
+ case Union:
+ MakeUnion();
+ setUnion(RHS.getUnionField(), RHS.getUnionValue());
+ break;
+ case MemberPointer:
+ MakeMemberPointer(RHS.getMemberPointerDecl(),
+ RHS.isMemberPointerToDerivedMember(),
+ RHS.getMemberPointerPath());
+ break;
+ case AddrLabelDiff:
+ MakeAddrLabelDiff();
+ setAddrLabelDiff(RHS.getAddrLabelDiffLHS(), RHS.getAddrLabelDiffRHS());
+ break;
+ }
}
-void APValue::MakeUninit() {
+void APValue::DestroyDataAndMakeUninit() {
if (Kind == Int)
((APSInt*)(char*)Data)->~APSInt();
else if (Kind == Float)
@@ -73,14 +197,31 @@ void APValue::MakeUninit() {
((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt();
else if (Kind == ComplexFloat)
((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat();
- else if (Kind == LValue) {
+ else if (Kind == LValue)
((LV*)(char*)Data)->~LV();
- }
+ else if (Kind == Array)
+ ((Arr*)(char*)Data)->~Arr();
+ else if (Kind == Struct)
+ ((StructData*)(char*)Data)->~StructData();
+ else if (Kind == Union)
+ ((UnionData*)(char*)Data)->~UnionData();
+ else if (Kind == MemberPointer)
+ ((MemberPointerData*)(char*)Data)->~MemberPointerData();
+ else if (Kind == AddrLabelDiff)
+ ((AddrLabelDiffData*)(char*)Data)->~AddrLabelDiffData();
Kind = Uninitialized;
}
+void APValue::swap(APValue &RHS) {
+ std::swap(Kind, RHS.Kind);
+ char TmpData[MaxSize];
+ memcpy(TmpData, Data, MaxSize);
+ memcpy(Data, RHS.Data, MaxSize);
+ memcpy(RHS.Data, TmpData, MaxSize);
+}
+
void APValue::dump() const {
- print(llvm::errs());
+ dump(llvm::errs());
llvm::errs() << '\n';
}
@@ -92,9 +233,8 @@ static double GetApproxValue(const llvm::APFloat &F) {
return V.convertToDouble();
}
-void APValue::print(raw_ostream &OS) const {
+void APValue::dump(raw_ostream &OS) const {
switch (getKind()) {
- default: llvm_unreachable("Unknown APValue kind!");
case Uninitialized:
OS << "Uninitialized";
return;
@@ -105,9 +245,12 @@ void APValue::print(raw_ostream &OS) const {
OS << "Float: " << GetApproxValue(getFloat());
return;
case Vector:
- OS << "Vector: " << getVectorElt(0);
- for (unsigned i = 1; i != getVectorLength(); ++i)
- OS << ", " << getVectorElt(i);
+ OS << "Vector: ";
+ getVectorElt(0).dump(OS);
+ for (unsigned i = 1; i != getVectorLength(); ++i) {
+ OS << ", ";
+ getVectorElt(i).dump(OS);
+ }
return;
case ComplexInt:
OS << "ComplexInt: " << getComplexIntReal() << ", " << getComplexIntImag();
@@ -115,74 +258,350 @@ void APValue::print(raw_ostream &OS) const {
case ComplexFloat:
OS << "ComplexFloat: " << GetApproxValue(getComplexFloatReal())
<< ", " << GetApproxValue(getComplexFloatImag());
+ return;
case LValue:
OS << "LValue: <todo>";
return;
+ case Array:
+ OS << "Array: ";
+ for (unsigned I = 0, N = getArrayInitializedElts(); I != N; ++I) {
+ getArrayInitializedElt(I).dump(OS);
+ if (I != getArraySize() - 1) OS << ", ";
+ }
+ if (hasArrayFiller()) {
+ OS << getArraySize() - getArrayInitializedElts() << " x ";
+ getArrayFiller().dump(OS);
+ }
+ return;
+ case Struct:
+ OS << "Struct ";
+ if (unsigned N = getStructNumBases()) {
+ OS << " bases: ";
+ getStructBase(0).dump(OS);
+ for (unsigned I = 1; I != N; ++I) {
+ OS << ", ";
+ getStructBase(I).dump(OS);
+ }
+ }
+ if (unsigned N = getStructNumFields()) {
+ OS << " fields: ";
+ getStructField(0).dump(OS);
+ for (unsigned I = 1; I != N; ++I) {
+ OS << ", ";
+ getStructField(I).dump(OS);
+ }
+ }
+ return;
+ case Union:
+ OS << "Union: ";
+ getUnionValue().dump(OS);
+ return;
+ case MemberPointer:
+ OS << "MemberPointer: <todo>";
+ return;
+ case AddrLabelDiff:
+ OS << "AddrLabelDiff: <todo>";
+ return;
}
+ llvm_unreachable("Unknown APValue kind!");
}
-static void WriteShortAPValueToStream(raw_ostream& Out,
- const APValue& V) {
- switch (V.getKind()) {
- default: llvm_unreachable("Unknown APValue kind!");
+void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{
+ switch (getKind()) {
case APValue::Uninitialized:
- Out << "Uninitialized";
- break;
+ Out << "<uninitialized>";
+ return;
case APValue::Int:
- Out << V.getInt();
- break;
+ if (Ty->isBooleanType())
+ Out << (getInt().getBoolValue() ? "true" : "false");
+ else
+ Out << getInt();
+ return;
case APValue::Float:
- Out << GetApproxValue(V.getFloat());
- break;
- case APValue::Vector:
- Out << '[';
- WriteShortAPValueToStream(Out, V.getVectorElt(0));
- for (unsigned i = 1; i != V.getVectorLength(); ++i) {
+ Out << GetApproxValue(getFloat());
+ return;
+ case APValue::Vector: {
+ Out << '{';
+ QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
+ getVectorElt(0).printPretty(Out, Ctx, ElemTy);
+ for (unsigned i = 1; i != getVectorLength(); ++i) {
Out << ", ";
- WriteShortAPValueToStream(Out, V.getVectorElt(i));
+ getVectorElt(i).printPretty(Out, Ctx, ElemTy);
}
- Out << ']';
- break;
+ Out << '}';
+ return;
+ }
case APValue::ComplexInt:
- Out << V.getComplexIntReal() << "+" << V.getComplexIntImag() << "i";
- break;
+ Out << getComplexIntReal() << "+" << getComplexIntImag() << "i";
+ return;
case APValue::ComplexFloat:
- Out << GetApproxValue(V.getComplexFloatReal()) << "+"
- << GetApproxValue(V.getComplexFloatImag()) << "i";
- break;
- case APValue::LValue:
- Out << "LValue: <todo>";
- break;
+ Out << GetApproxValue(getComplexFloatReal()) << "+"
+ << GetApproxValue(getComplexFloatImag()) << "i";
+ return;
+ case APValue::LValue: {
+ LValueBase Base = getLValueBase();
+ if (!Base) {
+ Out << "0";
+ return;
+ }
+
+ bool IsReference = Ty->isReferenceType();
+ QualType InnerTy
+ = IsReference ? Ty.getNonReferenceType() : Ty->getPointeeType();
+
+ if (!hasLValuePath()) {
+ // No lvalue path: just print the offset.
+ CharUnits O = getLValueOffset();
+ CharUnits S = Ctx.getTypeSizeInChars(InnerTy);
+ if (!O.isZero()) {
+ if (IsReference)
+ Out << "*(";
+ if (O % S) {
+ Out << "(char*)";
+ S = CharUnits::One();
+ }
+ Out << '&';
+ } else if (!IsReference)
+ Out << '&';
+
+ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>())
+ Out << *VD;
+ else
+ Base.get<const Expr*>()->printPretty(Out, Ctx, 0,
+ Ctx.getPrintingPolicy());
+ if (!O.isZero()) {
+ Out << " + " << (O / S);
+ if (IsReference)
+ Out << ')';
+ }
+ return;
+ }
+
+ // We have an lvalue path. Print it out nicely.
+ if (!IsReference)
+ Out << '&';
+ else if (isLValueOnePastTheEnd())
+ Out << "*(&";
+
+ QualType ElemTy;
+ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
+ Out << *VD;
+ ElemTy = VD->getType();
+ } else {
+ const Expr *E = Base.get<const Expr*>();
+ E->printPretty(Out, Ctx, 0,Ctx.getPrintingPolicy());
+ ElemTy = E->getType();
+ }
+
+ ArrayRef<LValuePathEntry> Path = getLValuePath();
+ const CXXRecordDecl *CastToBase = 0;
+ for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+ if (ElemTy->getAs<RecordType>()) {
+ // The lvalue refers to a class type, so the next path entry is a base
+ // or member.
+ const Decl *BaseOrMember =
+ BaseOrMemberType::getFromOpaqueValue(Path[I].BaseOrMember).getPointer();
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(BaseOrMember)) {
+ CastToBase = RD;
+ ElemTy = Ctx.getRecordType(RD);
+ } else {
+ const ValueDecl *VD = cast<ValueDecl>(BaseOrMember);
+ Out << ".";
+ if (CastToBase)
+ Out << *CastToBase << "::";
+ Out << *VD;
+ ElemTy = VD->getType();
+ }
+ } else {
+ // The lvalue must refer to an array.
+ Out << '[' << Path[I].ArrayIndex << ']';
+ ElemTy = Ctx.getAsArrayType(ElemTy)->getElementType();
+ }
+ }
+
+ // Handle formatting of one-past-the-end lvalues.
+ if (isLValueOnePastTheEnd()) {
+ // FIXME: If CastToBase is non-0, we should prefix the output with
+ // "(CastToBase*)".
+ Out << " + 1";
+ if (IsReference)
+ Out << ')';
+ }
+ return;
}
+ case APValue::Array: {
+ const ArrayType *AT = Ctx.getAsArrayType(Ty);
+ QualType ElemTy = AT->getElementType();
+ Out << '{';
+ if (unsigned N = getArrayInitializedElts()) {
+ getArrayInitializedElt(0).printPretty(Out, Ctx, ElemTy);
+ for (unsigned I = 1; I != N; ++I) {
+ Out << ", ";
+ if (I == 10) {
+ // Avoid printing out the entire contents of large arrays.
+ Out << "...";
+ break;
+ }
+ getArrayInitializedElt(I).printPretty(Out, Ctx, ElemTy);
+ }
+ }
+ Out << '}';
+ return;
+ }
+ case APValue::Struct: {
+ Out << '{';
+ const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl();
+ bool First = true;
+ if (unsigned N = getStructNumBases()) {
+ const CXXRecordDecl *CD = cast<CXXRecordDecl>(RD);
+ CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin();
+ for (unsigned I = 0; I != N; ++I, ++BI) {
+ assert(BI != CD->bases_end());
+ if (!First)
+ Out << ", ";
+ getStructBase(I).printPretty(Out, Ctx, BI->getType());
+ First = false;
+ }
+ }
+ for (RecordDecl::field_iterator FI = RD->field_begin();
+ FI != RD->field_end(); ++FI) {
+ if (!First)
+ Out << ", ";
+ if ((*FI)->isUnnamedBitfield()) continue;
+ getStructField((*FI)->getFieldIndex()).
+ printPretty(Out, Ctx, (*FI)->getType());
+ First = false;
+ }
+ Out << '}';
+ return;
+ }
+ case APValue::Union:
+ Out << '{';
+ if (const FieldDecl *FD = getUnionField()) {
+ Out << "." << *FD << " = ";
+ getUnionValue().printPretty(Out, Ctx, FD->getType());
+ }
+ Out << '}';
+ return;
+ case APValue::MemberPointer:
+ // FIXME: This is not enough to unambiguously identify the member in a
+ // multiple-inheritance scenario.
+ if (const ValueDecl *VD = getMemberPointerDecl()) {
+ Out << '&' << *cast<CXXRecordDecl>(VD->getDeclContext()) << "::" << *VD;
+ return;
+ }
+ Out << "0";
+ return;
+ case APValue::AddrLabelDiff:
+ Out << "&&" << getAddrLabelDiffLHS()->getLabel()->getName();
+ Out << " - ";
+ Out << "&&" << getAddrLabelDiffRHS()->getLabel()->getName();
+ return;
+ }
+ llvm_unreachable("Unknown APValue kind!");
+}
+
+std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const {
+ std::string Result;
+ llvm::raw_string_ostream Out(Result);
+ printPretty(Out, Ctx, Ty);
+ Out.flush();
+ return Result;
+}
+
+const APValue::LValueBase APValue::getLValueBase() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer();
+}
+
+bool APValue::isLValueOnePastTheEnd() const {
+ assert(isLValue() && "Invalid accessor");
+ return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt();
}
-const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
- const APValue &V) {
- llvm::SmallString<64> Buffer;
- llvm::raw_svector_ostream Out(Buffer);
- WriteShortAPValueToStream(Out, V);
- return DB << Out.str();
+CharUnits &APValue::getLValueOffset() {
+ assert(isLValue() && "Invalid accessor");
+ return ((LV*)(void*)Data)->Offset;
}
-const Expr* APValue::getLValueBase() const {
+bool APValue::hasLValuePath() const {
assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const void*)Data)->Base;
+ return ((const LV*)(const char*)Data)->hasPath();
}
-CharUnits APValue::getLValueOffset() const {
- assert(isLValue() && "Invalid accessor");
- return ((const LV*)(const void*)Data)->Offset;
+ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const {
+ assert(isLValue() && hasLValuePath() && "Invalid accessor");
+ const LV &LVal = *((const LV*)(const char*)Data);
+ return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
}
-void APValue::setLValue(const Expr *B, const CharUnits &O) {
+unsigned APValue::getLValueCallIndex() const {
assert(isLValue() && "Invalid accessor");
- ((LV*)(char*)Data)->Base = B;
- ((LV*)(char*)Data)->Offset = O;
+ return ((const LV*)(const char*)Data)->CallIndex;
+}
+
+void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
+ unsigned CallIndex) {
+ assert(isLValue() && "Invalid accessor");
+ LV &LVal = *((LV*)(char*)Data);
+ LVal.BaseAndIsOnePastTheEnd.setPointer(B);
+ LVal.BaseAndIsOnePastTheEnd.setInt(false);
+ LVal.Offset = O;
+ LVal.CallIndex = CallIndex;
+ LVal.resizePath((unsigned)-1);
+}
+
+void APValue::setLValue(LValueBase B, const CharUnits &O,
+ ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd,
+ unsigned CallIndex) {
+ assert(isLValue() && "Invalid accessor");
+ LV &LVal = *((LV*)(char*)Data);
+ LVal.BaseAndIsOnePastTheEnd.setPointer(B);
+ LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd);
+ LVal.Offset = O;
+ LVal.CallIndex = CallIndex;
+ LVal.resizePath(Path.size());
+ memcpy(LVal.getPath(), Path.data(), Path.size() * sizeof(LValuePathEntry));
+}
+
+const ValueDecl *APValue::getMemberPointerDecl() const {
+ assert(isMemberPointer() && "Invalid accessor");
+ const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
+ return MPD.MemberAndIsDerivedMember.getPointer();
+}
+
+bool APValue::isMemberPointerToDerivedMember() const {
+ assert(isMemberPointer() && "Invalid accessor");
+ const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
+ return MPD.MemberAndIsDerivedMember.getInt();
+}
+
+ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const {
+ assert(isMemberPointer() && "Invalid accessor");
+ const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data);
+ return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength);
}
void APValue::MakeLValue() {
assert(isUninit() && "Bad state change");
+ assert(sizeof(LV) <= MaxSize && "LV too big");
new ((void*)(char*)Data) LV();
Kind = LValue;
}
+void APValue::MakeArray(unsigned InitElts, unsigned Size) {
+ assert(isUninit() && "Bad state change");
+ new ((void*)(char*)Data) Arr(InitElts, Size);
+ Kind = Array;
+}
+
+void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
+ ArrayRef<const CXXRecordDecl*> Path) {
+ assert(isUninit() && "Bad state change");
+ MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData;
+ Kind = MemberPointer;
+ MPD->MemberAndIsDerivedMember.setPointer(Member);
+ MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember);
+ MPD->resizePath(Path.size());
+ memcpy(MPD->getPath(), Path.data(), Path.size()*sizeof(const CXXRecordDecl*));
+}
diff --git a/lib/AST/ASTConsumer.cpp b/lib/AST/ASTConsumer.cpp
index 04a084a06a44..1672bc8aed7c 100644
--- a/lib/AST/ASTConsumer.cpp
+++ b/lib/AST/ASTConsumer.cpp
@@ -15,8 +15,12 @@
#include "clang/AST/DeclGroup.h"
using namespace clang;
-void ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {}
+bool ASTConsumer::HandleTopLevelDecl(DeclGroupRef D) {
+ return true;
+}
void ASTConsumer::HandleInterestingDecl(DeclGroupRef D) {
HandleTopLevelDecl(D);
}
+
+void ASTConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {}
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 462428086ddd..acf5e0bbc9af 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -74,12 +74,14 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID,
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
ID.AddInteger(1);
ID.AddBoolean(NTTP->isParameterPack());
- ID.AddPointer(NTTP->getType().getAsOpaquePtr());
+ ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr());
if (NTTP->isExpandedParameterPack()) {
ID.AddBoolean(true);
ID.AddInteger(NTTP->getNumExpansionTypes());
- for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I)
- ID.AddPointer(NTTP->getExpansionType(I).getAsOpaquePtr());
+ for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
+ QualType T = NTTP->getExpansionType(I);
+ ID.AddPointer(T.getCanonicalType().getAsOpaquePtr());
+ }
} else
ID.AddBoolean(false);
continue;
@@ -193,7 +195,7 @@ CXXABI *ASTContext::createCXXABI(const TargetInfo &T) {
case CXXABI_Microsoft:
return CreateMicrosoftCXXABI(*this);
}
- return 0;
+ llvm_unreachable("Invalid CXXABI type!");
}
static const LangAS::Map *getAddressSpaceMap(const TargetInfo &T,
@@ -224,12 +226,14 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM,
SubstTemplateTemplateParmPacks(this_()),
GlobalNestedNameSpecifier(0),
Int128Decl(0), UInt128Decl(0),
- ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0),
+ ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0),
CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0),
FILEDecl(0),
- jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0),
- BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0),
- NullTypeSourceInfo(QualType()),
+ jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0),
+ BlockDescriptorType(0), BlockDescriptorExtendedType(0),
+ cudaConfigureCallDecl(0),
+ NullTypeSourceInfo(QualType()),
+ FirstLocalImport(), LastLocalImport(),
SourceMgr(SM), LangOpts(LOpts),
AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts),
Idents(idents), Selectors(sels),
@@ -257,12 +261,6 @@ ASTContext::~ASTContext() {
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
- OM = OverriddenMethods.begin(), OMEnd = OverriddenMethods.end();
- OM != OMEnd; ++OM)
- OM->second.Destroy();
-
// ASTRecordLayout objects in ASTRecordLayouts must always be destroyed
// because they can contain DenseMaps.
for (llvm::DenseMap<const ObjCContainerDecl*,
@@ -290,7 +288,7 @@ void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
}
void
-ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) {
+ASTContext::setExternalSource(OwningPtr<ExternalASTSource> &Source) {
ExternalSource.reset(Source.take());
}
@@ -330,14 +328,14 @@ void ASTContext::PrintStats() const {
llvm::errs() << NumImplicitCopyConstructorsDeclared << "/"
<< NumImplicitCopyConstructors
<< " implicit copy constructors created\n";
- if (getLangOptions().CPlusPlus)
+ if (getLangOpts().CPlusPlus)
llvm::errs() << NumImplicitMoveConstructorsDeclared << "/"
<< NumImplicitMoveConstructors
<< " implicit move constructors created\n";
llvm::errs() << NumImplicitCopyAssignmentOperatorsDeclared << "/"
<< NumImplicitCopyAssignmentOperators
<< " implicit copy assignment operators created\n";
- if (getLangOptions().CPlusPlus)
+ if (getLangOpts().CPlusPlus)
llvm::errs() << NumImplicitMoveAssignmentOperatorsDeclared << "/"
<< NumImplicitMoveAssignmentOperators
<< " implicit move assignment operators created\n";
@@ -461,9 +459,15 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
// Placeholder type for bound members.
InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember);
+ // Placeholder type for pseudo-objects.
+ InitBuiltinType(PseudoObjectTy, BuiltinType::PseudoObject);
+
// "any" type; useful for debugger-like clients.
InitBuiltinType(UnknownAnyTy, BuiltinType::UnknownAny);
+ // Placeholder type for unbridged ARC casts.
+ InitBuiltinType(ARCUnbridgedCastTy, BuiltinType::ARCUnbridgedCast);
+
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
DoubleComplexTy = getComplexType(DoubleTy);
@@ -475,7 +479,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
-
+
+ // Builtin type for __objc_yes and __objc_no
+ ObjCBuiltinBoolTy = SignedCharTy;
+
ObjCConstantStringType = QualType();
// void * type
@@ -675,6 +682,19 @@ void ASTContext::addOverriddenMethod(const CXXMethodDecl *Method,
OverriddenMethods[Method].push_back(Overridden);
}
+void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
+ assert(!Import->NextLocalImport && "Import declaration already in the chain");
+ assert(!Import->isFromASTFile() && "Non-local import declaration");
+ if (!FirstLocalImport) {
+ FirstLocalImport = Import;
+ LastLocalImport = Import;
+ return;
+ }
+
+ LastLocalImport->NextLocalImport = Import;
+ LastLocalImport = Import;
+}
+
//===----------------------------------------------------------------------===//
// Type Sizing and Analysis
//===----------------------------------------------------------------------===//
@@ -795,14 +815,24 @@ ASTContext::getTypeInfoInChars(QualType T) const {
return getTypeInfoInChars(T.getTypePtr());
}
-/// getTypeSize - Return the size of the specified type, in bits. This method
-/// does not work on incomplete types.
+std::pair<uint64_t, unsigned> ASTContext::getTypeInfo(const Type *T) const {
+ TypeInfoMap::iterator it = MemoizedTypeInfo.find(T);
+ if (it != MemoizedTypeInfo.end())
+ return it->second;
+
+ std::pair<uint64_t, unsigned> Info = getTypeInfoImpl(T);
+ MemoizedTypeInfo.insert(std::make_pair(T, Info));
+ return Info;
+}
+
+/// getTypeInfoImpl - Return the size of the specified type, in bits. This
+/// method does not work on incomplete types.
///
/// FIXME: Pointers into different addr spaces could have different sizes and
/// alignment requirements: getPointerInfo should take an AddrSpace, this
/// should take a QualType, &c.
std::pair<uint64_t, unsigned>
-ASTContext::getTypeInfo(const Type *T) const {
+ASTContext::getTypeInfoImpl(const Type *T) const {
uint64_t Width=0;
unsigned Align=8;
switch (T->getTypeClass()) {
@@ -812,7 +842,6 @@ ASTContext::getTypeInfo(const Type *T) const {
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
llvm_unreachable("Should not see dependent types");
- break;
case Type::FunctionNoProto:
case Type::FunctionProto:
@@ -831,7 +860,10 @@ ASTContext::getTypeInfo(const Type *T) const {
const ConstantArrayType *CAT = cast<ConstantArrayType>(T);
std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(CAT->getElementType());
- Width = EltInfo.first*CAT->getSize().getZExtValue();
+ uint64_t Size = CAT->getSize().getZExtValue();
+ assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) &&
+ "Overflow in array type bit size evaluation");
+ Width = EltInfo.first*Size;
Align = EltInfo.second;
Width = llvm::RoundUpToAlignment(Width, Align);
break;
@@ -1133,7 +1165,8 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const {
if (const ComplexType* CT = T->getAs<ComplexType>())
T = CT->getElementType().getTypePtr();
if (T->isSpecificBuiltinType(BuiltinType::Double) ||
- T->isSpecificBuiltinType(BuiltinType::LongLong))
+ T->isSpecificBuiltinType(BuiltinType::LongLong) ||
+ T->isSpecificBuiltinType(BuiltinType::ULongLong))
return std::max(ABIAlign, (unsigned)getTypeSize(T));
return ABIAlign;
@@ -1172,10 +1205,10 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
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);
+ Protocols.insert(Proto->getCanonicalDecl());
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
PE = Proto->protocol_end(); P != PE; ++P) {
- Protocols.insert(*P);
+ Protocols.insert((*P)->getCanonicalDecl());
CollectInheritedProtocols(*P, Protocols);
}
}
@@ -1193,7 +1226,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
PE = OC->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
- Protocols.insert(Proto);
+ Protocols.insert(Proto->getCanonicalDecl());
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
PE = Proto->protocol_end(); P != PE; ++P)
CollectInheritedProtocols(*P, Protocols);
@@ -1202,7 +1235,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(),
PE = OP->protocol_end(); P != PE; ++P) {
ObjCProtocolDecl *Proto = (*P);
- Protocols.insert(Proto);
+ Protocols.insert(Proto->getCanonicalDecl());
for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
PE = Proto->protocol_end(); P != PE; ++P)
CollectInheritedProtocols(*P, Protocols);
@@ -1225,6 +1258,24 @@ unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const {
return count;
}
+bool ASTContext::isSentinelNullExpr(const Expr *E) {
+ if (!E)
+ return false;
+
+ // nullptr_t is always treated as null.
+ if (E->getType()->isNullPtrType()) return true;
+
+ if (E->getType()->isAnyPointerType() &&
+ E->IgnoreParenCasts()->isNullPointerConstant(*this,
+ Expr::NPC_ValueDependentIsNull))
+ return true;
+
+ // Unfortunately, __null has type 'int'.
+ if (isa<GNUNullExpr>(E)) return true;
+
+ return false;
+}
+
/// \brief Get the implementation of ObjCInterfaceDecl,or NULL if none exists.
ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) {
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator
@@ -1255,6 +1306,17 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
ObjCImpls[CatD] = ImplD;
}
+ObjCInterfaceDecl *ASTContext::getObjContainingInterface(NamedDecl *ND) const {
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext()))
+ return ID;
+ if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext()))
+ return CD->getClassInterface();
+ if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext()))
+ return IMD->getClassInterface();
+
+ return 0;
+}
+
/// \brief Get the copy initialization expression of VarDecl,or NULL if
/// none exists.
Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
@@ -1336,8 +1398,8 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const {
QualType canon;
if (!baseType->isCanonicalUnqualified()) {
SplitQualType canonSplit = baseType->getCanonicalTypeInternal().split();
- canonSplit.second.addConsistentQualifiers(quals);
- canon = getExtQualType(canonSplit.first, canonSplit.second);
+ canonSplit.Quals.addConsistentQualifiers(quals);
+ canon = getExtQualType(canonSplit.Ty, canonSplit.Quals);
// Re-find the insert position.
(void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos);
@@ -1639,9 +1701,9 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
QualType Canon;
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
SplitQualType canonSplit = getCanonicalType(EltTy).split();
- Canon = getConstantArrayType(QualType(canonSplit.first, 0), ArySize,
+ Canon = getConstantArrayType(QualType(canonSplit.Ty, 0), ArySize,
ASM, IndexTypeQuals);
- Canon = getQualifiedType(Canon, canonSplit.second);
+ Canon = getQualifiedType(Canon, canonSplit.Quals);
// Get the new insert position for the node we care about.
ConstantArrayType *NewIP =
@@ -1666,7 +1728,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
QualType result;
SplitQualType split = type.getSplitDesugaredType();
- const Type *ty = split.first;
+ const Type *ty = split.Ty;
switch (ty->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
@@ -1785,7 +1847,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
}
// Apply the top-level qualifiers from the original.
- return getQualifiedType(result, split.second);
+ return getQualifiedType(result, split.Quals);
}
/// getVariableArrayType - Returns a non-unique reference to the type for a
@@ -1802,9 +1864,9 @@ QualType ASTContext::getVariableArrayType(QualType EltTy,
// Be sure to pull qualifiers off the element type.
if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) {
SplitQualType canonSplit = getCanonicalType(EltTy).split();
- Canon = getVariableArrayType(QualType(canonSplit.first, 0), NumElts, ASM,
+ Canon = getVariableArrayType(QualType(canonSplit.Ty, 0), NumElts, ASM,
IndexTypeQuals, Brackets);
- Canon = getQualifiedType(Canon, canonSplit.second);
+ Canon = getQualifiedType(Canon, canonSplit.Quals);
}
VariableArrayType *New = new(*this, TypeAlignment)
@@ -1849,7 +1911,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
void *insertPos = 0;
llvm::FoldingSetNodeID ID;
DependentSizedArrayType::Profile(ID, *this,
- QualType(canonElementType.first, 0),
+ QualType(canonElementType.Ty, 0),
ASM, elementTypeQuals, numElements);
// Look for an existing type with these properties.
@@ -1859,7 +1921,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
// If we don't have one, build one.
if (!canonTy) {
canonTy = new (*this, TypeAlignment)
- DependentSizedArrayType(*this, QualType(canonElementType.first, 0),
+ DependentSizedArrayType(*this, QualType(canonElementType.Ty, 0),
QualType(), numElements, ASM, elementTypeQuals,
brackets);
DependentSizedArrayTypes.InsertNode(canonTy, insertPos);
@@ -1868,11 +1930,11 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType,
// Apply qualifiers from the element type to the array.
QualType canon = getQualifiedType(QualType(canonTy,0),
- canonElementType.second);
+ canonElementType.Quals);
// If we didn't need extra canonicalization for the element type,
// then just use that as our result.
- if (QualType(canonElementType.first, 0) == elementType)
+ if (QualType(canonElementType.Ty, 0) == elementType)
return canon;
// Otherwise, we need to build a type which follows the spelling
@@ -1903,9 +1965,9 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType,
if (!elementType.isCanonical() || elementType.hasLocalQualifiers()) {
SplitQualType canonSplit = getCanonicalType(elementType).split();
- canon = getIncompleteArrayType(QualType(canonSplit.first, 0),
+ canon = getIncompleteArrayType(QualType(canonSplit.Ty, 0),
ASM, elementTypeQuals);
- canon = getQualifiedType(canon, canonSplit.second);
+ canon = getQualifiedType(canon, canonSplit.Quals);
// Get the new insert position for the node we care about.
IncompleteArrayType *existing =
@@ -2081,7 +2143,9 @@ ASTContext::getFunctionType(QualType ResultTy,
return QualType(FTP, 0);
// Determine whether the type being created is already canonical or not.
- bool isCanonical= EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical();
+ bool isCanonical =
+ EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() &&
+ !EPI.HasTrailingReturn;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i].isCanonicalAsParam())
isCanonical = false;
@@ -2100,6 +2164,7 @@ ASTContext::getFunctionType(QualType ResultTy,
CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));
FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI;
+ CanonicalEPI.HasTrailingReturn = false;
CanonicalEPI.ExceptionSpecType = EST_None;
CanonicalEPI.NumExceptions = 0;
CanonicalEPI.ExtInfo
@@ -2161,7 +2226,7 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl,
assert(NeedsInjectedClassNameType(Decl));
if (Decl->TypeForDecl) {
assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
- } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDeclaration()) {
+ } else if (CXXRecordDecl *PrevDecl = Decl->getPreviousDecl()) {
assert(PrevDecl->TypeForDecl && "previous declaration has no type");
Decl->TypeForDecl = PrevDecl->TypeForDecl;
assert(isa<InjectedClassNameType>(Decl->TypeForDecl));
@@ -2187,12 +2252,12 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const {
"Template type parameter types are always available.");
if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) {
- assert(!Record->getPreviousDeclaration() &&
+ assert(!Record->getPreviousDecl() &&
"struct/union has previous declaration");
assert(!NeedsInjectedClassNameType(Record));
return getRecordType(Record);
} else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) {
- assert(!Enum->getPreviousDeclaration() &&
+ assert(!Enum->getPreviousDecl() &&
"enum has previous declaration");
return getEnumType(Enum);
} else if (const UnresolvedUsingTypenameDecl *Using =
@@ -2225,7 +2290,7 @@ ASTContext::getTypedefType(const TypedefNameDecl *Decl,
QualType ASTContext::getRecordType(const RecordDecl *Decl) const {
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
- if (const RecordDecl *PrevDecl = Decl->getPreviousDeclaration())
+ if (const RecordDecl *PrevDecl = Decl->getPreviousDecl())
if (PrevDecl->TypeForDecl)
return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
@@ -2238,7 +2303,7 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const {
QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0);
- if (const EnumDecl *PrevDecl = Decl->getPreviousDeclaration())
+ if (const EnumDecl *PrevDecl = Decl->getPreviousDecl())
if (PrevDecl->TypeForDecl)
return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0);
@@ -2373,6 +2438,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
TemplateSpecializationTypeLoc TL
= cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+ TL.setTemplateKeywordLoc(SourceLocation());
TL.setTemplateNameLoc(NameLoc);
TL.setLAngleLoc(Args.getLAngleLoc());
TL.setRAngleLoc(Args.getRAngleLoc());
@@ -2399,6 +2465,17 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
Underlying);
}
+#ifndef NDEBUG
+static bool hasAnyPackExpansions(const TemplateArgument *Args,
+ unsigned NumArgs) {
+ for (unsigned I = 0; I != NumArgs; ++I)
+ if (Args[I].isPackExpansion())
+ return true;
+
+ return true;
+}
+#endif
+
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgument *Args,
@@ -2410,16 +2487,18 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Template = TemplateName(QTN->getTemplateDecl());
- bool isTypeAlias =
+ bool IsTypeAlias =
Template.getAsTemplateDecl() &&
isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
-
QualType CanonType;
if (!Underlying.isNull())
CanonType = getCanonicalType(Underlying);
else {
- assert(!isTypeAlias &&
- "Underlying type for template alias must be computed by caller");
+ // We can get here with an alias template when the specialization contains
+ // a pack expansion that does not match up with a parameter pack.
+ assert((!IsTypeAlias || hasAnyPackExpansions(Args, NumArgs)) &&
+ "Caller must compute aliased type");
+ IsTypeAlias = false;
CanonType = getCanonicalTemplateSpecializationType(Template, Args,
NumArgs);
}
@@ -2429,13 +2508,11 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
// we don't unique and don't want to lose.
void *Mem = Allocate(sizeof(TemplateSpecializationType) +
sizeof(TemplateArgument) * NumArgs +
- (isTypeAlias ? sizeof(QualType) : 0),
+ (IsTypeAlias? sizeof(QualType) : 0),
TypeAlignment);
TemplateSpecializationType *Spec
- = new (Mem) TemplateSpecializationType(Template,
- Args, NumArgs,
- CanonType,
- isTypeAlias ? Underlying : QualType());
+ = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, CanonType,
+ IsTypeAlias ? Underlying : QualType());
Types.push_back(Spec);
return QualType(Spec, 0);
@@ -2447,9 +2524,6 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
unsigned NumArgs) const {
assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
- assert((!Template.getAsTemplateDecl() ||
- !isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) &&
- "Underlying type for template alias must be computed by caller");
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
@@ -2676,8 +2750,12 @@ static bool areSortedAndUniqued(ObjCProtocolDecl * const *Protocols,
unsigned NumProtocols) {
if (NumProtocols == 0) return true;
+ if (Protocols[0]->getCanonicalDecl() != Protocols[0])
+ return false;
+
for (unsigned i = 1; i != NumProtocols; ++i)
- if (!CmpProtocolNames(Protocols[i-1], Protocols[i]))
+ if (!CmpProtocolNames(Protocols[i-1], Protocols[i]) ||
+ Protocols[i]->getCanonicalDecl() != Protocols[i])
return false;
return true;
}
@@ -2689,6 +2767,10 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,
// Sort protocols, keyed by name.
std::sort(Protocols, Protocols+NumProtocols, CmpProtocolNames);
+ // Canonicalize.
+ for (unsigned I = 0, N = NumProtocols; I != N; ++I)
+ Protocols[I] = Protocols[I]->getCanonicalDecl();
+
// Remove duplicates.
ProtocolsEnd = std::unique(Protocols, ProtocolsEnd);
NumProtocols = ProtocolsEnd-Protocols;
@@ -2774,11 +2856,21 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const {
/// getObjCInterfaceType - Return the unique reference to the type for the
/// specified ObjC interface decl. The list of protocols is optional.
-QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const {
+QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
+ ObjCInterfaceDecl *PrevDecl) const {
if (Decl->TypeForDecl)
return QualType(Decl->TypeForDecl, 0);
- // FIXME: redeclarations?
+ if (PrevDecl) {
+ assert(PrevDecl->TypeForDecl && "previous decl has no TypeForDecl");
+ Decl->TypeForDecl = PrevDecl->TypeForDecl;
+ return QualType(PrevDecl->TypeForDecl, 0);
+ }
+
+ // Prefer the definition, if there is one.
+ if (const ObjCInterfaceDecl *Def = Decl->getDefinition())
+ Decl = Def;
+
void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment);
ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl);
Decl->TypeForDecl = T;
@@ -2832,44 +2924,13 @@ QualType ASTContext::getTypeOfType(QualType tofType) const {
return QualType(tot, 0);
}
-/// getDecltypeForExpr - Given an expr, will return the decltype for that
-/// expression, according to the rules in C++0x [dcl.type.simple]p4
-static QualType getDecltypeForExpr(const Expr *e, const ASTContext &Context) {
- if (e->isTypeDependent())
- return Context.DependentTy;
-
- // If e is an id expression or a class member access, decltype(e) is defined
- // as the type of the entity named by e.
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(e)) {
- if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
- return VD->getType();
- }
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(e)) {
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
- return FD->getType();
- }
- // If e is a function call or an invocation of an overloaded operator,
- // (parentheses around e are ignored), decltype(e) is defined as the
- // return type of that function.
- if (const CallExpr *CE = dyn_cast<CallExpr>(e->IgnoreParens()))
- return CE->getCallReturnType();
-
- QualType T = e->getType();
-
- // Otherwise, where T is the type of e, if e is an lvalue, decltype(e) is
- // defined as T&, otherwise decltype(e) is defined as T.
- if (e->isLValue())
- T = Context.getLValueReferenceType(T);
-
- return T;
-}
/// getDecltypeType - Unlike many "get<Type>" functions, we don't unique
/// DecltypeType AST's. The only motivation to unique these nodes would be
/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be
/// an issue. This doesn't effect the type checker, since it operates
-/// on canonical type's (which are always unique).
-QualType ASTContext::getDecltypeType(Expr *e) const {
+/// on canonical types (which are always unique).
+QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const {
DecltypeType *dt;
// C++0x [temp.type]p2:
@@ -2895,8 +2956,8 @@ QualType ASTContext::getDecltypeType(Expr *e) const {
dt = Canon;
}
} else {
- QualType T = getDecltypeForExpr(e, *this);
- dt = new (*this, TypeAlignment) DecltypeType(e, T, getCanonicalType(T));
+ dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType,
+ getCanonicalType(UnderlyingType));
}
Types.push_back(dt);
return QualType(dt, 0);
@@ -2912,7 +2973,7 @@ QualType ASTContext::getUnaryTransformType(QualType BaseType,
new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType,
Kind,
UnderlyingType->isDependentType() ?
- QualType() : UnderlyingType);
+ QualType() : getCanonicalType(UnderlyingType));
Types.push_back(Ty);
return QualType(Ty, 0);
}
@@ -2995,6 +3056,16 @@ CanQualType ASTContext::getSizeType() const {
return getFromTargetType(Target->getSizeType());
}
+/// getIntMaxType - Return the unique type for "intmax_t" (C99 7.18.1.5).
+CanQualType ASTContext::getIntMaxType() const {
+ return getFromTargetType(Target->getIntMaxType());
+}
+
+/// getUIntMaxType - Return the unique type for "uintmax_t" (C99 7.18.1.5).
+CanQualType ASTContext::getUIntMaxType() const {
+ return getFromTargetType(Target->getUIntMaxType());
+}
+
/// getSignedWCharType - Return the type of "signed wchar_t".
/// Used when in C++, as a GCC extension.
QualType ASTContext::getSignedWCharType() const {
@@ -3009,7 +3080,7 @@ QualType ASTContext::getUnsignedWCharType() const {
return UnsignedIntTy;
}
-/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
+/// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType ASTContext::getPointerDiffType() const {
return getFromTargetType(Target->getPtrDiffType(0));
@@ -3046,12 +3117,12 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
// We then have to strip that sugar back off with
// getUnqualifiedDesugaredType(), which is silly.
const ArrayType *AT =
- dyn_cast<ArrayType>(splitType.first->getUnqualifiedDesugaredType());
+ dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType());
// If we don't have an array, just use the results in splitType.
if (!AT) {
- quals = splitType.second;
- return QualType(splitType.first, 0);
+ quals = splitType.Quals;
+ return QualType(splitType.Ty, 0);
}
// Otherwise, recurse on the array's element type.
@@ -3062,13 +3133,13 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type,
// can just use the results in splitType.
if (elementType == unqualElementType) {
assert(quals.empty()); // from the recursive call
- quals = splitType.second;
- return QualType(splitType.first, 0);
+ quals = splitType.Quals;
+ return QualType(splitType.Ty, 0);
}
// Otherwise, add in the qualifiers from the outermost type, then
// build the type back up.
- quals.addConsistentQualifiers(splitType.second);
+ quals.addConsistentQualifiers(splitType.Quals);
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
return getConstantArrayType(unqualElementType, CAT->getSize(),
@@ -3120,7 +3191,7 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) {
return true;
}
- if (getLangOptions().ObjC1) {
+ if (getLangOpts().ObjC1) {
const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(),
*T2OPType = T2->getAs<ObjCObjectPointerType>();
if (T1OPType && T2OPType) {
@@ -3242,8 +3313,11 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
case TemplateArgument::Expression:
return Arg;
- case TemplateArgument::Declaration:
- return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
+ case TemplateArgument::Declaration: {
+ if (Decl *D = Arg.getAsDecl())
+ return TemplateArgument(D->getCanonicalDecl());
+ return TemplateArgument((Decl*)0);
+ }
case TemplateArgument::Template:
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
@@ -3316,26 +3390,13 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
// types, e.g.,
// typedef typename T::type T1;
// typedef typename T1::type T2;
- if (const DependentNameType *DNT = T->getAs<DependentNameType>()) {
- NestedNameSpecifier *Prefix
- = getCanonicalNestedNameSpecifier(DNT->getQualifier());
- return NestedNameSpecifier::Create(*this, Prefix,
+ if (const DependentNameType *DNT = T->getAs<DependentNameType>())
+ return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
- }
- // Do the same thing as above, but with dependent-named specializations.
- if (const DependentTemplateSpecializationType *DTST
- = T->getAs<DependentTemplateSpecializationType>()) {
- NestedNameSpecifier *Prefix
- = getCanonicalNestedNameSpecifier(DTST->getQualifier());
-
- T = getDependentTemplateSpecializationType(DTST->getKeyword(),
- Prefix, DTST->getIdentifier(),
- DTST->getNumArgs(),
- DTST->getArgs());
- T = getCanonicalType(T);
- }
-
+ // Otherwise, just canonicalize the type, and force it to be a TypeSpec.
+ // FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the
+ // first place?
return NestedNameSpecifier::Create(*this, 0, false,
const_cast<Type*>(T.getTypePtr()));
}
@@ -3345,8 +3406,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
return NNS;
}
- // Required to silence a GCC warning
- return 0;
+ llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
@@ -3371,10 +3431,10 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const {
// we must propagate them down into the element type.
SplitQualType split = T.getSplitDesugaredType();
- Qualifiers qs = split.second;
+ Qualifiers qs = split.Quals;
// If we have a simple case, just return now.
- const ArrayType *ATy = dyn_cast<ArrayType>(split.first);
+ const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty);
if (ATy == 0 || qs.empty())
return ATy;
@@ -3461,11 +3521,11 @@ QualType ASTContext::getBaseElementType(QualType type) const {
Qualifiers qs;
while (true) {
SplitQualType split = type.getSplitDesugaredType();
- const ArrayType *array = split.first->getAsArrayTypeUnsafe();
+ const ArrayType *array = split.Ty->getAsArrayTypeUnsafe();
if (!array) break;
type = array->getElementType();
- qs.addConsistentQualifiers(split.second);
+ qs.addConsistentQualifiers(split.Quals);
}
return getQualifiedType(type, qs);
@@ -3507,7 +3567,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
FloatingRank EltRank = getFloatingRank(Size);
if (Domain->isComplexType()) {
switch (EltRank) {
- default: llvm_unreachable("getFloatingRank(): illegal value for rank");
+ case HalfRank: llvm_unreachable("Complex half is not supported");
case FloatRank: return FloatComplexTy;
case DoubleRank: return DoubleComplexTy;
case LongDoubleRank: return LongDoubleComplexTy;
@@ -3516,11 +3576,12 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size,
assert(Domain->isRealFloatingType() && "Unknown domain!");
switch (EltRank) {
- default: llvm_unreachable("getFloatingRank(): illegal value for rank");
+ case HalfRank: llvm_unreachable("Half ranks are not valid here");
case FloatRank: return FloatTy;
case DoubleRank: return DoubleTy;
case LongDoubleRank: return LongDoubleTy;
}
+ llvm_unreachable("getFloatingRank(): illegal value for rank");
}
/// getFloatingTypeOrder - Compare the rank of the two specified floating
@@ -3543,18 +3604,6 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const {
/// or if it is not canonicalized.
unsigned ASTContext::getIntegerRank(const Type *T) const {
assert(T->isCanonicalUnqualified() && "T should be canonicalized");
- if (const EnumType* ET = dyn_cast<EnumType>(T))
- T = ET->getDecl()->getPromotionType().getTypePtr();
-
- if (T->isSpecificBuiltinType(BuiltinType::WChar_S) ||
- T->isSpecificBuiltinType(BuiltinType::WChar_U))
- T = getFromTargetType(Target->getWCharType()).getTypePtr();
-
- if (T->isSpecificBuiltinType(BuiltinType::Char16))
- T = getFromTargetType(Target->getChar16Type()).getTypePtr();
-
- if (T->isSpecificBuiltinType(BuiltinType::Char32))
- T = getFromTargetType(Target->getChar32Type()).getTypePtr();
switch (cast<BuiltinType>(T)->getKind()) {
default: llvm_unreachable("getIntegerRank(): not a built-in integer");
@@ -3624,6 +3673,34 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
assert(Promotable->isPromotableIntegerType());
if (const EnumType *ET = Promotable->getAs<EnumType>())
return ET->getDecl()->getPromotionType();
+
+ if (const BuiltinType *BT = Promotable->getAs<BuiltinType>()) {
+ // C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t
+ // (3.9.1) can be converted to a prvalue of the first of the following
+ // types that can represent all the values of its underlying type:
+ // int, unsigned int, long int, unsigned long int, long long int, or
+ // unsigned long long int [...]
+ // FIXME: Is there some better way to compute this?
+ if (BT->getKind() == BuiltinType::WChar_S ||
+ BT->getKind() == BuiltinType::WChar_U ||
+ BT->getKind() == BuiltinType::Char16 ||
+ BT->getKind() == BuiltinType::Char32) {
+ bool FromIsSigned = BT->getKind() == BuiltinType::WChar_S;
+ uint64_t FromSize = getTypeSize(BT);
+ QualType PromoteTypes[] = { IntTy, UnsignedIntTy, LongTy, UnsignedLongTy,
+ LongLongTy, UnsignedLongLongTy };
+ for (size_t Idx = 0; Idx < llvm::array_lengthof(PromoteTypes); ++Idx) {
+ uint64_t ToSize = getTypeSize(PromoteTypes[Idx]);
+ if (FromSize < ToSize ||
+ (FromSize == ToSize &&
+ FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType()))
+ return PromoteTypes[Idx];
+ }
+ llvm_unreachable("char type should fit into long long");
+ }
+ }
+
+ // At this point, we should have a signed or unsigned integer type.
if (Promotable->isSignedIntegerType())
return IntTy;
uint64_t PromotableSize = getTypeSize(Promotable);
@@ -3696,7 +3773,7 @@ static RecordDecl *
CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK,
DeclContext *DC, IdentifierInfo *Id) {
SourceLocation Loc;
- if (Ctx.getLangOptions().CPlusPlus)
+ if (Ctx.getLangOpts().CPlusPlus)
return CXXRecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id);
else
return RecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id);
@@ -3831,7 +3908,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
bool ASTContext::BlockRequiresCopying(QualType Ty) const {
if (Ty->isObjCRetainableType())
return true;
- if (getLangOptions().CPlusPlus) {
+ if (getLangOpts().CPlusPlus) {
if (const RecordType *RT = Ty->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
return RD->hasConstCopyConstructor();
@@ -3856,7 +3933,7 @@ ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const {
bool HasCopyAndDispose = BlockRequiresCopying(Ty);
// FIXME: Move up
- llvm::SmallString<36> Name;
+ SmallString<36> Name;
llvm::raw_svector_ostream(Name) << "__Block_byref_" <<
++UniqueBlockByRefTypeID << '_' << DeclName;
RecordDecl *T;
@@ -4036,15 +4113,32 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
return false;
}
+/// getObjCEncodingForMethodParameter - Return the encoded type for a single
+/// method parameter or return type. If Extended, include class names and
+/// block object types.
+void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
+ QualType T, std::string& S,
+ bool Extended) const {
+ // Encode type qualifer, 'in', 'inout', etc. for the parameter.
+ getObjCEncodingForTypeQualifier(QT, S);
+ // Encode parameter type.
+ getObjCEncodingForTypeImpl(T, S, true, true, 0,
+ true /*OutermostType*/,
+ false /*EncodingProperty*/,
+ false /*StructField*/,
+ Extended /*EncodeBlockParameters*/,
+ Extended /*EncodeClassNames*/);
+}
+
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
- std::string& S) const {
+ std::string& S,
+ bool Extended) const {
// FIXME: This is not very efficient.
- // Encode type qualifer, 'in', 'inout', etc. for the return type.
- getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S);
- // Encode result type.
- getObjCEncodingForType(Decl->getResultType(), S);
+ // Encode return type.
+ getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(),
+ Decl->getResultType(), S, Extended);
// Compute size of all parameters.
// Start with computing size of a pointer in number of bytes.
// FIXME: There might(should) be a better way of doing this computation!
@@ -4082,10 +4176,8 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
PType = PVDecl->getType();
} else if (PType->isFunctionType())
PType = PVDecl->getType();
- // Process argument qualifiers for user supplied arguments; such as,
- // 'in', 'inout', etc.
- getObjCEncodingForTypeQualifier(PVDecl->getObjCDeclQualifier(), S);
- getObjCEncodingForType(PType, S);
+ getObjCEncodingForMethodParameter(PVDecl->getObjCDeclQualifier(),
+ PType, S, Extended);
S += charUnitsToString(ParmOffset);
ParmOffset += getObjCEncodingTypeSize(PType);
}
@@ -4112,7 +4204,7 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
/// kPropertyGetter = 'G', // followed by getter selector name
/// kPropertySetter = 'S', // followed by setter selector name
/// kPropertyInstanceVariable = 'V' // followed by instance variable name
-/// kPropertyType = 't' // followed by old-style type encoding.
+/// kPropertyType = 'T' // followed by old-style type encoding.
/// kPropertyWeak = 'W' // 'weak' property
/// kPropertyStrong = 'P' // property GC'able
/// kPropertyNonAtomic = 'N' // property non-atomic
@@ -4292,7 +4384,7 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S,
// information is not especially sensible, but we're stuck with it for
// compatibility with GCC, although providing it breaks anything that
// actually uses runtime introspection and wants to work on both runtimes...
- if (!Ctx->getLangOptions().NeXTRuntime) {
+ if (!Ctx->getLangOpts().NeXTRuntime) {
const RecordDecl *RD = FD->getParent();
const ASTRecordLayout &RL = Ctx->getASTRecordLayout(RD);
S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex()));
@@ -4311,7 +4403,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
const FieldDecl *FD,
bool OutermostType,
bool EncodingProperty,
- bool StructField) const {
+ bool StructField,
+ bool EncodeBlockParameters,
+ bool EncodeClassNames) const {
if (T->getAs<BuiltinType>()) {
if (FD && FD->isBitField())
return EncodeBitField(this, S, T, FD);
@@ -4490,8 +4584,40 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
return;
}
- if (T->isBlockPointerType()) {
+ if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) {
S += "@?"; // Unlike a pointer-to-function, which is "^?".
+ if (EncodeBlockParameters) {
+ const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>();
+
+ S += '<';
+ // Block return type
+ getObjCEncodingForTypeImpl(FT->getResultType(), S,
+ ExpandPointedToStructures, ExpandStructures,
+ FD,
+ false /* OutermostType */,
+ EncodingProperty,
+ false /* StructField */,
+ EncodeBlockParameters,
+ EncodeClassNames);
+ // Block self
+ S += "@?";
+ // Block parameters
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) {
+ for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(),
+ E = FPT->arg_type_end(); I && (I != E); ++I) {
+ getObjCEncodingForTypeImpl(*I, S,
+ ExpandPointedToStructures,
+ ExpandStructures,
+ FD,
+ false /* OutermostType */,
+ EncodingProperty,
+ false /* StructField */,
+ EncodeBlockParameters,
+ EncodeClassNames);
+ }
+ }
+ S += '>';
+ }
return;
}
@@ -4537,7 +4663,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
getObjCEncodingForTypeImpl(getObjCIdType(), S,
ExpandPointedToStructures,
ExpandStructures, FD);
- if (FD || EncodingProperty) {
+ if (FD || EncodingProperty || EncodeClassNames) {
// Note that we do extended encoding of protocol qualifer list
// Only when doing ivar or property encoding.
S += '"';
@@ -4566,7 +4692,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
S += '@';
- if (OPT->getInterfaceDecl() && (FD || EncodingProperty)) {
+ if (OPT->getInterfaceDecl() &&
+ (FD || EncodingProperty || EncodeClassNames)) {
S += '"';
S += OPT->getInterfaceDecl()->getIdentifier()->getName();
for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(),
@@ -4779,10 +4906,6 @@ TypedefDecl *ASTContext::getObjCSelDecl() const {
return ObjCSelDecl;
}
-void ASTContext::setObjCProtoType(QualType QT) {
- ObjCProtoType = QT;
-}
-
TypedefDecl *ASTContext::getObjCClassDecl() const {
if (!ObjCClassDecl) {
QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0);
@@ -4797,6 +4920,19 @@ TypedefDecl *ASTContext::getObjCClassDecl() const {
return ObjCClassDecl;
}
+ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const {
+ if (!ObjCProtocolClassDecl) {
+ ObjCProtocolClassDecl
+ = ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(),
+ SourceLocation(),
+ &Idents.get("Protocol"),
+ /*PrevDecl=*/0,
+ SourceLocation(), true);
+ }
+
+ return ObjCProtocolClassDecl;
+}
+
void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
assert(ObjCConstantStringType.isNull() &&
"'NSConstantString' type already set!");
@@ -4986,10 +5122,10 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const {
/// garbage collection attribute.
///
Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const {
- if (getLangOptions().getGC() == LangOptions::NonGC)
+ if (getLangOpts().getGC() == LangOptions::NonGC)
return Qualifiers::GCNone;
- assert(getLangOptions().ObjC1);
+ assert(getLangOpts().ObjC1);
Qualifiers::GC GCAttrs = Ty.getObjCGCAttr();
// Default behaviour under objective-C's gc is for ObjC pointers
@@ -5058,7 +5194,7 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
bool
ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto,
ObjCProtocolDecl *rProto) const {
- if (lProto == rProto)
+ if (declaresSameEntity(lProto, rProto))
return true;
for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(),
E = rProto->protocol_end(); PI != E; ++PI)
@@ -5359,7 +5495,7 @@ QualType ASTContext::areCommonBaseCompatible(
const ObjCObjectType *RHS = Rptr->getObjectType();
const ObjCInterfaceDecl* LDecl = LHS->getInterface();
const ObjCInterfaceDecl* RDecl = RHS->getInterface();
- if (!LDecl || !RDecl || (LDecl == RDecl))
+ if (!LDecl || !RDecl || (declaresSameEntity(LDecl, RDecl)))
return QualType();
do {
@@ -5483,7 +5619,7 @@ bool ASTContext::canBindObjCObjectType(QualType To, QualType From) {
/// same. See 6.7.[2,3,5] for additional rules.
bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
bool CompareUnqualified) {
- if (getLangOptions().CPlusPlus)
+ if (getLangOpts().CPlusPlus)
return hasSameType(LHS, RHS);
return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
@@ -5790,14 +5926,23 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
// Compatibility is based on the underlying type, not the promotion
// type.
if (const EnumType* ETy = LHS->getAs<EnumType>()) {
- if (ETy->getDecl()->getIntegerType() == RHSCan.getUnqualifiedType())
+ QualType TINT = ETy->getDecl()->getIntegerType();
+ if (!TINT.isNull() && hasSameType(TINT, RHSCan.getUnqualifiedType()))
return RHS;
}
if (const EnumType* ETy = RHS->getAs<EnumType>()) {
- if (ETy->getDecl()->getIntegerType() == LHSCan.getUnqualifiedType())
+ QualType TINT = ETy->getDecl()->getIntegerType();
+ if (!TINT.isNull() && hasSameType(TINT, LHSCan.getUnqualifiedType()))
return LHS;
}
-
+ // allow block pointer type to match an 'id' type.
+ if (OfBlockPointer && !BlockReturnType) {
+ if (LHS->isObjCIdType() && RHS->isBlockPointerType())
+ return LHS;
+ if (RHS->isObjCIdType() && LHS->isBlockPointerType())
+ return RHS;
+ }
+
return QualType();
}
@@ -5958,7 +6103,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
LHS->getAs<ObjCObjectPointerType>(),
RHS->getAs<ObjCObjectPointerType>(),
BlockReturnType))
- return LHS;
+ return LHS;
return QualType();
}
if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(),
@@ -5966,10 +6111,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return LHS;
return QualType();
- }
+ }
}
- return QualType();
+ llvm_unreachable("Invalid Type::Class!");
}
bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs(
@@ -6293,6 +6438,15 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
return QualType();
}
break;
+ case 'K':
+ assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'K'!");
+ Type = Context.getucontext_tType();
+
+ if (Type.isNull()) {
+ Error = ASTContext::GE_Missing_ucontext;
+ return QualType();
+ }
+ break;
}
// If there are modifiers and if we're allowed to parse them, go for it.
@@ -6323,6 +6477,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context,
case 'D':
Type = Context.getVolatileType(Type);
break;
+ case 'R':
+ Type = Type.withRestrict();
+ break;
}
}
@@ -6415,7 +6572,7 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
if (!FD->isInlined())
return External;
- if (!getLangOptions().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
+ if (!getLangOpts().CPlusPlus || FD->hasAttr<GNUInlineAttr>()) {
// GNU or C99 inline semantics. Determine whether this symbol should be
// externally visible.
if (FD->isInlineDefinitionExternallyVisible())
@@ -6447,7 +6604,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
TSK = VD->getTemplateSpecializationKind();
Linkage L = VD->getLinkage();
- if (L == ExternalLinkage && getLangOptions().CPlusPlus &&
+ if (L == ExternalLinkage && getLangOpts().CPlusPlus &&
VD->getType()->getLinkage() == UniqueExternalLinkage)
L = UniqueExternalLinkage;
@@ -6475,7 +6632,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
}
}
- return GVA_StrongExternal;
+ llvm_unreachable("Invalid Linkage!");
}
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
@@ -6592,6 +6749,13 @@ size_t ASTContext::getSideTableAllocatedMemory() const {
+ llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
}
+unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) {
+ CXXRecordDecl *Lambda = CallOperator->getParent();
+ return LambdaMangleContexts[Lambda->getDeclContext()]
+ .getManglingNumber(CallOperator);
+}
+
+
void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
ParamIndices[D] = index;
}
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 07820dc3cc56..ca4fe268522f 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -154,26 +154,34 @@ static std::string
ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
const DiagnosticsEngine::ArgumentValue *PrevArgs,
unsigned NumPrevArgs,
- SmallVectorImpl<intptr_t> &QualTypeVals) {
+ ArrayRef<intptr_t> QualTypeVals) {
// FIXME: Playing with std::string is really slow.
bool ForceAKA = false;
QualType CanTy = Ty.getCanonicalType();
std::string S = Ty.getAsString(Context.getPrintingPolicy());
std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
- for (SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(),
- E = QualTypeVals.end(); I != E; ++I) {
+ for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) {
QualType CompareTy =
- QualType::getFromOpaquePtr(reinterpret_cast<void*>(*I));
+ QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I]));
+ if (CompareTy.isNull())
+ continue;
if (CompareTy == Ty)
continue; // Same types
QualType CompareCanTy = CompareTy.getCanonicalType();
if (CompareCanTy == CanTy)
continue; // Same canonical types
std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
- if (CompareS != S)
- continue; // Original strings are different
- std::string CompareCanS = CompareCanTy.getAsString(Context.getPrintingPolicy());
+ bool aka;
+ QualType CompareDesugar = Desugar(Context, CompareTy, aka);
+ std::string CompareDesugarStr =
+ CompareDesugar.getAsString(Context.getPrintingPolicy());
+ if (CompareS != S && CompareDesugarStr != S)
+ continue; // The type string is different than the comparison string
+ // and the desugared comparison string.
+ std::string CompareCanS =
+ CompareCanTy.getAsString(Context.getPrintingPolicy());
+
if (CompareCanS == CanS)
continue; // No new info from canonical type
@@ -228,7 +236,7 @@ void clang::FormatASTNodeDiagnosticArgument(
unsigned NumPrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
- SmallVectorImpl<intptr_t> &QualTypeVals) {
+ ArrayRef<intptr_t> QualTypeVals) {
ASTContext &Context = *static_cast<ASTContext*>(Cookie);
std::string S;
@@ -286,7 +294,7 @@ void clang::FormatASTNodeDiagnosticArgument(
if (DC->isTranslationUnit()) {
// FIXME: Get these strings from some localized place
- if (Context.getLangOptions().CPlusPlus)
+ if (Context.getLangOpts().CPlusPlus)
S = "the global namespace";
else
S = "the global scope";
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index af66b04c3ad7..3879907ec6da 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -25,9 +25,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include <deque>
-using namespace clang;
-
-namespace {
+namespace clang {
class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
public DeclVisitor<ASTNodeImporter, Decl *>,
public StmtVisitor<ASTNodeImporter, Stmt *> {
@@ -80,7 +78,7 @@ namespace {
QualType VisitObjCObjectType(const ObjCObjectType *T);
QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
- // Importing declarations
+ // Importing declarations
bool ImportDeclParts(NamedDecl *D, DeclContext *&DC,
DeclContext *&LexicalDC, DeclarationName &Name,
SourceLocation &Loc);
@@ -88,10 +86,33 @@ namespace {
void ImportDeclarationNameLoc(const DeclarationNameInfo &From,
DeclarationNameInfo& To);
void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false);
+
+ /// \brief What we should import from the definition.
+ enum ImportDefinitionKind {
+ /// \brief Import the default subset of the definition, which might be
+ /// nothing (if minimal import is set) or might be everything (if minimal
+ /// import is not set).
+ IDK_Default,
+ /// \brief Import everything.
+ IDK_Everything,
+ /// \brief Import only the bare bones needed to establish a valid
+ /// DeclContext.
+ IDK_Basic
+ };
+
+ bool shouldForceImportDeclContext(ImportDefinitionKind IDK) {
+ return IDK == IDK_Everything ||
+ (IDK == IDK_Default && !Importer.isMinimalImport());
+ }
+
bool ImportDefinition(RecordDecl *From, RecordDecl *To,
- bool ForceImport = false);
+ ImportDefinitionKind Kind = IDK_Default);
bool ImportDefinition(EnumDecl *From, EnumDecl *To,
- bool ForceImport = false);
+ ImportDefinitionKind Kind = IDK_Default);
+ bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To,
+ ImportDefinitionKind Kind = IDK_Default);
+ bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To,
+ ImportDefinitionKind Kind = IDK_Default);
TemplateParameterList *ImportTemplateParameterList(
TemplateParameterList *Params);
TemplateArgument ImportTemplateArgument(const TemplateArgument &From);
@@ -102,6 +123,7 @@ namespace {
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
Decl *VisitDecl(Decl *D);
+ Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D);
Decl *VisitNamespaceDecl(NamespaceDecl *D);
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias);
Decl *VisitTypedefDecl(TypedefDecl *D);
@@ -128,8 +150,6 @@ namespace {
Decl *VisitObjCImplementationDecl(ObjCImplementationDecl *D);
Decl *VisitObjCPropertyDecl(ObjCPropertyDecl *D);
Decl *VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
- Decl *VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
- Decl *VisitObjCClassDecl(ObjCClassDecl *D);
Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@@ -154,6 +174,7 @@ namespace {
Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
};
}
+using namespace clang;
//----------------------------------------------------------------------------
// Structural Equivalence
@@ -304,6 +325,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return IsSameValue(*Arg1.getAsIntegral(), *Arg2.getAsIntegral());
case TemplateArgument::Declaration:
+ if (!Arg1.getAsDecl() || !Arg2.getAsDecl())
+ return !Arg1.getAsDecl() && !Arg2.getAsDecl();
return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl());
case TemplateArgument::Template:
@@ -334,7 +357,6 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
}
llvm_unreachable("Invalid template argument kind");
- return true;
}
/// \brief Determine structural equivalence for the common part of array
@@ -945,10 +967,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Base1->getType(), Base2->getType())) {
Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
<< Context.C2.getTypeDeclType(D2);
- Context.Diag2(Base2->getSourceRange().getBegin(), diag::note_odr_base)
+ Context.Diag2(Base2->getLocStart(), diag::note_odr_base)
<< Base2->getType()
<< Base2->getSourceRange();
- Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base)
+ Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
<< Base1->getType()
<< Base1->getSourceRange();
return false;
@@ -958,10 +980,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Base1->isVirtual() != Base2->isVirtual()) {
Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
<< Context.C2.getTypeDeclType(D2);
- Context.Diag2(Base2->getSourceRange().getBegin(),
+ Context.Diag2(Base2->getLocStart(),
diag::note_odr_virtual_base)
<< Base2->isVirtual() << Base2->getSourceRange();
- Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base)
+ Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
<< Base1->isVirtual()
<< Base1->getSourceRange();
return false;
@@ -971,7 +993,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent)
<< Context.C2.getTypeDeclType(D2);
const CXXBaseSpecifier *Base1 = D1CXX->bases_begin();
- Context.Diag1(Base1->getSourceRange().getBegin(), diag::note_odr_base)
+ Context.Diag1(Base1->getLocStart(), diag::note_odr_base)
<< Base1->getType()
<< Base1->getSourceRange();
Context.Diag2(D2->getLocation(), diag::note_odr_missing_base);
@@ -1324,82 +1346,43 @@ QualType ASTNodeImporter::VisitType(const Type *T) {
QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) {
switch (T->getKind()) {
- case BuiltinType::Void: return Importer.getToContext().VoidTy;
- case BuiltinType::Bool: return Importer.getToContext().BoolTy;
-
+#define SHARED_SINGLETON_TYPE(Expansion)
+#define BUILTIN_TYPE(Id, SingletonId) \
+ case BuiltinType::Id: return Importer.getToContext().SingletonId;
+#include "clang/AST/BuiltinTypes.def"
+
+ // FIXME: for Char16, Char32, and NullPtr, make sure that the "to"
+ // context supports C++.
+
+ // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to"
+ // context supports ObjC.
+
case BuiltinType::Char_U:
// The context we're importing from has an unsigned 'char'. If we're
// importing into a context with a signed 'char', translate to
// 'unsigned char' instead.
- if (Importer.getToContext().getLangOptions().CharIsSigned)
+ if (Importer.getToContext().getLangOpts().CharIsSigned)
return Importer.getToContext().UnsignedCharTy;
return Importer.getToContext().CharTy;
- case BuiltinType::UChar: return Importer.getToContext().UnsignedCharTy;
-
- case BuiltinType::Char16:
- // FIXME: Make sure that the "to" context supports C++!
- return Importer.getToContext().Char16Ty;
-
- case BuiltinType::Char32:
- // FIXME: Make sure that the "to" context supports C++!
- return Importer.getToContext().Char32Ty;
-
- case BuiltinType::UShort: return Importer.getToContext().UnsignedShortTy;
- case BuiltinType::UInt: return Importer.getToContext().UnsignedIntTy;
- case BuiltinType::ULong: return Importer.getToContext().UnsignedLongTy;
- case BuiltinType::ULongLong:
- return Importer.getToContext().UnsignedLongLongTy;
- case BuiltinType::UInt128: return Importer.getToContext().UnsignedInt128Ty;
-
case BuiltinType::Char_S:
// The context we're importing from has an unsigned 'char'. If we're
// importing into a context with a signed 'char', translate to
// 'unsigned char' instead.
- if (!Importer.getToContext().getLangOptions().CharIsSigned)
+ if (!Importer.getToContext().getLangOpts().CharIsSigned)
return Importer.getToContext().SignedCharTy;
return Importer.getToContext().CharTy;
- case BuiltinType::SChar: return Importer.getToContext().SignedCharTy;
case BuiltinType::WChar_S:
case BuiltinType::WChar_U:
// FIXME: If not in C++, shall we translate to the C equivalent of
// wchar_t?
return Importer.getToContext().WCharTy;
-
- case BuiltinType::Short : return Importer.getToContext().ShortTy;
- case BuiltinType::Int : return Importer.getToContext().IntTy;
- case BuiltinType::Long : return Importer.getToContext().LongTy;
- case BuiltinType::LongLong : return Importer.getToContext().LongLongTy;
- case BuiltinType::Int128 : return Importer.getToContext().Int128Ty;
- case BuiltinType::Half: return Importer.getToContext().HalfTy;
- case BuiltinType::Float: return Importer.getToContext().FloatTy;
- case BuiltinType::Double: return Importer.getToContext().DoubleTy;
- case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy;
-
- case BuiltinType::NullPtr:
- // FIXME: Make sure that the "to" context supports C++0x!
- return Importer.getToContext().NullPtrTy;
-
- case BuiltinType::Overload: return Importer.getToContext().OverloadTy;
- case BuiltinType::Dependent: return Importer.getToContext().DependentTy;
- case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy;
- case BuiltinType::BoundMember: return Importer.getToContext().BoundMemberTy;
-
- case BuiltinType::ObjCId:
- // FIXME: Make sure that the "to" context supports Objective-C!
- return Importer.getToContext().ObjCBuiltinIdTy;
-
- case BuiltinType::ObjCClass:
- return Importer.getToContext().ObjCBuiltinClassTy;
-
- case BuiltinType::ObjCSel:
- return Importer.getToContext().ObjCBuiltinSelTy;
}
-
- return QualType();
+
+ llvm_unreachable("Invalid BuiltinType Kind!");
}
QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) {
@@ -1600,7 +1583,11 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
if (!ToExpr)
return QualType();
- return Importer.getToContext().getDecltypeType(ToExpr);
+ QualType UnderlyingType = Importer.Import(T->getUnderlyingType());
+ if (UnderlyingType.isNull())
+ return QualType();
+
+ return Importer.getToContext().getDecltypeType(ToExpr, UnderlyingType);
}
QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
@@ -1813,11 +1800,11 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From,
To.setNamedTypeInfo(Importer.Import(FromTInfo));
return;
}
- llvm_unreachable("Unknown name kind.");
}
+ llvm_unreachable("Unknown name kind.");
}
-void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
+void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
if (Importer.isMinimalImport() && !ForceImport) {
Importer.ImportContext(FromDC);
return;
@@ -1831,16 +1818,75 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
}
bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
- bool ForceImport) {
- if (To->getDefinition() || To->isBeingDefined())
+ ImportDefinitionKind Kind) {
+ if (To->getDefinition() || To->isBeingDefined()) {
+ if (Kind == IDK_Everything)
+ ImportDeclContext(From, /*ForceImport=*/true);
+
return false;
+ }
To->startDefinition();
// Add base classes.
if (CXXRecordDecl *ToCXX = dyn_cast<CXXRecordDecl>(To)) {
CXXRecordDecl *FromCXX = cast<CXXRecordDecl>(From);
-
+
+ struct CXXRecordDecl::DefinitionData &ToData = ToCXX->data();
+ struct CXXRecordDecl::DefinitionData &FromData = FromCXX->data();
+ ToData.UserDeclaredConstructor = FromData.UserDeclaredConstructor;
+ ToData.UserDeclaredCopyConstructor = FromData.UserDeclaredCopyConstructor;
+ ToData.UserDeclaredMoveConstructor = FromData.UserDeclaredMoveConstructor;
+ ToData.UserDeclaredCopyAssignment = FromData.UserDeclaredCopyAssignment;
+ ToData.UserDeclaredMoveAssignment = FromData.UserDeclaredMoveAssignment;
+ ToData.UserDeclaredDestructor = FromData.UserDeclaredDestructor;
+ ToData.Aggregate = FromData.Aggregate;
+ ToData.PlainOldData = FromData.PlainOldData;
+ ToData.Empty = FromData.Empty;
+ ToData.Polymorphic = FromData.Polymorphic;
+ ToData.Abstract = FromData.Abstract;
+ ToData.IsStandardLayout = FromData.IsStandardLayout;
+ ToData.HasNoNonEmptyBases = FromData.HasNoNonEmptyBases;
+ ToData.HasPrivateFields = FromData.HasPrivateFields;
+ ToData.HasProtectedFields = FromData.HasProtectedFields;
+ ToData.HasPublicFields = FromData.HasPublicFields;
+ ToData.HasMutableFields = FromData.HasMutableFields;
+ ToData.HasOnlyCMembers = FromData.HasOnlyCMembers;
+ ToData.HasTrivialDefaultConstructor = FromData.HasTrivialDefaultConstructor;
+ ToData.HasConstexprNonCopyMoveConstructor
+ = FromData.HasConstexprNonCopyMoveConstructor;
+ ToData.DefaultedDefaultConstructorIsConstexpr
+ = FromData.DefaultedDefaultConstructorIsConstexpr;
+ ToData.DefaultedCopyConstructorIsConstexpr
+ = FromData.DefaultedCopyConstructorIsConstexpr;
+ ToData.DefaultedMoveConstructorIsConstexpr
+ = FromData.DefaultedMoveConstructorIsConstexpr;
+ ToData.HasConstexprDefaultConstructor
+ = FromData.HasConstexprDefaultConstructor;
+ ToData.HasConstexprCopyConstructor = FromData.HasConstexprCopyConstructor;
+ ToData.HasConstexprMoveConstructor = FromData.HasConstexprMoveConstructor;
+ ToData.HasTrivialCopyConstructor = FromData.HasTrivialCopyConstructor;
+ ToData.HasTrivialMoveConstructor = FromData.HasTrivialMoveConstructor;
+ ToData.HasTrivialCopyAssignment = FromData.HasTrivialCopyAssignment;
+ ToData.HasTrivialMoveAssignment = FromData.HasTrivialMoveAssignment;
+ ToData.HasTrivialDestructor = FromData.HasTrivialDestructor;
+ ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
+ ToData.HasNonLiteralTypeFieldsOrBases
+ = FromData.HasNonLiteralTypeFieldsOrBases;
+ // ComputedVisibleConversions not imported.
+ ToData.UserProvidedDefaultConstructor
+ = FromData.UserProvidedDefaultConstructor;
+ ToData.DeclaredDefaultConstructor = FromData.DeclaredDefaultConstructor;
+ ToData.DeclaredCopyConstructor = FromData.DeclaredCopyConstructor;
+ ToData.DeclaredMoveConstructor = FromData.DeclaredMoveConstructor;
+ ToData.DeclaredCopyAssignment = FromData.DeclaredCopyAssignment;
+ ToData.DeclaredMoveAssignment = FromData.DeclaredMoveAssignment;
+ ToData.DeclaredDestructor = FromData.DeclaredDestructor;
+ ToData.FailedImplicitMoveConstructor
+ = FromData.FailedImplicitMoveConstructor;
+ ToData.FailedImplicitMoveAssignment = FromData.FailedImplicitMoveAssignment;
+ ToData.IsLambda = FromData.IsLambda;
+
SmallVector<CXXBaseSpecifier *, 4> Bases;
for (CXXRecordDecl::base_class_iterator
Base1 = FromCXX->bases_begin(),
@@ -1871,15 +1917,20 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
ToCXX->setBases(Bases.data(), Bases.size());
}
- ImportDeclContext(From, ForceImport);
+ if (shouldForceImportDeclContext(Kind))
+ ImportDeclContext(From, /*ForceImport=*/true);
+
To->completeDefinition();
return false;
}
bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
- bool ForceImport) {
- if (To->getDefinition() || To->isBeingDefined())
+ ImportDefinitionKind Kind) {
+ if (To->getDefinition() || To->isBeingDefined()) {
+ if (Kind == IDK_Everything)
+ ImportDeclContext(From, /*ForceImport=*/true);
return false;
+ }
To->startDefinition();
@@ -1890,8 +1941,9 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To,
QualType ToPromotionType = Importer.Import(From->getPromotionType());
if (ToPromotionType.isNull())
return true;
-
- ImportDeclContext(From, ForceImport);
+
+ if (shouldForceImportDeclContext(Kind))
+ ImportDeclContext(From, /*ForceImport=*/true);
// FIXME: we might need to merge the number of positive or negative bits
// if the enumerator lists don't match.
@@ -1983,7 +2035,6 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
}
llvm_unreachable("Invalid template argument kind");
- return TemplateArgument();
}
bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
@@ -2029,6 +2080,15 @@ Decl *ASTNodeImporter::VisitDecl(Decl *D) {
return 0;
}
+Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ TranslationUnitDecl *ToD =
+ Importer.getToContext().getTranslationUnitDecl();
+
+ Importer.Imported(D, ToD);
+
+ return ToD;
+}
+
Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
// Import the major distinguishing characteristics of this namespace.
DeclContext *DC, *LexicalDC;
@@ -2074,10 +2134,12 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
NamespaceDecl *ToNamespace = MergeWithNamespace;
if (!ToNamespace) {
ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC,
+ D->isInline(),
Importer.Import(D->getLocStart()),
- Loc, Name.getAsIdentifierInfo());
+ Loc, Name.getAsIdentifierInfo(),
+ /*PrevDecl=*/0);
ToNamespace->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToNamespace);
+ LexicalDC->addDeclInternal(ToNamespace);
// If this is an anonymous namespace, register it as the anonymous
// namespace within its context.
@@ -2156,7 +2218,7 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) {
ToTypedef->setAccess(D->getAccess());
ToTypedef->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToTypedef);
- LexicalDC->addDecl(ToTypedef);
+ LexicalDC->addDeclInternal(ToTypedef);
return ToTypedef;
}
@@ -2183,7 +2245,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
if (!SearchName && D->getTypedefNameForAnonDecl()) {
SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName());
IDNS = Decl::IDNS_Ordinary;
- } else if (Importer.getToContext().getLangOptions().CPlusPlus)
+ } else if (Importer.getToContext().getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Ordinary;
// We may already have an enum of the same name; try to find and match it.
@@ -2227,7 +2289,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, D2);
- LexicalDC->addDecl(D2);
+ LexicalDC->addDeclInternal(D2);
// Import the integer type.
QualType ToIntegerType = Importer.Import(D->getIntegerType());
@@ -2268,7 +2330,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (!SearchName && D->getTypedefNameForAnonDecl()) {
SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName());
IDNS = Decl::IDNS_Ordinary;
- } else if (Importer.getToContext().getLangOptions().CPlusPlus)
+ } else if (Importer.getToContext().getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Ordinary;
// We may already have a record of the same name; try to find and match it.
@@ -2332,12 +2394,12 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(D2);
+ LexicalDC->addDeclInternal(D2);
}
Importer.Imported(D, D2);
- if (D->isCompleteDefinition() && ImportDefinition(D, D2))
+ if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default))
return 0;
return D2;
@@ -2389,7 +2451,7 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
ToEnumerator->setAccess(D->getAccess());
ToEnumerator->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToEnumerator);
- LexicalDC->addDecl(ToEnumerator);
+ LexicalDC->addDeclInternal(ToEnumerator);
return ToEnumerator;
}
@@ -2425,7 +2487,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Sema::IsOverload out to the AST library.
// Function overloading is okay in C++.
- if (Importer.getToContext().getLangOptions().CPlusPlus)
+ if (Importer.getToContext().getLangOpts().CPlusPlus)
continue;
// Complain about inconsistent function types.
@@ -2530,14 +2592,14 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Set the parameters.
for (unsigned I = 0, N = Parameters.size(); I != N; ++I) {
Parameters[I]->setOwningFunction(ToFunction);
- ToFunction->addDecl(Parameters[I]);
+ ToFunction->addDeclInternal(Parameters[I]);
}
ToFunction->setParams(Parameters);
// FIXME: Other bits to merge?
// Add this function to the lexical context.
- LexicalDC->addDecl(ToFunction);
+ LexicalDC->addDeclInternal(ToFunction);
return ToFunction;
}
@@ -2605,7 +2667,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
if (ToField->hasInClassInitializer())
ToField->setInClassInitializer(D->getInClassInitializer());
Importer.Imported(D, ToField);
- LexicalDC->addDecl(ToField);
+ LexicalDC->addDeclInternal(ToField);
return ToField;
}
@@ -2661,7 +2723,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
ToIndirectField->setAccess(D->getAccess());
ToIndirectField->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIndirectField);
- LexicalDC->addDecl(ToIndirectField);
+ LexicalDC->addDeclInternal(ToIndirectField);
return ToIndirectField;
}
@@ -2710,7 +2772,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
BitWidth, D->getSynthesize());
ToIvar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToIvar);
- LexicalDC->addDecl(ToIvar);
+ LexicalDC->addDeclInternal(ToIvar);
return ToIvar;
}
@@ -2791,6 +2853,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
} else {
Expr *Init = Importer.Import(DDef->getInit());
MergeWithVar->setInit(Init);
+ if (DDef->isInitKnownICE()) {
+ EvaluatedStmt *Eval = MergeWithVar->ensureEvaluatedStmt();
+ Eval->CheckedICE = true;
+ Eval->IsICE = DDef->isInitICE();
+ }
}
}
@@ -2823,7 +2890,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToVar);
- LexicalDC->addDecl(ToVar);
+ LexicalDC->addDeclInternal(ToVar);
// Merge the initializer.
// FIXME: Can we really import any initializer? Alternatively, we could force
@@ -3002,7 +3069,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
// Set the parameters.
for (unsigned I = 0, N = ToParams.size(); I != N; ++I) {
ToParams[I]->setOwningFunction(ToMethod);
- ToMethod->addDecl(ToParams[I]);
+ ToMethod->addDeclInternal(ToParams[I]);
}
SmallVector<SourceLocation, 12> SelLocs;
D->getSelectorLocs(SelLocs);
@@ -3010,7 +3077,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
ToMethod->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToMethod);
- LexicalDC->addDecl(ToMethod);
+ LexicalDC->addDeclInternal(ToMethod);
return ToMethod;
}
@@ -3037,9 +3104,11 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
Loc,
Importer.Import(D->getCategoryNameLoc()),
Name.getAsIdentifierInfo(),
- ToInterface);
+ ToInterface,
+ Importer.Import(D->getIvarLBraceLoc()),
+ Importer.Import(D->getIvarRBraceLoc()));
ToCategory->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToCategory);
+ LexicalDC->addDeclInternal(ToCategory);
Importer.Imported(D, ToCategory);
// Import protocols
@@ -3084,7 +3153,59 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
return ToCategory;
}
+bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From,
+ ObjCProtocolDecl *To,
+ ImportDefinitionKind Kind) {
+ if (To->getDefinition()) {
+ if (shouldForceImportDeclContext(Kind))
+ ImportDeclContext(From);
+ return false;
+ }
+
+ // Start the protocol definition
+ To->startDefinition();
+
+ // Import protocols
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> ProtocolLocs;
+ ObjCProtocolDecl::protocol_loc_iterator
+ FromProtoLoc = From->protocol_loc_begin();
+ for (ObjCProtocolDecl::protocol_iterator FromProto = From->protocol_begin(),
+ FromProtoEnd = From->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ return true;
+ Protocols.push_back(ToProto);
+ ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ // FIXME: If we're merging, make sure that the protocol list is the same.
+ To->setProtocolList(Protocols.data(), Protocols.size(),
+ ProtocolLocs.data(), Importer.getToContext());
+
+ if (shouldForceImportDeclContext(Kind)) {
+ // Import all of the members of this protocol.
+ ImportDeclContext(From, /*ForceImport=*/true);
+ }
+ return false;
+}
+
Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
+ // If this protocol has a definition in the translation unit we're coming
+ // from, but this particular declaration is not that definition, import the
+ // definition and map to that.
+ ObjCProtocolDecl *Definition = D->getDefinition();
+ if (Definition && Definition != D) {
+ Decl *ImportedDef = Importer.Import(Definition);
+ if (!ImportedDef)
+ return 0;
+
+ return Importer.Imported(D, ImportedDef);
+ }
+
// Import the major distinguishing characteristics of a protocol.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -3104,48 +3225,133 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
}
ObjCProtocolDecl *ToProto = MergeWithProtocol;
- if (!ToProto || ToProto->isForwardDecl()) {
- if (!ToProto) {
- ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
- Name.getAsIdentifierInfo(), Loc,
- Importer.Import(D->getAtStartLoc()));
- ToProto->setForwardDecl(D->isForwardDecl());
- ToProto->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToProto);
- }
- Importer.Imported(D, ToProto);
+ if (!ToProto) {
+ ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC,
+ Name.getAsIdentifierInfo(), Loc,
+ Importer.Import(D->getAtStartLoc()),
+ /*PrevDecl=*/0);
+ ToProto->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToProto);
+ }
+
+ Importer.Imported(D, ToProto);
- // Import protocols
- SmallVector<ObjCProtocolDecl *, 4> Protocols;
- SmallVector<SourceLocation, 4> ProtocolLocs;
- ObjCProtocolDecl::protocol_loc_iterator
- FromProtoLoc = D->protocol_loc_begin();
- for (ObjCProtocolDecl::protocol_iterator FromProto = D->protocol_begin(),
- FromProtoEnd = D->protocol_end();
- FromProto != FromProtoEnd;
- ++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- return 0;
- Protocols.push_back(ToProto);
- ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto))
+ return 0;
+
+ return ToProto;
+}
+
+bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From,
+ ObjCInterfaceDecl *To,
+ ImportDefinitionKind Kind) {
+ if (To->getDefinition()) {
+ // Check consistency of superclass.
+ ObjCInterfaceDecl *FromSuper = From->getSuperClass();
+ if (FromSuper) {
+ FromSuper = cast_or_null<ObjCInterfaceDecl>(Importer.Import(FromSuper));
+ if (!FromSuper)
+ return true;
}
- // FIXME: If we're merging, make sure that the protocol list is the same.
- ToProto->setProtocolList(Protocols.data(), Protocols.size(),
- ProtocolLocs.data(), Importer.getToContext());
- } else {
- Importer.Imported(D, ToProto);
+ ObjCInterfaceDecl *ToSuper = To->getSuperClass();
+ if ((bool)FromSuper != (bool)ToSuper ||
+ (FromSuper && !declaresSameEntity(FromSuper, ToSuper))) {
+ Importer.ToDiag(To->getLocation(),
+ diag::err_odr_objc_superclass_inconsistent)
+ << To->getDeclName();
+ if (ToSuper)
+ Importer.ToDiag(To->getSuperClassLoc(), diag::note_odr_objc_superclass)
+ << To->getSuperClass()->getDeclName();
+ else
+ Importer.ToDiag(To->getLocation(),
+ diag::note_odr_objc_missing_superclass);
+ if (From->getSuperClass())
+ Importer.FromDiag(From->getSuperClassLoc(),
+ diag::note_odr_objc_superclass)
+ << From->getSuperClass()->getDeclName();
+ else
+ Importer.FromDiag(From->getLocation(),
+ diag::note_odr_objc_missing_superclass);
+ }
+
+ if (shouldForceImportDeclContext(Kind))
+ ImportDeclContext(From);
+ return false;
}
+
+ // Start the definition.
+ To->startDefinition();
+
+ // If this class has a superclass, import it.
+ if (From->getSuperClass()) {
+ ObjCInterfaceDecl *Super = cast_or_null<ObjCInterfaceDecl>(
+ Importer.Import(From->getSuperClass()));
+ if (!Super)
+ return true;
+
+ To->setSuperClass(Super);
+ To->setSuperClassLoc(Importer.Import(From->getSuperClassLoc()));
+ }
+
+ // Import protocols
+ SmallVector<ObjCProtocolDecl *, 4> Protocols;
+ SmallVector<SourceLocation, 4> ProtocolLocs;
+ ObjCInterfaceDecl::protocol_loc_iterator
+ FromProtoLoc = From->protocol_loc_begin();
+
+ for (ObjCInterfaceDecl::protocol_iterator FromProto = From->protocol_begin(),
+ FromProtoEnd = From->protocol_end();
+ FromProto != FromProtoEnd;
+ ++FromProto, ++FromProtoLoc) {
+ ObjCProtocolDecl *ToProto
+ = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
+ if (!ToProto)
+ return true;
+ Protocols.push_back(ToProto);
+ ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
+ }
+
+ // FIXME: If we're merging, make sure that the protocol list is the same.
+ To->setProtocolList(Protocols.data(), Protocols.size(),
+ ProtocolLocs.data(), Importer.getToContext());
+
+ // Import categories. When the categories themselves are imported, they'll
+ // hook themselves into this interface.
+ for (ObjCCategoryDecl *FromCat = From->getCategoryList(); FromCat;
+ FromCat = FromCat->getNextClassCategory())
+ Importer.Import(FromCat);
- // Import all of the members of this protocol.
- ImportDeclContext(D);
+ // If we have an @implementation, import it as well.
+ if (From->getImplementation()) {
+ ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
+ Importer.Import(From->getImplementation()));
+ if (!Impl)
+ return true;
+
+ To->setImplementation(Impl);
+ }
- return ToProto;
+ if (shouldForceImportDeclContext(Kind)) {
+ // Import all of the members of this class.
+ ImportDeclContext(From, /*ForceImport=*/true);
+ }
+ return false;
}
Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ // If this class has a definition in the translation unit we're coming from,
+ // but this particular declaration is not that definition, import the
+ // definition and map to that.
+ ObjCInterfaceDecl *Definition = D->getDefinition();
+ if (Definition && Definition != D) {
+ Decl *ImportedDef = Importer.Import(Definition);
+ if (!ImportedDef)
+ return 0;
+
+ return Importer.Imported(D, ImportedDef);
+ }
+
// Import the major distinguishing characteristics of an @interface.
DeclContext *DC, *LexicalDC;
DeclarationName Name;
@@ -3153,6 +3359,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (ImportDeclParts(D, DC, LexicalDC, Name, Loc))
return 0;
+ // Look for an existing interface with the same name.
ObjCInterfaceDecl *MergeWithIface = 0;
llvm::SmallVector<NamedDecl *, 2> FoundDecls;
DC->localUncachedLookup(Name, FoundDecls);
@@ -3164,105 +3371,22 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
break;
}
+ // Create an interface declaration, if one does not already exist.
ObjCInterfaceDecl *ToIface = MergeWithIface;
- if (!ToIface || ToIface->isForwardDecl()) {
- if (!ToIface) {
- ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
- Importer.Import(D->getAtStartLoc()),
- Name.getAsIdentifierInfo(), Loc,
- D->isForwardDecl(),
- D->isImplicitInterfaceDecl());
- ToIface->setForwardDecl(D->isForwardDecl());
- ToIface->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToIface);
- }
- Importer.Imported(D, ToIface);
-
- if (D->getSuperClass()) {
- ObjCInterfaceDecl *Super
- = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getSuperClass()));
- if (!Super)
- return 0;
-
- ToIface->setSuperClass(Super);
- ToIface->setSuperClassLoc(Importer.Import(D->getSuperClassLoc()));
- }
-
- // Import protocols
- SmallVector<ObjCProtocolDecl *, 4> Protocols;
- 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;
- ++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- return 0;
- Protocols.push_back(ToProto);
- ProtocolLocs.push_back(Importer.Import(*FromProtoLoc));
- }
-
- // FIXME: If we're merging, make sure that the protocol list is the same.
- ToIface->setProtocolList(Protocols.data(), Protocols.size(),
- ProtocolLocs.data(), Importer.getToContext());
-
- // Import @end range
- ToIface->setAtEndRange(Importer.Import(D->getAtEndRange()));
- } else {
- Importer.Imported(D, ToIface);
-
- // Check for consistency of superclasses.
- DeclarationName FromSuperName, ToSuperName;
- if (D->getSuperClass())
- FromSuperName = Importer.Import(D->getSuperClass()->getDeclName());
- if (ToIface->getSuperClass())
- ToSuperName = ToIface->getSuperClass()->getDeclName();
- if (FromSuperName != ToSuperName) {
- Importer.ToDiag(ToIface->getLocation(),
- diag::err_odr_objc_superclass_inconsistent)
- << ToIface->getDeclName();
- if (ToIface->getSuperClass())
- Importer.ToDiag(ToIface->getSuperClassLoc(),
- diag::note_odr_objc_superclass)
- << ToIface->getSuperClass()->getDeclName();
- else
- Importer.ToDiag(ToIface->getLocation(),
- diag::note_odr_objc_missing_superclass);
- if (D->getSuperClass())
- Importer.FromDiag(D->getSuperClassLoc(),
- diag::note_odr_objc_superclass)
- << D->getSuperClass()->getDeclName();
- else
- Importer.FromDiag(D->getLocation(),
- diag::note_odr_objc_missing_superclass);
- return 0;
- }
+ if (!ToIface) {
+ ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC,
+ Importer.Import(D->getAtStartLoc()),
+ Name.getAsIdentifierInfo(),
+ /*PrevDecl=*/0,Loc,
+ D->isImplicitInterfaceDecl());
+ ToIface->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToIface);
}
+ Importer.Imported(D, ToIface);
- // Import categories. When the categories themselves are imported, they'll
- // hook themselves into this interface.
- for (ObjCCategoryDecl *FromCat = D->getCategoryList(); FromCat;
- FromCat = FromCat->getNextClassCategory())
- Importer.Import(FromCat);
-
- // Import all of the members of this class.
- ImportDeclContext(D);
-
- // If we have an @implementation, import it as well.
- if (D->getImplementation()) {
- ObjCImplementationDecl *Impl = cast_or_null<ObjCImplementationDecl>(
- Importer.Import(D->getImplementation()));
- if (!Impl)
- return 0;
+ if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface))
+ return 0;
- ToIface->setImplementation(Impl);
- }
-
return ToIface;
}
@@ -3278,11 +3402,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
if (!DC)
return 0;
+ SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc());
ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC,
Importer.Import(D->getIdentifier()),
Category->getClassInterface(),
Importer.Import(D->getLocation()),
- Importer.Import(D->getAtStartLoc()));
+ Importer.Import(D->getAtStartLoc()),
+ CategoryNameLoc);
DeclContext *LexicalDC = DC;
if (D->getDeclContext() != D->getLexicalDeclContext()) {
@@ -3293,7 +3419,7 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
ToImpl->setLexicalDeclContext(LexicalDC);
}
- LexicalDC->addDecl(ToImpl);
+ LexicalDC->addDeclInternal(ToImpl);
Category->setImplementation(ToImpl);
}
@@ -3326,7 +3452,9 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
Importer.ImportContext(D->getDeclContext()),
Iface, Super,
Importer.Import(D->getLocation()),
- Importer.Import(D->getAtStartLoc()));
+ Importer.Import(D->getAtStartLoc()),
+ Importer.Import(D->getIvarLBraceLoc()),
+ Importer.Import(D->getIvarRBraceLoc()));
if (D->getDeclContext() != D->getLexicalDeclContext()) {
DeclContext *LexicalDC
@@ -3346,7 +3474,7 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
if ((Super && !Impl->getSuperClass()) ||
(!Super && Impl->getSuperClass()) ||
(Super && Impl->getSuperClass() &&
- Super->getCanonicalDecl() != Impl->getSuperClass())) {
+ !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) {
Importer.ToDiag(Impl->getLocation(),
diag::err_odr_objc_superclass_inconsistent)
<< Iface->getDeclName();
@@ -3418,11 +3546,12 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
= ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc,
Name.getAsIdentifierInfo(),
Importer.Import(D->getAtLoc()),
+ Importer.Import(D->getLParenLoc()),
T,
D->getPropertyImplementation());
Importer.Imported(D, ToProperty);
ToProperty->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToProperty);
+ LexicalDC->addDeclInternal(ToProperty);
ToProperty->setPropertyAttributes(D->getPropertyAttributes());
ToProperty->setPropertyAttributesAsWritten(
@@ -3481,7 +3610,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
Importer.Import(D->getPropertyIvarDeclLoc()));
ToImpl->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToImpl);
- LexicalDC->addDecl(ToImpl);
+ LexicalDC->addDeclInternal(ToImpl);
} else {
// Check that we have the same kind of property implementation (@synthesize
// vs. @dynamic).
@@ -3519,79 +3648,6 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
return ToImpl;
}
-Decl *
-ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
- // Import the context of this declaration.
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return 0;
-
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return 0;
- }
-
- // Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
-
- SmallVector<ObjCProtocolDecl *, 4> Protocols;
- SmallVector<SourceLocation, 4> Locations;
- ObjCForwardProtocolDecl::protocol_loc_iterator FromProtoLoc
- = D->protocol_loc_begin();
- for (ObjCForwardProtocolDecl::protocol_iterator FromProto
- = D->protocol_begin(), FromProtoEnd = D->protocol_end();
- FromProto != FromProtoEnd;
- ++FromProto, ++FromProtoLoc) {
- ObjCProtocolDecl *ToProto
- = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto));
- if (!ToProto)
- continue;
-
- Protocols.push_back(ToProto);
- Locations.push_back(Importer.Import(*FromProtoLoc));
- }
-
- ObjCForwardProtocolDecl *ToForward
- = ObjCForwardProtocolDecl::Create(Importer.getToContext(), DC, Loc,
- Protocols.data(), Protocols.size(),
- Locations.data());
- ToForward->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToForward);
- Importer.Imported(D, ToForward);
- return ToForward;
-}
-
-Decl *ASTNodeImporter::VisitObjCClassDecl(ObjCClassDecl *D) {
- // Import the context of this declaration.
- DeclContext *DC = Importer.ImportContext(D->getDeclContext());
- if (!DC)
- return 0;
-
- DeclContext *LexicalDC = DC;
- if (D->getDeclContext() != D->getLexicalDeclContext()) {
- LexicalDC = Importer.ImportContext(D->getLexicalDeclContext());
- if (!LexicalDC)
- return 0;
- }
-
- // Import the location of this declaration.
- SourceLocation Loc = Importer.Import(D->getLocation());
- ObjCClassDecl::ObjCClassRef *From = D->getForwardDecl();
- ObjCInterfaceDecl *ToIface
- = cast_or_null<ObjCInterfaceDecl>(Importer.Import(From->getInterface()));
- ObjCClassDecl *ToClass = ObjCClassDecl::Create(Importer.getToContext(), DC,
- Loc,
- ToIface,
- Importer.Import(From->getLocation()));
-
- ToClass->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(ToClass);
- Importer.Imported(D, ToClass);
- return ToClass;
-}
-
Decl *ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
// For template arguments, we adopt the translation unit as our declaration
// context. This context will be fixed when the actual template declaration
@@ -3749,7 +3805,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
D2->setAccess(D->getAccess());
D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(D2);
+ LexicalDC->addDeclInternal(D2);
// Note the relationship between the class templates.
Importer.Imported(D, D2);
@@ -3844,7 +3900,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl(
// Add the specialization to this context.
D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDecl(D2);
+ LexicalDC->addDeclInternal(D2);
}
Importer.Imported(D, D2);
@@ -3891,7 +3947,9 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(),
Importer.Import(E->getQualifierLoc()),
+ Importer.Import(E->getTemplateKeywordLoc()),
ToD,
+ E->refersToEnclosingLocal(),
Importer.Import(E->getLocation()),
T, E->getValueKind(),
FoundD,
@@ -4116,7 +4174,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) {
return 0;
return ToContext.getTrivialTypeSourceInfo(T,
- FromTSI->getTypeLoc().getSourceRange().getBegin());
+ FromTSI->getTypeLoc().getLocStart());
}
Decl *ASTImporter::Import(Decl *FromD) {
@@ -4170,7 +4228,55 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) {
if (!FromDC)
return FromDC;
- return cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
+ DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC)));
+ if (!ToDC)
+ return 0;
+
+ // When we're using a record/enum/Objective-C class/protocol as a context, we
+ // need it to have a definition.
+ if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) {
+ RecordDecl *FromRecord = cast<RecordDecl>(FromDC);
+ if (ToRecord->isCompleteDefinition()) {
+ // Do nothing.
+ } else if (FromRecord->isCompleteDefinition()) {
+ ASTNodeImporter(*this).ImportDefinition(FromRecord, ToRecord,
+ ASTNodeImporter::IDK_Basic);
+ } else {
+ CompleteDecl(ToRecord);
+ }
+ } else if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(ToDC)) {
+ EnumDecl *FromEnum = cast<EnumDecl>(FromDC);
+ if (ToEnum->isCompleteDefinition()) {
+ // Do nothing.
+ } else if (FromEnum->isCompleteDefinition()) {
+ ASTNodeImporter(*this).ImportDefinition(FromEnum, ToEnum,
+ ASTNodeImporter::IDK_Basic);
+ } else {
+ CompleteDecl(ToEnum);
+ }
+ } else if (ObjCInterfaceDecl *ToClass = dyn_cast<ObjCInterfaceDecl>(ToDC)) {
+ ObjCInterfaceDecl *FromClass = cast<ObjCInterfaceDecl>(FromDC);
+ if (ToClass->getDefinition()) {
+ // Do nothing.
+ } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) {
+ ASTNodeImporter(*this).ImportDefinition(FromDef, ToClass,
+ ASTNodeImporter::IDK_Basic);
+ } else {
+ CompleteDecl(ToClass);
+ }
+ } else if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(ToDC)) {
+ ObjCProtocolDecl *FromProto = cast<ObjCProtocolDecl>(FromDC);
+ if (ToProto->getDefinition()) {
+ // Do nothing.
+ } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) {
+ ASTNodeImporter(*this).ImportDefinition(FromDef, ToProto,
+ ASTNodeImporter::IDK_Basic);
+ } else {
+ CompleteDecl(ToProto);
+ }
+ }
+
+ return ToDC;
}
Expr *ASTImporter::Import(Expr *FromE) {
@@ -4244,7 +4350,6 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) {
}
llvm_unreachable("Invalid nested name specifier kind");
- return 0;
}
NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
@@ -4339,7 +4444,6 @@ TemplateName ASTImporter::Import(TemplateName From) {
}
llvm_unreachable("Invalid template name kind");
- return TemplateName();
}
SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
@@ -4413,7 +4517,7 @@ void ASTImporter::ImportDefinition(Decl *From) {
if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(To)) {
if (!ToRecord->getDefinition()) {
Importer.ImportDefinition(cast<RecordDecl>(FromDC), ToRecord,
- /*ForceImport=*/true);
+ ASTNodeImporter::IDK_Everything);
return;
}
}
@@ -4421,11 +4525,27 @@ void ASTImporter::ImportDefinition(Decl *From) {
if (EnumDecl *ToEnum = dyn_cast<EnumDecl>(To)) {
if (!ToEnum->getDefinition()) {
Importer.ImportDefinition(cast<EnumDecl>(FromDC), ToEnum,
- /*ForceImport=*/true);
+ ASTNodeImporter::IDK_Everything);
return;
}
}
+
+ if (ObjCInterfaceDecl *ToIFace = dyn_cast<ObjCInterfaceDecl>(To)) {
+ if (!ToIFace->getDefinition()) {
+ Importer.ImportDefinition(cast<ObjCInterfaceDecl>(FromDC), ToIFace,
+ ASTNodeImporter::IDK_Everything);
+ return;
+ }
+ }
+ if (ObjCProtocolDecl *ToProto = dyn_cast<ObjCProtocolDecl>(To)) {
+ if (!ToProto->getDefinition()) {
+ Importer.ImportDefinition(cast<ObjCProtocolDecl>(FromDC), ToProto,
+ ASTNodeImporter::IDK_Everything);
+ return;
+ }
+ }
+
Importer.ImportDeclContext(FromDC, true);
}
}
@@ -4483,8 +4603,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) {
return DeclarationName::getUsingDirectiveName();
}
- // Silence bogus GCC warning
- return DeclarationName();
+ llvm_unreachable("Invalid DeclarationName Kind!");
}
IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) {
@@ -4521,6 +4640,26 @@ DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
return FromContext.getDiagnostics().Report(Loc, DiagID);
}
+void ASTImporter::CompleteDecl (Decl *D) {
+ if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
+ if (!ID->getDefinition())
+ ID->startDefinition();
+ }
+ else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
+ if (!PD->getDefinition())
+ PD->startDefinition();
+ }
+ else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ if (!TD->getDefinition() && !TD->isBeingDefined()) {
+ TD->startDefinition();
+ TD->setCompleteDefinition(true);
+ }
+ }
+ else {
+ assert (0 && "CompleteDecl called on a Decl that can't be completed");
+ }
+}
+
Decl *ASTImporter::Imported(Decl *From, Decl *To) {
ImportedDecls[From] = To;
return To;
diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp
index 3ca7d4d01d1c..cffcc6501eff 100644
--- a/lib/AST/AttrImpl.cpp
+++ b/lib/AST/AttrImpl.cpp
@@ -19,4 +19,8 @@ using namespace clang;
Attr::~Attr() { }
+void InheritableAttr::anchor() { }
+
+void InheritableParamAttr::anchor() { }
+
#include "clang/AST/AttrImpl.inc"
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 1f0100a580a3..716459a930cf 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -28,10 +28,12 @@ add_clang_library(clangAST
InheritViz.cpp
ItaniumCXXABI.cpp
ItaniumMangle.cpp
+ LambdaMangleContext.cpp
Mangle.cpp
MicrosoftCXXABI.cpp
MicrosoftMangle.cpp
NestedNameSpecifier.cpp
+ NSAPI.cpp
ParentMap.cpp
RecordLayout.cpp
RecordLayoutBuilder.cpp
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index f29bfd13192d..218673090aa7 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -23,12 +23,15 @@ using namespace clang;
void CXXBasePaths::ComputeDeclsFound() {
assert(NumDeclsFound == 0 && !DeclsFound &&
"Already computed the set of declarations");
-
- std::set<NamedDecl *> Decls;
- for (CXXBasePaths::paths_iterator Path = begin(), PathEnd = end();
- Path != PathEnd; ++Path)
- Decls.insert(*Path->Decls.first);
-
+
+ SmallVector<NamedDecl *, 8> Decls;
+ for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path)
+ Decls.push_back(*Path->Decls.first);
+
+ // Eliminate duplicated decls.
+ llvm::array_pod_sort(Decls.begin(), Decls.end());
+ Decls.erase(std::unique(Decls.begin(), Decls.end()), Decls.end());
+
NumDeclsFound = Decls.size();
DeclsFound = new NamedDecl * [NumDeclsFound];
std::copy(Decls.begin(), Decls.end(), DeclsFound);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 95d52cb0fa1b..399f2e48abee 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -24,6 +24,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/Module.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
@@ -47,8 +48,6 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) {
case VisibilityAttr::Protected:
return ProtectedVisibility;
}
-
- return DefaultVisibility;
}
// If we're on Mac OS X, an 'availability' for Mac OS X attribute
@@ -66,17 +65,6 @@ static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) {
}
typedef NamedDecl::LinkageInfo LinkageInfo;
-typedef std::pair<Linkage,Visibility> LVPair;
-
-static LVPair merge(LVPair L, LVPair R) {
- return LVPair(minLinkage(L.first, R.first),
- minVisibility(L.second, R.second));
-}
-
-static LVPair merge(LVPair L, LinkageInfo R) {
- return LVPair(minLinkage(L.first, R.linkage()),
- minVisibility(L.second, R.visibility()));
-}
namespace {
/// Flags controlling the computation of linkage and visibility.
@@ -112,11 +100,16 @@ struct LVFlags {
};
} // end anonymous namespace
+static LinkageInfo getLVForType(QualType T) {
+ std::pair<Linkage,Visibility> P = T->getLinkageAndVisibility();
+ return LinkageInfo(P.first, P.second, T->isVisibilityExplicit());
+}
+
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list.
-static LVPair
+static LinkageInfo
getLVForTemplateParameterList(const TemplateParameterList *Params) {
- LVPair LV(ExternalLinkage, DefaultVisibility);
+ LinkageInfo LV(ExternalLinkage, DefaultVisibility, false);
for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
@@ -125,20 +118,20 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) {
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
QualType T = NTTP->getExpansionType(I);
if (!T->isDependentType())
- LV = merge(LV, T->getLinkageAndVisibility());
+ LV.merge(getLVForType(T));
}
continue;
}
-
+
if (!NTTP->getType()->isDependentType()) {
- LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
+ LV.merge(getLVForType(NTTP->getType()));
continue;
}
}
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(*P)) {
- LV = merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters()));
+ LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters()));
}
}
@@ -150,10 +143,10 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F);
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
-static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
- unsigned NumArgs,
- LVFlags &F) {
- LVPair LV(ExternalLinkage, DefaultVisibility);
+static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs,
+ LVFlags &F) {
+ LinkageInfo LV(ExternalLinkage, DefaultVisibility, false);
for (unsigned I = 0; I != NumArgs; ++I) {
switch (Args[I].getKind()) {
@@ -161,9 +154,9 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
case TemplateArgument::Integral:
case TemplateArgument::Expression:
break;
-
+
case TemplateArgument::Type:
- LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility());
+ LV.merge(getLVForType(Args[I].getAsType()));
break;
case TemplateArgument::Declaration:
@@ -177,15 +170,15 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (TemplateDecl *Template
+ if (TemplateDecl *Template
= Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
- LV = merge(LV, getLVForDecl(Template, F));
+ LV.merge(getLVForDecl(Template, F));
break;
case TemplateArgument::Pack:
- LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
- Args[I].pack_size(),
- F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(Args[I].pack_begin(),
+ Args[I].pack_size(),
+ F));
break;
}
}
@@ -193,7 +186,7 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
return LV;
}
-static LVPair
+static LinkageInfo
getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
LVFlags &F) {
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
@@ -229,14 +222,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// and neither explicitly declared extern nor previously
// declared to have external linkage; or
// (there is no equivalent in C99)
- if (Context.getLangOptions().CPlusPlus &&
+ if (Context.getLangOpts().CPlusPlus &&
Var->getType().isConstant(Context) &&
Var->getStorageClass() != SC_Extern &&
Var->getStorageClass() != SC_PrivateExtern) {
bool FoundExtern = false;
- for (const VarDecl *PrevVar = Var->getPreviousDeclaration();
+ for (const VarDecl *PrevVar = Var->getPreviousDecl();
PrevVar && !FoundExtern;
- PrevVar = PrevVar->getPreviousDeclaration())
+ PrevVar = PrevVar->getPreviousDecl())
if (isExternalLinkage(PrevVar->getLinkage()))
FoundExtern = true;
@@ -244,8 +237,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
return LinkageInfo::internal();
}
if (Var->getStorageClass() == SC_None) {
- const VarDecl *PrevVar = Var->getPreviousDeclaration();
- for (; PrevVar; PrevVar = PrevVar->getPreviousDeclaration())
+ const VarDecl *PrevVar = Var->getPreviousDecl();
+ for (; PrevVar; PrevVar = PrevVar->getPreviousDecl())
if (PrevVar->getStorageClass() == SC_PrivateExtern)
break;
if (PrevVar)
@@ -274,7 +267,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (D->isInAnonymousNamespace()) {
const VarDecl *Var = dyn_cast<VarDecl>(D);
const FunctionDecl *Func = dyn_cast<FunctionDecl>(D);
- if ((!Var || !Var->isExternC()) && (!Func || !Func->isExternC()))
+ if ((!Var || !Var->getDeclContext()->isExternCContext()) &&
+ (!Func || !Func->getDeclContext()->isExternCContext()))
return LinkageInfo::uniqueExternal();
}
@@ -285,6 +279,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// scope and no storage-class specifier, its linkage is
// external.
LinkageInfo LV;
+ LV.mergeVisibility(Context.getLangOpts().getVisibilityMode());
if (F.ConsiderVisibilityAttributes) {
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
@@ -296,10 +291,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
for (const DeclContext *DC = D->getDeclContext();
!isa<TranslationUnitDecl>(DC);
DC = DC->getParent()) {
- if (!isa<NamespaceDecl>(DC)) continue;
- if (llvm::Optional<Visibility> Vis
- = cast<NamespaceDecl>(DC)->getExplicitVisibility()) {
- LV.setVisibility(*Vis, false);
+ const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+ if (!ND) continue;
+ if (llvm::Optional<Visibility> Vis = ND->getExplicitVisibility()) {
+ LV.setVisibility(*Vis, true);
F.ConsiderGlobalVisibility = false;
break;
}
@@ -335,18 +330,19 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
//
// Note that we don't want to make the variable non-external
// because of this, but unique-external linkage suits us.
- if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) {
- LVPair TypeLV = Var->getType()->getLinkageAndVisibility();
- if (TypeLV.first != ExternalLinkage)
+ if (Context.getLangOpts().CPlusPlus &&
+ !Var->getDeclContext()->isExternCContext()) {
+ LinkageInfo TypeLV = getLVForType(Var->getType());
+ if (TypeLV.linkage() != ExternalLinkage)
return LinkageInfo::uniqueExternal();
- if (!LV.visibilityExplicit())
- LV.mergeVisibility(TypeLV.second);
+ LV.mergeVisibilityWithMin(TypeLV.visibility(),
+ TypeLV.visibilityExplicit());
}
if (Var->getStorageClass() == SC_PrivateExtern)
LV.setVisibility(HiddenVisibility, true);
- if (!Context.getLangOptions().CPlusPlus &&
+ if (!Context.getLangOpts().CPlusPlus &&
(Var->getStorageClass() == SC_Extern ||
Var->getStorageClass() == SC_PrivateExtern)) {
@@ -359,7 +355,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// specified at the prior declaration. If no prior declaration
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
- if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
+ if (const VarDecl *PrevVar = Var->getPreviousDecl()) {
LinkageInfo PrevLV = getLVForDecl(PrevVar, F);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
@@ -381,7 +377,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// storage-class specifier, its linkage is determined exactly
// as if it were declared with the storage-class specifier
// extern.
- if (!Context.getLangOptions().CPlusPlus &&
+ if (!Context.getLangOpts().CPlusPlus &&
(Function->getStorageClass() == SC_Extern ||
Function->getStorageClass() == SC_PrivateExtern ||
Function->getStorageClass() == SC_None)) {
@@ -394,7 +390,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// specified at the prior declaration. If no prior declaration
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
- if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
+ if (const FunctionDecl *PrevFunc = Function->getPreviousDecl()) {
LinkageInfo PrevLV = getLVForDecl(PrevFunc, F);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
@@ -405,7 +401,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// unique-external linkage, it's not legally usable from outside
// this translation unit. However, we should use the C linkage
// rules instead for extern "C" declarations.
- if (Context.getLangOptions().CPlusPlus && !Function->isExternC() &&
+ if (Context.getLangOpts().CPlusPlus &&
+ !Function->getDeclContext()->isExternCContext() &&
Function->getType()->getLinkage() == UniqueExternalLinkage)
return LinkageInfo::uniqueExternal();
@@ -417,7 +414,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
LV.merge(getLVForDecl(specInfo->getTemplate(),
F.onlyTemplateVisibility()));
const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
- LV.merge(getLVForTemplateArgumentList(templateArgs, F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(templateArgs, F));
}
}
@@ -443,14 +440,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
// The arguments at which the template was instantiated.
const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
- LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs, F));
}
}
// Consider -fvisibility unless the type has C linkage.
if (F.ConsiderGlobalVisibility)
F.ConsiderGlobalVisibility =
- (Context.getLangOptions().CPlusPlus &&
+ (Context.getLangOpts().CPlusPlus &&
!Tag->getDeclContext()->isExternCContext());
// - an enumerator belonging to an enumeration with external linkage;
@@ -486,11 +483,6 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
if (LV.linkage() != ExternalLinkage)
return LinkageInfo(LV.linkage(), DefaultVisibility, false);
- // If we didn't end up with hidden visibility, consider attributes
- // and -fvisibility.
- if (F.ConsiderGlobalVisibility)
- LV.mergeVisibility(Context.getLangOptions().getVisibilityMode());
-
return LV;
}
@@ -507,6 +499,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
return LinkageInfo::none();
LinkageInfo LV;
+ LV.mergeVisibility(D->getASTContext().getLangOpts().getVisibilityMode());
// The flags we're going to use to compute the class's visibility.
LVFlags ClassF = F;
@@ -548,7 +541,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
if (FunctionTemplateSpecializationInfo *spec
= MD->getTemplateSpecializationInfo()) {
if (shouldConsiderTemplateLV(MD, spec)) {
- LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(*spec->TemplateArguments,
+ F));
if (F.ConsiderTemplateParameterTypes)
LV.merge(getLVForTemplateParameterList(
spec->getTemplate()->getTemplateParameters()));
@@ -567,8 +561,9 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
// about whether containing classes have visibility attributes,
// and that's intentional.
if (TSK != TSK_ExplicitInstantiationDeclaration &&
+ TSK != TSK_ExplicitInstantiationDefinition &&
F.ConsiderGlobalVisibility &&
- MD->getASTContext().getLangOptions().InlineVisibilityHidden) {
+ MD->getASTContext().getLangOpts().InlineVisibilityHidden) {
// InlineVisibilityHidden only applies to definitions, and
// isInlined() only gives meaningful answers on definitions
// anyway.
@@ -586,7 +581,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
if (shouldConsiderTemplateLV(spec)) {
// Merge template argument/parameter information for member
// class template specializations.
- LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F));
+ LV.mergeWithMin(getLVForTemplateArgumentList(spec->getTemplateArgs(),
+ F));
if (F.ConsiderTemplateParameterTypes)
LV.merge(getLVForTemplateParameterList(
spec->getSpecializedTemplate()->getTemplateParameters()));
@@ -597,18 +593,11 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
// Modify the variable's linkage by its type, but ignore the
// type's visibility unless it's a definition.
- LVPair TypeLV = VD->getType()->getLinkageAndVisibility();
- if (TypeLV.first != ExternalLinkage)
+ LinkageInfo TypeLV = getLVForType(VD->getType());
+ if (TypeLV.linkage() != ExternalLinkage)
LV.mergeLinkage(UniqueExternalLinkage);
if (!LV.visibilityExplicit())
- LV.mergeVisibility(TypeLV.second);
- }
-
- F.ConsiderGlobalVisibility &= !LV.visibilityExplicit();
-
- // Apply -fvisibility if desired.
- if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) {
- LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode());
+ LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit());
}
return LV;
@@ -623,6 +612,8 @@ static void clearLinkageForClass(const CXXRecordDecl *record) {
}
}
+void NamedDecl::anchor() { }
+
void NamedDecl::ClearLinkageCache() {
// Note that we can't skip clearing the linkage of children just
// because the parent doesn't have cached linkage: we don't cache
@@ -683,13 +674,13 @@ LinkageInfo NamedDecl::getLinkageAndVisibility() const {
llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const {
// Use the most recent declaration of a variable.
if (const VarDecl *var = dyn_cast<VarDecl>(this))
- return getVisibilityOf(var->getMostRecentDeclaration());
+ return getVisibilityOf(var->getMostRecentDecl());
// Use the most recent declaration of a function, and also handle
// function template specializations.
if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) {
if (llvm::Optional<Visibility> V
- = getVisibilityOf(fn->getMostRecentDeclaration()))
+ = getVisibilityOf(fn->getMostRecentDecl()))
return V;
// If the function is a specialization of a template with an
@@ -698,6 +689,12 @@ llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const {
= fn->getTemplateSpecializationInfo())
return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl());
+ // If the function is a member of a specialization of a class template
+ // and the corresponding decl has explicit visibility, use that.
+ FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
+ if (InstantiatedFrom)
+ return getVisibilityOf(InstantiatedFrom);
+
return llvm::Optional<Visibility>();
}
@@ -712,6 +709,14 @@ llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const {
= dyn_cast<ClassTemplateSpecializationDecl>(this))
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl());
+ // If this is a member class of a specialization of a class template
+ // and the corresponding decl has explicit visibility, use that.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
+ CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+ if (InstantiatedFrom)
+ return getVisibilityOf(InstantiatedFrom);
+ }
+
return llvm::Optional<Visibility>();
}
@@ -721,19 +726,46 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
switch (D->getKind()) {
default:
break;
+ case Decl::ParmVar:
+ return LinkageInfo::none();
case Decl::TemplateTemplateParm: // count these as external
case Decl::NonTypeTemplateParm:
case Decl::ObjCAtDefsField:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCCompatibleAlias:
- case Decl::ObjCForwardProtocol:
case Decl::ObjCImplementation:
case Decl::ObjCMethod:
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
return LinkageInfo::external();
+
+ case Decl::CXXRecord: {
+ const CXXRecordDecl *Record = cast<CXXRecordDecl>(D);
+ if (Record->isLambda()) {
+ if (!Record->getLambdaManglingNumber()) {
+ // This lambda has no mangling number, so it's internal.
+ return LinkageInfo::internal();
+ }
+
+ // This lambda has its linkage/visibility determined by its owner.
+ const DeclContext *DC = D->getDeclContext()->getRedeclContext();
+ if (Decl *ContextDecl = Record->getLambdaContextDecl()) {
+ if (isa<ParmVarDecl>(ContextDecl))
+ DC = ContextDecl->getDeclContext()->getRedeclContext();
+ else
+ return getLVForDecl(cast<NamedDecl>(ContextDecl), Flags);
+ }
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
+ return getLVForDecl(ND, Flags);
+
+ return LinkageInfo::external();
+ }
+
+ break;
+ }
}
// Handle linkage for namespace-scope names.
@@ -763,7 +795,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
// external linkage.
if (D->getLexicalDeclContext()->isFunctionOrMethod()) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- if (Function->isInAnonymousNamespace() && !Function->isExternC())
+ if (Function->isInAnonymousNamespace() &&
+ !Function->getDeclContext()->isExternCContext())
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
@@ -772,7 +805,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LV.setVisibility(*Vis);
}
- if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
+ if (const FunctionDecl *Prev = Function->getPreviousDecl()) {
LinkageInfo PrevLV = getLVForDecl(Prev, Flags);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
@@ -784,7 +817,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
if (const VarDecl *Var = dyn_cast<VarDecl>(D))
if (Var->getStorageClass() == SC_Extern ||
Var->getStorageClass() == SC_PrivateExtern) {
- if (Var->isInAnonymousNamespace() && !Var->isExternC())
+ if (Var->isInAnonymousNamespace() &&
+ !Var->getDeclContext()->isExternCContext())
return LinkageInfo::uniqueExternal();
LinkageInfo LV;
@@ -795,7 +829,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LV.setVisibility(*Vis);
}
- if (const VarDecl *Prev = Var->getPreviousDeclaration()) {
+ if (const VarDecl *Prev = Var->getPreviousDecl()) {
LinkageInfo PrevLV = getLVForDecl(Prev, Flags);
if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());
LV.mergeVisibility(PrevLV);
@@ -811,7 +845,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
}
std::string NamedDecl::getQualifiedNameAsString() const {
- return getQualifiedNameAsString(getASTContext().getLangOptions());
+ return getQualifiedNameAsString(getASTContext().getPrintingPolicy());
}
std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
@@ -904,7 +938,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
// For function declarations, we keep track of redeclarations.
- return FD->getPreviousDeclaration() == OldD;
+ return FD->getPreviousDecl() == OldD;
// For function templates, the underlying function declarations are linked.
if (const FunctionTemplateDecl *FunctionTemplate
@@ -933,6 +967,12 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const {
cast<UsingDecl>(OldD)->getQualifier());
}
+ // A typedef of an Objective-C class type can replace an Objective-C class
+ // declaration or definition, and vice versa.
+ if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) ||
+ (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD)))
+ return true;
+
// For non-function declarations, if the declarations are of the
// same kind then this must be a redeclaration, or semantic analysis
// would not have given us the new declaration.
@@ -943,23 +983,21 @@ bool NamedDecl::hasLinkage() const {
return getLinkage() != NoLinkage;
}
-NamedDecl *NamedDecl::getUnderlyingDecl() {
+NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
NamedDecl *ND = this;
- while (true) {
- if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
- ND = UD->getTargetDecl();
- else if (ObjCCompatibleAliasDecl *AD
- = dyn_cast<ObjCCompatibleAliasDecl>(ND))
- return AD->getClassInterface();
- else
- return ND;
- }
+ while (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
+ ND = UD->getTargetDecl();
+
+ if (ObjCCompatibleAliasDecl *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
+ return AD->getClassInterface();
+
+ return ND;
}
bool NamedDecl::isCXXInstanceMember() const {
- assert(isCXXClassMember() &&
- "checking whether non-member is instance member");
-
+ if (!isCXXClassMember())
+ return false;
+
const NamedDecl *D = this;
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@@ -1131,7 +1169,6 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
}
llvm_unreachable("Invalid storage class");
- return 0;
}
VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
@@ -1141,6 +1178,12 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S, SCAsWritten);
}
+VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl));
+ return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0,
+ QualType(), 0, SC_None, SC_None);
+}
+
void VarDecl::setStorageClass(StorageClass SC) {
assert(isLegalForVariable(SC));
if (getStorageClass() != SC)
@@ -1156,34 +1199,26 @@ SourceRange VarDecl::getSourceRange() const {
}
bool VarDecl::isExternC() const {
- ASTContext &Context = getASTContext();
- if (!Context.getLangOptions().CPlusPlus)
- return (getDeclContext()->isTranslationUnit() &&
- getStorageClass() != SC_Static) ||
- (getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
+ if (getLinkage() != ExternalLinkage)
+ return false;
const DeclContext *DC = getDeclContext();
- if (DC->isFunctionOrMethod())
+ if (DC->isRecord())
return false;
- for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
- if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != SC_Static;
-
- break;
- }
-
- }
-
- return false;
+ ASTContext &Context = getASTContext();
+ if (!Context.getLangOpts().CPlusPlus)
+ return true;
+ return DC->isExternCContext();
}
VarDecl *VarDecl::getCanonicalDecl() {
return getFirstDeclaration();
}
-VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
+VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(
+ ASTContext &C) const
+{
// C++ [basic.def]p2:
// A declaration is a definition unless [...] it contains the 'extern'
// specifier or a linkage-specification and neither an initializer [...],
@@ -1214,8 +1249,8 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
if (getStorageClassAsWritten() == SC_Extern ||
getStorageClassAsWritten() == SC_PrivateExtern) {
- for (const VarDecl *PrevVar = getPreviousDeclaration();
- PrevVar; PrevVar = PrevVar->getPreviousDeclaration()) {
+ for (const VarDecl *PrevVar = getPreviousDecl();
+ PrevVar; PrevVar = PrevVar->getPreviousDecl()) {
if (PrevVar->getLinkage() == InternalLinkage && PrevVar->hasInit())
return DeclarationOnly;
}
@@ -1225,7 +1260,7 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
// and without a storage class specifier or the scs 'static', constitutes
// a tentative definition.
// No such thing in C++.
- if (!getASTContext().getLangOptions().CPlusPlus && isFileVarDecl())
+ if (!C.getLangOpts().CPlusPlus && isFileVarDecl())
return TentativeDefinition;
// What's left is (in C, block-scope) declarations without initializers or
@@ -1263,23 +1298,26 @@ bool VarDecl::isTentativeDefinitionNow() const {
return true;
}
-VarDecl *VarDecl::getDefinition() {
+VarDecl *VarDecl::getDefinition(ASTContext &C) {
VarDecl *First = getFirstDeclaration();
for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
I != E; ++I) {
- if ((*I)->isThisDeclarationADefinition() == Definition)
+ if ((*I)->isThisDeclarationADefinition(C) == Definition)
return *I;
}
return 0;
}
-VarDecl::DefinitionKind VarDecl::hasDefinition() const {
+VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
DefinitionKind Kind = DeclarationOnly;
const VarDecl *First = getFirstDeclaration();
for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end();
- I != E; ++I)
- Kind = std::max(Kind, (*I)->isThisDeclarationADefinition());
+ I != E; ++I) {
+ Kind = std::max(Kind, (*I)->isThisDeclarationADefinition(C));
+ if (Kind == Definition)
+ break;
+ }
return Kind;
}
@@ -1334,6 +1372,130 @@ void VarDecl::setInit(Expr *I) {
Init = I;
}
+bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const {
+ const LangOptions &Lang = C.getLangOpts();
+
+ if (!Lang.CPlusPlus)
+ return false;
+
+ // In C++11, any variable of reference type can be used in a constant
+ // expression if it is initialized by a constant expression.
+ if (Lang.CPlusPlus0x && getType()->isReferenceType())
+ return true;
+
+ // Only const objects can be used in constant expressions in C++. C++98 does
+ // not require the variable to be non-volatile, but we consider this to be a
+ // defect.
+ if (!getType().isConstQualified() || getType().isVolatileQualified())
+ return false;
+
+ // In C++, const, non-volatile variables of integral or enumeration types
+ // can be used in constant expressions.
+ if (getType()->isIntegralOrEnumerationType())
+ return true;
+
+ // Additionally, in C++11, non-volatile constexpr variables can be used in
+ // constant expressions.
+ return Lang.CPlusPlus0x && isConstexpr();
+}
+
+/// Convert the initializer for this declaration to the elaborated EvaluatedStmt
+/// form, which contains extra information on the evaluated value of the
+/// initializer.
+EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
+ EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
+ if (!Eval) {
+ Stmt *S = Init.get<Stmt *>();
+ Eval = new (getASTContext()) EvaluatedStmt;
+ Eval->Value = S;
+ Init = Eval;
+ }
+ return Eval;
+}
+
+APValue *VarDecl::evaluateValue() const {
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ return evaluateValue(Notes);
+}
+
+APValue *VarDecl::evaluateValue(
+ llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
+ EvaluatedStmt *Eval = ensureEvaluatedStmt();
+
+ // We only produce notes indicating why an initializer is non-constant the
+ // first time it is evaluated. FIXME: The notes won't always be emitted the
+ // first time we try evaluation, so might not be produced at all.
+ if (Eval->WasEvaluated)
+ return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated;
+
+ const Expr *Init = cast<Expr>(Eval->Value);
+ assert(!Init->isValueDependent());
+
+ if (Eval->IsEvaluating) {
+ // FIXME: Produce a diagnostic for self-initialization.
+ Eval->CheckedICE = true;
+ Eval->IsICE = false;
+ return 0;
+ }
+
+ Eval->IsEvaluating = true;
+
+ bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(),
+ this, Notes);
+
+ // Ensure the result is an uninitialized APValue if evaluation fails.
+ if (!Result)
+ Eval->Evaluated = APValue();
+
+ Eval->IsEvaluating = false;
+ Eval->WasEvaluated = true;
+
+ // In C++11, we have determined whether the initializer was a constant
+ // expression as a side-effect.
+ if (getASTContext().getLangOpts().CPlusPlus0x && !Eval->CheckedICE) {
+ Eval->CheckedICE = true;
+ Eval->IsICE = Result && Notes.empty();
+ }
+
+ return Result ? &Eval->Evaluated : 0;
+}
+
+bool VarDecl::checkInitIsICE() const {
+ // Initializers of weak variables are never ICEs.
+ if (isWeak())
+ return false;
+
+ EvaluatedStmt *Eval = ensureEvaluatedStmt();
+ if (Eval->CheckedICE)
+ // We have already checked whether this subexpression is an
+ // integral constant expression.
+ return Eval->IsICE;
+
+ const Expr *Init = cast<Expr>(Eval->Value);
+ assert(!Init->isValueDependent());
+
+ // In C++11, evaluate the initializer to check whether it's a constant
+ // expression.
+ if (getASTContext().getLangOpts().CPlusPlus0x) {
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ evaluateValue(Notes);
+ return Eval->IsICE;
+ }
+
+ // It's an ICE whether or not the definition we found is
+ // out-of-line. See DR 721 and the discussion in Clang PR
+ // 6206 for details.
+
+ if (Eval->CheckingICE)
+ return false;
+ Eval->CheckingICE = true;
+
+ Eval->IsICE = Init->isIntegerConstantExpr(getASTContext());
+ Eval->CheckingICE = false;
+ Eval->CheckedICE = true;
+ return Eval->IsICE;
+}
+
bool VarDecl::extendsLifetimeOfTemporary() const {
assert(getType()->isReferenceType() &&"Non-references never extend lifetime");
@@ -1390,6 +1552,12 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
S, SCAsWritten, DefArg);
}
+ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl));
+ return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(),
+ 0, QualType(), 0, SC_None, SC_None, 0);
+}
+
SourceRange ParmVarDecl::getSourceRange() const {
if (!hasInheritedDefaultArg()) {
SourceRange ArgRange = getDefaultArgRange();
@@ -1412,21 +1580,6 @@ Expr *ParmVarDecl::getDefaultArg() {
return Arg;
}
-unsigned ParmVarDecl::getNumDefaultArgTemporaries() const {
- if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(getInit()))
- return E->getNumTemporaries();
-
- return 0;
-}
-
-CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) {
- assert(getNumDefaultArgTemporaries() &&
- "Default arguments does not have any temporaries!");
-
- ExprWithCleanups *E = cast<ExprWithCleanups>(getInit());
- return E->getTemporary(i);
-}
-
SourceRange ParmVarDecl::getDefaultArgRange() const {
if (const Expr *E = getInit())
return E->getSourceRange();
@@ -1540,7 +1693,7 @@ bool FunctionDecl::isMain() const {
const TranslationUnitDecl *tunit =
dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
return tunit &&
- !tunit->getASTContext().getLangOptions().Freestanding &&
+ !tunit->getASTContext().getLangOpts().Freestanding &&
getIdentifier() &&
getIdentifier()->isStr("main");
}
@@ -1568,27 +1721,21 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const {
}
bool FunctionDecl::isExternC() const {
- ASTContext &Context = getASTContext();
- // In C, any non-static, non-overloadable function has external
- // linkage.
- if (!Context.getLangOptions().CPlusPlus)
- return getStorageClass() != SC_Static && !getAttr<OverloadableAttr>();
+ if (getLinkage() != ExternalLinkage)
+ return false;
+
+ if (getAttr<OverloadableAttr>())
+ return false;
const DeclContext *DC = getDeclContext();
if (DC->isRecord())
return false;
- for (; !DC->isTranslationUnit(); DC = DC->getParent()) {
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) {
- if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
- return getStorageClass() != SC_Static &&
- !getAttr<OverloadableAttr>();
-
- break;
- }
- }
+ ASTContext &Context = getASTContext();
+ if (!Context.getLangOpts().CPlusPlus)
+ return true;
- return isMain();
+ return isMain() || DC->isExternCContext();
}
bool FunctionDecl::isGlobal() const {
@@ -1622,7 +1769,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
FunTmpl->setPreviousDeclaration(PrevFunTmpl);
}
- if (PrevDecl->IsInline)
+ if (PrevDecl && PrevDecl->IsInline)
IsInline = true;
}
@@ -1652,11 +1799,14 @@ void FunctionDecl::setStorageClass(StorageClass SC) {
/// value of type \c Builtin::ID if in the target-independent range
/// \c [1,Builtin::First), or a target-specific builtin value.
unsigned FunctionDecl::getBuiltinID() const {
- ASTContext &Context = getASTContext();
- if (!getIdentifier() || !getIdentifier()->getBuiltinID())
+ if (!getIdentifier())
return 0;
unsigned BuiltinID = getIdentifier()->getBuiltinID();
+ if (!BuiltinID)
+ return 0;
+
+ ASTContext &Context = getASTContext();
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
return BuiltinID;
@@ -1670,7 +1820,7 @@ unsigned FunctionDecl::getBuiltinID() const {
// If this function is at translation-unit scope and we're not in
// C++, it refers to the C library function.
- if (!Context.getLangOptions().CPlusPlus &&
+ if (!Context.getLangOpts().CPlusPlus &&
getDeclContext()->isTranslationUnit())
return BuiltinID;
@@ -1710,12 +1860,22 @@ void FunctionDecl::setParams(ASTContext &C,
}
}
+void FunctionDecl::setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls) {
+ assert(DeclsInPrototypeScope.empty() && "Already has prototype decls!");
+
+ if (!NewDecls.empty()) {
+ NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()];
+ std::copy(NewDecls.begin(), NewDecls.end(), A);
+ DeclsInPrototypeScope = llvm::ArrayRef<NamedDecl*>(A, NewDecls.size());
+ }
+}
+
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
/// arguments (in C++) or the last parameter is a parameter pack.
unsigned FunctionDecl::getMinRequiredArguments() const {
- if (!getASTContext().getLangOptions().CPlusPlus)
+ if (!getASTContext().getLangOpts().CPlusPlus)
return getNumParams();
unsigned NumRequiredArgs = getNumParams();
@@ -1777,31 +1937,79 @@ bool FunctionDecl::isInlined() const {
return false;
}
+static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
+ // Only consider file-scope declarations in this test.
+ if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
+ return false;
+
+ // Only consider explicit declarations; the presence of a builtin for a
+ // libcall shouldn't affect whether a definition is externally visible.
+ if (Redecl->isImplicit())
+ return false;
+
+ if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
+ return true; // Not an inline definition
+
+ return false;
+}
+
/// \brief For a function declaration in C or C++, determine whether this
/// declaration causes the definition to be externally visible.
///
-/// Determines whether this is the first non-inline redeclaration of an inline
-/// function in a language where "inline" does not normally require an
-/// externally visible definition.
+/// Specifically, this determines if adding the current declaration to the set
+/// of redeclarations of the given functions causes
+/// isInlineDefinitionExternallyVisible to change from false to true.
bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
assert(!doesThisDeclarationHaveABody() &&
"Must have a declaration without a body.");
ASTContext &Context = getASTContext();
- // In C99 mode, a function may have an inline definition (causing it to
- // be deferred) then redeclared later. As a special case, "extern inline"
- // is not required to produce an external symbol.
- if (Context.getLangOptions().GNUInline || !Context.getLangOptions().C99 ||
- Context.getLangOptions().CPlusPlus)
+ if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
+ // With GNU inlining, a declaration with 'inline' but not 'extern', forces
+ // an externally visible definition.
+ //
+ // FIXME: What happens if gnu_inline gets added on after the first
+ // declaration?
+ if (!isInlineSpecified() || getStorageClassAsWritten() == SC_Extern)
+ return false;
+
+ const FunctionDecl *Prev = this;
+ bool FoundBody = false;
+ while ((Prev = Prev->getPreviousDecl())) {
+ FoundBody |= Prev->Body;
+
+ if (Prev->Body) {
+ // If it's not the case that both 'inline' and 'extern' are
+ // specified on the definition, then it is always externally visible.
+ if (!Prev->isInlineSpecified() ||
+ Prev->getStorageClassAsWritten() != SC_Extern)
+ return false;
+ } else if (Prev->isInlineSpecified() &&
+ Prev->getStorageClassAsWritten() != SC_Extern) {
+ return false;
+ }
+ }
+ return FoundBody;
+ }
+
+ if (Context.getLangOpts().CPlusPlus)
return false;
- if (getLinkage() != ExternalLinkage || isInlineSpecified())
+
+ // C99 6.7.4p6:
+ // [...] If all of the file scope declarations for a function in a
+ // translation unit include the inline function specifier without extern,
+ // then the definition in that translation unit is an inline definition.
+ if (isInlineSpecified() && getStorageClass() != SC_Extern)
return false;
- const FunctionDecl *Definition = 0;
- if (hasBody(Definition))
- return Definition->isInlined() &&
- Definition->isInlineDefinitionExternallyVisible();
- return false;
+ const FunctionDecl *Prev = this;
+ bool FoundBody = false;
+ while ((Prev = Prev->getPreviousDecl())) {
+ FoundBody |= Prev->Body;
+ if (RedeclForcesDefC99(Prev))
+ return false;
+ }
+ return FoundBody;
}
/// \brief For an inline function definition in C or C++, determine whether the
@@ -1826,7 +2034,10 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
assert(isInlined() && "Function must be inline");
ASTContext &Context = getASTContext();
- if (Context.getLangOptions().GNUInline || hasAttr<GNUInlineAttr>()) {
+ if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
+ // Note: If you change the logic here, please change
+ // doesDeclarationForceExternallyVisibleDefinition as well.
+ //
// If it's not the case that both 'inline' and 'extern' are
// specified on the definition, then this inline definition is
// externally visible.
@@ -1845,7 +2056,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
return false;
}
-
+
// C99 6.7.4p6:
// [...] If all of the file scope declarations for a function in a
// translation unit include the inline function specifier without extern,
@@ -1853,17 +2064,8 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end();
Redecl != RedeclEnd;
++Redecl) {
- // Only consider file-scope declarations in this test.
- if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
- continue;
-
- // Only consider explicit declarations; the presence of a builtin for a
- // libcall shouldn't affect whether a definition is externally visible.
- if (Redecl->isImplicit())
- continue;
-
- if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
- return true; // Not an inline definition
+ if (RedeclForcesDefC99(*Redecl))
+ return true;
}
// C99 6.7.4p6:
@@ -1966,7 +2168,20 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
return true;
return PatternDecl->isInlined();
-}
+}
+
+bool FunctionDecl::isTemplateInstantiation() const {
+ switch (getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ return false;
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+ }
+ llvm_unreachable("All TSK values handled.");
+}
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
// Handle class scope explicit specialization special case.
@@ -2040,22 +2255,7 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
TemplateArgsAsWritten,
PointOfInstantiation);
TemplateOrSpecialization = Info;
-
- // Insert this function template specialization into the set of known
- // function template specializations.
- if (InsertPos)
- Template->addSpecialization(Info, InsertPos);
- else {
- // 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);
- (void)Existing;
- assert((!Existing || Existing->Function->isCanonicalDecl()) &&
- "Set is supposed to only contain canonical decls");
- }
+ Template->addSpecialization(Info, InsertPos);
}
void
@@ -2169,6 +2369,92 @@ SourceRange FunctionDecl::getSourceRange() const {
return SourceRange(getOuterLocStart(), EndRangeLoc);
}
+unsigned FunctionDecl::getMemoryFunctionKind() const {
+ IdentifierInfo *FnInfo = getIdentifier();
+
+ if (!FnInfo)
+ return 0;
+
+ // Builtin handling.
+ switch (getBuiltinID()) {
+ case Builtin::BI__builtin_memset:
+ case Builtin::BI__builtin___memset_chk:
+ case Builtin::BImemset:
+ return Builtin::BImemset;
+
+ case Builtin::BI__builtin_memcpy:
+ case Builtin::BI__builtin___memcpy_chk:
+ case Builtin::BImemcpy:
+ return Builtin::BImemcpy;
+
+ case Builtin::BI__builtin_memmove:
+ case Builtin::BI__builtin___memmove_chk:
+ case Builtin::BImemmove:
+ return Builtin::BImemmove;
+
+ case Builtin::BIstrlcpy:
+ return Builtin::BIstrlcpy;
+ case Builtin::BIstrlcat:
+ return Builtin::BIstrlcat;
+
+ case Builtin::BI__builtin_memcmp:
+ case Builtin::BImemcmp:
+ return Builtin::BImemcmp;
+
+ case Builtin::BI__builtin_strncpy:
+ case Builtin::BI__builtin___strncpy_chk:
+ case Builtin::BIstrncpy:
+ return Builtin::BIstrncpy;
+
+ case Builtin::BI__builtin_strncmp:
+ case Builtin::BIstrncmp:
+ return Builtin::BIstrncmp;
+
+ case Builtin::BI__builtin_strncasecmp:
+ case Builtin::BIstrncasecmp:
+ return Builtin::BIstrncasecmp;
+
+ case Builtin::BI__builtin_strncat:
+ case Builtin::BI__builtin___strncat_chk:
+ case Builtin::BIstrncat:
+ return Builtin::BIstrncat;
+
+ case Builtin::BI__builtin_strndup:
+ case Builtin::BIstrndup:
+ return Builtin::BIstrndup;
+
+ case Builtin::BI__builtin_strlen:
+ case Builtin::BIstrlen:
+ return Builtin::BIstrlen;
+
+ default:
+ if (isExternC()) {
+ if (FnInfo->isStr("memset"))
+ return Builtin::BImemset;
+ else if (FnInfo->isStr("memcpy"))
+ return Builtin::BImemcpy;
+ else if (FnInfo->isStr("memmove"))
+ return Builtin::BImemmove;
+ else if (FnInfo->isStr("memcmp"))
+ return Builtin::BImemcmp;
+ else if (FnInfo->isStr("strncpy"))
+ return Builtin::BIstrncpy;
+ else if (FnInfo->isStr("strncmp"))
+ return Builtin::BIstrncmp;
+ else if (FnInfo->isStr("strncasecmp"))
+ return Builtin::BIstrncasecmp;
+ else if (FnInfo->isStr("strncat"))
+ return Builtin::BIstrncat;
+ else if (FnInfo->isStr("strndup"))
+ return Builtin::BIstrndup;
+ else if (FnInfo->isStr("strlen"))
+ return Builtin::BIstrlen;
+ }
+ break;
+ }
+ return 0;
+}
+
//===----------------------------------------------------------------------===//
// FieldDecl Implementation
//===----------------------------------------------------------------------===//
@@ -2182,6 +2468,12 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
BW, Mutable, HasInit);
}
+FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FieldDecl));
+ return new (Mem) FieldDecl(Field, 0, SourceLocation(), SourceLocation(),
+ 0, QualType(), 0, 0, false, false);
+}
+
bool FieldDecl::isAnonymousStructOrUnion() const {
if (!isImplicit() || getDeclName())
return false;
@@ -2201,31 +2493,27 @@ unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
unsigned FieldDecl::getFieldIndex() const {
if (CachedFieldIndex) return CachedFieldIndex - 1;
- unsigned index = 0;
+ unsigned Index = 0;
const RecordDecl *RD = getParent();
const FieldDecl *LastFD = 0;
bool IsMsStruct = RD->hasAttr<MsStructAttr>();
-
- RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
- while (true) {
- assert(i != e && "failed to find field in parent!");
- if (*i == this)
- break;
+
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I, ++Index) {
+ (*I)->CachedFieldIndex = Index + 1;
if (IsMsStruct) {
// Zero-length bitfields following non-bitfield members are ignored.
- if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD)) {
- ++i;
+ if (getASTContext().ZeroBitfieldFollowsNonBitfield((*I), LastFD)) {
+ --Index;
continue;
}
- LastFD = (*i);
+ LastFD = (*I);
}
- ++i;
- ++index;
}
- CachedFieldIndex = index + 1;
- return index;
+ assert(CachedFieldIndex && "failed to find field in parent");
+ return CachedFieldIndex - 1;
}
SourceRange FieldDecl::getSourceRange() const {
@@ -2339,6 +2627,8 @@ void TagDecl::setTemplateParameterListsInfo(ASTContext &Context,
// EnumDecl Implementation
//===----------------------------------------------------------------------===//
+void EnumDecl::anchor() { }
+
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id,
@@ -2350,9 +2640,10 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
return Enum;
}
-EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0,
- false, false, false);
+EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl));
+ return new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), 0, 0,
+ false, false, false);
}
void EnumDecl::completeDefinition(QualType NewType,
@@ -2368,6 +2659,37 @@ void EnumDecl::completeDefinition(QualType NewType,
TagDecl::completeDefinition();
}
+TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const {
+ if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
+ return MSI->getTemplateSpecializationKind();
+
+ return TSK_Undeclared;
+}
+
+void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
+ SourceLocation PointOfInstantiation) {
+ MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
+ assert(MSI && "Not an instantiated member enumeration?");
+ MSI->setTemplateSpecializationKind(TSK);
+ if (TSK != TSK_ExplicitSpecialization &&
+ PointOfInstantiation.isValid() &&
+ MSI->getPointOfInstantiation().isInvalid())
+ MSI->setPointOfInstantiation(PointOfInstantiation);
+}
+
+EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const {
+ if (SpecializationInfo)
+ return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom());
+
+ return 0;
+}
+
+void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
+ TemplateSpecializationKind TSK) {
+ assert(!SpecializationInfo && "Member enum is already a specialization");
+ SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
+}
+
//===----------------------------------------------------------------------===//
// RecordDecl Implementation
//===----------------------------------------------------------------------===//
@@ -2392,9 +2714,10 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
return R;
}
-RecordDecl *RecordDecl::Create(const ASTContext &C, EmptyShell Empty) {
- return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(),
- SourceLocation(), 0, 0);
+RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl));
+ return new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(),
+ SourceLocation(), 0, 0);
}
bool RecordDecl::isInjectedClassName() const {
@@ -2502,10 +2825,14 @@ SourceRange BlockDecl::getSourceRange() const {
// Other Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
+void TranslationUnitDecl::anchor() { }
+
TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
return new (C) TranslationUnitDecl(C);
}
+void LabelDecl::anchor() { }
+
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II) {
return new (C) LabelDecl(DC, IdentL, II, 0, IdentL);
@@ -2518,17 +2845,14 @@ LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) LabelDecl(DC, IdentL, II, 0, GnuLabelL);
}
-
-NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id) {
- return new (C) NamespaceDecl(DC, StartLoc, IdLoc, Id);
+LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LabelDecl));
+ return new (Mem) LabelDecl(0, SourceLocation(), 0, 0, SourceLocation());
}
-NamespaceDecl *NamespaceDecl::getNextNamespace() {
- return dyn_cast_or_null<NamespaceDecl>(
- NextNamespace.get(getASTContext().getExternalSource()));
-}
+void ValueDecl::anchor() { }
+
+void ImplicitParamDecl::anchor() { }
ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation IdLoc,
@@ -2537,6 +2861,12 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ImplicitParamDecl(DC, IdLoc, Id, Type);
}
+ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ImplicitParamDecl));
+ return new (Mem) ImplicitParamDecl(0, SourceLocation(), 0, QualType());
+}
+
FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
const DeclarationNameInfo &NameInfo,
@@ -2553,10 +2883,22 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
return New;
}
+FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl));
+ return new (Mem) FunctionDecl(Function, 0, SourceLocation(),
+ DeclarationNameInfo(), QualType(), 0,
+ SC_None, SC_None, false, false);
+}
+
BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
return new (C) BlockDecl(DC, L);
}
+BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(BlockDecl));
+ return new (Mem) BlockDecl(0, SourceLocation());
+}
+
EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
SourceLocation L,
IdentifierInfo *Id, QualType T,
@@ -2564,6 +2906,15 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
return new (C) EnumConstantDecl(CD, L, Id, T, E, V);
}
+EnumConstantDecl *
+EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumConstantDecl));
+ return new (Mem) EnumConstantDecl(0, SourceLocation(), 0, QualType(), 0,
+ llvm::APSInt());
+}
+
+void IndirectFieldDecl::anchor() { }
+
IndirectFieldDecl *
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, NamedDecl **CH,
@@ -2571,6 +2922,13 @@ IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS);
}
+IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(IndirectFieldDecl));
+ return new (Mem) IndirectFieldDecl(0, SourceLocation(), DeclarationName(),
+ QualType(), 0, 0);
+}
+
SourceRange EnumConstantDecl::getSourceRange() const {
SourceLocation End = getLocation();
if (Init)
@@ -2578,12 +2936,21 @@ SourceRange EnumConstantDecl::getSourceRange() const {
return SourceRange(getLocation(), End);
}
+void TypeDecl::anchor() { }
+
TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo) {
return new (C) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo);
}
+void TypedefNameDecl::anchor() { }
+
+TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypedefDecl));
+ return new (Mem) TypedefDecl(0, SourceLocation(), SourceLocation(), 0, 0);
+}
+
TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -2591,6 +2958,11 @@ TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo);
}
+TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasDecl));
+ return new (Mem) TypeAliasDecl(0, SourceLocation(), SourceLocation(), 0, 0);
+}
+
SourceRange TypedefDecl::getSourceRange() const {
SourceLocation RangeEnd = getLocation();
if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
@@ -2607,9 +2979,96 @@ SourceRange TypeAliasDecl::getSourceRange() const {
return SourceRange(getLocStart(), RangeEnd);
}
+void FileScopeAsmDecl::anchor() { }
+
FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
StringLiteral *Str,
SourceLocation AsmLoc,
SourceLocation RParenLoc) {
return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc);
}
+
+FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FileScopeAsmDecl));
+ return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation());
+}
+
+//===----------------------------------------------------------------------===//
+// ImportDecl Implementation
+//===----------------------------------------------------------------------===//
+
+/// \brief Retrieve the number of module identifiers needed to name the given
+/// module.
+static unsigned getNumModuleIdentifiers(Module *Mod) {
+ unsigned Result = 1;
+ while (Mod->Parent) {
+ Mod = Mod->Parent;
+ ++Result;
+ }
+ return Result;
+}
+
+ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
+ Module *Imported,
+ ArrayRef<SourceLocation> IdentifierLocs)
+ : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true),
+ NextLocalImport()
+{
+ assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
+ SourceLocation *StoredLocs = reinterpret_cast<SourceLocation *>(this + 1);
+ memcpy(StoredLocs, IdentifierLocs.data(),
+ IdentifierLocs.size() * sizeof(SourceLocation));
+}
+
+ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
+ Module *Imported, SourceLocation EndLoc)
+ : Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false),
+ NextLocalImport()
+{
+ *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc;
+}
+
+ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc, Module *Imported,
+ ArrayRef<SourceLocation> IdentifierLocs) {
+ void *Mem = C.Allocate(sizeof(ImportDecl) +
+ IdentifierLocs.size() * sizeof(SourceLocation));
+ return new (Mem) ImportDecl(DC, StartLoc, Imported, IdentifierLocs);
+}
+
+ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
+ SourceLocation StartLoc,
+ Module *Imported,
+ SourceLocation EndLoc) {
+ void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation));
+ ImportDecl *Import = new (Mem) ImportDecl(DC, StartLoc, Imported, EndLoc);
+ Import->setImplicit();
+ return Import;
+}
+
+ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumLocations) {
+ void *Mem = AllocateDeserializedDecl(C, ID,
+ (sizeof(ImportDecl) +
+ NumLocations * sizeof(SourceLocation)));
+ return new (Mem) ImportDecl(EmptyShell());
+}
+
+ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
+ if (!ImportedAndComplete.getInt())
+ return ArrayRef<SourceLocation>();
+
+ const SourceLocation *StoredLocs
+ = reinterpret_cast<const SourceLocation *>(this + 1);
+ return ArrayRef<SourceLocation>(StoredLocs,
+ getNumModuleIdentifiers(getImportedModule()));
+}
+
+SourceRange ImportDecl::getSourceRange() const {
+ if (!ImportedAndComplete.getInt())
+ return SourceRange(getLocation(),
+ *reinterpret_cast<const SourceLocation *>(this + 1));
+
+ return SourceRange(getLocation(), getIdentifierLocs().back());
+}
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 321e40b43899..47a0d25093d5 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -39,7 +39,24 @@ using namespace clang;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
-static bool StatSwitch = false;
+void *Decl::AllocateDeserializedDecl(const ASTContext &Context,
+ unsigned ID,
+ unsigned Size) {
+ // Allocate an extra 8 bytes worth of storage, which ensures that the
+ // resulting pointer will still be 8-byte aligned.
+ void *Start = Context.Allocate(Size + 8);
+ void *Result = (char*)Start + 8;
+
+ unsigned *PrefixPtr = (unsigned *)Result - 2;
+
+ // Zero out the first 4 bytes; this is used to store the owning module ID.
+ PrefixPtr[0] = 0;
+
+ // Store the global declaration ID in the second 4 bytes.
+ PrefixPtr[1] = ID;
+
+ return Result;
+}
const char *Decl::getDeclKindName() const {
switch (DeclKind) {
@@ -52,7 +69,7 @@ const char *Decl::getDeclKindName() const {
void Decl::setInvalidDecl(bool Invalid) {
InvalidDecl = Invalid;
- if (Invalid) {
+ if (Invalid && !isa<ParmVarDecl>(this)) {
// Defensive maneuver for ill-formed code: we're likely not to make it to
// a point where we set the access specifier, so default it to "public"
// to avoid triggering asserts elsewhere in the front end.
@@ -69,9 +86,9 @@ const char *DeclContext::getDeclKindName() const {
}
}
-bool Decl::CollectingStats(bool Enable) {
- if (Enable) StatSwitch = true;
- return StatSwitch;
+bool Decl::StatisticsEnabled = false;
+void Decl::EnableStatistics() {
+ StatisticsEnabled = true;
}
void Decl::PrintStats() {
@@ -100,7 +117,6 @@ void Decl::PrintStats() {
void Decl::add(Kind k) {
switch (k) {
- default: llvm_unreachable("Declaration not in DeclNodes.inc!");
#define DECL(DERIVED, BASE) case DERIVED: ++n##DERIVED##s; break;
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
@@ -185,15 +201,24 @@ void Decl::setLexicalDeclContext(DeclContext *DC) {
return;
if (isInSemaDC()) {
- MultipleDC *MDC = new (getASTContext()) MultipleDC();
- MDC->SemanticDC = getDeclContext();
- MDC->LexicalDC = DC;
- DeclCtx = MDC;
+ setDeclContextsImpl(getDeclContext(), DC, getASTContext());
} else {
getMultipleDC()->LexicalDC = DC;
}
}
+void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC,
+ ASTContext &Ctx) {
+ if (SemaDC == LexicalDC) {
+ DeclCtx = SemaDC;
+ } else {
+ Decl::MultipleDC *MDC = new (Ctx) Decl::MultipleDC();
+ MDC->SemanticDC = SemaDC;
+ MDC->LexicalDC = LexicalDC;
+ DeclCtx = MDC;
+ }
+}
+
bool Decl::isInAnonymousNamespace() const {
const DeclContext *DC = getDeclContext();
do {
@@ -282,13 +307,20 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
// Match the platform name.
if (A->getPlatform()->getName() != TargetPlatform)
return AR_Available;
-
+
+ std::string HintMessage;
+ if (!A->getMessage().empty()) {
+ HintMessage = " - ";
+ HintMessage += A->getMessage();
+ }
+
// Make sure that this declaration has not been marked 'unavailable'.
if (A->getUnavailable()) {
if (Message) {
Message->clear();
llvm::raw_string_ostream Out(*Message);
- Out << "not available on " << PrettyPlatformName;
+ Out << "not available on " << PrettyPlatformName
+ << HintMessage;
}
return AR_Unavailable;
@@ -301,7 +333,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
Out << "introduced in " << PrettyPlatformName << ' '
- << A->getIntroduced();
+ << A->getIntroduced() << HintMessage;
}
return AR_NotYetIntroduced;
@@ -313,7 +345,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
Out << "obsoleted in " << PrettyPlatformName << ' '
- << A->getObsoleted();
+ << A->getObsoleted() << HintMessage;
}
return AR_Unavailable;
@@ -325,7 +357,7 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
Message->clear();
llvm::raw_string_ostream Out(*Message);
Out << "first deprecated in " << PrettyPlatformName << ' '
- << A->getDeprecated();
+ << A->getDeprecated() << HintMessage;
}
return AR_Deprecated;
@@ -391,7 +423,7 @@ bool Decl::canBeWeakImported(bool &IsDefinition) const {
}
} else if (isa<ObjCPropertyDecl>(this) || isa<ObjCMethodDecl>(this))
return false;
- else if (!(getASTContext().getLangOptions().ObjCNonFragileABI &&
+ else if (!(getASTContext().getLangOpts().ObjCNonFragileABI &&
isa<ObjCInterfaceDecl>(this)))
return false;
@@ -488,9 +520,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case LinkageSpec:
case FileScopeAsm:
case StaticAssert:
- case ObjCClass:
case ObjCPropertyImpl:
- case ObjCForwardProtocol:
case Block:
case TranslationUnit:
@@ -501,17 +531,18 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCImplementation:
case ObjCCategory:
case ObjCCategoryImpl:
+ case Import:
// Never looked up by name.
return 0;
}
- return 0;
+ llvm_unreachable("Invalid DeclKind!");
}
-void Decl::setAttrs(const AttrVec &attrs) {
+void Decl::setAttrsImpl(const AttrVec &attrs, ASTContext &Ctx) {
assert(!HasAttrs && "Decl already contains attrs.");
- AttrVec &AttrBlank = getASTContext().getDeclAttrs(this);
+ AttrVec &AttrBlank = Ctx.getDeclAttrs(this);
assert(AttrBlank.empty() && "HasAttrs was wrong?");
AttrBlank = attrs;
@@ -640,7 +671,11 @@ void Decl::CheckAccessDeclContext() const {
}
DeclContext *Decl::getNonClosureContext() {
- DeclContext *DC = getDeclContext();
+ return getDeclContext()->getNonClosureAncestor();
+}
+
+DeclContext *DeclContext::getNonClosureAncestor() {
+ DeclContext *DC = this;
// This is basically "while (DC->isClosure()) DC = DC->getParent();"
// except that it's significantly more efficient to cast to a known
@@ -704,10 +739,14 @@ bool DeclContext::isDependentContext() const {
if (isa<ClassTemplatePartialSpecializationDecl>(this))
return true;
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this)) {
if (Record->getDescribedClassTemplate())
return true;
-
+
+ if (Record->isDependentLambda())
+ return true;
+ }
+
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getDescribedFunctionTemplate())
return true;
@@ -767,9 +806,18 @@ DeclContext *DeclContext::getPrimaryContext() {
return this;
case Decl::ObjCInterface:
+ if (ObjCInterfaceDecl *Def = cast<ObjCInterfaceDecl>(this)->getDefinition())
+ return Def;
+
+ return this;
+
case Decl::ObjCProtocol:
+ if (ObjCProtocolDecl *Def = cast<ObjCProtocolDecl>(this)->getDefinition())
+ return Def;
+
+ return this;
+
case Decl::ObjCCategory:
- // FIXME: Can Objective-C interfaces be forward-declared?
return this;
case Decl::ObjCImplementation:
@@ -804,21 +852,27 @@ DeclContext *DeclContext::getPrimaryContext() {
}
}
-DeclContext *DeclContext::getNextContext() {
- switch (DeclKind) {
- case Decl::Namespace:
- // Return the next namespace
- return static_cast<NamespaceDecl*>(this)->getNextNamespace();
-
- default:
- return 0;
+void
+DeclContext::collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts){
+ Contexts.clear();
+
+ if (DeclKind != Decl::Namespace) {
+ Contexts.push_back(this);
+ return;
}
+
+ NamespaceDecl *Self = static_cast<NamespaceDecl *>(this);
+ for (NamespaceDecl *N = Self->getMostRecentDecl(); N;
+ N = N->getPreviousDecl())
+ Contexts.push_back(N);
+
+ std::reverse(Contexts.begin(), Contexts.end());
}
std::pair<Decl *, Decl *>
-DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls,
+DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls,
bool FieldsAlreadyLoaded) {
- // Build up a chain of declarations via the Decl::NextDeclInContext field.
+ // Build up a chain of declarations via the Decl::NextInContextAndBits field.
Decl *FirstNewDecl = 0;
Decl *PrevDecl = 0;
for (unsigned I = 0, N = Decls.size(); I != N; ++I) {
@@ -827,7 +881,7 @@ DeclContext::BuildDeclChain(const SmallVectorImpl<Decl*> &Decls,
Decl *D = Decls[I];
if (PrevDecl)
- PrevDecl->NextDeclInContext = D;
+ PrevDecl->NextInContextAndBits.setPointer(D);
else
FirstNewDecl = D;
@@ -873,7 +927,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
Decl *ExternalFirst, *ExternalLast;
llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls,
FieldsAlreadyLoaded);
- ExternalLast->NextDeclInContext = FirstDecl;
+ ExternalLast->NextInContextAndBits.setPointer(FirstDecl);
FirstDecl = ExternalFirst;
if (!LastDecl)
LastDecl = ExternalLast;
@@ -884,7 +938,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name) {
ASTContext &Context = DC->getParentASTContext();
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr))
+ if (!(Map = DC->LookupPtr.getPointer()))
Map = DC->CreateStoredDeclsMap(Context);
StoredDeclsList &List = (*Map)[Name];
@@ -901,7 +955,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
ASTContext &Context = DC->getParentASTContext();;
StoredDeclsMap *Map;
- if (!(Map = DC->LookupPtr))
+ if (!(Map = DC->LookupPtr.getPointer()))
Map = DC->CreateStoredDeclsMap(Context);
StoredDeclsList &List = (*Map)[Name];
@@ -948,7 +1002,7 @@ bool DeclContext::decls_empty() const {
void DeclContext::removeDecl(Decl *D) {
assert(D->getLexicalDeclContext() == this &&
"decl being removed from non-lexical context");
- assert((D->NextDeclInContext || D == LastDecl) &&
+ assert((D->NextInContextAndBits.getPointer() || D == LastDecl) &&
"decl is not in decls list");
// Remove D from the decl chain. This is O(n) but hopefully rare.
@@ -956,12 +1010,12 @@ void DeclContext::removeDecl(Decl *D) {
if (D == LastDecl)
FirstDecl = LastDecl = 0;
else
- FirstDecl = D->NextDeclInContext;
+ FirstDecl = D->NextInContextAndBits.getPointer();
} else {
- for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) {
+ for (Decl *I = FirstDecl; true; I = I->NextInContextAndBits.getPointer()) {
assert(I && "decl not found in linked list");
- if (I->NextDeclInContext == D) {
- I->NextDeclInContext = D->NextDeclInContext;
+ if (I->NextInContextAndBits.getPointer() == D) {
+ I->NextInContextAndBits.setPointer(D->NextInContextAndBits.getPointer());
if (D == LastDecl) LastDecl = I;
break;
}
@@ -969,7 +1023,7 @@ void DeclContext::removeDecl(Decl *D) {
}
// Mark that D is no longer in the decl chain.
- D->NextDeclInContext = 0;
+ D->NextInContextAndBits.setPointer(0);
// Remove D from the lookup table if necessary.
if (isa<NamedDecl>(D)) {
@@ -978,12 +1032,13 @@ void DeclContext::removeDecl(Decl *D) {
// Remove only decls that have a name
if (!ND->getDeclName()) return;
- StoredDeclsMap *Map = getPrimaryContext()->LookupPtr;
+ StoredDeclsMap *Map = getPrimaryContext()->LookupPtr.getPointer();
if (!Map) return;
StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
assert(Pos != Map->end() && "no lookup entry for decl");
- Pos->second.remove(ND);
+ if (Pos->second.getAsVector() || Pos->second.getAsDecl() == ND)
+ Pos->second.remove(ND);
}
}
@@ -994,7 +1049,7 @@ void DeclContext::addHiddenDecl(Decl *D) {
"Decl already inserted into a DeclContext");
if (FirstDecl) {
- LastDecl->NextDeclInContext = D;
+ LastDecl->NextInContextAndBits.setPointer(D);
LastDecl = D;
} else {
FirstDecl = LastDecl = D;
@@ -1004,55 +1059,118 @@ void DeclContext::addHiddenDecl(Decl *D) {
// update it's class-specific state.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(this))
Record->addedMember(D);
+
+ // If this is a newly-created (not de-serialized) import declaration, wire
+ // it in to the list of local import declarations.
+ if (!D->isFromASTFile()) {
+ if (ImportDecl *Import = dyn_cast<ImportDecl>(D))
+ D->getASTContext().addedLocalImportDecl(Import);
+ }
}
void DeclContext::addDecl(Decl *D) {
addHiddenDecl(D);
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
- ND->getDeclContext()->makeDeclVisibleInContext(ND);
+ ND->getDeclContext()->getPrimaryContext()->
+ makeDeclVisibleInContextWithFlags(ND, false, true);
+}
+
+void DeclContext::addDeclInternal(Decl *D) {
+ addHiddenDecl(D);
+
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ ND->getDeclContext()->getPrimaryContext()->
+ makeDeclVisibleInContextWithFlags(ND, true, true);
+}
+
+/// shouldBeHidden - Determine whether a declaration which was declared
+/// within its semantic context should be invisible to qualified name lookup.
+static bool shouldBeHidden(NamedDecl *D) {
+ // Skip unnamed declarations.
+ if (!D->getDeclName())
+ return true;
+
+ // Skip entities that can't be found by name lookup into a particular
+ // context.
+ if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
+ D->isTemplateParameter())
+ return true;
+
+ // Skip template specializations.
+ // FIXME: This feels like a hack. Should DeclarationName support
+ // template-ids, or is there a better way to keep specializations
+ // from being visible?
+ if (isa<ClassTemplateSpecializationDecl>(D))
+ return true;
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FD->isFunctionTemplateSpecialization())
+ return true;
+
+ return false;
}
/// buildLookup - Build the lookup data structure with all of the
-/// declarations in DCtx (and any other contexts linked to it or
-/// transparent contexts nested within it).
-void DeclContext::buildLookup(DeclContext *DCtx) {
- for (; DCtx; DCtx = DCtx->getNextContext()) {
- for (decl_iterator D = DCtx->decls_begin(),
- DEnd = DCtx->decls_end();
- D != DEnd; ++D) {
- // Insert this declaration into the lookup structure, but only
- // if it's semantically in its decl context. During non-lazy
- // lookup building, this is implicitly enforced by addDecl.
- if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
- if (D->getDeclContext() == DCtx)
- makeDeclVisibleInContextImpl(ND);
-
- // Insert any forward-declared Objective-C interface into the lookup
- // data structure.
- if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D))
- makeDeclVisibleInContextImpl(Class->getForwardInterfaceDecl());
-
- // 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() || InnerCtx->isInlineNamespace())
- buildLookup(InnerCtx->getPrimaryContext());
- }
+/// declarations in this DeclContext (and any other contexts linked
+/// to it or transparent contexts nested within it) and return it.
+StoredDeclsMap *DeclContext::buildLookup() {
+ assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
+
+ if (!LookupPtr.getInt())
+ return LookupPtr.getPointer();
+
+ llvm::SmallVector<DeclContext *, 2> Contexts;
+ collectAllContexts(Contexts);
+ for (unsigned I = 0, N = Contexts.size(); I != N; ++I)
+ buildLookupImpl(Contexts[I]);
+
+ // We no longer have any lazy decls.
+ LookupPtr.setInt(false);
+ return LookupPtr.getPointer();
+}
+
+/// buildLookupImpl - Build part of the lookup data structure for the
+/// declarations contained within DCtx, which will either be this
+/// DeclContext, a DeclContext linked to it, or a transparent context
+/// nested within it.
+void DeclContext::buildLookupImpl(DeclContext *DCtx) {
+ for (decl_iterator I = DCtx->decls_begin(), E = DCtx->decls_end();
+ I != E; ++I) {
+ Decl *D = *I;
+
+ // Insert this declaration into the lookup structure, but only if
+ // it's semantically within its decl context. Any other decls which
+ // should be found in this context are added eagerly.
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ if (ND->getDeclContext() == DCtx && !shouldBeHidden(ND))
+ makeDeclVisibleInContextImpl(ND, false);
+
+ // If this declaration is itself a transparent declaration context
+ // or inline namespace, add the members of this declaration of that
+ // context (recursively).
+ if (DeclContext *InnerCtx = dyn_cast<DeclContext>(D))
+ if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace())
+ buildLookupImpl(InnerCtx);
}
}
DeclContext::lookup_result
DeclContext::lookup(DeclarationName Name) {
+ assert(DeclKind != Decl::LinkageSpec &&
+ "Should not perform lookups into linkage specs!");
+
DeclContext *PrimaryContext = getPrimaryContext();
if (PrimaryContext != this)
return PrimaryContext->lookup(Name);
if (hasExternalVisibleStorage()) {
- // Check to see if we've already cached the lookup results.
- if (LookupPtr) {
- StoredDeclsMap::iterator I = LookupPtr->find(Name);
- if (I != LookupPtr->end())
+ // If a PCH has a result for this name, and we have a local declaration, we
+ // will have imported the PCH result when adding the local declaration.
+ // FIXME: For modules, we could have had more declarations added by module
+ // imoprts since we saw the declaration of the local name.
+ if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ StoredDeclsMap::iterator I = Map->find(Name);
+ if (I != Map->end())
return I->second.getLookupResult();
}
@@ -1060,20 +1178,18 @@ DeclContext::lookup(DeclarationName Name) {
return Source->FindExternalVisibleDeclsByName(this, Name);
}
- /// If there is no lookup data structure, build one now by walking
- /// all of the linked DeclContexts (in declaration order!) and
- /// inserting their values.
- if (!LookupPtr) {
- buildLookup(this);
+ StoredDeclsMap *Map = LookupPtr.getPointer();
+ if (LookupPtr.getInt())
+ Map = buildLookup();
- if (!LookupPtr)
- return lookup_result(lookup_iterator(0), lookup_iterator(0));
- }
+ if (!Map)
+ return lookup_result(lookup_iterator(0), lookup_iterator(0));
- StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
- if (Pos == LookupPtr->end())
+ StoredDeclsMap::iterator I = Map->find(Name);
+ if (I == Map->end())
return lookup_result(lookup_iterator(0), lookup_iterator(0));
- return Pos->second.getLookupResult();
+
+ return I->second.getLookupResult();
}
DeclContext::lookup_const_result
@@ -1094,10 +1210,10 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
}
// If we have a lookup table, check there first. Maybe we'll get lucky.
- if (LookupPtr) {
- StoredDeclsMap::iterator Pos = LookupPtr->find(Name);
- if (Pos != LookupPtr->end()) {
- Results.insert(Results.end(),
+ if (StoredDeclsMap *Map = LookupPtr.getPointer()) {
+ StoredDeclsMap::iterator Pos = Map->find(Name);
+ if (Pos != Map->end()) {
+ Results.insert(Results.end(),
Pos->second.getLookupResult().first,
Pos->second.getLookupResult().second);
return;
@@ -1147,79 +1263,97 @@ bool DeclContext::InEnclosingNamespaceSetOf(const DeclContext *O) const {
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
- // from being visible?
- if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter())
+void DeclContext::makeDeclVisibleInContext(NamedDecl *D) {
+ DeclContext *PrimaryDC = this->getPrimaryContext();
+ DeclContext *DeclDC = D->getDeclContext()->getPrimaryContext();
+ // If the decl is being added outside of its semantic decl context, we
+ // need to ensure that we eagerly build the lookup information for it.
+ PrimaryDC->makeDeclVisibleInContextWithFlags(D, false, PrimaryDC == DeclDC);
+}
+
+void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
+ bool Recoverable) {
+ assert(this == getPrimaryContext() && "expected a primary DC");
+
+ // Skip declarations within functions.
+ // FIXME: We shouldn't need to build lookup tables for function declarations
+ // ever, and we can't do so correctly because we can't model the nesting of
+ // scopes which occurs within functions. We use "qualified" lookup into
+ // function declarations when handling friend declarations inside nested
+ // classes, and consequently accept the following invalid code:
+ //
+ // void f() { void g(); { int g; struct S { friend void g(); }; } }
+ if (isFunctionOrMethod() && !isa<FunctionDecl>(D))
return;
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- if (FD->isFunctionTemplateSpecialization())
- return;
- DeclContext *PrimaryContext = getPrimaryContext();
- if (PrimaryContext != this) {
- PrimaryContext->makeDeclVisibleInContext(D, Recoverable);
+ // Skip declarations which should be invisible to name lookup.
+ if (shouldBeHidden(D))
return;
- }
- // If we already have a lookup data structure, perform the insertion
- // into it. If we haven't deserialized externally stored decls, deserialize
- // them so we can add the decl. Otherwise, be lazy and don't build that
- // structure until someone asks for it.
- if (LookupPtr || !Recoverable || hasExternalVisibleStorage())
- makeDeclVisibleInContextImpl(D);
+ // If we already have a lookup data structure, perform the insertion into
+ // it. If we might have externally-stored decls with this name, look them
+ // up and perform the insertion. If this decl was declared outside its
+ // semantic context, buildLookup won't add it, so add it now.
+ //
+ // FIXME: As a performance hack, don't add such decls into the translation
+ // unit unless we're in C++, since qualified lookup into the TU is never
+ // performed.
+ if (LookupPtr.getPointer() || hasExternalVisibleStorage() ||
+ ((!Recoverable || D->getDeclContext() != D->getLexicalDeclContext()) &&
+ (getParentASTContext().getLangOpts().CPlusPlus ||
+ !isTranslationUnit()))) {
+ // If we have lazily omitted any decls, they might have the same name as
+ // the decl which we are adding, so build a full lookup table before adding
+ // this decl.
+ buildLookup();
+ makeDeclVisibleInContextImpl(D, Internal);
+ } else {
+ LookupPtr.setInt(true);
+ }
// 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);
+ getParent()->getPrimaryContext()->
+ makeDeclVisibleInContextWithFlags(D, Internal, Recoverable);
Decl *DCAsDecl = cast<Decl>(this);
- // Notify that a decl was made visible unless it's a Tag being defined.
+ // Notify that a decl was made visible unless we are a Tag being defined.
if (!(isa<TagDecl>(DCAsDecl) && cast<TagDecl>(DCAsDecl)->isBeingDefined()))
if (ASTMutationListener *L = DCAsDecl->getASTMutationListener())
L->AddedVisibleDecl(this, D);
}
-void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
- // Skip unnamed declarations.
- if (!D->getDeclName())
- return;
-
- // Skip entities that can't be found by name lookup into a particular
- // context.
- if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
- D->isTemplateParameter())
- return;
-
- ASTContext *C = 0;
- if (!LookupPtr) {
- C = &getParentASTContext();
- CreateStoredDeclsMap(*C);
+void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) {
+ // Find or create the stored declaration map.
+ StoredDeclsMap *Map = LookupPtr.getPointer();
+ if (!Map) {
+ ASTContext *C = &getParentASTContext();
+ Map = 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());
+ if (!Internal)
+ if (ExternalASTSource *Source = getParentASTContext().getExternalSource())
+ if (hasExternalVisibleStorage() &&
+ Map->find(D->getDeclName()) == Map->end())
+ Source->FindExternalVisibleDeclsByName(this, D->getDeclName());
// Insert this declaration into the map.
- StoredDeclsList &DeclNameEntries = (*LookupPtr)[D->getDeclName()];
+ StoredDeclsList &DeclNameEntries = (*Map)[D->getDeclName()];
if (DeclNameEntries.isNull()) {
DeclNameEntries.setOnlyValue(D);
return;
}
- // 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 (DeclNameEntries.HandleRedeclaration(D))
+ if (DeclNameEntries.HandleRedeclaration(D)) {
+ // This declaration has replaced an existing one for which
+ // declarationReplaces returns true.
return;
+ }
// Put this declaration into the appropriate slot.
DeclNameEntries.AddSubsequentDecl(D);
@@ -1229,6 +1363,8 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
/// this context.
DeclContext::udir_iterator_range
DeclContext::getUsingDirectives() const {
+ // FIXME: Use something more efficient than normal lookup for using
+ // directives. In C++, using directives are looked up more than anything else.
lookup_const_result Result = lookup(UsingDirectiveDecl::getName());
return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first),
reinterpret_cast<udir_iterator>(Result.second));
@@ -1239,7 +1375,7 @@ DeclContext::getUsingDirectives() const {
//===----------------------------------------------------------------------===//
StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
- assert(!LookupPtr && "context already has a decls map");
+ assert(!LookupPtr.getPointer() && "context already has a decls map");
assert(getPrimaryContext() == this &&
"creating decls map on non-primary context");
@@ -1251,7 +1387,7 @@ StoredDeclsMap *DeclContext::CreateStoredDeclsMap(ASTContext &C) const {
M = new StoredDeclsMap();
M->Previous = C.LastSDM;
C.LastSDM = llvm::PointerIntPair<StoredDeclsMap*,1>(M, Dependent);
- LookupPtr = M;
+ LookupPtr.setPointer(M);
return M;
}
@@ -1283,11 +1419,11 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,
assert(Parent->isDependentContext()
&& "cannot iterate dependent diagnostics of non-dependent context");
Parent = Parent->getPrimaryContext();
- if (!Parent->LookupPtr)
+ if (!Parent->LookupPtr.getPointer())
Parent->CreateStoredDeclsMap(C);
DependentStoredDeclsMap *Map
- = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr);
+ = static_cast<DependentStoredDeclsMap*>(Parent->LookupPtr.getPointer());
// Allocate the copy of the PartialDiagnostic via the ASTContext's
// BumpPtrAllocator, rather than the ASTContext itself.
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index f3da67c4ff81..114322b1a8a6 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/STLExtras.h"
@@ -27,6 +28,13 @@ using namespace clang;
// Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
+void AccessSpecDecl::anchor() { }
+
+AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(AccessSpecDecl));
+ return new (Mem) AccessSpecDecl(EmptyShell());
+}
+
CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
: UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false),
@@ -34,17 +42,24 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
- HasMutableFields(false), HasTrivialDefaultConstructor(true),
- HasConstexprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
+ HasMutableFields(false), HasOnlyCMembers(true),
+ HasTrivialDefaultConstructor(true),
+ HasConstexprNonCopyMoveConstructor(false),
+ DefaultedDefaultConstructorIsConstexpr(true),
+ DefaultedCopyConstructorIsConstexpr(true),
+ DefaultedMoveConstructorIsConstexpr(true),
+ HasConstexprDefaultConstructor(false), HasConstexprCopyConstructor(false),
+ HasConstexprMoveConstructor(false), HasTrivialCopyConstructor(true),
HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
+ HasIrrelevantDestructor(true),
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false),
DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
DeclaredCopyAssignment(false), DeclaredMoveAssignment(false),
DeclaredDestructor(false), FailedImplicitMoveConstructor(false),
- FailedImplicitMoveAssignment(false), NumBases(0), NumVBases(0), Bases(),
- VBases(), Definition(D), FirstFriend(0) {
+ FailedImplicitMoveAssignment(false), IsLambda(false), NumBases(0),
+ NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend(0) {
}
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -68,24 +83,41 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
return R;
}
-CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, EmptyShell Empty) {
- return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(),
- SourceLocation(), 0, 0);
+CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
+ SourceLocation Loc, bool Dependent) {
+ CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc,
+ 0, 0);
+ R->IsBeingDefined = true;
+ R->DefinitionData = new (C) struct LambdaDefinitionData(R, Dependent);
+ C.getTypeDeclType(R, /*PrevDecl=*/0);
+ return R;
+}
+
+CXXRecordDecl *
+CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl));
+ return new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(),
+ SourceLocation(), 0, 0);
}
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
ASTContext &C = getASTContext();
-
- // C++ [dcl.init.aggr]p1:
- // An aggregate is an array or a class (clause 9) with [...]
- // no base classes [...].
- data().Aggregate = false;
if (!data().Bases.isOffset() && data().NumBases > 0)
C.Deallocate(data().getBases());
+ if (NumBases) {
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is [...] a class with [...] no base classes [...].
+ data().Aggregate = false;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class...
+ data().PlainOldData = false;
+ }
+
// The set of seen virtual base types.
llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;
@@ -105,14 +137,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
CXXRecordDecl *BaseClassDecl
= cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
- // C++ [dcl.init.aggr]p1:
- // An aggregate is [...] a class with [...] no base classes [...].
- data().Aggregate = false;
-
- // C++ [class]p4:
- // A POD-struct is an aggregate class...
- data().PlainOldData = false;
-
// A class with a non-empty base class is not empty.
// FIXME: Standard ref?
if (!BaseClassDecl->isEmpty()) {
@@ -190,6 +214,13 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// A standard-layout class is a class that: [...]
// -- has [...] no virtual base classes
data().IsStandardLayout = false;
+
+ // C++11 [dcl.constexpr]p4:
+ // In the definition of a constexpr constructor [...]
+ // -- the class shall not have any virtual base classes
+ data().DefaultedDefaultConstructorIsConstexpr = false;
+ data().DefaultedCopyConstructorIsConstexpr = false;
+ data().DefaultedMoveConstructorIsConstexpr = false;
} else {
// C++ [class.ctor]p5:
// A default constructor is trivial [...] if:
@@ -221,6 +252,32 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
data().HasTrivialCopyAssignment = false;
if (!BaseClassDecl->hasTrivialMoveAssignment())
data().HasTrivialMoveAssignment = false;
+
+ // C++11 [class.ctor]p6:
+ // If that user-written default constructor would satisfy the
+ // requirements of a constexpr constructor, the implicitly-defined
+ // default constructor is constexpr.
+ if (!BaseClassDecl->hasConstexprDefaultConstructor())
+ data().DefaultedDefaultConstructorIsConstexpr = false;
+
+ // C++11 [class.copy]p13:
+ // If the implicitly-defined constructor would satisfy the requirements
+ // of a constexpr constructor, the implicitly-defined constructor is
+ // constexpr.
+ // C++11 [dcl.constexpr]p4:
+ // -- every constructor involved in initializing [...] base class
+ // sub-objects shall be a constexpr constructor
+ if (!BaseClassDecl->hasConstexprCopyConstructor())
+ data().DefaultedCopyConstructorIsConstexpr = false;
+ if (BaseClassDecl->hasDeclaredMoveConstructor() ||
+ BaseClassDecl->needsImplicitMoveConstructor())
+ // FIXME: If the implicit move constructor generated for the base class
+ // would be ill-formed, the implicit move constructor generated for the
+ // derived class calls the base class' copy constructor.
+ data().DefaultedMoveConstructorIsConstexpr &=
+ BaseClassDecl->hasConstexprMoveConstructor();
+ else if (!BaseClassDecl->hasConstexprCopyConstructor())
+ data().DefaultedMoveConstructorIsConstexpr = false;
}
// C++ [class.ctor]p3:
@@ -228,7 +285,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
// have trivial destructors.
if (!BaseClassDecl->hasTrivialDestructor())
data().HasTrivialDestructor = false;
-
+
+ if (!BaseClassDecl->hasIrrelevantDestructor())
+ data().HasIrrelevantDestructor = false;
+
// A class has an Objective-C object member if... or any of its bases
// has an Objective-C object member.
if (BaseClassDecl->hasObjectMember())
@@ -410,6 +470,12 @@ void CXXRecordDecl::markedVirtualFunctionPure() {
}
void CXXRecordDecl::addedMember(Decl *D) {
+ if (!D->isImplicit() &&
+ !isa<FieldDecl>(D) &&
+ !isa<IndirectFieldDecl>(D) &&
+ (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class))
+ data().HasOnlyCMembers = false;
+
// Ignore friends and invalid declarations.
if (D->getFriendObjectKind() || D->isInvalidDecl())
return;
@@ -453,8 +519,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
// -- class X has no virtual functions [...]
data().HasTrivialCopyAssignment = false;
data().HasTrivialMoveAssignment = false;
- // FIXME: Destructor?
-
+
// C++0x [class]p7:
// A standard-layout class is a class that: [...]
// -- has no virtual functions
@@ -472,13 +537,21 @@ void CXXRecordDecl::addedMember(Decl *D) {
// If this is a special member function, note that it was added and then
// return early.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
- if (Constructor->isDefaultConstructor())
+ if (Constructor->isDefaultConstructor()) {
data().DeclaredDefaultConstructor = true;
- else if (Constructor->isCopyConstructor())
+ if (Constructor->isConstexpr()) {
+ data().HasConstexprDefaultConstructor = true;
+ data().HasConstexprNonCopyMoveConstructor = true;
+ }
+ } else if (Constructor->isCopyConstructor()) {
data().DeclaredCopyConstructor = true;
- else if (Constructor->isMoveConstructor())
+ if (Constructor->isConstexpr())
+ data().HasConstexprCopyConstructor = true;
+ } else if (Constructor->isMoveConstructor()) {
data().DeclaredMoveConstructor = true;
- else
+ if (Constructor->isConstexpr())
+ data().HasConstexprMoveConstructor = true;
+ } else
goto NotASpecialMember;
return;
} else if (isa<CXXDestructorDecl>(D)) {
@@ -508,14 +581,18 @@ NotASpecialMember:;
// to all functions.
bool UserProvided = Constructor->isUserProvided();
- // C++0x [class.ctor]p5:
- // A default constructor is trivial if it is not user-provided [...]
if (Constructor->isDefaultConstructor()) {
data().DeclaredDefaultConstructor = true;
if (UserProvided) {
+ // C++0x [class.ctor]p5:
+ // A default constructor is trivial if it is not user-provided [...]
data().HasTrivialDefaultConstructor = false;
data().UserProvidedDefaultConstructor = true;
}
+ if (Constructor->isConstexpr()) {
+ data().HasConstexprDefaultConstructor = true;
+ data().HasConstexprNonCopyMoveConstructor = true;
+ }
}
// Note when we have a user-declared copy or move constructor, which will
@@ -530,6 +607,9 @@ NotASpecialMember:;
// user-provided [...]
if (UserProvided)
data().HasTrivialCopyConstructor = false;
+
+ if (Constructor->isConstexpr())
+ data().HasConstexprCopyConstructor = true;
} else if (Constructor->isMoveConstructor()) {
data().UserDeclaredMoveConstructor = true;
data().DeclaredMoveConstructor = true;
@@ -539,6 +619,9 @@ NotASpecialMember:;
// user-provided [...]
if (UserProvided)
data().HasTrivialMoveConstructor = false;
+
+ if (Constructor->isConstexpr())
+ data().HasConstexprMoveConstructor = true;
}
}
if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) {
@@ -553,7 +636,7 @@ NotASpecialMember:;
// C++0x [dcl.init.aggr]p1:
// An aggregate is an array or a class with no user-provided
// constructors [...].
- if (!getASTContext().getLangOptions().CPlusPlus0x || UserProvided)
+ if (!getASTContext().getLangOpts().CPlusPlus0x || UserProvided)
data().Aggregate = false;
// C++ [class]p4:
@@ -569,17 +652,29 @@ NotASpecialMember:;
if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) {
data().DeclaredDestructor = true;
data().UserDeclaredDestructor = true;
-
+ data().HasIrrelevantDestructor = false;
+
// C++ [class]p4:
// A POD-struct is an aggregate class that has [...] no user-defined
// destructor.
// This bit is the C++03 POD bit, not the 0x one.
data().PlainOldData = false;
- // C++0x [class.dtor]p5:
- // A destructor is trivial if it is not user-provided and [...]
- if (DD->isUserProvided())
+ // C++11 [class.dtor]p5:
+ // A destructor is trivial if it is not user-provided and if
+ // -- the destructor is not virtual.
+ if (DD->isUserProvided() || DD->isVirtual()) {
data().HasTrivialDestructor = false;
+ // C++11 [dcl.constexpr]p1:
+ // The constexpr specifier shall be applied only to [...] the
+ // declaration of a static data member of a literal type.
+ // C++11 [basic.types]p10:
+ // A type is a literal type if it is [...] a class type that [...] has
+ // a trivial destructor.
+ data().DefaultedDefaultConstructorIsConstexpr = false;
+ data().DefaultedCopyConstructorIsConstexpr = false;
+ data().DefaultedMoveConstructorIsConstexpr = false;
+ }
return;
}
@@ -634,14 +729,14 @@ NotASpecialMember:;
// hasn't been set yet. That's really just a misdesign in Sema.
if (FunTmpl) {
- if (FunTmpl->getPreviousDeclaration())
- data().Conversions.replace(FunTmpl->getPreviousDeclaration(),
+ if (FunTmpl->getPreviousDecl())
+ data().Conversions.replace(FunTmpl->getPreviousDecl(),
FunTmpl);
else
data().Conversions.addDecl(FunTmpl);
} else {
- if (Conversion->getPreviousDeclaration())
- data().Conversions.replace(Conversion->getPreviousDeclaration(),
+ if (Conversion->getPreviousDecl())
+ data().Conversions.replace(Conversion->getPreviousDecl(),
Conversion);
else
data().Conversions.addDecl(Conversion);
@@ -703,7 +798,7 @@ NotASpecialMember:;
ASTContext &Context = getASTContext();
QualType T = Context.getBaseElementType(Field->getType());
if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
- if (!Context.getLangOptions().ObjCAutoRefCount ||
+ if (!Context.getLangOpts().ObjCAutoRefCount ||
T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone)
setHasObjectMember(true);
} else if (!T.isPODType(Context))
@@ -718,12 +813,8 @@ NotASpecialMember:;
data().IsStandardLayout = false;
}
- // Record if this field is the first non-literal field or base.
- // As a slight variation on the standard, we regard mutable members as being
- // non-literal, since mutating a constexpr variable would break C++11
- // constant expression semantics.
- if ((!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) ||
- Field->isMutable())
+ // Record if this field is the first non-literal or volatile field or base.
+ if (!T->isLiteralType() || T.isVolatileQualified())
data().HasNonLiteralTypeFieldsOrBases = true;
if (Field->hasInClassInitializer()) {
@@ -746,7 +837,7 @@ NotASpecialMember:;
CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
if (FieldRec->getDefinition()) {
// C++0x [class.ctor]p5:
- // A defulat constructor is trivial [...] if:
+ // A default constructor is trivial [...] if:
// -- for all the non-static data members of its class that are of
// class type (or array thereof), each such class has a trivial
// default constructor.
@@ -779,6 +870,8 @@ NotASpecialMember:;
if (!FieldRec->hasTrivialDestructor())
data().HasTrivialDestructor = false;
+ if (!FieldRec->hasIrrelevantDestructor())
+ data().HasIrrelevantDestructor = false;
if (FieldRec->hasObjectMember())
setHasObjectMember(true);
@@ -818,7 +911,41 @@ NotASpecialMember:;
// Keep track of the presence of mutable fields.
if (FieldRec->hasMutableFields())
data().HasMutableFields = true;
+
+ // C++11 [class.copy]p13:
+ // If the implicitly-defined constructor would satisfy the
+ // requirements of a constexpr constructor, the implicitly-defined
+ // constructor is constexpr.
+ // C++11 [dcl.constexpr]p4:
+ // -- every constructor involved in initializing non-static data
+ // members [...] shall be a constexpr constructor
+ if (!Field->hasInClassInitializer() &&
+ !FieldRec->hasConstexprDefaultConstructor())
+ // The standard requires any in-class initializer to be a constant
+ // expression. We consider this to be a defect.
+ data().DefaultedDefaultConstructorIsConstexpr = false;
+
+ if (!FieldRec->hasConstexprCopyConstructor())
+ data().DefaultedCopyConstructorIsConstexpr = false;
+
+ if (FieldRec->hasDeclaredMoveConstructor() ||
+ FieldRec->needsImplicitMoveConstructor())
+ // FIXME: If the implicit move constructor generated for the member's
+ // class would be ill-formed, the implicit move constructor generated
+ // for this class calls the member's copy constructor.
+ data().DefaultedMoveConstructorIsConstexpr &=
+ FieldRec->hasConstexprMoveConstructor();
+ else if (!FieldRec->hasConstexprCopyConstructor())
+ data().DefaultedMoveConstructorIsConstexpr = false;
}
+ } else {
+ // Base element type of field is a non-class type.
+ if (!T->isLiteralType()) {
+ data().DefaultedDefaultConstructorIsConstexpr = false;
+ data().DefaultedCopyConstructorIsConstexpr = false;
+ data().DefaultedMoveConstructorIsConstexpr = false;
+ } else if (!Field->hasInClassInitializer())
+ data().DefaultedDefaultConstructorIsConstexpr = false;
}
// C++0x [class]p7:
@@ -849,6 +976,35 @@ NotASpecialMember:;
data().Conversions.addDecl(Shadow, Shadow->getAccess());
}
+bool CXXRecordDecl::isCLike() const {
+ if (getTagKind() == TTK_Class || !TemplateOrInstantiation.isNull())
+ return false;
+ if (!hasDefinition())
+ return true;
+
+ return isPOD() && data().HasOnlyCMembers;
+}
+
+void CXXRecordDecl::getCaptureFields(
+ llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
+ FieldDecl *&ThisCapture) const {
+ Captures.clear();
+ ThisCapture = 0;
+
+ LambdaDefinitionData &Lambda = getLambdaData();
+ RecordDecl::field_iterator Field = field_begin();
+ for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
+ C != CEnd; ++C, ++Field) {
+ if (C->capturesThis()) {
+ ThisCapture = *Field;
+ continue;
+ }
+
+ Captures[C->getCapturedVar()] = *Field;
+ }
+}
+
+
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
QualType T;
if (isa<UsingShadowDecl>(Conv))
@@ -1087,7 +1243,7 @@ void CXXRecordDecl::completeDefinition() {
void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
RecordDecl::completeDefinition();
- if (hasObjectMember() && getASTContext().getLangOptions().ObjCAutoRefCount) {
+ if (hasObjectMember() && getASTContext().getLangOpts().ObjCAutoRefCount) {
// Objective-C Automatic Reference Counting:
// If a class has a non-static data member of Objective-C pointer
// type (or array thereof), it is a non-POD type and its
@@ -1099,6 +1255,7 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
Data.HasTrivialCopyConstructor = false;
Data.HasTrivialCopyAssignment = false;
Data.HasTrivialDestructor = false;
+ Data.HasIrrelevantDestructor = false;
}
// If the class may be abstract (but hasn't been marked as such), check for
@@ -1157,6 +1314,8 @@ bool CXXRecordDecl::mayBeAbstract() const {
return false;
}
+void CXXMethodDecl::anchor() { }
+
CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation StartLoc,
@@ -1169,6 +1328,14 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
EndLocation);
}
+CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXMethodDecl));
+ return new (Mem) CXXMethodDecl(CXXMethod, 0, SourceLocation(),
+ DeclarationNameInfo(), QualType(),
+ 0, false, SC_None, false, false,
+ SourceLocation());
+}
+
bool CXXMethodDecl::isUsualDeallocationFunction() const {
if (getOverloadedOperator() != OO_Delete &&
getOverloadedOperator() != OO_Array_Delete)
@@ -1254,19 +1421,23 @@ void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
assert(MD->isCanonicalDecl() && "Method is not canonical!");
assert(!MD->getParent()->isDependentContext() &&
"Can't add an overridden method to a class template!");
+ assert(MD->isVirtual() && "Method is not virtual!");
getASTContext().addOverriddenMethod(this, MD);
}
CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const {
+ if (isa<CXXConstructorDecl>(this)) return 0;
return getASTContext().overridden_methods_begin(this);
}
CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
+ if (isa<CXXConstructorDecl>(this)) return 0;
return getASTContext().overridden_methods_end(this);
}
unsigned CXXMethodDecl::size_overridden_methods() const {
+ if (isa<CXXConstructorDecl>(this)) return 0;
return getASTContext().overridden_methods_size(this);
}
@@ -1296,14 +1467,20 @@ bool CXXMethodDecl::hasInlineBody() const {
return CheckFn->hasBody(fn) && !fn->isOutOfLine();
}
+bool CXXMethodDecl::isLambdaStaticInvoker() const {
+ return getParent()->isLambda() &&
+ getIdentifier() && getIdentifier()->getName() == "__invoke";
+}
+
+
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
TypeSourceInfo *TInfo, bool IsVirtual,
SourceLocation L, Expr *Init,
SourceLocation R,
SourceLocation EllipsisLoc)
: Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false),
- SourceOrderOrNumArrayIndices(0)
+ LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
+ IsWritten(false), SourceOrderOrNumArrayIndices(0)
{
}
@@ -1313,7 +1490,7 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation L, Expr *Init,
SourceLocation R)
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsVirtual(false),
+ LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
IsWritten(false), SourceOrderOrNumArrayIndices(0)
{
}
@@ -1324,17 +1501,17 @@ CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
SourceLocation L, Expr *Init,
SourceLocation R)
: Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
- LParenLoc(L), RParenLoc(R), IsVirtual(false),
+ LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
IsWritten(false), SourceOrderOrNumArrayIndices(0)
{
}
CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
- SourceLocation D, SourceLocation L,
- CXXConstructorDecl *Target, Expr *Init,
+ TypeSourceInfo *TInfo,
+ SourceLocation L, Expr *Init,
SourceLocation R)
- : Initializee(Target), MemberOrEllipsisLocation(D), Init(Init),
- LParenLoc(L), RParenLoc(R), IsVirtual(false),
+ : Initializee(TInfo), MemberOrEllipsisLocation(), Init(Init),
+ LParenLoc(L), RParenLoc(R), IsDelegating(true), IsVirtual(false),
IsWritten(false), SourceOrderOrNumArrayIndices(0)
{
}
@@ -1383,13 +1560,16 @@ const Type *CXXCtorInitializer::getBaseClass() const {
}
SourceLocation CXXCtorInitializer::getSourceLocation() const {
- if (isAnyMemberInitializer() || isDelegatingInitializer())
+ if (isAnyMemberInitializer())
return getMemberLocation();
if (isInClassMemberInitializer())
return getAnyMember()->getLocation();
- return getBaseClassLoc().getLocalSourceRange().getBegin();
+ if (TypeSourceInfo *TSInfo = Initializee.get<TypeSourceInfo*>())
+ return TSInfo->getTypeLoc().getLocalSourceRange().getBegin();
+
+ return SourceLocation();
}
SourceRange CXXCtorInitializer::getSourceRange() const {
@@ -1403,10 +1583,13 @@ SourceRange CXXCtorInitializer::getSourceRange() const {
return SourceRange(getSourceLocation(), getRParenLoc());
}
+void CXXConstructorDecl::anchor() { }
+
CXXConstructorDecl *
-CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationNameInfo(),
- QualType(), 0, false, false, false, false);
+CXXConstructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConstructorDecl));
+ return new (Mem) CXXConstructorDecl(0, SourceLocation(),DeclarationNameInfo(),
+ QualType(), 0, false, false, false,false);
}
CXXConstructorDecl *
@@ -1424,6 +1607,15 @@ CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isConstexpr);
}
+CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
+ assert(isDelegatingConstructor() && "Not a delegating constructor!");
+ Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
+ if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(E))
+ return Construct->getConstructor();
+
+ return 0;
+}
+
bool CXXConstructorDecl::isDefaultConstructor() const {
// C++ [class.ctor]p5:
// A default constructor for a class X is a constructor of class
@@ -1524,8 +1716,8 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const {
// Hack: we store the inherited constructor in the overridden method table
- method_iterator It = begin_overridden_methods();
- if (It == end_overridden_methods())
+ method_iterator It = getASTContext().overridden_methods_begin(this);
+ if (It == getASTContext().overridden_methods_end(this))
return 0;
return cast<CXXConstructorDecl>(*It);
@@ -1534,13 +1726,17 @@ const CXXConstructorDecl *CXXConstructorDecl::getInheritedConstructor() const {
void
CXXConstructorDecl::setInheritedConstructor(const CXXConstructorDecl *BaseCtor){
// Hack: we store the inherited constructor in the overridden method table
- assert(size_overridden_methods() == 0 && "Base ctor already set.");
- addOverriddenMethod(BaseCtor);
+ assert(getASTContext().overridden_methods_size(this) == 0 &&
+ "Base ctor already set.");
+ getASTContext().addOverriddenMethod(this, BaseCtor);
}
+void CXXDestructorDecl::anchor() { }
+
CXXDestructorDecl *
-CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(),
+CXXDestructorDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXDestructorDecl));
+ return new (Mem) CXXDestructorDecl(0, SourceLocation(), DeclarationNameInfo(),
QualType(), 0, false, false);
}
@@ -1557,11 +1753,14 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
isImplicitlyDeclared);
}
+void CXXConversionDecl::anchor() { }
+
CXXConversionDecl *
-CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(),
- QualType(), 0, false, false, false,
- SourceLocation());
+CXXConversionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXConversionDecl));
+ return new (Mem) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(),
+ QualType(), 0, false, false, false,
+ SourceLocation());
}
CXXConversionDecl *
@@ -1579,6 +1778,13 @@ CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
EndLocation);
}
+bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
+ return isImplicit() && getParent()->isLambda() &&
+ getConversionType()->isBlockPointerType();
+}
+
+void LinkageSpecDecl::anchor() { }
+
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
DeclContext *DC,
SourceLocation ExternLoc,
@@ -1588,6 +1794,14 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, RBraceLoc);
}
+LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LinkageSpecDecl));
+ return new (Mem) LinkageSpecDecl(0, SourceLocation(), SourceLocation(),
+ lang_c, SourceLocation());
+}
+
+void UsingDirectiveDecl::anchor() { }
+
UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation NamespaceLoc,
@@ -1601,6 +1815,14 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
IdentLoc, Used, CommonAncestor);
}
+UsingDirectiveDecl *
+UsingDirectiveDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDirectiveDecl));
+ return new (Mem) UsingDirectiveDecl(0, SourceLocation(), SourceLocation(),
+ NestedNameSpecifierLoc(),
+ SourceLocation(), 0, 0);
+}
+
NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
if (NamespaceAliasDecl *NA =
dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
@@ -1608,6 +1830,36 @@ NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
return cast_or_null<NamespaceDecl>(NominatedNamespace);
}
+void NamespaceDecl::anchor() { }
+
+NamespaceDecl::NamespaceDecl(DeclContext *DC, bool Inline,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ NamespaceDecl *PrevDecl)
+ : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
+ LocStart(StartLoc), RBraceLoc(), AnonOrFirstNamespaceAndInline(0, Inline)
+{
+ setPreviousDeclaration(PrevDecl);
+
+ if (PrevDecl)
+ AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace());
+}
+
+NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
+ bool Inline, SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ NamespaceDecl *PrevDecl) {
+ return new (C) NamespaceDecl(DC, Inline, StartLoc, IdLoc, Id, PrevDecl);
+}
+
+NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceDecl));
+ return new (Mem) NamespaceDecl(0, false, SourceLocation(), SourceLocation(),
+ 0, 0);
+}
+
+void NamespaceAliasDecl::anchor() { }
+
NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
SourceLocation AliasLoc,
@@ -1621,6 +1873,22 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
QualifierLoc, IdentLoc, Namespace);
}
+NamespaceAliasDecl *
+NamespaceAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NamespaceAliasDecl));
+ return new (Mem) NamespaceAliasDecl(0, SourceLocation(), SourceLocation(), 0,
+ NestedNameSpecifierLoc(),
+ SourceLocation(), 0);
+}
+
+void UsingShadowDecl::anchor() { }
+
+UsingShadowDecl *
+UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingShadowDecl));
+ return new (Mem) UsingShadowDecl(0, SourceLocation(), 0, 0);
+}
+
UsingDecl *UsingShadowDecl::getUsingDecl() const {
const UsingShadowDecl *Shadow = this;
while (const UsingShadowDecl *NextShadow =
@@ -1629,14 +1897,16 @@ UsingDecl *UsingShadowDecl::getUsingDecl() const {
return cast<UsingDecl>(Shadow->UsingOrNextShadow);
}
+void UsingDecl::anchor() { }
+
void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
"declaration already in set");
assert(S->getUsingDecl() == this);
- if (FirstUsingShadow)
- S->UsingOrNextShadow = FirstUsingShadow;
- FirstUsingShadow = S;
+ if (FirstUsingShadow.getPointer())
+ S->UsingOrNextShadow = FirstUsingShadow.getPointer();
+ FirstUsingShadow.setPointer(S);
}
void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
@@ -1646,13 +1916,14 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
// Remove S from the shadow decl chain. This is O(n) but hopefully rare.
- if (FirstUsingShadow == S) {
- FirstUsingShadow = dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow);
+ if (FirstUsingShadow.getPointer() == S) {
+ FirstUsingShadow.setPointer(
+ dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow));
S->UsingOrNextShadow = this;
return;
}
- UsingShadowDecl *Prev = FirstUsingShadow;
+ UsingShadowDecl *Prev = FirstUsingShadow.getPointer();
while (Prev->UsingOrNextShadow != S)
Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow);
Prev->UsingOrNextShadow = S->UsingOrNextShadow;
@@ -1666,6 +1937,14 @@ UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
return new (C) UsingDecl(DC, UL, QualifierLoc, NameInfo, IsTypeNameArg);
}
+UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UsingDecl));
+ return new (Mem) UsingDecl(0, SourceLocation(), NestedNameSpecifierLoc(),
+ DeclarationNameInfo(), false);
+}
+
+void UnresolvedUsingValueDecl::anchor() { }
+
UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
@@ -1675,6 +1954,16 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
QualifierLoc, NameInfo);
}
+UnresolvedUsingValueDecl *
+UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(UnresolvedUsingValueDecl));
+ return new (Mem) UnresolvedUsingValueDecl(0, QualType(), SourceLocation(),
+ NestedNameSpecifierLoc(),
+ DeclarationNameInfo());
+}
+
+void UnresolvedUsingTypenameDecl::anchor() { }
+
UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation UsingLoc,
@@ -1687,6 +1976,19 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
TargetName.getAsIdentifierInfo());
}
+UnresolvedUsingTypenameDecl *
+UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID,
+ sizeof(UnresolvedUsingTypenameDecl));
+ return new (Mem) UnresolvedUsingTypenameDecl(0, SourceLocation(),
+ SourceLocation(),
+ NestedNameSpecifierLoc(),
+ SourceLocation(),
+ 0);
+}
+
+void StaticAssertDecl::anchor() { }
+
StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StaticAssertLoc,
Expr *AssertExpr,
@@ -1696,9 +1998,14 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
RParenLoc);
}
+StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(StaticAssertDecl));
+ return new (Mem) StaticAssertDecl(0, SourceLocation(), 0, 0,SourceLocation());
+}
+
static const char *getAccessName(AccessSpecifier AS) {
switch (AS) {
- default:
case AS_none:
llvm_unreachable("Invalid access specifier!");
case AS_public:
@@ -1708,9 +2015,15 @@ static const char *getAccessName(AccessSpecifier AS) {
case AS_protected:
return "protected";
}
+ llvm_unreachable("Invalid access specifier!");
}
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
AccessSpecifier AS) {
return DB << getAccessName(AS);
}
+
+const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB,
+ AccessSpecifier AS) {
+ return DB << getAccessName(AS);
+}
diff --git a/lib/AST/DeclFriend.cpp b/lib/AST/DeclFriend.cpp
index 99bfe40c31f4..6e3bd8d4225b 100644
--- a/lib/AST/DeclFriend.cpp
+++ b/lib/AST/DeclFriend.cpp
@@ -16,6 +16,8 @@
#include "clang/AST/DeclTemplate.h"
using namespace clang;
+void FriendDecl::anchor() { }
+
FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
FriendUnion Friend,
@@ -40,6 +42,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
return FD;
}
-FriendDecl *FriendDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) FriendDecl(Empty);
+FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendDecl));
+ return new (Mem) FriendDecl(EmptyShell());
}
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index a589b7f9d3e9..2370d3c018f2 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -46,6 +46,8 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
+void ObjCContainerDecl::anchor() { }
+
/// getIvarDecl - This method looks up an ivar in this ContextDecl.
///
ObjCIvarDecl *
@@ -147,6 +149,8 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
return 0;
}
+void ObjCInterfaceDecl::anchor() { }
+
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the primary class.
@@ -154,7 +158,11 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
ObjCPropertyDecl *
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId) const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
if (ObjCPropertyDecl *PD =
@@ -175,11 +183,12 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
ASTContext &C)
{
- if (ExternallyCompleted)
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
- if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
- AllReferencedProtocols.set(ExtList, ExtNum, C);
+ if (data().AllReferencedProtocols.empty() &&
+ data().ReferencedProtocols.empty()) {
+ data().AllReferencedProtocols.set(ExtList, ExtNum, C);
return;
}
@@ -214,7 +223,28 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
ProtocolRefs.push_back(*p);
}
- AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
+ data().AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(),C);
+}
+
+void ObjCInterfaceDecl::allocateDefinitionData() {
+ assert(!hasDefinition() && "ObjC class already has a definition");
+ Data = new (getASTContext()) DefinitionData();
+ Data->Definition = this;
+
+ // Make the type point at the definition, now that we have one.
+ if (TypeForDecl)
+ cast<ObjCInterfaceType>(TypeForDecl)->Decl = this;
+}
+
+void ObjCInterfaceDecl::startDefinition() {
+ allocateDefinitionData();
+
+ // Update all of the declarations with a pointer to the definition.
+ for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
+ RD != RDEnd; ++RD) {
+ if (*RD != this)
+ RD->Data = Data;
+ }
}
/// getFirstClassExtension - Find first class extension of the given class.
@@ -237,6 +267,13 @@ const ObjCCategoryDecl* ObjCCategoryDecl::getNextClassExtension() const {
ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
ObjCInterfaceDecl *&clsDeclared) {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
ObjCInterfaceDecl* ClassDecl = this;
while (ClassDecl != NULL) {
if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) {
@@ -261,6 +298,13 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
/// the it returns NULL.
ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
const IdentifierInfo*ICName) {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
ObjCInterfaceDecl* ClassDecl = this;
while (ClassDecl != NULL) {
if (ClassDecl->getIdentifier() == ICName)
@@ -272,12 +316,17 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass(
/// lookupMethod - This method returns an instance/class method by looking in
/// the class, its categories, and its super classes (using a linear search).
-ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
- bool isInstance) const {
+ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
+ bool isInstance,
+ bool shallowCategoryLookup) const {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
const ObjCInterfaceDecl* ClassDecl = this;
ObjCMethodDecl *MethodDecl = 0;
- if (ExternallyCompleted)
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
while (ClassDecl != NULL) {
@@ -285,28 +334,30 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
return MethodDecl;
// Didn't find one yet - look through protocols.
- const ObjCList<ObjCProtocolDecl> &Protocols =
- ClassDecl->getReferencedProtocols();
- for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end(); I != E; ++I)
+ for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(),
+ E = ClassDecl->protocol_end();
+ I != E; ++I)
if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
return MethodDecl;
-
+
// Didn't find one yet - now look through categories.
ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList();
while (CatDecl) {
if ((MethodDecl = CatDecl->getMethod(Sel, isInstance)))
return MethodDecl;
- // Didn't find one yet - look through protocols.
- const ObjCList<ObjCProtocolDecl> &Protocols =
- CatDecl->getReferencedProtocols();
- for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
- E = Protocols.end(); I != E; ++I)
- if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
- return MethodDecl;
+ if (!shallowCategoryLookup) {
+ // Didn't find one yet - look through protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I)
+ if ((MethodDecl = (*I)->lookupMethod(Sel, isInstance)))
+ return MethodDecl;
+ }
CatDecl = CatDecl->getNextClassCategory();
}
+
ClassDecl = ClassDecl->getSuperClass();
}
return NULL;
@@ -315,6 +366,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
const Selector &Sel,
bool Instance) {
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
ObjCMethodDecl *Method = 0;
if (ObjCImplementationDecl *ImpDecl = getImplementation())
Method = Instance ? ImpDecl->getInstanceMethod(Sel)
@@ -351,6 +409,12 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
HasRelatedResultType);
}
+ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCMethodDecl));
+ return new (Mem) ObjCMethodDecl(SourceLocation(), SourceLocation(),
+ Selector(), QualType(), 0, 0);
+}
+
void ObjCMethodDecl::setAsRedeclaration(const ObjCMethodDecl *PrevMethod) {
assert(PrevMethod);
getASTContext().setObjCMethodRedeclaration(PrevMethod, this);
@@ -452,6 +516,10 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
return MD;
}
+ if (isRedeclaration())
+ return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
+ isInstanceMethod());
+
return this;
}
@@ -560,17 +628,26 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
bool selfIsPseudoStrong = false;
bool selfIsConsumed = false;
- if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) {
- selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
-
- // 'self' is always __strong. It's actually pseudo-strong except
- // in init methods, though.
- Qualifiers qs;
- qs.setObjCLifetime(Qualifiers::OCL_Strong);
- selfTy = Context.getQualifiedType(selfTy, qs);
-
- // In addition, 'self' is const unless this is an init method.
- if (getMethodFamily() != OMF_init) {
+
+ if (Context.getLangOpts().ObjCAutoRefCount) {
+ if (isInstanceMethod()) {
+ selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
+
+ // 'self' is always __strong. It's actually pseudo-strong except
+ // in init methods (or methods labeled ns_consumes_self), though.
+ Qualifiers qs;
+ qs.setObjCLifetime(Qualifiers::OCL_Strong);
+ selfTy = Context.getQualifiedType(selfTy, qs);
+
+ // In addition, 'self' is const unless this is an init method.
+ if (getMethodFamily() != OMF_init && !selfIsConsumed) {
+ selfTy = selfTy.withConst();
+ selfIsPseudoStrong = true;
+ }
+ }
+ else {
+ assert(isClassMethod());
+ // 'self' is always const in class methods.
selfTy = selfTy.withConst();
selfIsPseudoStrong = true;
}
@@ -608,28 +685,45 @@ ObjCInterfaceDecl *ObjCMethodDecl::getClassInterface() {
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//
-ObjCInterfaceDecl *ObjCInterfaceDecl::Create(ASTContext &C,
+ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
+ ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc,
- bool ForwardDecl, bool isInternal){
- return new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc, ForwardDecl,
- isInternal);
+ bool isInternal){
+ ObjCInterfaceDecl *Result = new (C) ObjCInterfaceDecl(DC, atLoc, Id, ClassLoc,
+ PrevDecl, isInternal);
+ C.getObjCInterfaceType(Result, PrevDecl);
+ return Result;
+}
+
+ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCInterfaceDecl));
+ return new (Mem) ObjCInterfaceDecl(0, SourceLocation(), 0, SourceLocation(),
+ 0, false);
}
ObjCInterfaceDecl::
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
- SourceLocation CLoc, bool FD, bool isInternal)
+ SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
+ bool isInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, atLoc),
- TypeForDecl(0), SuperClass(0),
- CategoryList(0), IvarList(0),
- ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false) {
+ TypeForDecl(0), Data()
+{
+ setPreviousDeclaration(PrevDecl);
+
+ // Copy the 'data' pointer over.
+ if (PrevDecl)
+ Data = PrevDecl->Data;
+
+ setImplicit(isInternal);
}
void ObjCInterfaceDecl::LoadExternalDefinition() const {
- assert(ExternallyCompleted && "Class is not externally completed");
- ExternallyCompleted = false;
+ assert(data().ExternallyCompleted && "Class is not externally completed");
+ data().ExternallyCompleted = false;
getASTContext().getExternalSource()->CompleteType(
const_cast<ObjCInterfaceDecl *>(this));
}
@@ -637,35 +731,44 @@ void ObjCInterfaceDecl::LoadExternalDefinition() const {
void ObjCInterfaceDecl::setExternallyCompleted() {
assert(getASTContext().getExternalSource() &&
"Class can't be externally completed without an external source");
- assert(!ForwardDecl &&
+ assert(hasDefinition() &&
"Forward declarations can't be externally completed");
- ExternallyCompleted = true;
+ data().ExternallyCompleted = true;
}
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
- if (ExternallyCompleted)
- LoadExternalDefinition();
-
- return getASTContext().getObjCImplementation(
- const_cast<ObjCInterfaceDecl*>(this));
+ if (const ObjCInterfaceDecl *Def = getDefinition()) {
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return getASTContext().getObjCImplementation(
+ const_cast<ObjCInterfaceDecl*>(Def));
+ }
+
+ // FIXME: Should make sure no callers ever do this.
+ return 0;
}
void ObjCInterfaceDecl::setImplementation(ObjCImplementationDecl *ImplD) {
- getASTContext().setObjCImplementation(this, ImplD);
+ getASTContext().setObjCImplementation(getDefinition(), 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;
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().IvarList)
+ return data().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)
+ data().IvarList = (*I); ++I;
+ for (curIvar = data().IvarList; I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
}
@@ -674,9 +777,9 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
if (!CDecl->ivar_empty()) {
ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(),
E = CDecl->ivar_end();
- if (!IvarList) {
- IvarList = (*I); ++I;
- curIvar = IvarList;
+ if (!data().IvarList) {
+ data().IvarList = (*I); ++I;
+ curIvar = data().IvarList;
}
for ( ;I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
@@ -687,15 +790,15 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
if (!ImplDecl->ivar_empty()) {
ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(),
E = ImplDecl->ivar_end();
- if (!IvarList) {
- IvarList = (*I); ++I;
- curIvar = IvarList;
+ if (!data().IvarList) {
+ data().IvarList = (*I); ++I;
+ curIvar = data().IvarList;
}
for ( ;I != E; curIvar = *I, ++I)
curIvar->setNextIvar(*I);
}
}
- return IvarList;
+ return data().IvarList;
}
/// FindCategoryDeclaration - Finds category declaration in the list of
@@ -704,7 +807,11 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
///
ObjCCategoryDecl *
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
- if (ExternallyCompleted)
+ // FIXME: Should make sure no callers ever do this.
+ if (!hasDefinition())
+ return 0;
+
+ if (data().ExternallyCompleted)
LoadExternalDefinition();
for (ObjCCategoryDecl *Category = getCategoryList();
@@ -739,13 +846,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::getCategoryClassMethod(Selector Sel) const {
bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
bool lookupCategory,
bool RHSIsQualifiedID) {
+ if (!hasDefinition())
+ return false;
+
ObjCInterfaceDecl *IDecl = this;
// 1st, look up the class.
- const ObjCList<ObjCProtocolDecl> &Protocols =
- IDecl->getReferencedProtocols();
-
- for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(),
- E = Protocols.end(); PI != E; ++PI) {
+ for (ObjCInterfaceDecl::protocol_iterator
+ PI = IDecl->protocol_begin(), E = IDecl->protocol_end(); PI != E; ++PI){
if (getASTContext().ProtocolCompatibleWithProtocol(lProto, *PI))
return true;
// This is dubious and is added to be compatible with gcc. In gcc, it is
@@ -782,6 +889,8 @@ bool ObjCInterfaceDecl::ClassImplementsProtocol(ObjCProtocolDecl *lProto,
// ObjCIvarDecl
//===----------------------------------------------------------------------===//
+void ObjCIvarDecl::anchor() { }
+
ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
@@ -824,6 +933,12 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
ac, BW, synthesized);
}
+ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCIvarDecl));
+ return new (Mem) ObjCIvarDecl(0, SourceLocation(), SourceLocation(), 0,
+ QualType(), 0, ObjCIvarDecl::None, 0, false);
+}
+
const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
const ObjCContainerDecl *DC = cast<ObjCContainerDecl>(getDeclContext());
@@ -852,6 +967,8 @@ const ObjCInterfaceDecl *ObjCIvarDecl::getContainingInterface() const {
// ObjCAtDefsFieldDecl
//===----------------------------------------------------------------------===//
+void ObjCAtDefsFieldDecl::anchor() { }
+
ObjCAtDefsFieldDecl
*ObjCAtDefsFieldDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -859,15 +976,46 @@ ObjCAtDefsFieldDecl
return new (C) ObjCAtDefsFieldDecl(DC, StartLoc, IdLoc, Id, T, BW);
}
+ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCAtDefsFieldDecl));
+ return new (Mem) ObjCAtDefsFieldDecl(0, SourceLocation(), SourceLocation(),
+ 0, QualType(), 0);
+}
+
//===----------------------------------------------------------------------===//
// ObjCProtocolDecl
//===----------------------------------------------------------------------===//
+void ObjCProtocolDecl::anchor() { }
+
+ObjCProtocolDecl::ObjCProtocolDecl(DeclContext *DC, IdentifierInfo *Id,
+ SourceLocation nameLoc,
+ SourceLocation atStartLoc,
+ ObjCProtocolDecl *PrevDecl)
+ : ObjCContainerDecl(ObjCProtocol, DC, Id, nameLoc, atStartLoc), Data()
+{
+ setPreviousDeclaration(PrevDecl);
+ if (PrevDecl)
+ Data = PrevDecl->Data;
+}
+
ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
SourceLocation nameLoc,
- SourceLocation atStartLoc) {
- return new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc);
+ SourceLocation atStartLoc,
+ ObjCProtocolDecl *PrevDecl) {
+ ObjCProtocolDecl *Result
+ = new (C) ObjCProtocolDecl(DC, Id, nameLoc, atStartLoc, PrevDecl);
+
+ return Result;
+}
+
+ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCProtocolDecl));
+ return new (Mem) ObjCProtocolDecl(0, 0, SourceLocation(), SourceLocation(),
+ 0);
}
ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) {
@@ -898,87 +1046,57 @@ ObjCMethodDecl *ObjCProtocolDecl::lookupMethod(Selector Sel,
return NULL;
}
-//===----------------------------------------------------------------------===//
-// ObjCClassDecl
-//===----------------------------------------------------------------------===//
-
-ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L,
- ObjCInterfaceDecl *const Elt,
- const SourceLocation Loc,
- ASTContext &C)
- : Decl(ObjCClass, DC, L) {
- setClass(C, Elt, Loc);
+void ObjCProtocolDecl::allocateDefinitionData() {
+ assert(!Data && "Protocol already has a definition!");
+ Data = new (getASTContext()) DefinitionData;
+ Data->Definition = this;
}
-ObjCClassDecl *ObjCClassDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- ObjCInterfaceDecl *const Elt,
- const SourceLocation Loc) {
- return new (C) ObjCClassDecl(DC, L, Elt, Loc, C);
-}
-
-void ObjCClassDecl::setClass(ASTContext &C, ObjCInterfaceDecl*const Cls,
- const SourceLocation Loc) {
-
- ForwardDecl = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef),
- llvm::alignOf<ObjCClassRef>());
- new (ForwardDecl) ObjCClassRef(Cls, Loc);
-}
-
-SourceRange ObjCClassDecl::getSourceRange() const {
- // FIXME: We should include the semicolon
- return SourceRange(getLocation(), ForwardDecl->getLocation());
-}
-
-//===----------------------------------------------------------------------===//
-// ObjCForwardProtocolDecl
-//===----------------------------------------------------------------------===//
-
-ObjCForwardProtocolDecl::
-ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
- ObjCProtocolDecl *const *Elts, unsigned nElts,
- const SourceLocation *Locs, ASTContext &C)
-: Decl(ObjCForwardProtocol, DC, L) {
- ReferencedProtocols.set(Elts, nElts, Locs, C);
-}
-
-
-ObjCForwardProtocolDecl *
-ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L,
- ObjCProtocolDecl *const *Elts,
- unsigned NumElts,
- const SourceLocation *Locs) {
- return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
+void ObjCProtocolDecl::startDefinition() {
+ allocateDefinitionData();
+
+ // Update all of the declarations with a pointer to the definition.
+ for (redecl_iterator RD = redecls_begin(), RDEnd = redecls_end();
+ RD != RDEnd; ++RD)
+ RD->Data = this->Data;
}
//===----------------------------------------------------------------------===//
// ObjCCategoryDecl
//===----------------------------------------------------------------------===//
+void ObjCCategoryDecl::anchor() { }
+
ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
- ObjCInterfaceDecl *IDecl) {
+ ObjCInterfaceDecl *IDecl,
+ SourceLocation IvarLBraceLoc,
+ SourceLocation IvarRBraceLoc) {
ObjCCategoryDecl *CatDecl = new (C) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc,
CategoryNameLoc, Id,
- IDecl);
+ IDecl,
+ IvarLBraceLoc, IvarRBraceLoc);
if (IDecl) {
// Link this category into its class's category list.
CatDecl->NextClassCategory = IDecl->getCategoryList();
- IDecl->setCategoryList(CatDecl);
- if (ASTMutationListener *L = C.getASTMutationListener())
- L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+ if (IDecl->hasDefinition()) {
+ IDecl->setCategoryList(CatDecl);
+ if (ASTMutationListener *L = C.getASTMutationListener())
+ L->AddedObjCCategoryToInterface(CatDecl, IDecl);
+ }
}
return CatDecl;
}
-ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(),
- SourceLocation(), 0, 0);
+ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCategoryDecl));
+ return new (Mem) ObjCCategoryDecl(0, SourceLocation(), SourceLocation(),
+ SourceLocation(), 0, 0);
}
ObjCCategoryImplDecl *ObjCCategoryDecl::getImplementation() const {
@@ -995,14 +1113,26 @@ void ObjCCategoryDecl::setImplementation(ObjCCategoryImplDecl *ImplD) {
// ObjCCategoryImplDecl
//===----------------------------------------------------------------------===//
+void ObjCCategoryImplDecl::anchor() { }
+
ObjCCategoryImplDecl *
ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
ObjCInterfaceDecl *ClassInterface,
SourceLocation nameLoc,
- SourceLocation atStartLoc) {
+ SourceLocation atStartLoc,
+ SourceLocation CategoryNameLoc) {
+ if (ClassInterface && ClassInterface->hasDefinition())
+ ClassInterface = ClassInterface->getDefinition();
return new (C) ObjCCategoryImplDecl(DC, Id, ClassInterface,
- nameLoc, atStartLoc);
+ nameLoc, atStartLoc, CategoryNameLoc);
+}
+
+ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCategoryImplDecl));
+ return new (Mem) ObjCCategoryImplDecl(0, 0, 0, SourceLocation(),
+ SourceLocation(), SourceLocation());
}
ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
@@ -1013,6 +1143,8 @@ ObjCCategoryDecl *ObjCCategoryImplDecl::getCategoryDecl() const {
}
+void ObjCImplDecl::anchor() { }
+
void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) {
// FIXME: The context should be correct before we get here.
property->setLexicalDeclContext(this);
@@ -1066,8 +1198,8 @@ FindPropertyImplDecl(IdentifierInfo *Id) const {
}
raw_ostream &clang::operator<<(raw_ostream &OS,
- const ObjCCategoryImplDecl *CID) {
- OS << CID->getName();
+ const ObjCCategoryImplDecl &CID) {
+ OS << CID.getName();
return OS;
}
@@ -1075,14 +1207,28 @@ raw_ostream &clang::operator<<(raw_ostream &OS,
// ObjCImplementationDecl
//===----------------------------------------------------------------------===//
+void ObjCImplementationDecl::anchor() { }
+
ObjCImplementationDecl *
ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
ObjCInterfaceDecl *ClassInterface,
ObjCInterfaceDecl *SuperDecl,
SourceLocation nameLoc,
- SourceLocation atStartLoc) {
+ SourceLocation atStartLoc,
+ SourceLocation IvarLBraceLoc,
+ SourceLocation IvarRBraceLoc) {
+ if (ClassInterface && ClassInterface->hasDefinition())
+ ClassInterface = ClassInterface->getDefinition();
return new (C) ObjCImplementationDecl(DC, ClassInterface, SuperDecl,
- nameLoc, atStartLoc);
+ nameLoc, atStartLoc,
+ IvarLBraceLoc, IvarRBraceLoc);
+}
+
+ObjCImplementationDecl *
+ObjCImplementationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCImplementationDecl));
+ return new (Mem) ObjCImplementationDecl(0, 0, 0, SourceLocation(),
+ SourceLocation());
}
void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
@@ -1099,8 +1245,8 @@ void ObjCImplementationDecl::setIvarInitializers(ASTContext &C,
}
raw_ostream &clang::operator<<(raw_ostream &OS,
- const ObjCImplementationDecl *ID) {
- OS << ID->getName();
+ const ObjCImplementationDecl &ID) {
+ OS << ID.getName();
return OS;
}
@@ -1108,6 +1254,8 @@ raw_ostream &clang::operator<<(raw_ostream &OS,
// ObjCCompatibleAliasDecl
//===----------------------------------------------------------------------===//
+void ObjCCompatibleAliasDecl::anchor() { }
+
ObjCCompatibleAliasDecl *
ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@@ -1116,17 +1264,34 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ObjCCompatibleAliasDecl(DC, L, Id, AliasedClass);
}
+ObjCCompatibleAliasDecl *
+ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCCompatibleAliasDecl));
+ return new (Mem) ObjCCompatibleAliasDecl(0, SourceLocation(), 0, 0);
+}
+
//===----------------------------------------------------------------------===//
// ObjCPropertyDecl
//===----------------------------------------------------------------------===//
+void ObjCPropertyDecl::anchor() { }
+
ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id,
SourceLocation AtLoc,
+ SourceLocation LParenLoc,
TypeSourceInfo *T,
PropertyControl propControl) {
- return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T);
+ return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T);
+}
+
+ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void * Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCPropertyDecl));
+ return new (Mem) ObjCPropertyDecl(0, SourceLocation(), 0, SourceLocation(),
+ SourceLocation(),
+ 0);
}
//===----------------------------------------------------------------------===//
@@ -1145,6 +1310,13 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
ivarLoc);
}
+ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ObjCPropertyImplDecl));
+ return new (Mem) ObjCPropertyImplDecl(0, SourceLocation(), SourceLocation(),
+ 0, Dynamic, 0, SourceLocation());
+}
+
SourceRange ObjCPropertyImplDecl::getSourceRange() const {
SourceLocation EndLoc = getLocation();
if (IvarLoc.isValid())
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 08a1ab5723cd..74e1c1bb9df9 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/Module.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -58,6 +59,7 @@ namespace {
void VisitLabelDecl(LabelDecl *D);
void VisitParmVarDecl(ParmVarDecl *D);
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
+ void VisitImportDecl(ImportDecl *D);
void VisitStaticAssertDecl(StaticAssertDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
@@ -68,10 +70,8 @@ namespace {
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitObjCMethodDecl(ObjCMethodDecl *D);
- void VisitObjCClassDecl(ObjCClassDecl *D);
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
- void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
@@ -85,6 +85,7 @@ namespace {
void PrintTemplateParameters(const TemplateParameterList *Params,
const TemplateArgumentList *Args);
+ void prettyPrintAttributes(Decl *D);
};
}
@@ -182,6 +183,16 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
return Out;
}
+void DeclPrinter::prettyPrintAttributes(Decl *D) {
+ if (D->hasAttrs()) {
+ AttrVec &Attrs = D->getAttrs();
+ for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
+ Attr *A = *i;
+ A->printPretty(Out, Context);
+ }
+ }
+}
+
void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
this->Indent();
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
@@ -320,11 +331,11 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
Out << "__module_private__ ";
}
Out << S;
+ prettyPrintAttributes(D);
}
void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
- Out << "using " << D->getNameAsString() << " = "
- << D->getUnderlyingType().getAsString(Policy);
+ Out << "using " << *D << " = " << D->getUnderlyingType().getAsString(Policy);
}
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
@@ -350,6 +361,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
VisitDeclContext(D);
Indent() << "}";
}
+ prettyPrintAttributes(D);
}
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
@@ -376,7 +388,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (!Policy.SuppressSpecifiers) {
- switch (D->getStorageClass()) {
+ switch (D->getStorageClassAsWritten()) {
case SC_None: break;
case SC_Extern: Out << "extern "; break;
case SC_Static: Out << "static "; break;
@@ -466,12 +478,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
}
- if (D->hasAttr<NoReturnAttr>())
- Proto += " __attribute((noreturn))";
-
- if (D->hasAttr<ReturnsTwiceAttr>())
- Proto += " __attribute((returns_twice))";
-
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
bool HasInitializerList = false;
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
@@ -542,6 +548,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
Out << Proto;
+ prettyPrintAttributes(D);
if (D->isPure())
Out << " = 0";
@@ -588,16 +595,18 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
Out << " = ";
Init->printPretty(Out, Context, 0, Policy, Indentation);
}
+ prettyPrintAttributes(D);
}
void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
- Out << D->getNameAsString() << ":";
+ Out << *D << ":";
}
void DeclPrinter::VisitVarDecl(VarDecl *D) {
- if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None)
- Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " ";
+ StorageClass SCAsWritten = D->getStorageClassAsWritten();
+ if (!Policy.SuppressSpecifiers && SCAsWritten != SC_None)
+ Out << VarDecl::getStorageClassSpecifierString(SCAsWritten) << " ";
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
Out << "__thread ";
@@ -612,17 +621,22 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
Out << Name;
Expr *Init = D->getInit();
if (!Policy.SuppressInitializers && Init) {
- if (D->hasCXXDirectInitializer())
- Out << "(";
- else {
- CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init);
- if (!CCE || CCE->getConstructor()->isCopyConstructor())
- Out << " = ";
+ bool ImplicitInit = false;
+ if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init))
+ ImplicitInit = D->getInitStyle() == VarDecl::CallInit &&
+ Construct->getNumArgs() == 0 && !Construct->isListInitialization();
+ if (!ImplicitInit) {
+ if (D->getInitStyle() == VarDecl::CallInit)
+ Out << "(";
+ else if (D->getInitStyle() == VarDecl::CInit) {
+ Out << " = ";
+ }
+ Init->printPretty(Out, Context, 0, Policy, Indentation);
+ if (D->getInitStyle() == VarDecl::CallInit)
+ Out << ")";
}
- Init->printPretty(Out, Context, 0, Policy, Indentation);
- if (D->hasCXXDirectInitializer())
- Out << ")";
}
+ prettyPrintAttributes(D);
}
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
@@ -635,6 +649,11 @@ void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
Out << ")";
}
+void DeclPrinter::VisitImportDecl(ImportDecl *D) {
+ Out << "@__experimental_modules_import " << D->getImportedModule()->getFullModuleName()
+ << ";\n";
+}
+
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
Out << "static_assert(";
D->getAssertExpr()->printPretty(Out, Context, 0, Policy, Indentation);
@@ -745,7 +764,7 @@ void DeclPrinter::PrintTemplateParameters(
if (TTP->isParameterPack())
Out << "... ";
- Out << TTP->getNameAsString();
+ Out << *TTP;
if (Args) {
Out << " = ";
@@ -829,10 +848,6 @@ void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Objective-C declarations
//----------------------------------------------------------------------------
-void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
- Out << "@class " << *D->getForwardInterfaceDecl();
-}
-
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstanceMethod())
Out << "- ";
@@ -882,6 +897,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
std::string I = OID->getNameAsString();
ObjCInterfaceDecl *SID = OID->getSuperClass();
+ if (!OID->isThisDeclarationADefinition()) {
+ Out << "@class " << I << ";";
+ return;
+ }
+
if (SID)
Out << "@interface " << I << " : " << *SID;
else
@@ -914,17 +934,12 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
// FIXME: implement the rest...
}
-void DeclPrinter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
- Out << "@protocol ";
- for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
- E = D->protocol_end();
- I != E; ++I) {
- if (I != D->protocol_begin()) Out << ", ";
- Out << **I;
- }
-}
-
void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
+ if (!PID->isThisDeclarationADefinition()) {
+ Out << "@protocol " << PID->getIdentifier() << ";\n";
+ return;
+ }
+
Out << "@protocol " << *PID << '\n';
VisitDeclContext(PID, false);
Out << "@end";
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 558a4ccac96b..4590195d6b31 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -112,42 +112,34 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
//===----------------------------------------------------------------------===//
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
- // Find the first declaration of this function template.
- RedeclarableTemplateDecl *First = getCanonicalDecl();
+ if (!Common) {
+ // Walk the previous-declaration chain until we either find a declaration
+ // with a common pointer or we run out of previous declarations.
+ llvm::SmallVector<RedeclarableTemplateDecl *, 2> PrevDecls;
+ for (RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
+ Prev = Prev->getPreviousDecl()) {
+ if (Prev->Common) {
+ Common = Prev->Common;
+ break;
+ }
+
+ PrevDecls.push_back(Prev);
+ }
- if (First->CommonOrPrev.isNull()) {
- CommonBase *CommonPtr = First->newCommon(getASTContext());
- First->CommonOrPrev = CommonPtr;
- CommonPtr->Latest = First;
+ // If we never found a common pointer, allocate one now.
+ if (!Common) {
+ // FIXME: If any of the declarations is from an AST file, we probably
+ // need an update record to add the common data.
+
+ Common = newCommon(getASTContext());
+ }
+
+ // Update any previous declarations we saw with the common pointer.
+ for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I)
+ PrevDecls[I]->Common = Common;
}
- 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;
+ return Common;
}
template <class EntryType>
@@ -160,7 +152,7 @@ RedeclarableTemplateDecl::findSpecializationImpl(
llvm::FoldingSetNodeID ID;
EntryType::Profile(ID,Args,NumArgs, getASTContext());
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
- return Entry ? SETraits::getMostRecentDeclaration(Entry) : 0;
+ return Entry ? SETraits::getMostRecentDecl(Entry) : 0;
}
/// \brief Generate the injected template arguments for the given template
@@ -181,7 +173,7 @@ static void GenerateInjectedTemplateArgs(ASTContext &Context,
Arg = TemplateArgument(ArgType);
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
- Expr *E = new (Context) DeclRefExpr(NTTP,
+ Expr *E = new (Context) DeclRefExpr(NTTP, /*enclosing*/ false,
NTTP->getType().getNonLValueExprType(Context),
Expr::getValueKindForType(NTTP->getType()),
NTTP->getLocation());
@@ -224,9 +216,11 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
}
-FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, EmptyShell) {
- return new (C) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(),
- 0, 0);
+FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionTemplateDecl));
+ return new (Mem) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(),
+ 0, 0);
}
RedeclarableTemplateDecl::CommonBase *
@@ -244,7 +238,10 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
void FunctionTemplateDecl::addSpecialization(
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
- getSpecializations().InsertNode(Info, InsertPos);
+ if (InsertPos)
+ getSpecializations().InsertNode(Info, InsertPos);
+ else
+ getSpecializations().GetOrInsertNode(Info);
if (ASTMutationListener *L = getASTMutationListener())
L->AddedCXXTemplateSpecialization(this, Info->Function);
}
@@ -284,8 +281,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
return New;
}
-ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) ClassTemplateDecl(Empty);
+ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ClassTemplateDecl));
+ return new (Mem) ClassTemplateDecl(EmptyShell());
}
void ClassTemplateDecl::LoadLazySpecializations() {
@@ -326,7 +325,14 @@ ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
void *InsertPos) {
- getSpecializations().InsertNode(D, InsertPos);
+ if (InsertPos)
+ getSpecializations().InsertNode(D, InsertPos);
+ else {
+ ClassTemplateSpecializationDecl *Existing
+ = getSpecializations().GetOrInsertNode(D);
+ (void)Existing;
+ assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
+ }
if (ASTMutationListener *L = getASTMutationListener())
L->AddedCXXTemplateSpecialization(this, D);
}
@@ -342,7 +348,15 @@ ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
void ClassTemplateDecl::AddPartialSpecialization(
ClassTemplatePartialSpecializationDecl *D,
void *InsertPos) {
- getPartialSpecializations().InsertNode(D, InsertPos);
+ if (InsertPos)
+ getPartialSpecializations().InsertNode(D, InsertPos);
+ else {
+ ClassTemplatePartialSpecializationDecl *Existing
+ = getPartialSpecializations().GetOrInsertNode(D);
+ (void)Existing;
+ assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
+ }
+
if (ASTMutationListener *L = getASTMutationListener())
L->AddedCXXTemplateSpecialization(this, D);
}
@@ -357,7 +371,7 @@ void ClassTemplateDecl::getPartialSpecializations(
P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
P != PEnd; ++P) {
assert(!PS[P->getSequenceNumber()]);
- PS[P->getSequenceNumber()] = P->getMostRecentDeclaration();
+ PS[P->getSequenceNumber()] = P->getMostRecentDecl();
}
}
@@ -370,7 +384,7 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
PEnd = getPartialSpecializations().end();
P != PEnd; ++P) {
if (Context.hasSameType(P->getInjectedSpecializationType(), T))
- return P->getMostRecentDeclaration();
+ return P->getMostRecentDecl();
}
return 0;
@@ -385,7 +399,7 @@ ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
PEnd = getPartialSpecializations().end();
P != PEnd; ++P) {
if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
- return P->getMostRecentDeclaration();
+ return P->getMostRecentDecl();
}
return 0;
@@ -433,9 +447,10 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
}
TemplateTypeParmDecl *
-TemplateTypeParmDecl::Create(const ASTContext &C, EmptyShell Empty) {
- return new (C) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(),
- 0, false);
+TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTypeParmDecl));
+ return new (Mem) TemplateTypeParmDecl(0, SourceLocation(), SourceLocation(),
+ 0, false);
}
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
@@ -520,6 +535,27 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
ExpandedTInfos);
}
+NonTypeTemplateParmDecl *
+NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(NonTypeTemplateParmDecl));
+ return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(),
+ SourceLocation(), 0, 0, 0,
+ QualType(), false, 0);
+}
+
+NonTypeTemplateParmDecl *
+NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
+ unsigned NumExpandedTypes) {
+ unsigned Size = sizeof(NonTypeTemplateParmDecl)
+ + NumExpandedTypes * 2 * sizeof(void*);
+
+ void *Mem = AllocateDeserializedDecl(C, ID, Size);
+ return new (Mem) NonTypeTemplateParmDecl(0, SourceLocation(),
+ SourceLocation(), 0, 0, 0,
+ QualType(), 0, 0, NumExpandedTypes,
+ 0);
+}
+
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
if (hasDefaultArgument() && !defaultArgumentWasInherited())
return SourceRange(getOuterLocStart(),
@@ -537,6 +573,8 @@ SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
// TemplateTemplateParmDecl Method Implementations
//===----------------------------------------------------------------------===//
+void TemplateTemplateParmDecl::anchor() { }
+
TemplateTemplateParmDecl *
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
@@ -546,6 +584,13 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
Params);
}
+TemplateTemplateParmDecl *
+TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TemplateTemplateParmDecl));
+ return new (Mem) TemplateTemplateParmDecl(0, SourceLocation(), 0, 0, false,
+ 0, 0);
+}
+
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//
@@ -582,6 +627,12 @@ FunctionTemplateSpecializationInfo::Create(ASTContext &C, FunctionDecl *FD,
}
//===----------------------------------------------------------------------===//
+// TemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void TemplateDecl::anchor() { }
+
+//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
ClassTemplateSpecializationDecl::
@@ -628,9 +679,11 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
}
ClassTemplateSpecializationDecl *
-ClassTemplateSpecializationDecl::Create(ASTContext &Context, EmptyShell Empty) {
- return
- new (Context)ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
+ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID,
+ sizeof(ClassTemplateSpecializationDecl));
+ return new (Mem) ClassTemplateSpecializationDecl(ClassTemplateSpecialization);
}
void
@@ -682,6 +735,8 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
//===----------------------------------------------------------------------===//
// ClassTemplatePartialSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
+void ClassTemplatePartialSpecializationDecl::anchor() { }
+
ClassTemplatePartialSpecializationDecl::
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
DeclContext *DC,
@@ -740,15 +795,19 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,
}
ClassTemplatePartialSpecializationDecl *
-ClassTemplatePartialSpecializationDecl::Create(ASTContext &Context,
- EmptyShell Empty) {
- return new (Context)ClassTemplatePartialSpecializationDecl();
+ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID,
+ sizeof(ClassTemplatePartialSpecializationDecl));
+ return new (Mem) ClassTemplatePartialSpecializationDecl();
}
//===----------------------------------------------------------------------===//
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
+void FriendTemplateDecl::anchor() { }
+
FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
DeclContext *DC,
SourceLocation L,
@@ -761,9 +820,10 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
return Result;
}
-FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
- EmptyShell Empty) {
- return new (Context) FriendTemplateDecl(Empty);
+FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FriendTemplateDecl));
+ return new (Mem) FriendTemplateDecl(EmptyShell());
}
//===----------------------------------------------------------------------===//
@@ -780,10 +840,11 @@ TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl);
}
-TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
- EmptyShell) {
- return new (C) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
- 0, 0);
+TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasTemplateDecl));
+ return new (Mem) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
+ 0, 0);
}
void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) {
@@ -796,3 +857,16 @@ TypeAliasTemplateDecl::newCommon(ASTContext &C) {
return CommonPtr;
}
+//===----------------------------------------------------------------------===//
+// ClassScopeFunctionSpecializationDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void ClassScopeFunctionSpecializationDecl::anchor() { }
+
+ClassScopeFunctionSpecializationDecl *
+ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
+ unsigned ID) {
+ void *Mem = AllocateDeserializedDecl(C, ID,
+ sizeof(ClassScopeFunctionSpecializationDecl));
+ return new (Mem) ClassScopeFunctionSpecializationDecl(0, SourceLocation(), 0);
+}
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index bf647ed7ac35..64924ad95095 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -53,7 +53,7 @@ public:
void *FETokenInfo;
};
-/// CXXLiberalOperatorName - Contains the actual identifier that makes up the
+/// CXXLiteralOperatorName - Contains the actual identifier that makes up the
/// name.
///
/// This identifier is stored here rather than directly in DeclarationName so as
@@ -64,6 +64,10 @@ class CXXLiteralOperatorIdName
public:
IdentifierInfo *ID;
+ /// FETokenInfo - Extra information associated with this operator
+ /// name that can be used by the front end.
+ void *FETokenInfo;
+
void Profile(llvm::FoldingSetNodeID &FSID) {
FSID.AddPointer(ID);
}
@@ -125,8 +129,8 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
case DeclarationName::CXXUsingDirective:
return 0;
}
-
- return 0;
+
+ llvm_unreachable("Invalid DeclarationName Kind!");
}
} // end namespace clang
@@ -189,7 +193,6 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
return ObjCMultiArgSelector;
}
- break;
}
// Can't actually get here.
@@ -334,7 +337,7 @@ void *DeclarationName::getFETokenInfoAsVoid() const {
return getAsCXXOperatorIdName()->FETokenInfo;
case CXXLiteralOperatorName:
- return getCXXLiteralIdentifier()->getFETokenInfo<void>();
+ return getAsCXXLiteralOperatorIdName()->FETokenInfo;
default:
llvm_unreachable("Declaration name has no FETokenInfo");
@@ -358,7 +361,7 @@ void DeclarationName::setFETokenInfo(void *T) {
break;
case CXXLiteralOperatorName:
- getCXXLiteralIdentifier()->setFETokenInfo(T);
+ getAsCXXLiteralOperatorIdName()->FETokenInfo = T;
break;
default:
@@ -472,6 +475,7 @@ DeclarationNameTable::getCXXLiteralOperatorName(IdentifierInfo *II) {
CXXLiteralOperatorIdName *LiteralName = new (Ctx) CXXLiteralOperatorIdName;
LiteralName->ExtraKindOrNumArgs = DeclarationNameExtra::CXXLiteralOperator;
LiteralName->ID = II;
+ LiteralName->FETokenInfo = 0;
LiteralNames->InsertNode(LiteralName, InsertPos);
return DeclarationName(LiteralName);
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 2568adaa5a44..4c7cd8a6793b 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -39,8 +39,7 @@
#include "clang/AST/TypeVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -66,7 +65,6 @@ template <class Impl> struct XMLDeclVisitor {
void dispatch(Decl *D) {
switch (D->getKind()) {
- default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
#define DECL(DERIVED, BASE) \
case Decl::DERIVED: \
DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
@@ -121,7 +119,6 @@ template <class Impl> struct XMLTypeVisitor {
void dispatch(Type *T) {
switch (T->getTypeClass()) {
- default: llvm_unreachable("Type that isn't part of TypeNodes.inc!");
#define TYPE(DERIVED, BASE) \
case Type::DERIVED: \
DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
@@ -167,7 +164,6 @@ static StringRef getTypeKindName(Type *T) {
}
llvm_unreachable("unknown type kind!");
- return "unknown_type";
}
struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
@@ -227,7 +223,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
//---- General utilities -------------------------------------------//
void setPointer(StringRef prop, const void *p) {
- llvm::SmallString<10> buffer;
+ SmallString<10> buffer;
llvm::raw_svector_ostream os(buffer);
os << p;
os.flush();
@@ -243,7 +239,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
void setInteger(StringRef prop, unsigned n) {
- llvm::SmallString<10> buffer;
+ SmallString<10> buffer;
llvm::raw_svector_ostream os(buffer);
os << n;
os.flush();
@@ -324,7 +320,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
break;
case TemplateArgument::Declaration: {
- visitDeclRef(A.getAsDecl());
+ if (Decl *D = A.getAsDecl())
+ visitDeclRef(D);
break;
}
case TemplateArgument::Integral: {
@@ -411,7 +408,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
template <class T> void visitRedeclarableAttrs(T *D) {
- if (T *Prev = D->getPreviousDeclaration())
+ if (T *Prev = D->getPreviousDecl())
setPointer("previous", Prev);
}
@@ -465,7 +462,13 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
if (D->getStorageClass() != SC_None)
set("storage",
VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
- setFlag("directinit", D->hasCXXDirectInitializer());
+ StringRef initStyle = "";
+ switch (D->getInitStyle()) {
+ case VarDecl::CInit: initStyle = "c"; break;
+ case VarDecl::CallInit: initStyle = "call"; break;
+ case VarDecl::ListInit: initStyle = "list"; break;
+ }
+ set("initstyle", initStyle);
setFlag("nrvo", D->isNRVOVariable());
// TODO: instantiation, etc.
}
@@ -495,6 +498,10 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
for (FunctionDecl::param_iterator
I = D->param_begin(), E = D->param_end(); I != E; ++I)
dispatch(*I);
+ for (llvm::ArrayRef<NamedDecl*>::iterator
+ I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end();
+ I != E; ++I)
+ dispatch(*I);
if (D->doesThisDeclarationHaveABody())
dispatch(D->getBody());
}
@@ -740,11 +747,6 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
visitDeclContext(D);
}
- // ObjCClassDecl
- void visitObjCClassDeclChildren(ObjCClassDecl *D) {
- visitDeclRef(D->getForwardInterfaceDecl());
- }
-
// ObjCInterfaceDecl
void visitCategoryList(ObjCCategoryDecl *D) {
if (!D) return;
@@ -755,7 +757,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
setPointer("typeptr", D->getTypeForDecl());
- setFlag("forward_decl", D->isForwardDecl());
+ setFlag("forward_decl", !D->isThisDeclarationADefinition());
setFlag("implicit_interface", D->isImplicitInterfaceDecl());
}
void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
@@ -815,18 +817,11 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
}
- // ObjCForwardProtocolDecl
- void visitObjCForwardProtocolDeclChildren(ObjCForwardProtocolDecl *D) {
- for (ObjCForwardProtocolDecl::protocol_iterator
- I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
- visitDeclRef(*I);
- }
-
// ObjCProtocolDecl
- void visitObjCProtocolDeclAttrs(ObjCProtocolDecl *D) {
- setFlag("forward_decl", D->isForwardDecl());
- }
void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
+ if (!D->isThisDeclarationADefinition())
+ return;
+
if (D->protocol_begin() != D->protocol_end()) {
TemporaryContainer C(*this, "protocols");
for (ObjCInterfaceDecl::protocol_iterator
@@ -835,6 +830,9 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
}
}
void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
+ if (!D->isThisDeclarationADefinition())
+ return;
+
visitDeclContext(D);
}
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index b0bcfe09f6dc..868109e3d56e 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/LiteralSupport.h"
@@ -29,6 +30,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cstring>
using namespace clang;
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
@@ -92,6 +94,8 @@ bool Expr::isKnownToHaveBooleanValue() const {
// Amusing macro metaprogramming hack: check whether a class provides
// a more specific implementation of getExprLoc().
+//
+// See also Stmt.cpp:{getLocStart(),getLocEnd()}.
namespace {
/// This implementation is used when a class provides a custom
/// implementation of getExprLoc.
@@ -108,7 +112,7 @@ namespace {
template <class E>
SourceLocation getExprLocImpl(const Expr *expr,
SourceLocation (Expr::*v)() const) {
- return static_cast<const E*>(expr)->getSourceRange().getBegin();
+ return static_cast<const E*>(expr)->getLocStart();
}
}
@@ -123,7 +127,6 @@ SourceLocation Expr::getExprLoc() const {
#include "clang/AST/StmtNodes.inc"
}
llvm_unreachable("unknown statement kind");
- return SourceLocation();
}
//===----------------------------------------------------------------------===//
@@ -133,7 +136,7 @@ SourceLocation Expr::getExprLoc() const {
/// \brief Compute the type-, value-, and instantiation-dependence of a
/// declaration reference
/// based on the declaration being referenced.
-static void computeDeclRefDependence(NamedDecl *D, QualType T,
+static void computeDeclRefDependence(ASTContext &Ctx, NamedDecl *D, QualType T,
bool &TypeDependent,
bool &ValueDependent,
bool &InstantiationDependent) {
@@ -184,21 +187,29 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
// (VD) - a constant with integral or enumeration type and is
// initialized with an expression that is value-dependent.
+ // (VD) - a constant with literal type and is initialized with an
+ // expression that is value-dependent [C++11].
+ // (VD) - FIXME: Missing from the standard:
+ // - an entity with reference type and is initialized with an
+ // expression that is value-dependent [C++11]
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
- if (Var->getType()->isIntegralOrEnumerationType() &&
- Var->getType().getCVRQualifiers() == Qualifiers::Const) {
+ if ((Ctx.getLangOpts().CPlusPlus0x ?
+ Var->getType()->isLiteralType() :
+ Var->getType()->isIntegralOrEnumerationType()) &&
+ (Var->getType().getCVRQualifiers() == Qualifiers::Const ||
+ Var->getType()->isReferenceType())) {
if (const Expr *Init = Var->getAnyInitializer())
if (Init->isValueDependent()) {
ValueDependent = true;
InstantiationDependent = true;
}
- }
-
+ }
+
// (VD) - FIXME: Missing from the standard:
// - a member function or a static data member of the current
// instantiation
- else if (Var->isStaticDataMember() &&
- Var->getDeclContext()->isDependentContext()) {
+ if (Var->isStaticDataMember() &&
+ Var->getDeclContext()->isDependentContext()) {
ValueDependent = true;
InstantiationDependent = true;
}
@@ -212,16 +223,15 @@ static void computeDeclRefDependence(NamedDecl *D, QualType T,
if (isa<CXXMethodDecl>(D) && D->getDeclContext()->isDependentContext()) {
ValueDependent = true;
InstantiationDependent = true;
- return;
- }
+ }
}
-void DeclRefExpr::computeDependence() {
+void DeclRefExpr::computeDependence(ASTContext &Ctx) {
bool TypeDependent = false;
bool ValueDependent = false;
bool InstantiationDependent = false;
- computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent,
- InstantiationDependent);
+ computeDeclRefDependence(Ctx, getDecl(), getType(), TypeDependent,
+ ValueDependent, InstantiationDependent);
// (TD) C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
@@ -250,8 +260,11 @@ void DeclRefExpr::computeDependence() {
ExprBits.ContainsUnexpandedParameterPack = true;
}
-DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
- ValueDecl *D, const DeclarationNameInfo &NameInfo,
+DeclRefExpr::DeclRefExpr(ASTContext &Ctx,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ ValueDecl *D, bool RefersToEnclosingLocal,
+ const DeclarationNameInfo &NameInfo,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs,
QualType T, ExprValueKind VK)
@@ -263,38 +276,48 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifierLoc QualifierLoc,
DeclRefExprBits.HasFoundDecl = FoundD ? 1 : 0;
if (FoundD)
getInternalFoundDecl() = FoundD;
- DeclRefExprBits.HasExplicitTemplateArgs = TemplateArgs ? 1 : 0;
+ DeclRefExprBits.HasTemplateKWAndArgsInfo
+ = (TemplateArgs || TemplateKWLoc.isValid()) ? 1 : 0;
+ DeclRefExprBits.RefersToEnclosingLocal = RefersToEnclosingLocal;
if (TemplateArgs) {
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs,
+ Dependent,
+ InstantiationDependent,
+ ContainsUnexpandedParameterPack);
if (InstantiationDependent)
setInstantiationDependent(true);
+ } else if (TemplateKWLoc.isValid()) {
+ getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
DeclRefExprBits.HadMultipleCandidates = 0;
- computeDependence();
+ computeDependence(Ctx);
}
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
ValueDecl *D,
+ bool RefersToEnclosingLocal,
SourceLocation NameLoc,
QualType T,
ExprValueKind VK,
NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs) {
- return Create(Context, QualifierLoc, D,
+ return Create(Context, QualifierLoc, TemplateKWLoc, D,
+ RefersToEnclosingLocal,
DeclarationNameInfo(D->getDeclName(), NameLoc),
T, VK, FoundD, TemplateArgs);
}
DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
ValueDecl *D,
+ bool RefersToEnclosingLocal,
const DeclarationNameInfo &NameInfo,
QualType T,
ExprValueKind VK,
@@ -310,25 +333,28 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context,
if (FoundD)
Size += sizeof(NamedDecl *);
if (TemplateArgs)
- Size += ASTTemplateArgumentListInfo::sizeFor(*TemplateArgs);
+ Size += ASTTemplateKWAndArgsInfo::sizeFor(TemplateArgs->size());
+ else if (TemplateKWLoc.isValid())
+ Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
- return new (Mem) DeclRefExpr(QualifierLoc, D, NameInfo, FoundD, TemplateArgs,
- T, VK);
+ return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
+ RefersToEnclosingLocal,
+ NameInfo, FoundD, TemplateArgs, T, VK);
}
DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context,
bool HasQualifier,
bool HasFoundDecl,
- bool HasExplicitTemplateArgs,
+ bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
std::size_t Size = sizeof(DeclRefExpr);
if (HasQualifier)
Size += sizeof(NestedNameSpecifierLoc);
if (HasFoundDecl)
Size += sizeof(NamedDecl *);
- if (HasExplicitTemplateArgs)
- Size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
+ if (HasTemplateKWAndArgsInfo)
+ Size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
void *Mem = Context.Allocate(Size, llvm::alignOf<DeclRefExpr>());
return new (Mem) DeclRefExpr(EmptyShell());
@@ -342,6 +368,16 @@ SourceRange DeclRefExpr::getSourceRange() const {
R.setEnd(getRAngleLoc());
return R;
}
+SourceLocation DeclRefExpr::getLocStart() const {
+ if (hasQualifier())
+ return getQualifierLoc().getBeginLoc();
+ return getNameInfo().getLocStart();
+}
+SourceLocation DeclRefExpr::getLocEnd() const {
+ if (hasExplicitTemplateArgs())
+ return getRAngleLoc();
+ return getNameInfo().getLocEnd();
+}
// FIXME: Maybe this should use DeclPrinter with a special "print predefined
// expr" policy instead.
@@ -352,7 +388,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
if (IT != PrettyFunction && IT != PrettyFunctionNoVirtual)
return FD->getNameAsString();
- llvm::SmallString<256> Name;
+ SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
@@ -362,22 +398,24 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
Out << "static ";
}
- PrintingPolicy Policy(Context.getLangOptions());
-
+ PrintingPolicy Policy(Context.getLangOpts());
std::string Proto = FD->getQualifiedNameAsString(Policy);
+ llvm::raw_string_ostream POut(Proto);
- const FunctionType *AFT = FD->getType()->getAs<FunctionType>();
+ const FunctionDecl *Decl = FD;
+ if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern())
+ Decl = Pattern;
+ const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
const FunctionProtoType *FT = 0;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
- Proto += "(";
+ POut << "(";
if (FT) {
- llvm::raw_string_ostream POut(Proto);
- for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+ for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
if (i) POut << ", ";
std::string Param;
- FD->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
+ Decl->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
POut << Param;
}
@@ -386,16 +424,74 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
POut << "...";
}
}
- Proto += ")";
+ POut << ")";
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
Qualifiers ThisQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
if (ThisQuals.hasConst())
- Proto += " const";
+ POut << " const";
if (ThisQuals.hasVolatile())
- Proto += " volatile";
+ POut << " volatile";
+ RefQualifierKind Ref = MD->getRefQualifier();
+ if (Ref == RQ_LValue)
+ POut << " &";
+ else if (Ref == RQ_RValue)
+ POut << " &&";
+ }
+
+ typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
+ SpecsTy Specs;
+ const DeclContext *Ctx = FD->getDeclContext();
+ while (Ctx && isa<NamedDecl>(Ctx)) {
+ const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
+ if (Spec && !Spec->isExplicitSpecialization())
+ Specs.push_back(Spec);
+ Ctx = Ctx->getParent();
}
+ std::string TemplateParams;
+ llvm::raw_string_ostream TOut(TemplateParams);
+ for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend();
+ I != E; ++I) {
+ const TemplateParameterList *Params
+ = (*I)->getSpecializedTemplate()->getTemplateParameters();
+ const TemplateArgumentList &Args = (*I)->getTemplateArgs();
+ assert(Params->size() == Args.size());
+ for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) {
+ StringRef Param = Params->getParam(i)->getName();
+ if (Param.empty()) continue;
+ TOut << Param << " = ";
+ Args.get(i).print(Policy, TOut);
+ TOut << ", ";
+ }
+ }
+
+ FunctionTemplateSpecializationInfo *FSI
+ = FD->getTemplateSpecializationInfo();
+ if (FSI && !FSI->isExplicitSpecialization()) {
+ const TemplateParameterList* Params
+ = FSI->getTemplate()->getTemplateParameters();
+ const TemplateArgumentList* Args = FSI->TemplateArguments;
+ assert(Params->size() == Args->size());
+ for (unsigned i = 0, e = Params->size(); i != e; ++i) {
+ StringRef Param = Params->getParam(i)->getName();
+ if (Param.empty()) continue;
+ TOut << Param << " = ";
+ Args->get(i).print(Policy, TOut);
+ TOut << ", ";
+ }
+ }
+
+ TOut.flush();
+ if (!TemplateParams.empty()) {
+ // remove the trailing comma and space
+ TemplateParams.resize(TemplateParams.size() - 2);
+ POut << " [" << TemplateParams << "]";
+ }
+
+ POut.flush();
+
if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
AFT->getResultType().getAsStringInternal(Proto, Policy);
@@ -405,7 +501,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
return Name.str().str();
}
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurrentDecl)) {
- llvm::SmallString<256> Name;
+ SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
Out << (MD->isInstanceMethod() ? '-' : '+');
Out << '[';
@@ -417,7 +513,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) {
if (const ObjCCategoryImplDecl *CID =
dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext()))
- Out << '(' << CID << ')';
+ Out << '(' << *CID << ')';
Out << ' ';
Out << MD->getSelector().getAsString();
@@ -468,7 +564,7 @@ FloatingLiteral::Create(ASTContext &C, const llvm::APFloat &V,
FloatingLiteral *
FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) {
- return new (C) FloatingLiteral(Empty);
+ return new (C) FloatingLiteral(C, Empty);
}
/// getValueAsApproximateDouble - This returns the value as an inaccurate
@@ -482,6 +578,30 @@ double FloatingLiteral::getValueAsApproximateDouble() const {
return V.convertToDouble();
}
+int StringLiteral::mapCharByteWidth(TargetInfo const &target,StringKind k) {
+ int CharByteWidth = 0;
+ switch(k) {
+ case Ascii:
+ case UTF8:
+ CharByteWidth = target.getCharWidth();
+ break;
+ case Wide:
+ CharByteWidth = target.getWCharWidth();
+ break;
+ case UTF16:
+ CharByteWidth = target.getChar16Width();
+ break;
+ case UTF32:
+ CharByteWidth = target.getChar32Width();
+ break;
+ }
+ assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple");
+ CharByteWidth /= 8;
+ assert((CharByteWidth==1 || CharByteWidth==2 || CharByteWidth==4)
+ && "character byte widths supported are 1, 2, and 4 only");
+ return CharByteWidth;
+}
+
StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str,
StringKind Kind, bool Pascal, QualType Ty,
const SourceLocation *Loc,
@@ -494,12 +614,8 @@ StringLiteral *StringLiteral::Create(ASTContext &C, StringRef Str,
StringLiteral *SL = new (Mem) StringLiteral(Ty);
// OPTIMIZE: could allocate this appended to the StringLiteral.
- char *AStrData = new (C, 1) char[Str.size()];
- memcpy(AStrData, Str.data(), Str.size());
- SL->StrData = AStrData;
- SL->ByteLength = Str.size();
- SL->Kind = Kind;
- SL->IsPascal = Pascal;
+ SL->setString(C,Str,Kind,Pascal);
+
SL->TokLocs[0] = Loc[0];
SL->NumConcatenated = NumStrs;
@@ -513,17 +629,46 @@ StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) {
sizeof(SourceLocation)*(NumStrs-1),
llvm::alignOf<StringLiteral>());
StringLiteral *SL = new (Mem) StringLiteral(QualType());
- SL->StrData = 0;
- SL->ByteLength = 0;
+ SL->CharByteWidth = 0;
+ SL->Length = 0;
SL->NumConcatenated = NumStrs;
return SL;
}
-void StringLiteral::setString(ASTContext &C, StringRef Str) {
- char *AStrData = new (C, 1) char[Str.size()];
- memcpy(AStrData, Str.data(), Str.size());
- StrData = AStrData;
- ByteLength = Str.size();
+void StringLiteral::setString(ASTContext &C, StringRef Str,
+ StringKind Kind, bool IsPascal) {
+ //FIXME: we assume that the string data comes from a target that uses the same
+ // code unit size and endianess for the type of string.
+ this->Kind = Kind;
+ this->IsPascal = IsPascal;
+
+ CharByteWidth = mapCharByteWidth(C.getTargetInfo(),Kind);
+ assert((Str.size()%CharByteWidth == 0)
+ && "size of data must be multiple of CharByteWidth");
+ Length = Str.size()/CharByteWidth;
+
+ switch(CharByteWidth) {
+ case 1: {
+ char *AStrData = new (C) char[Length];
+ std::memcpy(AStrData,Str.data(),Str.size());
+ StrData.asChar = AStrData;
+ break;
+ }
+ case 2: {
+ uint16_t *AStrData = new (C) uint16_t[Length];
+ std::memcpy(AStrData,Str.data(),Str.size());
+ StrData.asUInt16 = AStrData;
+ break;
+ }
+ case 4: {
+ uint32_t *AStrData = new (C) uint32_t[Length];
+ std::memcpy(AStrData,Str.data(),Str.size());
+ StrData.asUInt32 = AStrData;
+ break;
+ }
+ default:
+ assert(false && "unsupported CharByteWidth");
+ }
}
/// getLocationOfByte - Return a source location that points to the specified
@@ -596,7 +741,6 @@ getLocationOfByte(unsigned ByteNo, const SourceManager &SM,
/// corresponds to, e.g. "sizeof" or "[pre]++".
const char *UnaryOperator::getOpcodeStr(Opcode Op) {
switch (Op) {
- default: llvm_unreachable("Unknown unary operator");
case UO_PostInc: return "++";
case UO_PostDec: return "--";
case UO_PreInc: return "++";
@@ -611,6 +755,7 @@ const char *UnaryOperator::getOpcodeStr(Opcode Op) {
case UO_Imag: return "__imag";
case UO_Extension: return "__extension__";
}
+ llvm_unreachable("Unknown unary operator");
}
UnaryOperatorKind
@@ -778,7 +923,7 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) {
/// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If
/// not, return 0.
-unsigned CallExpr::isBuiltinCall(const ASTContext &Context) const {
+unsigned CallExpr::isBuiltinCall() const {
// All simple function calls (e.g. func()) are implicitly cast to pointer to
// function. As a result, we try and obtain the DeclRefExpr from the
// ImplicitCastExpr.
@@ -826,6 +971,24 @@ SourceRange CallExpr::getSourceRange() const {
end = getArg(getNumArgs() - 1)->getLocEnd();
return SourceRange(begin, end);
}
+SourceLocation CallExpr::getLocStart() const {
+ if (isa<CXXOperatorCallExpr>(this))
+ return cast<CXXOperatorCallExpr>(this)->getSourceRange().getBegin();
+
+ SourceLocation begin = getCallee()->getLocStart();
+ if (begin.isInvalid() && getNumArgs() > 0)
+ begin = getArg(0)->getLocStart();
+ return begin;
+}
+SourceLocation CallExpr::getLocEnd() const {
+ if (isa<CXXOperatorCallExpr>(this))
+ return cast<CXXOperatorCallExpr>(this)->getSourceRange().getEnd();
+
+ SourceLocation end = getRParenLoc();
+ if (end.isInvalid() && getNumArgs() > 0)
+ end = getArg(getNumArgs() - 1)->getLocEnd();
+ return end;
+}
OffsetOfExpr *OffsetOfExpr::Create(ASTContext &C, QualType type,
SourceLocation OperatorLoc,
@@ -886,6 +1049,7 @@ IdentifierInfo *OffsetOfExpr::OffsetOfNode::getFieldName() const {
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
ValueDecl *memberdecl,
DeclAccessPair founddecl,
DeclarationNameInfo nameinfo,
@@ -902,7 +1066,9 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
Size += sizeof(MemberNameQualifier);
if (targs)
- Size += ASTTemplateArgumentListInfo::sizeFor(*targs);
+ Size += ASTTemplateKWAndArgsInfo::sizeFor(targs->size());
+ else if (TemplateKWLoc.isValid())
+ Size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>());
MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo,
@@ -926,41 +1092,46 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
NQ->FoundDecl = founddecl;
}
+ E->HasTemplateKWAndArgsInfo = (targs || TemplateKWLoc.isValid());
+
if (targs) {
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- E->HasExplicitTemplateArgumentList = true;
- E->getExplicitTemplateArgs().initializeFrom(*targs, Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *targs,
+ Dependent,
+ InstantiationDependent,
+ ContainsUnexpandedParameterPack);
if (InstantiationDependent)
E->setInstantiationDependent(true);
+ } else if (TemplateKWLoc.isValid()) {
+ E->getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
return E;
}
SourceRange MemberExpr::getSourceRange() const {
- SourceLocation StartLoc;
+ return SourceRange(getLocStart(), getLocEnd());
+}
+SourceLocation MemberExpr::getLocStart() const {
if (isImplicitAccess()) {
if (hasQualifier())
- StartLoc = getQualifierLoc().getBeginLoc();
- else
- StartLoc = MemberLoc;
- } else {
- // FIXME: We don't want this to happen. Rather, we should be able to
- // detect all kinds of implicit accesses more cleanly.
- StartLoc = getBase()->getLocStart();
- if (StartLoc.isInvalid())
- StartLoc = MemberLoc;
+ return getQualifierLoc().getBeginLoc();
+ return MemberLoc;
}
-
- SourceLocation EndLoc =
- HasExplicitTemplateArgumentList? getRAngleLoc()
- : getMemberNameInfo().getEndLoc();
-
- return SourceRange(StartLoc, EndLoc);
+
+ // FIXME: We don't want this to happen. Rather, we should be able to
+ // detect all kinds of implicit accesses more cleanly.
+ SourceLocation BaseStartLoc = getBase()->getLocStart();
+ if (BaseStartLoc.isValid())
+ return BaseStartLoc;
+ return MemberLoc;
+}
+SourceLocation MemberExpr::getLocEnd() const {
+ if (hasExplicitTemplateArgs())
+ return getRAngleLoc();
+ return getMemberNameInfo().getEndLoc();
}
void CastExpr::CheckCastConsistency() const {
@@ -983,6 +1154,11 @@ void CastExpr::CheckCastConsistency() const {
assert(getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
+ case CK_ReinterpretMemberPointer:
+ assert(getType()->isMemberPointerType());
+ assert(getSubExpr()->getType()->isMemberPointerType());
+ goto CheckNoBasePath;
+
case CK_BitCast:
// Arbitrary casts to C pointer types count as bitcasts.
// Otherwise, we should only have block and ObjC pointer casts
@@ -1001,6 +1177,11 @@ void CastExpr::CheckCastConsistency() const {
!getSubExpr()->getType()->isBlockPointerType());
goto CheckNoBasePath;
+ case CK_CopyAndAutoreleaseBlockObject:
+ assert(getType()->isBlockPointerType());
+ assert(getSubExpr()->getType()->isBlockPointerType());
+ goto CheckNoBasePath;
+
// These should not have an inheritance path.
case CK_Dynamic:
case CK_ToUnion:
@@ -1035,8 +1216,9 @@ void CastExpr::CheckCastConsistency() const {
case CK_Dependent:
case CK_LValueToRValue:
- case CK_GetObjCProperty:
case CK_NoOp:
+ case CK_AtomicToNonAtomic:
+ case CK_NonAtomicToAtomic:
case CK_PointerToBoolean:
case CK_IntegralToBoolean:
case CK_FloatingToBoolean:
@@ -1061,8 +1243,6 @@ const char *CastExpr::getCastKindName() const {
return "LValueBitCast";
case CK_LValueToRValue:
return "LValueToRValue";
- case CK_GetObjCProperty:
- return "GetObjCProperty";
case CK_NoOp:
return "NoOp";
case CK_BaseToDerived:
@@ -1087,6 +1267,8 @@ const char *CastExpr::getCastKindName() const {
return "BaseToDerivedMemberPointer";
case CK_DerivedToBaseMemberPointer:
return "DerivedToBaseMemberPointer";
+ case CK_ReinterpretMemberPointer:
+ return "ReinterpretMemberPointer";
case CK_UserDefinedConversion:
return "UserDefinedConversion";
case CK_ConstructorConversion:
@@ -1151,10 +1333,15 @@ const char *CastExpr::getCastKindName() const {
return "ARCReclaimReturnedObject";
case CK_ARCExtendBlockObject:
return "ARCCExtendBlockObject";
+ case CK_AtomicToNonAtomic:
+ return "AtomicToNonAtomic";
+ case CK_NonAtomicToAtomic:
+ return "NonAtomicToAtomic";
+ case CK_CopyAndAutoreleaseBlockObject:
+ return "CopyAndAutoreleaseBlockObject";
}
llvm_unreachable("Unhandled cast kind!");
- return 0;
}
Expr *CastExpr::getSubExprAsWritten() {
@@ -1196,7 +1383,6 @@ CXXBaseSpecifier **CastExpr::path_buffer() {
#include "clang/AST/StmtNodes.inc"
default:
llvm_unreachable("non-cast expressions not possible here");
- return 0;
}
}
@@ -1284,7 +1470,7 @@ const char *BinaryOperator::getOpcodeStr(Opcode Op) {
case BO_Comma: return ",";
}
- return "";
+ llvm_unreachable("Invalid OpCode!");
}
BinaryOperatorKind
@@ -1355,9 +1541,10 @@ InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc,
: Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false,
false, false),
InitExprs(C, numInits),
- LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
- HadArrayRangeDesignator(false)
-{
+ LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0)
+{
+ sawArrayRangeDesignator(false);
+ setInitializesStdInitializerList(false);
for (unsigned I = 0; I != numInits; ++I) {
if (initExprs[I]->isTypeDependent())
ExprBits.TypeDependent = true;
@@ -1394,6 +1581,7 @@ Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) {
}
void InitListExpr::setArrayFiller(Expr *filler) {
+ assert(!hasArrayFiller() && "Filler already set!");
ArrayFillerOrUnionFieldInit = filler;
// Fill out any "holes" in the array due to designated initializers.
Expr **inits = getInits();
@@ -1433,9 +1621,10 @@ SourceRange InitListExpr::getSourceRange() const {
/// getFunctionType - Return the underlying function type for this block.
///
-const FunctionType *BlockExpr::getFunctionType() const {
- return getType()->getAs<BlockPointerType>()->
- getPointeeType()->getAs<FunctionType>();
+const FunctionProtoType *BlockExpr::getFunctionType() const {
+ // The block pointer is never sugared, but the function type might be.
+ return cast<BlockPointerType>(getType())
+ ->getPointeeType()->castAs<FunctionProtoType>();
}
SourceLocation BlockExpr::getCaretLocation() const {
@@ -1591,7 +1780,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
// Fallthrough for generic call handling.
}
case CallExprClass:
- case CXXMemberCallExprClass: {
+ case CXXMemberCallExprClass:
+ case UserDefinedLiteralClass: {
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const Decl *FD = CE->getCalleeDecl()) {
@@ -1620,7 +1810,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case ObjCMessageExprClass: {
const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
- if (Ctx.getLangOptions().ObjCAutoRefCount &&
+ if (Ctx.getLangOpts().ObjCAutoRefCount &&
ME->isInstanceMessage() &&
!ME->getType()->isVoidType() &&
ME->getSelector().getIdentifierInfoForSlot(0) &&
@@ -1644,6 +1834,19 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
R1 = getSourceRange();
return true;
+ case PseudoObjectExprClass: {
+ const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this);
+
+ // Only complain about things that have the form of a getter.
+ if (isa<UnaryOperator>(PO->getSyntacticForm()) ||
+ isa<BinaryOperator>(PO->getSyntacticForm()))
+ return false;
+
+ Loc = getExprLoc();
+ R1 = getSourceRange();
+ return true;
+ }
+
case StmtExprClass: {
// Statement exprs don't logically have side effects themselves, but are
// sometimes used in macros in ways that give them a type that is unused.
@@ -1730,14 +1933,8 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const {
->isOBJCGCCandidate(Ctx);
case CStyleCastExprClass:
return cast<CStyleCastExpr>(E)->getSubExpr()->isOBJCGCCandidate(Ctx);
- case BlockDeclRefExprClass:
case DeclRefExprClass: {
-
- const Decl *D;
- if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E))
- D = BDRE->getDecl();
- else
- D = cast<DeclRefExpr>(E)->getDecl();
+ const Decl *D = cast<DeclRefExpr>(E)->getDecl();
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasGlobalStorage())
@@ -1766,7 +1963,7 @@ bool Expr::isBoundMemberFunction(ASTContext &Ctx) const {
}
QualType Expr::findBoundMemberType(const Expr *expr) {
- assert(expr->getType()->isSpecificPlaceholderType(BuiltinType::BoundMember));
+ assert(expr->hasPlaceholderType(BuiltinType::BoundMember));
// Bound member expressions are always one of these possibilities:
// x->m x.m x->*y x.*y
@@ -1910,8 +2107,9 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
// pointer, or member function pointer that does not have a non-throwing
// exception-specification
case CallExprClass:
+ case CXXMemberCallExprClass:
case CXXOperatorCallExprClass:
- case CXXMemberCallExprClass: {
+ case UserDefinedLiteralClass: {
const CallExpr *CE = cast<CallExpr>(this);
CanThrowResult CT;
if (isTypeDependent())
@@ -1934,15 +2132,22 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
+ case LambdaExprClass: {
+ const LambdaExpr *Lambda = cast<LambdaExpr>(this);
+ CanThrowResult CT = Expr::CT_Cannot;
+ for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
+ CapEnd = Lambda->capture_init_end();
+ Cap != CapEnd; ++Cap)
+ CT = MergeCanThrow(CT, (*Cap)->CanThrow(C));
+ return CT;
+ }
+
case CXXNewExprClass: {
CanThrowResult CT;
if (isTypeDependent())
CT = CT_Dependent;
else
- CT = MergeCanThrow(
- CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew()),
- CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getConstructor(),
- /*NullThrows*/false));
+ CT = CanCalleeThrow(C, this, cast<CXXNewExpr>(this)->getOperatorNew());
if (CT == CT_Can)
return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
@@ -1979,38 +2184,47 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
// specs.
case ObjCMessageExprClass:
case ObjCPropertyRefExprClass:
+ case ObjCSubscriptRefExprClass:
+ return CT_Can;
+
+ // All the ObjC literals that are implemented as calls are
+ // potentially throwing unless we decide to close off that
+ // possibility.
+ case ObjCArrayLiteralClass:
+ case ObjCDictionaryLiteralClass:
+ case ObjCNumericLiteralClass:
return CT_Can;
// Many other things have subexpressions, so we have to test those.
// Some are simple:
- case ParenExprClass:
- case MemberExprClass:
- case CXXReinterpretCastExprClass:
- case CXXConstCastExprClass:
case ConditionalOperatorClass:
case CompoundLiteralExprClass:
- case ExtVectorElementExprClass:
- case InitListExprClass:
- case DesignatedInitExprClass:
- case ParenListExprClass:
- case VAArgExprClass:
+ case CXXConstCastExprClass:
case CXXDefaultArgExprClass:
+ case CXXReinterpretCastExprClass:
+ case DesignatedInitExprClass:
case ExprWithCleanupsClass:
- case ObjCIvarRefExprClass:
+ case ExtVectorElementExprClass:
+ case InitListExprClass:
+ case MemberExprClass:
case ObjCIsaExprClass:
+ case ObjCIvarRefExprClass:
+ case ParenExprClass:
+ case ParenListExprClass:
case ShuffleVectorExprClass:
+ case VAArgExprClass:
return CanSubExprsThrow(C, this);
// Some might be dependent for other reasons.
- case UnaryOperatorClass:
case ArraySubscriptExprClass:
- case ImplicitCastExprClass:
+ case BinaryOperatorClass:
+ case CompoundAssignOperatorClass:
case CStyleCastExprClass:
case CXXStaticCastExprClass:
case CXXFunctionalCastExprClass:
- case BinaryOperatorClass:
- case CompoundAssignOperatorClass:
- case MaterializeTemporaryExprClass: {
+ case ImplicitCastExprClass:
+ case MaterializeTemporaryExprClass:
+ case UnaryOperatorClass: {
CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
@@ -2030,16 +2244,71 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
return cast<GenericSelectionExpr>(this)->getResultExpr()->CanThrow(C);
// Some expressions are always dependent.
- case DependentScopeDeclRefExprClass:
- case CXXUnresolvedConstructExprClass:
case CXXDependentScopeMemberExprClass:
+ case CXXUnresolvedConstructExprClass:
+ case DependentScopeDeclRefExprClass:
return CT_Dependent;
- default:
- // All other expressions don't have subexpressions, or else they are
- // unevaluated.
+ case AtomicExprClass:
+ case AsTypeExprClass:
+ case BinaryConditionalOperatorClass:
+ case BlockExprClass:
+ case CUDAKernelCallExprClass:
+ case DeclRefExprClass:
+ case ObjCBridgedCastExprClass:
+ case ObjCIndirectCopyRestoreExprClass:
+ case ObjCProtocolExprClass:
+ case ObjCSelectorExprClass:
+ case OffsetOfExprClass:
+ case PackExpansionExprClass:
+ case PseudoObjectExprClass:
+ case SubstNonTypeTemplateParmExprClass:
+ case SubstNonTypeTemplateParmPackExprClass:
+ case UnaryExprOrTypeTraitExprClass:
+ case UnresolvedLookupExprClass:
+ case UnresolvedMemberExprClass:
+ // FIXME: Can any of the above throw? If so, when?
return CT_Cannot;
+
+ case AddrLabelExprClass:
+ case ArrayTypeTraitExprClass:
+ case BinaryTypeTraitExprClass:
+ case TypeTraitExprClass:
+ case CXXBoolLiteralExprClass:
+ case CXXNoexceptExprClass:
+ case CXXNullPtrLiteralExprClass:
+ case CXXPseudoDestructorExprClass:
+ case CXXScalarValueInitExprClass:
+ case CXXThisExprClass:
+ case CXXUuidofExprClass:
+ case CharacterLiteralClass:
+ case ExpressionTraitExprClass:
+ case FloatingLiteralClass:
+ case GNUNullExprClass:
+ case ImaginaryLiteralClass:
+ case ImplicitValueInitExprClass:
+ case IntegerLiteralClass:
+ case ObjCEncodeExprClass:
+ case ObjCStringLiteralClass:
+ case ObjCBoolLiteralExprClass:
+ case OpaqueValueExprClass:
+ case PredefinedExprClass:
+ case SizeOfPackExprClass:
+ case StringLiteralClass:
+ case UnaryTypeTraitExprClass:
+ // These expressions can never throw.
+ return CT_Cannot;
+
+#define STMT(CLASS, PARENT) case CLASS##Class:
+#define STMT_RANGE(Base, First, Last)
+#define LAST_STMT_RANGE(BASE, FIRST, LAST)
+#define EXPR(CLASS, PARENT)
+#define ABSTRACT_STMT(STMT)
+#include "clang/AST/StmtNodes.inc"
+ case NoStmtClass:
+ llvm_unreachable("Invalid class for expression");
}
+ llvm_unreachable("Bogus StmtClass");
}
Expr* Expr::IgnoreParens() {
@@ -2364,24 +2633,14 @@ bool Expr::isImplicitCXXThis() const {
/// hasAnyTypeDependentArguments - Determines if any of the expressions
/// in Exprs is type-dependent.
-bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {
- for (unsigned I = 0; I < NumExprs; ++I)
+bool Expr::hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs) {
+ for (unsigned I = 0; I < Exprs.size(); ++I)
if (Exprs[I]->isTypeDependent())
return true;
return false;
}
-/// hasAnyValueDependentArguments - Determines if any of the expressions
-/// in Exprs is value-dependent.
-bool Expr::hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs) {
- for (unsigned I = 0; I < NumExprs; ++I)
- if (Exprs[I]->isValueDependent())
- return true;
-
- return false;
-}
-
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
@@ -2399,6 +2658,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
switch (getStmtClass()) {
default: break;
+ case IntegerLiteralClass:
+ case FloatingLiteralClass:
case StringLiteralClass:
case ObjCStringLiteralClass:
case ObjCEncodeExprClass:
@@ -2408,15 +2669,20 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
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;
+ if (CE->getConstructor()->isTrivial()) {
+ // 1) an application of the trivial default constructor or
+ 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.
+ if (CE->isElidable() &&
+ CE->getArg(0)->isConstantInitializer(Ctx, false))
+ 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);
+ // 3) a foldable constexpr constructor.
+ break;
}
case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like
@@ -2456,36 +2722,38 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
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() == 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, 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, false);
-
+ case CStyleCastExprClass: {
+ const CastExpr *CE = cast<CastExpr>(this);
+
+ // If we're promoting an integer to an _Atomic type then this is constant
+ // if the integer is constant. We also need to check the converse in case
+ // someone does something like:
+ //
+ // int a = (_Atomic(int))42;
+ //
+ // I doubt anyone would write code like this directly, but it's quite
+ // possible as the result of macro expansions.
+ if (CE->getCastKind() == CK_NonAtomicToAtomic ||
+ CE->getCastKind() == CK_AtomicToNonAtomic)
+ return CE->getSubExpr()->isConstantInitializer(Ctx, false);
+
+ // Handle bitcasts of vector constants.
+ if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast)
+ return CE->getSubExpr()->isConstantInitializer(Ctx, false);
+
+ // Handle misc casts we want to ignore.
+ // FIXME: Is it really safe to ignore all these?
+ if (CE->getCastKind() == CK_NoOp ||
+ CE->getCastKind() == CK_LValueToRValue ||
+ CE->getCastKind() == CK_ToUnion ||
+ CE->getCastKind() == CK_ConstructorConversion)
+ return CE->getSubExpr()->isConstantInitializer(Ctx, false);
+
break;
-
+ }
case MaterializeTemporaryExprClass:
return cast<MaterializeTemporaryExpr>(this)->GetTemporaryExpr()
->isConstantInitializer(Ctx, false);
@@ -2493,6 +2761,60 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
return isEvaluatable(Ctx);
}
+namespace {
+ /// \brief Look for a call to a non-trivial function within an expression.
+ class NonTrivialCallFinder : public EvaluatedExprVisitor<NonTrivialCallFinder>
+ {
+ typedef EvaluatedExprVisitor<NonTrivialCallFinder> Inherited;
+
+ bool NonTrivial;
+
+ public:
+ explicit NonTrivialCallFinder(ASTContext &Context)
+ : Inherited(Context), NonTrivial(false) { }
+
+ bool hasNonTrivialCall() const { return NonTrivial; }
+
+ void VisitCallExpr(CallExpr *E) {
+ if (CXXMethodDecl *Method
+ = dyn_cast_or_null<CXXMethodDecl>(E->getCalleeDecl())) {
+ if (Method->isTrivial()) {
+ // Recurse to children of the call.
+ Inherited::VisitStmt(E);
+ return;
+ }
+ }
+
+ NonTrivial = true;
+ }
+
+ void VisitCXXConstructExpr(CXXConstructExpr *E) {
+ if (E->getConstructor()->isTrivial()) {
+ // Recurse to children of the call.
+ Inherited::VisitStmt(E);
+ return;
+ }
+
+ NonTrivial = true;
+ }
+
+ void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+ if (E->getTemporary()->getDestructor()->isTrivial()) {
+ Inherited::VisitStmt(E);
+ return;
+ }
+
+ NonTrivial = true;
+ }
+ };
+}
+
+bool Expr::hasNonTrivialCall(ASTContext &Ctx) {
+ NonTrivialCallFinder Finder(Ctx);
+ Finder.Visit(this);
+ return Finder.hasNonTrivialCall();
+}
+
/// isNullPointerConstant - C99 6.3.2.3p3 - Return whether this is a null
/// pointer constant or not, as well as the specific kind of constant detected.
/// Null pointer constants can be integer constant expressions with the
@@ -2518,7 +2840,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
// Strip off a cast to void*, if it exists. Except in C++.
if (const ExplicitCastExpr *CE = dyn_cast<ExplicitCastExpr>(this)) {
- if (!Ctx.getLangOptions().CPlusPlus) {
+ if (!Ctx.getLangOpts().CPlusPlus) {
// Check that it is a cast to void*.
if (const PointerType *PT = CE->getType()->getAs<PointerType>()) {
QualType Pointee = PT->getPointeeType();
@@ -2548,6 +2870,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
} else if (const MaterializeTemporaryExpr *M
= dyn_cast<MaterializeTemporaryExpr>(this)) {
return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC);
+ } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) {
+ if (const Expr *Source = OVE->getSourceExpr())
+ return Source->isNullPointerConstant(Ctx, NPC);
}
// C++0x nullptr_t is always a null pointer constant.
@@ -2563,15 +2888,22 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
}
// This expression must be an integer type.
if (!getType()->isIntegerType() ||
- (Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType()))
+ (Ctx.getLangOpts().CPlusPlus && getType()->isEnumeralType()))
return NPCK_NotNull;
// If we have an integer constant expression, we need to *evaluate* it and
- // test for the value 0.
- llvm::APSInt Result;
- bool IsNull = isIntegerConstantExpr(Result, Ctx) && Result == 0;
+ // test for the value 0. Don't use the C++11 constant expression semantics
+ // for this, for now; once the dust settles on core issue 903, we might only
+ // allow a literal 0 here in C++11 mode.
+ if (Ctx.getLangOpts().CPlusPlus0x) {
+ if (!isCXX98IntegralConstantExpr(Ctx))
+ return NPCK_NotNull;
+ } else {
+ if (!isIntegerConstantExpr(Ctx))
+ return NPCK_NotNull;
+ }
- return (IsNull ? NPCK_ZeroInteger : NPCK_NotNull);
+ return (EvaluateKnownConstInt(Ctx) == 0) ? NPCK_ZeroInteger : NPCK_NotNull;
}
/// \brief If this expression is an l-value for an Objective C
@@ -2722,7 +3054,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
- SourceLocation RBracLoc)
+ SourceLocation RBracLoc,
+ bool isImplicit)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary,
/*TypeDependent=*/false, /*ValueDependent=*/false,
/*InstantiationDependent=*/false,
@@ -2730,8 +3063,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
Kind(IsInstanceSuper? SuperInstance : SuperClass),
- HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
- LBracLoc(LBracLoc), RBracLoc(RBracLoc)
+ HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit),
+ SuperLoc(SuperLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
setReceiverPointer(SuperType.getAsOpaquePtr());
@@ -2746,14 +3079,15 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
- SourceLocation RBracLoc)
+ SourceLocation RBracLoc,
+ bool isImplicit)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
T->isDependentType(), T->isInstantiationDependentType(),
T->containsUnexpandedParameterPack()),
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
Kind(Class),
- HasMethod(Method != 0), IsDelegateInitCall(false),
+ HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit),
LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
@@ -2769,7 +3103,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SelectorLocationsKind SelLocsK,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
- SourceLocation RBracLoc)
+ SourceLocation RBracLoc,
+ bool isImplicit)
: Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(),
Receiver->isTypeDependent(),
Receiver->isInstantiationDependent(),
@@ -2777,7 +3112,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
: Sel.getAsOpaquePtr())),
Kind(Instance),
- HasMethod(Method != 0), IsDelegateInitCall(false),
+ HasMethod(Method != 0), IsDelegateInitCall(false), IsImplicit(isImplicit),
LBracLoc(LBracLoc), RBracLoc(RBracLoc)
{
initArgsAndSelLocs(Args, SelLocs, SelLocsK);
@@ -2803,8 +3138,10 @@ void ObjCMessageExpr::initArgsAndSelLocs(ArrayRef<Expr *> Args,
}
SelLocsKind = SelLocsK;
- if (SelLocsK == SelLoc_NonStandard)
- std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
+ if (!isImplicit()) {
+ if (SelLocsK == SelLoc_NonStandard)
+ std::copy(SelLocs.begin(), SelLocs.end(), getStoredSelLocs());
+ }
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@@ -2817,12 +3154,19 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
- SourceLocation RBracLoc) {
- SelectorLocationsKind SelLocsK;
- ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ SourceLocation RBracLoc,
+ bool isImplicit) {
+ assert((!SelLocs.empty() || isImplicit) &&
+ "No selector locs for non-implicit message");
+ ObjCMessageExpr *Mem;
+ SelectorLocationsKind SelLocsK = SelectorLocationsKind();
+ if (isImplicit)
+ Mem = alloc(Context, Args.size(), 0);
+ else
+ Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper,
SuperType, Sel, SelLocs, SelLocsK,
- Method, Args, RBracLoc);
+ Method, Args, RBracLoc, isImplicit);
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@@ -2833,11 +3177,19 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
- SourceLocation RBracLoc) {
- SelectorLocationsKind SelLocsK;
- ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ SourceLocation RBracLoc,
+ bool isImplicit) {
+ assert((!SelLocs.empty() || isImplicit) &&
+ "No selector locs for non-implicit message");
+ ObjCMessageExpr *Mem;
+ SelectorLocationsKind SelLocsK = SelectorLocationsKind();
+ if (isImplicit)
+ Mem = alloc(Context, Args.size(), 0);
+ else
+ Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
- SelLocs, SelLocsK, Method, Args, RBracLoc);
+ SelLocs, SelLocsK, Method, Args, RBracLoc,
+ isImplicit);
}
ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
@@ -2848,11 +3200,19 @@ ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T,
ArrayRef<SourceLocation> SelLocs,
ObjCMethodDecl *Method,
ArrayRef<Expr *> Args,
- SourceLocation RBracLoc) {
- SelectorLocationsKind SelLocsK;
- ObjCMessageExpr *Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
+ SourceLocation RBracLoc,
+ bool isImplicit) {
+ assert((!SelLocs.empty() || isImplicit) &&
+ "No selector locs for non-implicit message");
+ ObjCMessageExpr *Mem;
+ SelectorLocationsKind SelLocsK = SelectorLocationsKind();
+ if (isImplicit)
+ Mem = alloc(Context, Args.size(), 0);
+ else
+ Mem = alloc(Context, Args, RBracLoc, SelLocs, Sel, SelLocsK);
return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel,
- SelLocs, SelLocsK, Method, Args, RBracLoc);
+ SelLocs, SelLocsK, Method, Args, RBracLoc,
+ isImplicit);
}
ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context,
@@ -2902,7 +3262,7 @@ SourceRange ObjCMessageExpr::getReceiverRange() const {
return getSuperLoc();
}
- return SourceLocation();
+ llvm_unreachable("Invalid ReceiverKind!");
}
Selector ObjCMessageExpr::getSelector() const {
@@ -2951,8 +3311,8 @@ StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
case OBC_BridgeRetained:
return "__bridge_retained";
}
-
- return "__bridge";
+
+ llvm_unreachable("Invalid BridgeKind!");
}
bool ChooseExpr::isConditionTrue(const ASTContext &C) const {
@@ -3225,11 +3585,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx,
ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc,
Expr **exprs, unsigned nexprs,
- SourceLocation rparenloc, QualType T)
- : Expr(ParenListExprClass, T, VK_RValue, OK_Ordinary,
+ SourceLocation rparenloc)
+ : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary,
false, false, false, false),
NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) {
- assert(!T.isNull() && "ParenListExpr must have a valid type");
Exprs = new (C) Stmt*[nexprs];
for (unsigned i = 0; i != nexprs; ++i) {
if (exprs[i]->isTypeDependent())
@@ -3256,6 +3615,72 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) {
return cast<OpaqueValueExpr>(e);
}
+PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context, EmptyShell sh,
+ unsigned numSemanticExprs) {
+ void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) +
+ (1 + numSemanticExprs) * sizeof(Expr*),
+ llvm::alignOf<PseudoObjectExpr>());
+ return new(buffer) PseudoObjectExpr(sh, numSemanticExprs);
+}
+
+PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs)
+ : Expr(PseudoObjectExprClass, shell) {
+ PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1;
+}
+
+PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax,
+ ArrayRef<Expr*> semantics,
+ unsigned resultIndex) {
+ assert(syntax && "no syntactic expression!");
+ assert(semantics.size() && "no semantic expressions!");
+
+ QualType type;
+ ExprValueKind VK;
+ if (resultIndex == NoResult) {
+ type = C.VoidTy;
+ VK = VK_RValue;
+ } else {
+ assert(resultIndex < semantics.size());
+ type = semantics[resultIndex]->getType();
+ VK = semantics[resultIndex]->getValueKind();
+ assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary);
+ }
+
+ void *buffer = C.Allocate(sizeof(PseudoObjectExpr) +
+ (1 + semantics.size()) * sizeof(Expr*),
+ llvm::alignOf<PseudoObjectExpr>());
+ return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics,
+ resultIndex);
+}
+
+PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK,
+ Expr *syntax, ArrayRef<Expr*> semantics,
+ unsigned resultIndex)
+ : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary,
+ /*filled in at end of ctor*/ false, false, false, false) {
+ PseudoObjectExprBits.NumSubExprs = semantics.size() + 1;
+ PseudoObjectExprBits.ResultIndex = resultIndex + 1;
+
+ for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) {
+ Expr *E = (i == 0 ? syntax : semantics[i-1]);
+ getSubExprsBuffer()[i] = E;
+
+ if (E->isTypeDependent())
+ ExprBits.TypeDependent = true;
+ if (E->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (E->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (E->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ if (isa<OpaqueValueExpr>(E))
+ assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 &&
+ "opaque-value semantic expressions for pseudo-object "
+ "operations must have sources");
+ }
+}
+
//===----------------------------------------------------------------------===//
// ExprIterator.
//===----------------------------------------------------------------------===//
@@ -3298,24 +3723,117 @@ Stmt::child_range ObjCMessageExpr::children() {
reinterpret_cast<Stmt **>(getArgs() + getNumArgs()));
}
-// Blocks
-BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
- SourceLocation l, bool ByRef,
- bool constAdded)
- : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false, false,
- d->isParameterPack()),
- D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded)
+ObjCArrayLiteral::ObjCArrayLiteral(llvm::ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl *Method,
+ SourceRange SR)
+ : Expr(ObjCArrayLiteralClass, T, VK_RValue, OK_Ordinary,
+ false, false, false, false),
+ NumElements(Elements.size()), Range(SR), ArrayWithObjectsMethod(Method)
{
- bool TypeDependent = false;
- bool ValueDependent = false;
- bool InstantiationDependent = false;
- computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent,
- InstantiationDependent);
- ExprBits.TypeDependent = TypeDependent;
- ExprBits.ValueDependent = ValueDependent;
- ExprBits.InstantiationDependent = InstantiationDependent;
+ Expr **SaveElements = getElements();
+ for (unsigned I = 0, N = Elements.size(); I != N; ++I) {
+ if (Elements[I]->isTypeDependent() || Elements[I]->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (Elements[I]->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (Elements[I]->containsUnexpandedParameterPack())
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ SaveElements[I] = Elements[I];
+ }
}
+ObjCArrayLiteral *ObjCArrayLiteral::Create(ASTContext &C,
+ llvm::ArrayRef<Expr *> Elements,
+ QualType T, ObjCMethodDecl * Method,
+ SourceRange SR) {
+ void *Mem = C.Allocate(sizeof(ObjCArrayLiteral)
+ + Elements.size() * sizeof(Expr *));
+ return new (Mem) ObjCArrayLiteral(Elements, T, Method, SR);
+}
+
+ObjCArrayLiteral *ObjCArrayLiteral::CreateEmpty(ASTContext &C,
+ unsigned NumElements) {
+
+ void *Mem = C.Allocate(sizeof(ObjCArrayLiteral)
+ + NumElements * sizeof(Expr *));
+ return new (Mem) ObjCArrayLiteral(EmptyShell(), NumElements);
+}
+
+ObjCDictionaryLiteral::ObjCDictionaryLiteral(
+ ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions,
+ QualType T, ObjCMethodDecl *method,
+ SourceRange SR)
+ : Expr(ObjCDictionaryLiteralClass, T, VK_RValue, OK_Ordinary, false, false,
+ false, false),
+ NumElements(VK.size()), HasPackExpansions(HasPackExpansions), Range(SR),
+ DictWithObjectsMethod(method)
+{
+ KeyValuePair *KeyValues = getKeyValues();
+ ExpansionData *Expansions = getExpansionData();
+ for (unsigned I = 0; I < NumElements; I++) {
+ if (VK[I].Key->isTypeDependent() || VK[I].Key->isValueDependent() ||
+ VK[I].Value->isTypeDependent() || VK[I].Value->isValueDependent())
+ ExprBits.ValueDependent = true;
+ if (VK[I].Key->isInstantiationDependent() ||
+ VK[I].Value->isInstantiationDependent())
+ ExprBits.InstantiationDependent = true;
+ if (VK[I].EllipsisLoc.isInvalid() &&
+ (VK[I].Key->containsUnexpandedParameterPack() ||
+ VK[I].Value->containsUnexpandedParameterPack()))
+ ExprBits.ContainsUnexpandedParameterPack = true;
+
+ KeyValues[I].Key = VK[I].Key;
+ KeyValues[I].Value = VK[I].Value;
+ if (Expansions) {
+ Expansions[I].EllipsisLoc = VK[I].EllipsisLoc;
+ if (VK[I].NumExpansions)
+ Expansions[I].NumExpansionsPlusOne = *VK[I].NumExpansions + 1;
+ else
+ Expansions[I].NumExpansionsPlusOne = 0;
+ }
+ }
+}
+
+ObjCDictionaryLiteral *
+ObjCDictionaryLiteral::Create(ASTContext &C,
+ ArrayRef<ObjCDictionaryElement> VK,
+ bool HasPackExpansions,
+ QualType T, ObjCMethodDecl *method,
+ SourceRange SR) {
+ unsigned ExpansionsSize = 0;
+ if (HasPackExpansions)
+ ExpansionsSize = sizeof(ExpansionData) * VK.size();
+
+ void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) +
+ sizeof(KeyValuePair) * VK.size() + ExpansionsSize);
+ return new (Mem) ObjCDictionaryLiteral(VK, HasPackExpansions, T, method, SR);
+}
+
+ObjCDictionaryLiteral *
+ObjCDictionaryLiteral::CreateEmpty(ASTContext &C, unsigned NumElements,
+ bool HasPackExpansions) {
+ unsigned ExpansionsSize = 0;
+ if (HasPackExpansions)
+ ExpansionsSize = sizeof(ExpansionData) * NumElements;
+ void *Mem = C.Allocate(sizeof(ObjCDictionaryLiteral) +
+ sizeof(KeyValuePair) * NumElements + ExpansionsSize);
+ return new (Mem) ObjCDictionaryLiteral(EmptyShell(), NumElements,
+ HasPackExpansions);
+}
+
+ObjCSubscriptRefExpr *ObjCSubscriptRefExpr::Create(ASTContext &C,
+ Expr *base,
+ Expr *key, QualType T,
+ ObjCMethodDecl *getMethod,
+ ObjCMethodDecl *setMethod,
+ SourceLocation RB) {
+ void *Mem = C.Allocate(sizeof(ObjCSubscriptRefExpr));
+ return new (Mem) ObjCSubscriptRefExpr(base, key, T, VK_LValue,
+ OK_ObjCSubscript,
+ getMethod, setMethod, RB);
+}
AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr,
QualType t, AtomicOp op, SourceLocation RP)
@@ -3323,6 +3841,7 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr,
false, false, false, false),
NumSubExprs(nexpr), BuiltinLoc(BLoc), RParenLoc(RP), Op(op)
{
+ assert(nexpr == getNumSubExprs(op) && "wrong number of subexpressions");
for (unsigned i = 0; i < nexpr; i++) {
if (args[i]->isTypeDependent())
ExprBits.TypeDependent = true;
@@ -3336,3 +3855,49 @@ AtomicExpr::AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr,
SubExprs[i] = args[i];
}
}
+
+unsigned AtomicExpr::getNumSubExprs(AtomicOp Op) {
+ switch (Op) {
+ case AO__c11_atomic_init:
+ case AO__c11_atomic_load:
+ case AO__atomic_load_n:
+ return 2;
+
+ case AO__c11_atomic_store:
+ case AO__c11_atomic_exchange:
+ case AO__atomic_load:
+ case AO__atomic_store:
+ case AO__atomic_store_n:
+ case AO__atomic_exchange_n:
+ case AO__c11_atomic_fetch_add:
+ case AO__c11_atomic_fetch_sub:
+ case AO__c11_atomic_fetch_and:
+ case AO__c11_atomic_fetch_or:
+ case AO__c11_atomic_fetch_xor:
+ case AO__atomic_fetch_add:
+ case AO__atomic_fetch_sub:
+ case AO__atomic_fetch_and:
+ case AO__atomic_fetch_or:
+ case AO__atomic_fetch_xor:
+ case AO__atomic_fetch_nand:
+ case AO__atomic_add_fetch:
+ case AO__atomic_sub_fetch:
+ case AO__atomic_and_fetch:
+ case AO__atomic_or_fetch:
+ case AO__atomic_xor_fetch:
+ case AO__atomic_nand_fetch:
+ return 3;
+
+ case AO__atomic_exchange:
+ return 4;
+
+ case AO__c11_atomic_compare_exchange_strong:
+ case AO__c11_atomic_compare_exchange_weak:
+ return 5;
+
+ case AO__atomic_compare_exchange:
+ case AO__atomic_compare_exchange_n:
+ return 6;
+ }
+ llvm_unreachable("unknown atomic op");
+}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index ad5ec8b8331a..8cf519c93dc2 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -45,30 +45,26 @@ SourceRange CXXScalarValueInitExpr::getSourceRange() const {
// CXXNewExpr
CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
- Expr **placementArgs, unsigned numPlaceArgs,
- SourceRange TypeIdParens, Expr *arraySize,
- CXXConstructorDecl *constructor, bool initializer,
- Expr **constructorArgs, unsigned numConsArgs,
- bool HadMultipleCandidates,
FunctionDecl *operatorDelete,
- bool usualArrayDeleteWantsSize, QualType ty,
- TypeSourceInfo *AllocatedTypeInfo,
- SourceLocation startLoc, SourceLocation endLoc,
- SourceLocation constructorLParen,
- SourceLocation constructorRParen)
+ bool usualArrayDeleteWantsSize,
+ Expr **placementArgs, unsigned numPlaceArgs,
+ SourceRange typeIdParens, Expr *arraySize,
+ InitializationStyle initializationStyle,
+ Expr *initializer, QualType ty,
+ TypeSourceInfo *allocatedTypeInfo,
+ SourceLocation startLoc, SourceRange directInitRange)
: Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary,
ty->isDependentType(), ty->isDependentType(),
ty->isInstantiationDependentType(),
ty->containsUnexpandedParameterPack()),
- GlobalNew(globalNew), Initializer(initializer),
- UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize),
- HadMultipleCandidates(HadMultipleCandidates),
- SubExprs(0), OperatorNew(operatorNew),
- OperatorDelete(operatorDelete), Constructor(constructor),
- AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens),
- StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen),
- ConstructorRParen(constructorRParen) {
- AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs);
+ SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete),
+ AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens),
+ StartLoc(startLoc), DirectInitRange(directInitRange),
+ GlobalNew(globalNew), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {
+ assert((initializer != 0 || initializationStyle == NoInit) &&
+ "Only NoInit can have no initializer.");
+ StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;
+ AllocateArgsArray(C, arraySize != 0, numPlaceArgs, initializer != 0);
unsigned i = 0;
if (Array) {
if (arraySize->isInstantiationDependent())
@@ -80,33 +76,33 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
SubExprs[i++] = arraySize;
}
- for (unsigned j = 0; j < NumPlacementArgs; ++j) {
- if (placementArgs[j]->isInstantiationDependent())
+ if (initializer) {
+ if (initializer->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
- if (placementArgs[j]->containsUnexpandedParameterPack())
+
+ if (initializer->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- SubExprs[i++] = placementArgs[j];
+ SubExprs[i++] = initializer;
}
- for (unsigned j = 0; j < NumConstructorArgs; ++j) {
- if (constructorArgs[j]->isInstantiationDependent())
+ for (unsigned j = 0; j < NumPlacementArgs; ++j) {
+ if (placementArgs[j]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
- if (constructorArgs[j]->containsUnexpandedParameterPack())
+ if (placementArgs[j]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
- SubExprs[i++] = constructorArgs[j];
+ SubExprs[i++] = placementArgs[j];
}
}
void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray,
- unsigned numPlaceArgs, unsigned numConsArgs){
+ unsigned numPlaceArgs, bool hasInitializer){
assert(SubExprs == 0 && "SubExprs already allocated");
Array = isArray;
NumPlacementArgs = numPlaceArgs;
- NumConstructorArgs = numConsArgs;
-
- unsigned TotalSize = Array + NumPlacementArgs + NumConstructorArgs;
+
+ unsigned TotalSize = Array + hasInitializer + NumPlacementArgs;
SubExprs = new (C) Stmt*[TotalSize];
}
@@ -115,6 +111,18 @@ bool CXXNewExpr::shouldNullCheckAllocation(ASTContext &Ctx) const {
castAs<FunctionProtoType>()->isNothrow(Ctx);
}
+SourceLocation CXXNewExpr::getEndLoc() const {
+ switch (getInitializationStyle()) {
+ case NoInit:
+ return AllocatedTypeInfo->getTypeLoc().getEndLoc();
+ case CallInit:
+ return DirectInitRange.getEnd();
+ case ListInit:
+ return getInitializer()->getSourceRange().getEnd();
+ }
+ llvm_unreachable("bogus initialization style");
+}
+
// CXXDeleteExpr
QualType CXXDeleteExpr::getDestroyedType() const {
const Expr *Arg = getArgument();
@@ -191,40 +199,45 @@ SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
return SourceRange(Base->getLocStart(), End);
}
-
// UnresolvedLookupExpr
UnresolvedLookupExpr *
UnresolvedLookupExpr::Create(ASTContext &C,
CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
bool ADL,
- const TemplateArgumentListInfo &Args,
- UnresolvedSetIterator Begin,
- UnresolvedSetIterator End)
+ const TemplateArgumentListInfo *Args,
+ UnresolvedSetIterator Begin,
+ UnresolvedSetIterator End)
{
- void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) +
- ASTTemplateArgumentListInfo::sizeFor(Args));
- return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo,
- ADL, /*Overload*/ true, &Args,
+ assert(Args || TemplateKWLoc.isValid());
+ unsigned num_args = Args ? Args->size() : 0;
+ void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) +
+ ASTTemplateKWAndArgsInfo::sizeFor(num_args));
+ return new (Mem) UnresolvedLookupExpr(C, NamingClass, QualifierLoc,
+ TemplateKWLoc, NameInfo,
+ ADL, /*Overload*/ true, Args,
Begin, End, /*StdIsAssociated=*/false);
}
UnresolvedLookupExpr *
-UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs,
+UnresolvedLookupExpr::CreateEmpty(ASTContext &C,
+ bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(UnresolvedLookupExpr);
- if (HasExplicitTemplateArgs)
- size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
+ if (HasTemplateKWAndArgsInfo)
+ size += ASTTemplateKWAndArgsInfo::sizeFor(NumTemplateArgs);
void *Mem = C.Allocate(size, llvm::alignOf<UnresolvedLookupExpr>());
UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell());
- E->HasExplicitTemplateArgs = HasExplicitTemplateArgs;
+ E->HasTemplateKWAndArgsInfo = HasTemplateKWAndArgsInfo;
return E;
}
OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin,
@@ -243,8 +256,9 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
(QualifierLoc &&
QualifierLoc.getNestedNameSpecifier()
->containsUnexpandedParameterPack()))),
- Results(0), NumResults(End - Begin), NameInfo(NameInfo),
- QualifierLoc(QualifierLoc), HasExplicitTemplateArgs(TemplateArgs != 0)
+ NameInfo(NameInfo), QualifierLoc(QualifierLoc),
+ Results(0), NumResults(End - Begin),
+ HasTemplateKWAndArgsInfo(TemplateArgs != 0 || TemplateKWLoc.isValid())
{
NumResults = End - Begin;
if (NumResults) {
@@ -271,9 +285,10 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
bool Dependent = false;
bool InstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent,
- InstantiationDependent,
- ContainsUnexpandedParameterPack);
+ getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *TemplateArgs,
+ Dependent,
+ InstantiationDependent,
+ ContainsUnexpandedParameterPack);
if (Dependent) {
ExprBits.TypeDependent = true;
@@ -283,6 +298,8 @@ OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C,
ExprBits.InstantiationDependent = true;
if (ContainsUnexpandedParameterPack)
ExprBits.ContainsUnexpandedParameterPack = true;
+ } else if (TemplateKWLoc.isValid()) {
+ getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
if (isTypeDependent())
@@ -314,6 +331,7 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const {
// DependentScopeDeclRefExpr
DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args)
: Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary,
@@ -326,47 +344,52 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
QualifierLoc.getNestedNameSpecifier()
->containsUnexpandedParameterPack()))),
QualifierLoc(QualifierLoc), NameInfo(NameInfo),
- HasExplicitTemplateArgs(Args != 0)
+ HasTemplateKWAndArgsInfo(Args != 0 || TemplateKWLoc.isValid())
{
if (Args) {
bool Dependent = true;
bool InstantiationDependent = true;
bool ContainsUnexpandedParameterPack
= ExprBits.ContainsUnexpandedParameterPack;
-
- reinterpret_cast<ASTTemplateArgumentListInfo*>(this+1)
- ->initializeFrom(*Args, Dependent, InstantiationDependent,
- ContainsUnexpandedParameterPack);
-
+ getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc, *Args,
+ Dependent,
+ InstantiationDependent,
+ ContainsUnexpandedParameterPack);
ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
+ } else if (TemplateKWLoc.isValid()) {
+ getTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
}
}
DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::Create(ASTContext &C,
NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *Args) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
if (Args)
- size += ASTTemplateArgumentListInfo::sizeFor(*Args);
+ size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size());
+ else if (TemplateKWLoc.isValid())
+ size += ASTTemplateKWAndArgsInfo::sizeFor(0);
void *Mem = C.Allocate(size);
- return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
- NameInfo, Args);
+ return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, QualifierLoc,
+ TemplateKWLoc, NameInfo, Args);
}
DependentScopeDeclRefExpr *
DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C,
- bool HasExplicitTemplateArgs,
+ bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs) {
std::size_t size = sizeof(DependentScopeDeclRefExpr);
- if (HasExplicitTemplateArgs)
- size += ASTTemplateArgumentListInfo::sizeFor(NumTemplateArgs);
+