From bca07a4524feb4edec581062d631a13116320a24 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 20 Feb 2011 13:06:31 +0000 Subject: Vendor import of clang trunk r126079: http://llvm.org/svn/llvm-project/cfe/trunk@126079 --- lib/AST/ASTContext.cpp | 1999 +++++---- lib/AST/ASTDiagnostic.cpp | 56 +- lib/AST/ASTImporter.cpp | 1353 +++++- lib/AST/CMakeLists.txt | 9 +- lib/AST/CXXABI.h | 9 + lib/AST/CXXInheritance.cpp | 57 +- lib/AST/Decl.cpp | 927 +++- lib/AST/DeclBase.cpp | 118 +- lib/AST/DeclCXX.cpp | 719 +++- lib/AST/DeclObjC.cpp | 57 +- lib/AST/DeclPrinter.cpp | 83 +- lib/AST/DeclTemplate.cpp | 363 +- lib/AST/DeclarationName.cpp | 31 +- lib/AST/DumpXML.cpp | 1028 +++++ lib/AST/Expr.cpp | 1336 ++++-- lib/AST/ExprCXX.cpp | 835 ++-- lib/AST/ExprClassification.cpp | 194 +- lib/AST/ExprConstant.cpp | 727 +++- lib/AST/FullExpr.cpp | 45 - lib/AST/InheritViz.cpp | 39 +- lib/AST/ItaniumCXXABI.cpp | 21 + lib/AST/ItaniumMangle.cpp | 2705 ++++++++++++ lib/AST/Mangle.cpp | 135 + lib/AST/MicrosoftCXXABI.cpp | 25 +- lib/AST/MicrosoftMangle.cpp | 1188 +++++ lib/AST/NestedNameSpecifier.cpp | 42 +- lib/AST/ParentMap.cpp | 17 +- lib/AST/RecordLayout.cpp | 30 +- lib/AST/RecordLayoutBuilder.cpp | 649 +-- lib/AST/Stmt.cpp | 256 +- lib/AST/StmtDumper.cpp | 172 +- lib/AST/StmtIterator.cpp | 18 +- lib/AST/StmtPrinter.cpp | 155 +- lib/AST/StmtProfile.cpp | 99 +- lib/AST/TemplateBase.cpp | 356 +- lib/AST/TemplateName.cpp | 57 +- lib/AST/Type.cpp | 911 ++-- lib/AST/TypeLoc.cpp | 53 +- lib/AST/TypePrinter.cpp | 521 ++- lib/Analysis/AnalysisContext.cpp | 27 +- lib/Analysis/CFG.cpp | 1816 ++++++-- lib/Analysis/CFGStmtMap.cpp | 19 +- lib/Analysis/CMakeLists.txt | 4 +- lib/Analysis/CocoaConventions.cpp | 180 + lib/Analysis/FormatString.cpp | 4 +- lib/Analysis/LiveVariables.cpp | 12 +- lib/Analysis/PrintfFormatString.cpp | 54 +- lib/Analysis/PseudoConstantAnalysis.cpp | 10 +- lib/Analysis/ReachableCode.cpp | 44 +- lib/Analysis/UninitializedValues.cpp | 23 +- lib/Analysis/UninitializedValuesV2.cpp | 610 +++ lib/Basic/Builtins.cpp | 24 +- lib/Basic/CMakeLists.txt | 8 +- lib/Basic/Diagnostic.cpp | 914 +--- lib/Basic/DiagnosticIDs.cpp | 586 +++ lib/Basic/FileManager.cpp | 464 +- lib/Basic/FileSystemStatCache.cpp | 120 + lib/Basic/IdentifierTable.cpp | 31 +- lib/Basic/Makefile | 8 +- lib/Basic/SourceLocation.cpp | 10 + lib/Basic/SourceManager.cpp | 350 +- lib/Basic/TargetInfo.cpp | 52 +- lib/Basic/Targets.cpp | 409 +- lib/Basic/Version.cpp | 62 +- lib/CMakeLists.txt | 2 +- lib/Checker/AdjustedReturnValueChecker.cpp | 95 - lib/Checker/AggExprVisitor.cpp | 62 - lib/Checker/AnalysisConsumer.cpp | 598 --- lib/Checker/AnalysisManager.cpp | 31 - lib/Checker/ArrayBoundChecker.cpp | 91 - lib/Checker/AttrNonNullChecker.cpp | 113 - lib/Checker/BasicConstraintManager.cpp | 333 -- lib/Checker/BasicObjCFoundationChecks.cpp | 585 --- lib/Checker/BasicObjCFoundationChecks.h | 38 - lib/Checker/BasicStore.cpp | 580 --- lib/Checker/BasicValueFactory.cpp | 289 -- lib/Checker/BugReporter.cpp | 1873 -------- lib/Checker/BugReporterVisitors.cpp | 458 -- lib/Checker/BuiltinFunctionChecker.cpp | 84 - lib/Checker/CFRefCount.cpp | 3521 --------------- lib/Checker/CMakeLists.txt | 84 - lib/Checker/CStringChecker.cpp | 1055 ----- lib/Checker/CallAndMessageChecker.cpp | 346 -- lib/Checker/CastSizeChecker.cpp | 91 - lib/Checker/CastToStructChecker.cpp | 78 - lib/Checker/CheckDeadStores.cpp | 289 -- lib/Checker/CheckObjCDealloc.cpp | 261 -- lib/Checker/CheckObjCInstMethSignature.cpp | 119 - lib/Checker/CheckSecuritySyntaxOnly.cpp | 494 --- lib/Checker/CheckSizeofPointer.cpp | 71 - lib/Checker/Checker.cpp | 35 - lib/Checker/CheckerHelpers.cpp | 80 - lib/Checker/CocoaConventions.cpp | 196 - lib/Checker/DereferenceChecker.cpp | 156 - lib/Checker/DivZeroChecker.cpp | 85 - lib/Checker/Environment.cpp | 228 - lib/Checker/ExplodedGraph.cpp | 281 -- lib/Checker/FixedAddressChecker.cpp | 71 - lib/Checker/FlatStore.cpp | 202 - lib/Checker/FrontendActions.cpp | 21 - lib/Checker/GRBlockCounter.cpp | 85 - lib/Checker/GRCXXExprEngine.cpp | 240 -- lib/Checker/GRCoreEngine.cpp | 770 ---- lib/Checker/GRExprEngine.cpp | 3730 ---------------- lib/Checker/GRExprEngineExperimentalChecks.cpp | 44 - lib/Checker/GRExprEngineExperimentalChecks.h | 30 - lib/Checker/GRExprEngineInternalChecks.h | 52 - lib/Checker/GRState.cpp | 549 --- lib/Checker/HTMLDiagnostics.cpp | 577 --- lib/Checker/IdempotentOperationChecker.cpp | 703 --- lib/Checker/LLVMConventionsChecker.cpp | 312 -- lib/Checker/MacOSXAPIChecker.cpp | 141 - lib/Checker/Makefile | 18 - lib/Checker/MallocChecker.cpp | 736 ---- lib/Checker/ManagerRegistry.cpp | 20 - lib/Checker/MemRegion.cpp | 957 ----- lib/Checker/NSAutoreleasePoolChecker.cpp | 86 - lib/Checker/NSErrorChecker.cpp | 237 - lib/Checker/NoReturnFunctionChecker.cpp | 79 - lib/Checker/OSAtomicChecker.cpp | 202 - lib/Checker/ObjCUnusedIVarsChecker.cpp | 161 - lib/Checker/PathDiagnostic.cpp | 274 -- lib/Checker/PlistDiagnostics.cpp | 471 -- lib/Checker/PointerArithChecker.cpp | 71 - lib/Checker/PointerSubChecker.cpp | 78 - lib/Checker/PthreadLockChecker.cpp | 141 - lib/Checker/RangeConstraintManager.cpp | 439 -- lib/Checker/RegionStore.cpp | 1816 -------- lib/Checker/ReturnPointerRangeChecker.cpp | 97 - lib/Checker/ReturnUndefChecker.cpp | 68 - lib/Checker/SVals.cpp | 354 -- lib/Checker/SValuator.cpp | 157 - lib/Checker/SimpleConstraintManager.cpp | 299 -- lib/Checker/SimpleConstraintManager.h | 89 - lib/Checker/SimpleSValuator.cpp | 891 ---- lib/Checker/StackAddrLeakChecker.cpp | 204 - lib/Checker/Store.cpp | 332 -- lib/Checker/StreamChecker.cpp | 468 -- lib/Checker/SymbolManager.cpp | 342 -- lib/Checker/UndefBranchChecker.cpp | 119 - lib/Checker/UndefCapturedBlockVarChecker.cpp | 101 - lib/Checker/UndefResultChecker.cpp | 86 - lib/Checker/UndefinedArraySubscriptChecker.cpp | 56 - lib/Checker/UndefinedAssignmentChecker.cpp | 93 - lib/Checker/UnixAPIChecker.cpp | 222 - lib/Checker/UnreachableCodeChecker.cpp | 226 - lib/Checker/VLASizeChecker.cpp | 135 - lib/Checker/ValueManager.cpp | 162 - lib/CodeGen/ABIInfo.h | 31 +- lib/CodeGen/BackendUtil.cpp | 42 +- lib/CodeGen/CGBlocks.cpp | 1806 ++++---- lib/CodeGen/CGBlocks.h | 253 +- lib/CodeGen/CGBuiltin.cpp | 680 ++- lib/CodeGen/CGCXX.cpp | 251 +- lib/CodeGen/CGCXX.h | 36 - lib/CodeGen/CGCXXABI.cpp | 174 + lib/CodeGen/CGCXXABI.h | 28 +- lib/CodeGen/CGCall.cpp | 157 +- lib/CodeGen/CGClass.cpp | 188 +- lib/CodeGen/CGCleanup.cpp | 1144 +++++ lib/CodeGen/CGCleanup.h | 560 +++ lib/CodeGen/CGDebugInfo.cpp | 1006 +++-- lib/CodeGen/CGDebugInfo.h | 56 +- lib/CodeGen/CGDecl.cpp | 349 +- lib/CodeGen/CGDeclCXX.cpp | 194 +- lib/CodeGen/CGException.cpp | 442 +- lib/CodeGen/CGException.h | 558 +-- lib/CodeGen/CGExpr.cpp | 662 ++- lib/CodeGen/CGExprAgg.cpp | 480 ++- lib/CodeGen/CGExprCXX.cpp | 488 ++- lib/CodeGen/CGExprComplex.cpp | 293 +- lib/CodeGen/CGExprConstant.cpp | 286 +- lib/CodeGen/CGExprScalar.cpp | 937 ++-- lib/CodeGen/CGObjC.cpp | 675 +-- lib/CodeGen/CGObjCGNU.cpp | 107 +- lib/CodeGen/CGObjCMac.cpp | 252 +- lib/CodeGen/CGObjCRuntime.h | 12 +- lib/CodeGen/CGRTTI.cpp | 276 +- lib/CodeGen/CGRecordLayout.h | 69 +- lib/CodeGen/CGRecordLayoutBuilder.cpp | 613 ++- lib/CodeGen/CGStmt.cpp | 228 +- lib/CodeGen/CGTemporaries.cpp | 70 +- lib/CodeGen/CGVTT.cpp | 88 +- lib/CodeGen/CGVTables.cpp | 262 +- lib/CodeGen/CGVTables.h | 126 +- lib/CodeGen/CGValue.h | 132 +- lib/CodeGen/CMakeLists.txt | 13 +- lib/CodeGen/CodeGenAction.cpp | 64 +- lib/CodeGen/CodeGenFunction.cpp | 899 +--- lib/CodeGen/CodeGenFunction.h | 815 +++- lib/CodeGen/CodeGenModule.cpp | 527 ++- lib/CodeGen/CodeGenModule.h | 168 +- lib/CodeGen/CodeGenTBAA.cpp | 180 + lib/CodeGen/CodeGenTBAA.h | 76 + lib/CodeGen/CodeGenTypes.cpp | 69 +- lib/CodeGen/CodeGenTypes.h | 20 +- lib/CodeGen/GlobalDecl.h | 8 +- lib/CodeGen/ItaniumCXXABI.cpp | 309 +- lib/CodeGen/Mangle.cpp | 2515 ----------- lib/CodeGen/Mangle.h | 177 - lib/CodeGen/MicrosoftCXXABI.cpp | 1178 +---- lib/CodeGen/ModuleBuilder.cpp | 13 + lib/CodeGen/TargetInfo.cpp | 414 +- lib/CodeGen/TargetInfo.h | 9 + lib/Driver/Action.cpp | 2 +- lib/Driver/Arg.cpp | 2 +- lib/Driver/ArgList.cpp | 40 +- lib/Driver/CMakeLists.txt | 2 +- lib/Driver/Compilation.cpp | 20 +- lib/Driver/Driver.cpp | 153 +- lib/Driver/DriverOptions.cpp | 2 +- lib/Driver/HostInfo.cpp | 68 +- lib/Driver/Job.cpp | 2 +- lib/Driver/OptTable.cpp | 5 +- lib/Driver/Option.cpp | 2 +- lib/Driver/Phases.cpp | 2 +- lib/Driver/Tool.cpp | 2 +- lib/Driver/ToolChain.cpp | 55 +- lib/Driver/ToolChains.cpp | 516 ++- lib/Driver/ToolChains.h | 52 +- lib/Driver/Tools.cpp | 1025 ++++- lib/Driver/Tools.h | 45 +- lib/Driver/Types.cpp | 4 +- lib/Frontend/ASTConsumers.cpp | 40 +- lib/Frontend/ASTMerge.cpp | 21 +- lib/Frontend/ASTUnit.cpp | 770 ++-- lib/Frontend/CMakeLists.txt | 13 +- lib/Frontend/CacheTokens.cpp | 46 +- lib/Frontend/CompilerInstance.cpp | 221 +- lib/Frontend/CompilerInvocation.cpp | 334 +- lib/Frontend/DeclXML.cpp | 20 +- lib/Frontend/DependencyFile.cpp | 25 +- lib/Frontend/DocumentXML.cpp | 19 +- lib/Frontend/FrontendAction.cpp | 125 +- lib/Frontend/FrontendActions.cpp | 33 +- lib/Frontend/FrontendOptions.cpp | 1 + lib/Frontend/HeaderIncludeGen.cpp | 113 + lib/Frontend/InitHeaderSearch.cpp | 230 +- lib/Frontend/InitPreprocessor.cpp | 22 +- lib/Frontend/MultiplexConsumer.cpp | 221 + lib/Frontend/PrintPreprocessedOutput.cpp | 114 +- lib/Frontend/StmtXML.cpp | 16 +- lib/Frontend/TextDiagnosticBuffer.cpp | 3 + lib/Frontend/TextDiagnosticPrinter.cpp | 186 +- lib/Frontend/TypeXML.cpp | 6 +- lib/Frontend/VerifyDiagnosticsClient.cpp | 10 +- lib/FrontendTool/CMakeLists.txt | 3 +- lib/FrontendTool/ExecuteCompilerInvocation.cpp | 10 +- lib/Headers/CMakeLists.txt | 47 +- lib/Headers/altivec.h | 2454 +++++++++-- lib/Headers/emmintrin.h | 15 +- lib/Headers/limits.h | 6 +- lib/Headers/mm_malloc.h | 47 +- lib/Headers/mmintrin.h | 84 +- lib/Headers/stdbool.h | 8 +- lib/Headers/stddef.h | 17 +- lib/Headers/xmmintrin.h | 8 +- lib/Index/ASTVisitor.h | 3 +- lib/Index/CMakeLists.txt | 5 +- lib/Index/CallGraph.cpp | 2 +- lib/Lex/CMakeLists.txt | 8 +- lib/Lex/HeaderMap.cpp | 10 +- lib/Lex/HeaderSearch.cpp | 44 +- lib/Lex/Lexer.cpp | 230 +- lib/Lex/LiteralSupport.cpp | 275 +- lib/Lex/MacroInfo.cpp | 3 +- lib/Lex/PPDirectives.cpp | 212 +- lib/Lex/PPExpressions.cpp | 51 +- lib/Lex/PPLexerChange.cpp | 14 +- lib/Lex/PPMacroExpansion.cpp | 152 +- lib/Lex/PTHLexer.cpp | 44 +- lib/Lex/Pragma.cpp | 208 +- lib/Lex/PreprocessingRecord.cpp | 62 +- lib/Lex/Preprocessor.cpp | 227 +- lib/Lex/TokenConcatenation.cpp | 10 +- lib/Lex/TokenLexer.cpp | 11 +- lib/Makefile | 2 +- lib/Parse/CMakeLists.txt | 2 +- lib/Parse/ParseAST.cpp | 24 - lib/Parse/ParseCXXInlineMethods.cpp | 313 +- lib/Parse/ParseDecl.cpp | 681 +-- lib/Parse/ParseDeclCXX.cpp | 524 ++- lib/Parse/ParseExpr.cpp | 527 ++- lib/Parse/ParseExprCXX.cpp | 160 +- lib/Parse/ParseInit.cpp | 15 +- lib/Parse/ParseObjc.cpp | 281 +- lib/Parse/ParsePragma.cpp | 113 +- lib/Parse/ParsePragma.h | 40 +- lib/Parse/ParseStmt.cpp | 326 +- lib/Parse/ParseTemplate.cpp | 97 +- lib/Parse/ParseTentative.cpp | 236 +- lib/Parse/Parser.cpp | 208 +- lib/Parse/RAIIObjectsForParser.h | 16 + lib/Rewrite/CMakeLists.txt | 4 +- lib/Rewrite/FixItRewriter.cpp | 7 +- lib/Rewrite/FrontendActions.cpp | 13 +- lib/Rewrite/HTMLRewrite.cpp | 25 +- lib/Rewrite/RewriteMacros.cpp | 4 +- lib/Rewrite/RewriteObjC.cpp | 873 ++-- lib/Rewrite/RewriteRope.cpp | 6 +- lib/Rewrite/TokenRewriter.cpp | 6 +- lib/Sema/AnalysisBasedWarnings.cpp | 208 +- lib/Sema/AttributeList.cpp | 51 +- lib/Sema/CMakeLists.txt | 3 +- lib/Sema/CodeCompleteConsumer.cpp | 353 +- lib/Sema/DeclSpec.cpp | 114 +- lib/Sema/JumpDiagnostics.cpp | 62 +- lib/Sema/Sema.cpp | 267 +- lib/Sema/SemaAccess.cpp | 95 +- lib/Sema/SemaAttr.cpp | 81 +- lib/Sema/SemaCXXCast.cpp | 496 ++- lib/Sema/SemaCXXScopeSpec.cpp | 30 +- lib/Sema/SemaChecking.cpp | 806 ++-- lib/Sema/SemaCodeComplete.cpp | 3317 +++++++++----- lib/Sema/SemaDecl.cpp | 2813 +++++++----- lib/Sema/SemaDeclAttr.cpp | 1150 +++-- lib/Sema/SemaDeclCXX.cpp | 1969 ++++++--- lib/Sema/SemaDeclObjC.cpp | 354 +- lib/Sema/SemaExceptionSpec.cpp | 37 +- lib/Sema/SemaExpr.cpp | 4525 ++++++++++++++------ lib/Sema/SemaExprCXX.cpp | 1736 ++++++-- lib/Sema/SemaExprObjC.cpp | 378 +- lib/Sema/SemaInit.cpp | 1322 +++--- lib/Sema/SemaLookup.cpp | 1007 +++-- lib/Sema/SemaObjCProperty.cpp | 218 +- lib/Sema/SemaOverload.cpp | 3984 ++++++++++------- lib/Sema/SemaStmt.cpp | 561 ++- lib/Sema/SemaTemplate.cpp | 2333 ++++++---- lib/Sema/SemaTemplateDeduction.cpp | 2648 ++++++++---- lib/Sema/SemaTemplateInstantiate.cpp | 858 +++- lib/Sema/SemaTemplateInstantiateDecl.cpp | 874 ++-- lib/Sema/SemaTemplateVariadic.cpp | 748 ++++ lib/Sema/SemaType.cpp | 1532 +++++-- lib/Sema/TargetAttributesSema.cpp | 55 +- lib/Sema/TreeTransform.h | 3031 ++++++++----- lib/Sema/TypeLocBuilder.h | 180 + lib/Serialization/ASTCommon.cpp | 10 +- lib/Serialization/ASTCommon.h | 8 +- lib/Serialization/ASTReader.cpp | 1848 +++++--- lib/Serialization/ASTReaderDecl.cpp | 849 ++-- lib/Serialization/ASTReaderStmt.cpp | 727 ++-- lib/Serialization/ASTWriter.cpp | 1154 ++++- lib/Serialization/ASTWriterDecl.cpp | 260 +- lib/Serialization/ASTWriterStmt.cpp | 277 +- lib/Serialization/CMakeLists.txt | 3 +- lib/Serialization/GeneratePCH.cpp | 24 +- lib/StaticAnalyzer/CMakeLists.txt | 3 + .../Checkers/AdjustedReturnValueChecker.cpp | 96 + .../Checkers/AnalyzerStatsChecker.cpp | 123 + lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp | 92 + .../Checkers/ArrayBoundCheckerV2.cpp | 277 ++ lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp | 136 + .../Checkers/BasicObjCFoundationChecks.cpp | 521 +++ .../Checkers/BasicObjCFoundationChecks.h | 35 + .../Checkers/BuiltinFunctionChecker.cpp | 83 + lib/StaticAnalyzer/Checkers/CMakeLists.txt | 70 + lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 1053 +++++ .../Checkers/CallAndMessageChecker.cpp | 358 ++ lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp | 91 + .../Checkers/CastToStructChecker.cpp | 84 + lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp | 284 ++ .../Checkers/CheckObjCInstMethSignature.cpp | 140 + .../Checkers/CheckSecuritySyntaxOnly.cpp | 517 +++ lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp | 87 + lib/StaticAnalyzer/Checkers/Checkers.td | 197 + lib/StaticAnalyzer/Checkers/ChrootChecker.cpp | 167 + .../Checkers/ClangSACheckerProvider.cpp | 137 + .../Checkers/ClangSACheckerProvider.h | 29 + lib/StaticAnalyzer/Checkers/ClangSACheckers.h | 34 + lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp | 363 ++ lib/StaticAnalyzer/Checkers/DebugCheckers.cpp | 80 + lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp | 205 + lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp | 86 + lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp | 37 + lib/StaticAnalyzer/Checkers/ExperimentalChecks.h | 31 + lib/StaticAnalyzer/Checkers/ExprEngine.cpp | 3655 ++++++++++++++++ .../Checkers/FixedAddressChecker.cpp | 77 + .../Checkers/IdempotentOperationChecker.cpp | 822 ++++ lib/StaticAnalyzer/Checkers/InternalChecks.h | 51 + .../Checkers/LLVMConventionsChecker.cpp | 311 ++ lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp | 146 + lib/StaticAnalyzer/Checkers/Makefile | 24 + lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 731 ++++ .../Checkers/NSAutoreleasePoolChecker.cpp | 92 + lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp | 238 + .../Checkers/NoReturnFunctionChecker.cpp | 80 + lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp | 203 + lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp | 100 + .../Checkers/ObjCSelfInitChecker.cpp | 356 ++ .../Checkers/ObjCUnusedIVarsChecker.cpp | 184 + .../Checkers/PointerArithChecker.cpp | 77 + lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp | 84 + lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp | 152 + .../Checkers/ReturnPointerRangeChecker.cpp | 95 + lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp | 69 + .../Checkers/StackAddrLeakChecker.cpp | 210 + lib/StaticAnalyzer/Checkers/StreamChecker.cpp | 470 ++ lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp | 120 + .../Checkers/UndefCapturedBlockVarChecker.cpp | 102 + lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp | 87 + .../Checkers/UndefinedArraySubscriptChecker.cpp | 57 + .../Checkers/UndefinedAssignmentChecker.cpp | 94 + lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp | 282 ++ .../Checkers/UnreachableCodeChecker.cpp | 228 + lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp | 138 + lib/StaticAnalyzer/Core/AggExprVisitor.cpp | 69 + lib/StaticAnalyzer/Core/AnalysisManager.cpp | 32 + lib/StaticAnalyzer/Core/BasicConstraintManager.cpp | 338 ++ lib/StaticAnalyzer/Core/BasicStore.cpp | 604 +++ lib/StaticAnalyzer/Core/BasicValueFactory.cpp | 288 ++ lib/StaticAnalyzer/Core/BlockCounter.cpp | 86 + lib/StaticAnalyzer/Core/BugReporter.cpp | 1896 ++++++++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 457 ++ lib/StaticAnalyzer/Core/CFRefCount.cpp | 3519 +++++++++++++++ lib/StaticAnalyzer/Core/CMakeLists.txt | 41 + lib/StaticAnalyzer/Core/CXXExprEngine.cpp | 322 ++ lib/StaticAnalyzer/Core/Checker.cpp | 35 + lib/StaticAnalyzer/Core/CheckerHelpers.cpp | 80 + lib/StaticAnalyzer/Core/CheckerManager.cpp | 85 + lib/StaticAnalyzer/Core/CoreEngine.cpp | 848 ++++ lib/StaticAnalyzer/Core/Environment.cpp | 234 + lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 392 ++ lib/StaticAnalyzer/Core/FlatStore.cpp | 204 + lib/StaticAnalyzer/Core/GRState.cpp | 606 +++ lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 581 +++ lib/StaticAnalyzer/Core/Makefile | 17 + lib/StaticAnalyzer/Core/MemRegion.cpp | 988 +++++ lib/StaticAnalyzer/Core/ObjCMessage.cpp | 99 + lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 280 ++ lib/StaticAnalyzer/Core/PlistDiagnostics.cpp | 472 ++ lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 441 ++ lib/StaticAnalyzer/Core/RegionStore.cpp | 1813 ++++++++ lib/StaticAnalyzer/Core/SValBuilder.cpp | 310 ++ lib/StaticAnalyzer/Core/SVals.cpp | 378 ++ .../Core/SimpleConstraintManager.cpp | 303 ++ lib/StaticAnalyzer/Core/SimpleConstraintManager.h | 93 + lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 917 ++++ lib/StaticAnalyzer/Core/Store.cpp | 338 ++ lib/StaticAnalyzer/Core/SymbolManager.cpp | 345 ++ lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp | 70 + lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 544 +++ lib/StaticAnalyzer/Frontend/AnalysisConsumer.h | 41 + lib/StaticAnalyzer/Frontend/CMakeLists.txt | 20 + .../Frontend/CheckerRegistration.cpp | 50 + lib/StaticAnalyzer/Frontend/FrontendActions.cpp | 22 + lib/StaticAnalyzer/Frontend/Makefile | 19 + lib/StaticAnalyzer/Makefile | 18 + lib/StaticAnalyzer/README.txt | 139 + 448 files changed, 100849 insertions(+), 64270 deletions(-) create mode 100644 lib/AST/DumpXML.cpp delete mode 100644 lib/AST/FullExpr.cpp create mode 100644 lib/AST/ItaniumMangle.cpp create mode 100644 lib/AST/Mangle.cpp create mode 100644 lib/AST/MicrosoftMangle.cpp create mode 100644 lib/Analysis/CocoaConventions.cpp create mode 100644 lib/Analysis/UninitializedValuesV2.cpp create mode 100644 lib/Basic/DiagnosticIDs.cpp create mode 100644 lib/Basic/FileSystemStatCache.cpp delete mode 100644 lib/Checker/AdjustedReturnValueChecker.cpp delete mode 100644 lib/Checker/AggExprVisitor.cpp delete mode 100644 lib/Checker/AnalysisConsumer.cpp delete mode 100644 lib/Checker/AnalysisManager.cpp delete mode 100644 lib/Checker/ArrayBoundChecker.cpp delete mode 100644 lib/Checker/AttrNonNullChecker.cpp delete mode 100644 lib/Checker/BasicConstraintManager.cpp delete mode 100644 lib/Checker/BasicObjCFoundationChecks.cpp delete mode 100644 lib/Checker/BasicObjCFoundationChecks.h delete mode 100644 lib/Checker/BasicStore.cpp delete mode 100644 lib/Checker/BasicValueFactory.cpp delete mode 100644 lib/Checker/BugReporter.cpp delete mode 100644 lib/Checker/BugReporterVisitors.cpp delete mode 100644 lib/Checker/BuiltinFunctionChecker.cpp delete mode 100644 lib/Checker/CFRefCount.cpp delete mode 100644 lib/Checker/CMakeLists.txt delete mode 100644 lib/Checker/CStringChecker.cpp delete mode 100644 lib/Checker/CallAndMessageChecker.cpp delete mode 100644 lib/Checker/CastSizeChecker.cpp delete mode 100644 lib/Checker/CastToStructChecker.cpp delete mode 100644 lib/Checker/CheckDeadStores.cpp delete mode 100644 lib/Checker/CheckObjCDealloc.cpp delete mode 100644 lib/Checker/CheckObjCInstMethSignature.cpp delete mode 100644 lib/Checker/CheckSecuritySyntaxOnly.cpp delete mode 100644 lib/Checker/CheckSizeofPointer.cpp delete mode 100644 lib/Checker/Checker.cpp delete mode 100644 lib/Checker/CheckerHelpers.cpp delete mode 100644 lib/Checker/CocoaConventions.cpp delete mode 100644 lib/Checker/DereferenceChecker.cpp delete mode 100644 lib/Checker/DivZeroChecker.cpp delete mode 100644 lib/Checker/Environment.cpp delete mode 100644 lib/Checker/ExplodedGraph.cpp delete mode 100644 lib/Checker/FixedAddressChecker.cpp delete mode 100644 lib/Checker/FlatStore.cpp delete mode 100644 lib/Checker/FrontendActions.cpp delete mode 100644 lib/Checker/GRBlockCounter.cpp delete mode 100644 lib/Checker/GRCXXExprEngine.cpp delete mode 100644 lib/Checker/GRCoreEngine.cpp delete mode 100644 lib/Checker/GRExprEngine.cpp delete mode 100644 lib/Checker/GRExprEngineExperimentalChecks.cpp delete mode 100644 lib/Checker/GRExprEngineExperimentalChecks.h delete mode 100644 lib/Checker/GRExprEngineInternalChecks.h delete mode 100644 lib/Checker/GRState.cpp delete mode 100644 lib/Checker/HTMLDiagnostics.cpp delete mode 100644 lib/Checker/IdempotentOperationChecker.cpp delete mode 100644 lib/Checker/LLVMConventionsChecker.cpp delete mode 100644 lib/Checker/MacOSXAPIChecker.cpp delete mode 100644 lib/Checker/Makefile delete mode 100644 lib/Checker/MallocChecker.cpp delete mode 100644 lib/Checker/ManagerRegistry.cpp delete mode 100644 lib/Checker/MemRegion.cpp delete mode 100644 lib/Checker/NSAutoreleasePoolChecker.cpp delete mode 100644 lib/Checker/NSErrorChecker.cpp delete mode 100644 lib/Checker/NoReturnFunctionChecker.cpp delete mode 100644 lib/Checker/OSAtomicChecker.cpp delete mode 100644 lib/Checker/ObjCUnusedIVarsChecker.cpp delete mode 100644 lib/Checker/PathDiagnostic.cpp delete mode 100644 lib/Checker/PlistDiagnostics.cpp delete mode 100644 lib/Checker/PointerArithChecker.cpp delete mode 100644 lib/Checker/PointerSubChecker.cpp delete mode 100644 lib/Checker/PthreadLockChecker.cpp delete mode 100644 lib/Checker/RangeConstraintManager.cpp delete mode 100644 lib/Checker/RegionStore.cpp delete mode 100644 lib/Checker/ReturnPointerRangeChecker.cpp delete mode 100644 lib/Checker/ReturnUndefChecker.cpp delete mode 100644 lib/Checker/SVals.cpp delete mode 100644 lib/Checker/SValuator.cpp delete mode 100644 lib/Checker/SimpleConstraintManager.cpp delete mode 100644 lib/Checker/SimpleConstraintManager.h delete mode 100644 lib/Checker/SimpleSValuator.cpp delete mode 100644 lib/Checker/StackAddrLeakChecker.cpp delete mode 100644 lib/Checker/Store.cpp delete mode 100644 lib/Checker/StreamChecker.cpp delete mode 100644 lib/Checker/SymbolManager.cpp delete mode 100644 lib/Checker/UndefBranchChecker.cpp delete mode 100644 lib/Checker/UndefCapturedBlockVarChecker.cpp delete mode 100644 lib/Checker/UndefResultChecker.cpp delete mode 100644 lib/Checker/UndefinedArraySubscriptChecker.cpp delete mode 100644 lib/Checker/UndefinedAssignmentChecker.cpp delete mode 100644 lib/Checker/UnixAPIChecker.cpp delete mode 100644 lib/Checker/UnreachableCodeChecker.cpp delete mode 100644 lib/Checker/VLASizeChecker.cpp delete mode 100644 lib/Checker/ValueManager.cpp delete mode 100644 lib/CodeGen/CGCXX.h create mode 100644 lib/CodeGen/CGCXXABI.cpp create mode 100644 lib/CodeGen/CGCleanup.cpp create mode 100644 lib/CodeGen/CGCleanup.h create mode 100644 lib/CodeGen/CodeGenTBAA.cpp create mode 100644 lib/CodeGen/CodeGenTBAA.h delete mode 100644 lib/CodeGen/Mangle.cpp delete mode 100644 lib/CodeGen/Mangle.h create mode 100644 lib/Frontend/HeaderIncludeGen.cpp create mode 100644 lib/Frontend/MultiplexConsumer.cpp create mode 100644 lib/Sema/SemaTemplateVariadic.cpp create mode 100644 lib/Sema/TypeLocBuilder.h create mode 100644 lib/StaticAnalyzer/CMakeLists.txt create mode 100644 lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp create mode 100644 lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp create mode 100644 lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.h create mode 100644 lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CMakeLists.txt create mode 100644 lib/StaticAnalyzer/Checkers/CStringChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CastToStructChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CheckObjCInstMethSignature.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp create mode 100644 lib/StaticAnalyzer/Checkers/CheckSizeofPointer.cpp create mode 100644 lib/StaticAnalyzer/Checkers/Checkers.td create mode 100644 lib/StaticAnalyzer/Checkers/ChrootChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h create mode 100644 lib/StaticAnalyzer/Checkers/ClangSACheckers.h create mode 100644 lib/StaticAnalyzer/Checkers/DeadStoresChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/DebugCheckers.cpp create mode 100644 lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ExperimentalChecks.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ExperimentalChecks.h create mode 100644 lib/StaticAnalyzer/Checkers/ExprEngine.cpp create mode 100644 lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/InternalChecks.h create mode 100644 lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/Makefile create mode 100644 lib/StaticAnalyzer/Checkers/MallocChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ObjCUnusedIVarsChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/StackAddrLeakChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/StreamChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp create mode 100644 lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp create mode 100644 lib/StaticAnalyzer/Core/AggExprVisitor.cpp create mode 100644 lib/StaticAnalyzer/Core/AnalysisManager.cpp create mode 100644 lib/StaticAnalyzer/Core/BasicConstraintManager.cpp create mode 100644 lib/StaticAnalyzer/Core/BasicStore.cpp create mode 100644 lib/StaticAnalyzer/Core/BasicValueFactory.cpp create mode 100644 lib/StaticAnalyzer/Core/BlockCounter.cpp create mode 100644 lib/StaticAnalyzer/Core/BugReporter.cpp create mode 100644 lib/StaticAnalyzer/Core/BugReporterVisitors.cpp create mode 100644 lib/StaticAnalyzer/Core/CFRefCount.cpp create mode 100644 lib/StaticAnalyzer/Core/CMakeLists.txt create mode 100644 lib/StaticAnalyzer/Core/CXXExprEngine.cpp create mode 100644 lib/StaticAnalyzer/Core/Checker.cpp create mode 100644 lib/StaticAnalyzer/Core/CheckerHelpers.cpp create mode 100644 lib/StaticAnalyzer/Core/CheckerManager.cpp create mode 100644 lib/StaticAnalyzer/Core/CoreEngine.cpp create mode 100644 lib/StaticAnalyzer/Core/Environment.cpp create mode 100644 lib/StaticAnalyzer/Core/ExplodedGraph.cpp create mode 100644 lib/StaticAnalyzer/Core/FlatStore.cpp create mode 100644 lib/StaticAnalyzer/Core/GRState.cpp create mode 100644 lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp create mode 100644 lib/StaticAnalyzer/Core/Makefile create mode 100644 lib/StaticAnalyzer/Core/MemRegion.cpp create mode 100644 lib/StaticAnalyzer/Core/ObjCMessage.cpp create mode 100644 lib/StaticAnalyzer/Core/PathDiagnostic.cpp create mode 100644 lib/StaticAnalyzer/Core/PlistDiagnostics.cpp create mode 100644 lib/StaticAnalyzer/Core/RangeConstraintManager.cpp create mode 100644 lib/StaticAnalyzer/Core/RegionStore.cpp create mode 100644 lib/StaticAnalyzer/Core/SValBuilder.cpp create mode 100644 lib/StaticAnalyzer/Core/SVals.cpp create mode 100644 lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp create mode 100644 lib/StaticAnalyzer/Core/SimpleConstraintManager.h create mode 100644 lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp create mode 100644 lib/StaticAnalyzer/Core/Store.cpp create mode 100644 lib/StaticAnalyzer/Core/SymbolManager.cpp create mode 100644 lib/StaticAnalyzer/Core/TextPathDiagnostics.cpp create mode 100644 lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp create mode 100644 lib/StaticAnalyzer/Frontend/AnalysisConsumer.h create mode 100644 lib/StaticAnalyzer/Frontend/CMakeLists.txt create mode 100644 lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp create mode 100644 lib/StaticAnalyzer/Frontend/FrontendActions.cpp create mode 100644 lib/StaticAnalyzer/Frontend/Makefile create mode 100644 lib/StaticAnalyzer/Makefile create mode 100644 lib/StaticAnalyzer/README.txt (limited to 'lib') diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4591a0f3c55c..945dfb87f297 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -20,7 +20,9 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/Mangle.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -50,7 +52,7 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, TemplateTemplateParmDecl *Parm) { ID.AddInteger(Parm->getDepth()); ID.AddInteger(Parm->getPosition()); - // FIXME: Parameter pack + ID.AddBoolean(Parm->isParameterPack()); TemplateParameterList *Params = Parm->getTemplateParameters(); ID.AddInteger(Params->size()); @@ -65,8 +67,15 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*P)) { ID.AddInteger(1); - // FIXME: Parameter pack + ID.AddBoolean(NTTP->isParameterPack()); ID.AddPointer(NTTP->getType().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()); + } else + ID.AddBoolean(false); continue; } @@ -78,7 +87,7 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, TemplateTemplateParmDecl * ASTContext::getCanonicalTemplateTemplateParmDecl( - TemplateTemplateParmDecl *TTP) { + TemplateTemplateParmDecl *TTP) const { // Check if we already have a canonical template template parameter. llvm::FoldingSetNodeID ID; CanonicalTemplateTemplateParm::Profile(ID, TTP); @@ -102,14 +111,40 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TTP->getIndex(), 0, false, TTP->isParameterPack())); else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast(*P)) - CanonParams.push_back( - NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), - SourceLocation(), NTTP->getDepth(), - NTTP->getPosition(), 0, - getCanonicalType(NTTP->getType()), - 0)); - else + = dyn_cast(*P)) { + QualType T = getCanonicalType(NTTP->getType()); + TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); + NonTypeTemplateParmDecl *Param; + if (NTTP->isExpandedParameterPack()) { + llvm::SmallVector ExpandedTypes; + llvm::SmallVector ExpandedTInfos; + for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { + ExpandedTypes.push_back(getCanonicalType(NTTP->getExpansionType(I))); + ExpandedTInfos.push_back( + getTrivialTypeSourceInfo(ExpandedTypes.back())); + } + + Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), + SourceLocation(), + NTTP->getDepth(), + NTTP->getPosition(), 0, + T, + TInfo, + ExpandedTypes.data(), + ExpandedTypes.size(), + ExpandedTInfos.data()); + } else { + Param = NonTypeTemplateParmDecl::Create(*this, getTranslationUnitDecl(), + SourceLocation(), + NTTP->getDepth(), + NTTP->getPosition(), 0, + T, + NTTP->isParameterPack(), + TInfo); + } + CanonParams.push_back(Param); + + } else CanonParams.push_back(getCanonicalTemplateTemplateParmDecl( cast(*P))); } @@ -117,7 +152,9 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(), - TTP->getPosition(), 0, + TTP->getPosition(), + TTP->isParameterPack(), + 0, TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams.data(), @@ -160,12 +197,13 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), + cudaConfigureCallDecl(0), NullTypeSourceInfo(QualType()), SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), - ExternalSource(0), PrintingPolicy(LOpts), + ExternalSource(0), Listener(0), PrintingPolicy(LOpts), LastSDM(0, 0), UniqueBlockByRefTypeID(0), UniqueBlockParmTypeID(0) { ObjCIdRedefinitionType = QualType(); @@ -314,9 +352,12 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); - if (LangOpts.CPlusPlus) // C++ 3.9.1p5 - InitBuiltinType(WCharTy, BuiltinType::WChar); - else // C99 + if (LangOpts.CPlusPlus) { // C++ 3.9.1p5 + if (!LangOpts.ShortWChar) + InitBuiltinType(WCharTy, BuiltinType::WChar_S); + else // -fshort-wchar makes wchar_t be unsigned. + InitBuiltinType(WCharTy, BuiltinType::WChar_U); + } else // C99 WCharTy = getFromTargetType(Target.getWCharType()); if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++ @@ -329,9 +370,6 @@ void ASTContext::InitBuiltinTypes() { else // C99 Char32Ty = getFromTargetType(Target.getChar32Type()); - // Placeholder type for functions. - InitBuiltinType(OverloadTy, BuiltinType::Overload); - // Placeholder type for type-dependent expressions whose type is // completely unknown. No code should ever check a type against // DependentTy and users should never see it; however, it is here to @@ -339,9 +377,8 @@ void ASTContext::InitBuiltinTypes() { // expressions. InitBuiltinType(DependentTy, BuiltinType::Dependent); - // Placeholder type for C++0x auto declarations whose real type has - // not yet been deduced. - InitBuiltinType(UndeducedAutoTy, BuiltinType::UndeducedAuto); + // Placeholder type for functions. + InitBuiltinType(OverloadTy, BuiltinType::Overload); // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); @@ -369,6 +406,10 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(NullPtrTy, BuiltinType::NullPtr); } +Diagnostic &ASTContext::getDiagnostics() const { + return SourceMgr.getDiagnostics(); +} + AttrVec& ASTContext::getDeclAttrs(const Decl *D) { AttrVec *&Result = DeclAttrs[D]; if (!Result) { @@ -525,12 +566,33 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { /// this method will assert on them. /// If @p RefAsPointee, references are treated like their underlying type /// (for alignof), else they're treated like pointers (for CodeGen). -CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) { +CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { unsigned Align = Target.getCharWidth(); - Align = std::max(Align, D->getMaxAlignment()); + bool UseAlignAttrOnly = false; + if (unsigned AlignFromAttr = D->getMaxAlignment()) { + Align = AlignFromAttr; + + // __attribute__((aligned)) can increase or decrease alignment + // *except* on a struct or struct member, where it only increases + // alignment unless 'packed' is also specified. + // + // It is an error for [[align]] to decrease alignment, so we can + // ignore that possibility; Sema should diagnose it. + if (isa(D)) { + UseAlignAttrOnly = D->hasAttr() || + cast(D)->getParent()->hasAttr(); + } else { + UseAlignAttrOnly = true; + } + } - if (const ValueDecl *VD = dyn_cast(D)) { + // If we're using the align attribute only, just ignore everything + // else about the declaration and its type. + if (UseAlignAttrOnly) { + // do nothing + + } else if (const ValueDecl *VD = dyn_cast(D)) { QualType T = VD->getType(); if (const ReferenceType* RT = T->getAs()) { if (RefAsPointee) @@ -539,41 +601,61 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) { T = getPointerType(RT->getPointeeType()); } if (!T->isIncompleteType() && !T->isFunctionType()) { + // Adjust alignments of declarations with array type by the + // large-array alignment on the target. unsigned MinWidth = Target.getLargeArrayMinWidth(); - unsigned ArrayAlign = Target.getLargeArrayAlign(); - if (isa(T) && MinWidth != 0) - Align = std::max(Align, ArrayAlign); - if (ConstantArrayType *CT = dyn_cast(T)) { - unsigned Size = getTypeSize(CT); - if (MinWidth != 0 && MinWidth <= Size) - Align = std::max(Align, ArrayAlign); + const ArrayType *arrayType; + if (MinWidth && (arrayType = getAsArrayType(T))) { + if (isa(arrayType)) + Align = std::max(Align, Target.getLargeArrayAlign()); + else if (isa(arrayType) && + MinWidth <= getTypeSize(cast(arrayType))) + Align = std::max(Align, Target.getLargeArrayAlign()); + + // Walk through any array types while we're at it. + T = getBaseElementType(arrayType); } - // Incomplete or function types default to 1. - while (isa(T) || isa(T)) - T = cast(T)->getElementType(); - Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); } - if (const FieldDecl *FD = dyn_cast(VD)) { - // In the case of a field in a packed struct, we want the minimum - // of the alignment of the field and the alignment of the struct. - Align = std::min(Align, - getPreferredTypeAlign(FD->getParent()->getTypeForDecl())); + + // Fields can be subject to extra alignment constraints, like if + // the field is packed, the struct is packed, or the struct has a + // a max-field-alignment constraint (#pragma pack). So calculate + // the actual alignment of the field within the struct, and then + // (as we're expected to) constrain that by the alignment of the type. + if (const FieldDecl *field = dyn_cast(VD)) { + // So calculate the alignment of the field. + const ASTRecordLayout &layout = getASTRecordLayout(field->getParent()); + + // Start with the record's overall alignment. + unsigned fieldAlign = toBits(layout.getAlignment()); + + // Use the GCD of that and the offset within the record. + uint64_t offset = layout.getFieldOffset(field->getFieldIndex()); + if (offset > 0) { + // Alignment is always a power of 2, so the GCD will be a power of 2, + // which means we get to do this crazy thing instead of Euclid's. + uint64_t lowBitOfOffset = offset & (~offset + 1); + if (lowBitOfOffset < fieldAlign) + fieldAlign = static_cast(lowBitOfOffset); + } + + Align = std::min(Align, fieldAlign); } } - return CharUnits::fromQuantity(Align / Target.getCharWidth()); + return toCharUnitsFromBits(Align); } std::pair -ASTContext::getTypeInfoInChars(const Type *T) { +ASTContext::getTypeInfoInChars(const Type *T) const { std::pair Info = getTypeInfo(T); - return std::make_pair(CharUnits::fromQuantity(Info.first / getCharWidth()), - CharUnits::fromQuantity(Info.second / getCharWidth())); + return std::make_pair(toCharUnitsFromBits(Info.first), + toCharUnitsFromBits(Info.second)); } std::pair -ASTContext::getTypeInfoInChars(QualType T) { +ASTContext::getTypeInfoInChars(QualType T) const { return getTypeInfoInChars(T.getTypePtr()); } @@ -584,7 +666,7 @@ ASTContext::getTypeInfoInChars(QualType T) { /// alignment requirements: getPointerInfo should take an AddrSpace, this /// should take a QualType, &c. std::pair -ASTContext::getTypeInfo(const Type *T) { +ASTContext::getTypeInfo(const Type *T) const { uint64_t Width=0; unsigned Align=8; switch (T->getTypeClass()) { @@ -652,7 +734,8 @@ ASTContext::getTypeInfo(const Type *T) { Width = Target.getCharWidth(); Align = Target.getCharAlign(); break; - case BuiltinType::WChar: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: Width = Target.getWCharWidth(); Align = Target.getWCharAlign(); break; @@ -760,8 +843,8 @@ ASTContext::getTypeInfo(const Type *T) { case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); - Width = Layout.getSize(); - Align = Layout.getAlignment(); + Width = toBits(Layout.getSize()); + Align = toBits(Layout.getAlignment()); break; } case Type::Record: @@ -779,8 +862,8 @@ ASTContext::getTypeInfo(const Type *T) { const RecordType *RT = cast(TT); const ASTRecordLayout &Layout = getASTRecordLayout(RT->getDecl()); - Width = Layout.getSize(); - Align = Layout.getAlignment(); + Width = toBits(Layout.getSize()); + Align = toBits(Layout.getAlignment()); break; } @@ -788,11 +871,26 @@ ASTContext::getTypeInfo(const Type *T) { return getTypeInfo(cast(T)-> getReplacementType().getTypePtr()); + case Type::Auto: { + const AutoType *A = cast(T); + assert(A->isDeduced() && "Cannot request the size of a dependent type"); + return getTypeInfo(cast(T)->getDeducedType().getTypePtr()); + } + + case Type::Paren: + return getTypeInfo(cast(T)->getInnerType().getTypePtr()); + case Type::Typedef: { const TypedefDecl *Typedef = cast(T)->getDecl(); std::pair Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); - Align = std::max(Typedef->getMaxAlignment(), Info.second); + // If the typedef has an aligned attribute on it, it overrides any computed + // alignment we have. This violates the GCC documentation (which says that + // attribute(aligned) can only round up) but matches its implementation. + if (unsigned AttrAlign = Typedef->getMaxAlignment()) + Align = AttrAlign; + else + Align = Info.second; Width = Info.first; break; } @@ -811,6 +909,10 @@ ASTContext::getTypeInfo(const Type *T) { case Type::Elaborated: return getTypeInfo(cast(T)->getNamedType().getTypePtr()); + case Type::Attributed: + return getTypeInfo( + cast(T)->getEquivalentType().getTypePtr()); + case Type::TemplateSpecialization: assert(getCanonicalType(T) != T && "Cannot request the size of a dependent type"); @@ -824,29 +926,39 @@ ASTContext::getTypeInfo(const Type *T) { return std::make_pair(Width, Align); } +/// toCharUnitsFromBits - Convert a size in bits to a size in characters. +CharUnits ASTContext::toCharUnitsFromBits(int64_t BitSize) const { + return CharUnits::fromQuantity(BitSize / getCharWidth()); +} + +/// toBits - Convert a size in characters to a size in characters. +int64_t ASTContext::toBits(CharUnits CharSize) const { + return CharSize.getQuantity() * getCharWidth(); +} + /// getTypeSizeInChars - Return the size of the specified type, in characters. /// This method does not work on incomplete types. -CharUnits ASTContext::getTypeSizeInChars(QualType T) { - return CharUnits::fromQuantity(getTypeSize(T) / getCharWidth()); +CharUnits ASTContext::getTypeSizeInChars(QualType T) const { + return toCharUnitsFromBits(getTypeSize(T)); } -CharUnits ASTContext::getTypeSizeInChars(const Type *T) { - return CharUnits::fromQuantity(getTypeSize(T) / getCharWidth()); +CharUnits ASTContext::getTypeSizeInChars(const Type *T) const { + return toCharUnitsFromBits(getTypeSize(T)); } /// getTypeAlignInChars - Return the ABI-specified alignment of a type, in /// characters. This method does not work on incomplete types. -CharUnits ASTContext::getTypeAlignInChars(QualType T) { - return CharUnits::fromQuantity(getTypeAlign(T) / getCharWidth()); +CharUnits ASTContext::getTypeAlignInChars(QualType T) const { + return toCharUnitsFromBits(getTypeAlign(T)); } -CharUnits ASTContext::getTypeAlignInChars(const Type *T) { - return CharUnits::fromQuantity(getTypeAlign(T) / getCharWidth()); +CharUnits ASTContext::getTypeAlignInChars(const Type *T) const { + return toCharUnitsFromBits(getTypeAlign(T)); } /// getPreferredTypeAlign - Return the "preferred" alignment of the specified /// type for the current target in bits. This can be different than the ABI /// alignment in cases where it is beneficial for performance to overalign /// a data type. -unsigned ASTContext::getPreferredTypeAlign(const Type *T) { +unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { unsigned ABIAlign = getTypeAlign(T); // Double and long long should be naturally aligned if possible. @@ -863,7 +975,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) { /// Collect all ivars, including those synthesized, in the current class. /// void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, - llvm::SmallVectorImpl &Ivars) { + llvm::SmallVectorImpl &Ivars) const { // FIXME. This need be removed but there are two many places which // assume const-ness of ObjCInterfaceDecl ObjCInterfaceDecl *IDecl = const_cast(OI); @@ -880,7 +992,7 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, /// void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass, - llvm::SmallVectorImpl &Ivars) { + llvm::SmallVectorImpl &Ivars) const { if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) DeepCollectObjCIvars(SuperClass, false, Ivars); if (!leafClass) { @@ -940,7 +1052,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, } } -unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) { +unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; @@ -985,6 +1097,25 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCImpls[CatD] = ImplD; } +/// \brief Get the copy initialization expression of VarDecl,or NULL if +/// none exists. +Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { + assert(VD && "Passed null params"); + assert(VD->hasAttr() && + "getBlockVarCopyInits - not __block var"); + llvm::DenseMap::iterator + I = BlockVarCopyInits.find(VD); + return (I != BlockVarCopyInits.end()) ? cast(I->second) : 0; +} + +/// \brief Set the copy inialization expression of a block var decl. +void ASTContext::setBlockVarCopyInits(VarDecl*VD, Expr* Init) { + assert(VD && Init && "Passed null params"); + assert(VD->hasAttr() && + "setBlockVarCopyInits - not __block var"); + BlockVarCopyInits[VD] = Init; +} + /// \brief Allocate an uninitialized TypeSourceInfo. /// /// The caller should initialize the memory held by TypeSourceInfo using @@ -994,7 +1125,7 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, /// should refer to how the declarator was written in source code, not to /// what type semantic analysis resolved the declarator to. TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T, - unsigned DataSize) { + unsigned DataSize) const { if (!DataSize) DataSize = TypeLoc::getFullDataSizeForType(T); else @@ -1008,19 +1139,20 @@ TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T, } TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T, - SourceLocation L) { + SourceLocation L) const { TypeSourceInfo *DI = CreateTypeSourceInfo(T); - DI->getTypeLoc().initialize(L); + DI->getTypeLoc().initialize(const_cast(*this), L); return DI; } const ASTRecordLayout & -ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) { +ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const { return getObjCLayout(D, 0); } const ASTRecordLayout & -ASTContext::getASTObjCImplementationLayout(const ObjCImplementationDecl *D) { +ASTContext::getASTObjCImplementationLayout( + const ObjCImplementationDecl *D) const { return getObjCLayout(D->getClassInterface(), D); } @@ -1028,38 +1160,38 @@ ASTContext::getASTObjCImplementationLayout(const ObjCImplementationDecl *D) { // Type creation/memoization methods //===----------------------------------------------------------------------===// -QualType ASTContext::getExtQualType(const Type *TypeNode, Qualifiers Quals) { - unsigned Fast = Quals.getFastQualifiers(); - Quals.removeFastQualifiers(); +QualType +ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const { + unsigned fastQuals = quals.getFastQualifiers(); + quals.removeFastQualifiers(); // Check if we've already instantiated this type. llvm::FoldingSetNodeID ID; - ExtQuals::Profile(ID, TypeNode, Quals); - void *InsertPos = 0; - if (ExtQuals *EQ = ExtQualNodes.FindNodeOrInsertPos(ID, InsertPos)) { - assert(EQ->getQualifiers() == Quals); - QualType T = QualType(EQ, Fast); - return T; + ExtQuals::Profile(ID, baseType, quals); + void *insertPos = 0; + if (ExtQuals *eq = ExtQualNodes.FindNodeOrInsertPos(ID, insertPos)) { + assert(eq->getQualifiers() == quals); + return QualType(eq, fastQuals); } - ExtQuals *New = new (*this, TypeAlignment) ExtQuals(*this, TypeNode, Quals); - ExtQualNodes.InsertNode(New, InsertPos); - QualType T = QualType(New, Fast); - return T; -} - -QualType ASTContext::getVolatileType(QualType T) { - QualType CanT = getCanonicalType(T); - if (CanT.isVolatileQualified()) return T; + // If the base type is not canonical, make the appropriate canonical type. + QualType canon; + if (!baseType->isCanonicalUnqualified()) { + SplitQualType canonSplit = baseType->getCanonicalTypeInternal().split(); + canonSplit.second.addConsistentQualifiers(quals); + canon = getExtQualType(canonSplit.first, canonSplit.second); - QualifierCollector Quals; - const Type *TypeNode = Quals.strip(T); - Quals.addVolatile(); + // Re-find the insert position. + (void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos); + } - return getExtQualType(TypeNode, Quals); + ExtQuals *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals); + ExtQualNodes.InsertNode(eq, insertPos); + return QualType(eq, fastQuals); } -QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) { +QualType +ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) const { QualType CanT = getCanonicalType(T); if (CanT.getAddressSpace() == AddressSpace) return T; @@ -1079,13 +1211,13 @@ QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) { } QualType ASTContext::getObjCGCQualType(QualType T, - Qualifiers::GC GCAttr) { + Qualifiers::GC GCAttr) const { QualType CanT = getCanonicalType(T); if (CanT.getObjCGCAttr() == GCAttr) return T; - if (T->isPointerType()) { - QualType Pointee = T->getAs()->getPointeeType(); + if (const PointerType *ptr = T->getAs()) { + QualType Pointee = ptr->getPointeeType(); if (Pointee->isAnyPointerType()) { QualType ResultType = getObjCGCQualType(Pointee, GCAttr); return getPointerType(ResultType); @@ -1106,79 +1238,28 @@ QualType ASTContext::getObjCGCQualType(QualType T, return getExtQualType(TypeNode, Quals); } -static QualType getExtFunctionType(ASTContext& Context, QualType T, - const FunctionType::ExtInfo &Info) { - QualType ResultType; - if (const PointerType *Pointer = T->getAs()) { - QualType Pointee = Pointer->getPointeeType(); - ResultType = getExtFunctionType(Context, Pointee, Info); - if (ResultType == Pointee) - return T; - - ResultType = Context.getPointerType(ResultType); - } else if (const BlockPointerType *BlockPointer - = T->getAs()) { - QualType Pointee = BlockPointer->getPointeeType(); - ResultType = getExtFunctionType(Context, Pointee, Info); - if (ResultType == Pointee) - return T; - - ResultType = Context.getBlockPointerType(ResultType); - } else if (const MemberPointerType *MemberPointer - = T->getAs()) { - QualType Pointee = MemberPointer->getPointeeType(); - ResultType = getExtFunctionType(Context, Pointee, Info); - if (ResultType == Pointee) - return T; - - ResultType = Context.getMemberPointerType(ResultType, - MemberPointer->getClass()); - } else if (const FunctionType *F = T->getAs()) { - if (F->getExtInfo() == Info) - return T; - - if (const FunctionNoProtoType *FNPT = dyn_cast(F)) { - ResultType = Context.getFunctionNoProtoType(FNPT->getResultType(), - Info); - } else { - const FunctionProtoType *FPT = cast(F); - ResultType - = Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), - FPT->getNumArgs(), FPT->isVariadic(), - FPT->getTypeQuals(), - FPT->hasExceptionSpec(), - FPT->hasAnyExceptionSpec(), - FPT->getNumExceptions(), - FPT->exception_begin(), - Info); - } - } else +const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, + FunctionType::ExtInfo Info) { + if (T->getExtInfo() == Info) return T; - return Context.getQualifiedType(ResultType, T.getLocalQualifiers()); -} - -QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) { - FunctionType::ExtInfo Info = getFunctionExtInfo(T); - return getExtFunctionType(*this, T, - Info.withNoReturn(AddNoReturn)); -} - -QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) { - FunctionType::ExtInfo Info = getFunctionExtInfo(T); - return getExtFunctionType(*this, T, - Info.withCallingConv(CallConv)); -} + QualType Result; + if (const FunctionNoProtoType *FNPT = dyn_cast(T)) { + Result = getFunctionNoProtoType(FNPT->getResultType(), Info); + } else { + const FunctionProtoType *FPT = cast(T); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.ExtInfo = Info; + Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), + FPT->getNumArgs(), EPI); + } -QualType ASTContext::getRegParmType(QualType T, unsigned RegParm) { - FunctionType::ExtInfo Info = getFunctionExtInfo(T); - return getExtFunctionType(*this, T, - Info.withRegParm(RegParm)); + return cast(Result.getTypePtr()); } /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. -QualType ASTContext::getComplexType(QualType T) { +QualType ASTContext::getComplexType(QualType T) const { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1196,7 +1277,7 @@ QualType ASTContext::getComplexType(QualType T) { // Get the new insert position for the node we care about. ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical); Types.push_back(New); @@ -1206,7 +1287,7 @@ QualType ASTContext::getComplexType(QualType T) { /// getPointerType - Return the uniqued reference to the type for a pointer to /// the specified type. -QualType ASTContext::getPointerType(QualType T) { +QualType ASTContext::getPointerType(QualType T) const { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1224,7 +1305,7 @@ QualType ASTContext::getPointerType(QualType T) { // Get the new insert position for the node we care about. PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical); Types.push_back(New); @@ -1234,7 +1315,7 @@ QualType ASTContext::getPointerType(QualType T) { /// getBlockPointerType - Return the uniqued reference to the type for /// a pointer to the specified block. -QualType ASTContext::getBlockPointerType(QualType T) { +QualType ASTContext::getBlockPointerType(QualType T) const { assert(T->isFunctionType() && "block of function types only"); // Unique pointers, to guarantee there is only one block of a particular // structure. @@ -1255,7 +1336,7 @@ QualType ASTContext::getBlockPointerType(QualType T) { // Get the new insert position for the node we care about. BlockPointerType *NewIP = BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } BlockPointerType *New = new (*this, TypeAlignment) BlockPointerType(T, Canonical); @@ -1266,7 +1347,8 @@ QualType ASTContext::getBlockPointerType(QualType T) { /// getLValueReferenceType - Return the uniqued reference to the type for an /// lvalue reference to the specified type. -QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) { +QualType +ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1289,7 +1371,7 @@ QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) { // Get the new insert position for the node we care about. LValueReferenceType *NewIP = LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } LValueReferenceType *New @@ -1303,7 +1385,7 @@ QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) { /// getRValueReferenceType - Return the uniqued reference to the type for an /// rvalue reference to the specified type. -QualType ASTContext::getRValueReferenceType(QualType T) { +QualType ASTContext::getRValueReferenceType(QualType T) const { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1326,7 +1408,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) { // Get the new insert position for the node we care about. RValueReferenceType *NewIP = RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } RValueReferenceType *New @@ -1338,7 +1420,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) { /// getMemberPointerType - Return the uniqued reference to the type for a /// member pointer to the specified type, in the specified class. -QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) { +QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1358,7 +1440,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) { // Get the new insert position for the node we care about. MemberPointerType *NewIP = MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } MemberPointerType *New = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical); @@ -1372,7 +1454,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) { QualType ASTContext::getConstantArrayType(QualType EltTy, const llvm::APInt &ArySizeIn, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals) { + unsigned IndexTypeQuals) const { assert((EltTy->isDependentType() || EltTy->isIncompleteType() || EltTy->isConstantSizeType()) && "Constant array of VLAs is illegal!"); @@ -1380,55 +1462,185 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // Convert the array size into a canonical width matching the pointer size for // the target. llvm::APInt ArySize(ArySizeIn); - ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); + ArySize = + ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); llvm::FoldingSetNodeID ID; - ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, EltTypeQuals); + ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals); void *InsertPos = 0; if (ConstantArrayType *ATP = ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(ATP, 0); - // If the element type isn't canonical, this won't be a canonical type either, - // so fill in the canonical type field. - QualType Canonical; - if (!EltTy.isCanonical()) { - Canonical = getConstantArrayType(getCanonicalType(EltTy), ArySize, - ASM, EltTypeQuals); + // If the element type isn't canonical or has qualifiers, this won't + // be a canonical type either, so fill in the canonical type field. + QualType Canon; + if (!EltTy.isCanonical() || EltTy.hasLocalQualifiers()) { + SplitQualType canonSplit = getCanonicalType(EltTy).split(); + Canon = getConstantArrayType(QualType(canonSplit.first, 0), ArySize, + ASM, IndexTypeQuals); + Canon = getQualifiedType(Canon, canonSplit.second); + // Get the new insert position for the node we care about. ConstantArrayType *NewIP = ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } ConstantArrayType *New = new(*this,TypeAlignment) - ConstantArrayType(EltTy, Canonical, ArySize, ASM, EltTypeQuals); + ConstantArrayType(EltTy, Canon, ArySize, ASM, IndexTypeQuals); ConstantArrayTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); } +/// getVariableArrayDecayedType - Turns the given type, which may be +/// variably-modified, into the corresponding type with all the known +/// sizes replaced with [*]. +QualType ASTContext::getVariableArrayDecayedType(QualType type) const { + // Vastly most common case. + if (!type->isVariablyModifiedType()) return type; + + QualType result; + + SplitQualType split = type.getSplitDesugaredType(); + const Type *ty = split.first; + switch (ty->getTypeClass()) { +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("didn't desugar past all non-canonical types?"); + + // These types should never be variably-modified. + case Type::Builtin: + case Type::Complex: + case Type::Vector: + case Type::ExtVector: + case Type::DependentSizedExtVector: + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Record: + case Type::Enum: + case Type::UnresolvedUsing: + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::Decltype: + case Type::DependentName: + case Type::InjectedClassName: + case Type::TemplateSpecialization: + case Type::DependentTemplateSpecialization: + case Type::TemplateTypeParm: + case Type::SubstTemplateTypeParmPack: + case Type::Auto: + case Type::PackExpansion: + llvm_unreachable("type should never be variably-modified"); + + // These types can be variably-modified but should never need to + // further decay. + case Type::FunctionNoProto: + case Type::FunctionProto: + case Type::BlockPointer: + case Type::MemberPointer: + return type; + + // These types can be variably-modified. All these modifications + // preserve structure except as noted by comments. + // TODO: if we ever care about optimizing VLAs, there are no-op + // optimizations available here. + case Type::Pointer: + result = getPointerType(getVariableArrayDecayedType( + cast(ty)->getPointeeType())); + break; + + case Type::LValueReference: { + const LValueReferenceType *lv = cast(ty); + result = getLValueReferenceType( + getVariableArrayDecayedType(lv->getPointeeType()), + lv->isSpelledAsLValue()); + break; + } + + case Type::RValueReference: { + const RValueReferenceType *lv = cast(ty); + result = getRValueReferenceType( + getVariableArrayDecayedType(lv->getPointeeType())); + break; + } + + case Type::ConstantArray: { + const ConstantArrayType *cat = cast(ty); + result = getConstantArrayType( + getVariableArrayDecayedType(cat->getElementType()), + cat->getSize(), + cat->getSizeModifier(), + cat->getIndexTypeCVRQualifiers()); + break; + } + + case Type::DependentSizedArray: { + const DependentSizedArrayType *dat = cast(ty); + result = getDependentSizedArrayType( + getVariableArrayDecayedType(dat->getElementType()), + dat->getSizeExpr(), + dat->getSizeModifier(), + dat->getIndexTypeCVRQualifiers(), + dat->getBracketsRange()); + break; + } + + // Turn incomplete types into [*] types. + case Type::IncompleteArray: { + const IncompleteArrayType *iat = cast(ty); + result = getVariableArrayType( + getVariableArrayDecayedType(iat->getElementType()), + /*size*/ 0, + ArrayType::Normal, + iat->getIndexTypeCVRQualifiers(), + SourceRange()); + break; + } + + // Turn VLA types into [*] types. + case Type::VariableArray: { + const VariableArrayType *vat = cast(ty); + result = getVariableArrayType( + getVariableArrayDecayedType(vat->getElementType()), + /*size*/ 0, + ArrayType::Star, + vat->getIndexTypeCVRQualifiers(), + vat->getBracketsRange()); + break; + } + } + + // Apply the top-level qualifiers from the original. + return getQualifiedType(result, split.second); +} + /// getVariableArrayType - Returns a non-unique reference to the type for a /// variable array of the specified element type. QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals, - SourceRange Brackets) { + unsigned IndexTypeQuals, + SourceRange Brackets) const { // Since we don't unique expressions, it isn't possible to unique VLA's // that have an expression provided for their size. - QualType CanonType; + QualType Canon; - if (!EltTy.isCanonical()) { - if (NumElts) - NumElts->Retain(); - CanonType = getVariableArrayType(getCanonicalType(EltTy), NumElts, ASM, - EltTypeQuals, Brackets); + // 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, + IndexTypeQuals, Brackets); + Canon = getQualifiedType(Canon, canonSplit.second); } VariableArrayType *New = new(*this, TypeAlignment) - VariableArrayType(EltTy, CanonType, NumElts, ASM, EltTypeQuals, Brackets); + VariableArrayType(EltTy, Canon, NumElts, ASM, IndexTypeQuals, Brackets); VariableArrayTypes.push_back(New); Types.push_back(New); @@ -1438,109 +1650,118 @@ QualType ASTContext::getVariableArrayType(QualType EltTy, /// getDependentSizedArrayType - Returns a non-unique reference to /// the type for a dependently-sized array of the specified element /// type. -QualType ASTContext::getDependentSizedArrayType(QualType EltTy, - Expr *NumElts, +QualType ASTContext::getDependentSizedArrayType(QualType elementType, + Expr *numElements, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals, - SourceRange Brackets) { - assert((!NumElts || NumElts->isTypeDependent() || - NumElts->isValueDependent()) && + unsigned elementTypeQuals, + SourceRange brackets) const { + assert((!numElements || numElements->isTypeDependent() || + numElements->isValueDependent()) && "Size must be type- or value-dependent!"); - void *InsertPos = 0; - DependentSizedArrayType *Canon = 0; - llvm::FoldingSetNodeID ID; - - if (NumElts) { - // Dependently-sized array types that do not have a specified - // number of elements will have their sizes deduced from an - // initializer. - DependentSizedArrayType::Profile(ID, *this, getCanonicalType(EltTy), ASM, - EltTypeQuals, NumElts); - - Canon = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos); + // Dependently-sized array types that do not have a specified number + // of elements will have their sizes deduced from a dependent + // initializer. We do no canonicalization here at all, which is okay + // because they can't be used in most locations. + if (!numElements) { + DependentSizedArrayType *newType + = new (*this, TypeAlignment) + DependentSizedArrayType(*this, elementType, QualType(), + numElements, ASM, elementTypeQuals, + brackets); + Types.push_back(newType); + return QualType(newType, 0); } - DependentSizedArrayType *New; - if (Canon) { - // We already have a canonical version of this array type; use it as - // the canonical type for a newly-built type. - New = new (*this, TypeAlignment) - DependentSizedArrayType(*this, EltTy, QualType(Canon, 0), - NumElts, ASM, EltTypeQuals, Brackets); - } else { - QualType CanonEltTy = getCanonicalType(EltTy); - if (CanonEltTy == EltTy) { - New = new (*this, TypeAlignment) - DependentSizedArrayType(*this, EltTy, QualType(), - NumElts, ASM, EltTypeQuals, Brackets); - - if (NumElts) { - DependentSizedArrayType *CanonCheck - = DependentSizedArrayTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(!CanonCheck && "Dependent-sized canonical array type broken"); - (void)CanonCheck; - DependentSizedArrayTypes.InsertNode(New, InsertPos); - } - } else { - QualType Canon = getDependentSizedArrayType(CanonEltTy, NumElts, - ASM, EltTypeQuals, - SourceRange()); - New = new (*this, TypeAlignment) - DependentSizedArrayType(*this, EltTy, Canon, - NumElts, ASM, EltTypeQuals, Brackets); - } - } + // Otherwise, we actually build a new type every time, but we + // also build a canonical type. - Types.push_back(New); - return QualType(New, 0); -} + SplitQualType canonElementType = getCanonicalType(elementType).split(); -QualType ASTContext::getIncompleteArrayType(QualType EltTy, + void *insertPos = 0; + llvm::FoldingSetNodeID ID; + DependentSizedArrayType::Profile(ID, *this, + QualType(canonElementType.first, 0), + ASM, elementTypeQuals, numElements); + + // Look for an existing type with these properties. + DependentSizedArrayType *canonTy = + DependentSizedArrayTypes.FindNodeOrInsertPos(ID, insertPos); + + // If we don't have one, build one. + if (!canonTy) { + canonTy = new (*this, TypeAlignment) + DependentSizedArrayType(*this, QualType(canonElementType.first, 0), + QualType(), numElements, ASM, elementTypeQuals, + brackets); + DependentSizedArrayTypes.InsertNode(canonTy, insertPos); + Types.push_back(canonTy); + } + + // Apply qualifiers from the element type to the array. + QualType canon = getQualifiedType(QualType(canonTy,0), + canonElementType.second); + + // If we didn't need extra canonicalization for the element type, + // then just use that as our result. + if (QualType(canonElementType.first, 0) == elementType) + return canon; + + // Otherwise, we need to build a type which follows the spelling + // of the element type. + DependentSizedArrayType *sugaredType + = new (*this, TypeAlignment) + DependentSizedArrayType(*this, elementType, canon, numElements, + ASM, elementTypeQuals, brackets); + Types.push_back(sugaredType); + return QualType(sugaredType, 0); +} + +QualType ASTContext::getIncompleteArrayType(QualType elementType, ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals) { + unsigned elementTypeQuals) const { llvm::FoldingSetNodeID ID; - IncompleteArrayType::Profile(ID, EltTy, ASM, EltTypeQuals); + IncompleteArrayType::Profile(ID, elementType, ASM, elementTypeQuals); - void *InsertPos = 0; - if (IncompleteArrayType *ATP = - IncompleteArrayTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(ATP, 0); + void *insertPos = 0; + if (IncompleteArrayType *iat = + IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos)) + return QualType(iat, 0); // If the element type isn't canonical, this won't be a canonical type - // either, so fill in the canonical type field. - QualType Canonical; + // either, so fill in the canonical type field. We also have to pull + // qualifiers off the element type. + QualType canon; - if (!EltTy.isCanonical()) { - Canonical = getIncompleteArrayType(getCanonicalType(EltTy), - ASM, EltTypeQuals); + if (!elementType.isCanonical() || elementType.hasLocalQualifiers()) { + SplitQualType canonSplit = getCanonicalType(elementType).split(); + canon = getIncompleteArrayType(QualType(canonSplit.first, 0), + ASM, elementTypeQuals); + canon = getQualifiedType(canon, canonSplit.second); // Get the new insert position for the node we care about. - IncompleteArrayType *NewIP = - IncompleteArrayTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + IncompleteArrayType *existing = + IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos); + assert(!existing && "Shouldn't be in the map!"); (void) existing; } - IncompleteArrayType *New = new (*this, TypeAlignment) - IncompleteArrayType(EltTy, Canonical, ASM, EltTypeQuals); + IncompleteArrayType *newType = new (*this, TypeAlignment) + IncompleteArrayType(elementType, canon, ASM, elementTypeQuals); - IncompleteArrayTypes.InsertNode(New, InsertPos); - Types.push_back(New); - return QualType(New, 0); + IncompleteArrayTypes.InsertNode(newType, insertPos); + Types.push_back(newType); + return QualType(newType, 0); } /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, - VectorType::AltiVecSpecific AltiVecSpec) { - BuiltinType *baseType; - - baseType = dyn_cast(getCanonicalType(vecType).getTypePtr()); - assert(baseType != 0 && "getVectorType(): Expecting a built-in type"); + VectorType::VectorKind VecKind) const { + assert(vecType->isBuiltinType()); // Check if we've already instantiated a vector of this type. llvm::FoldingSetNodeID ID; - VectorType::Profile(ID, vecType, NumElts, Type::Vector, AltiVecSpec); + VectorType::Profile(ID, vecType, NumElts, Type::Vector, VecKind); void *InsertPos = 0; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) @@ -1550,15 +1771,14 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, // so fill in the canonical type field. QualType Canonical; if (!vecType.isCanonical()) { - Canonical = getVectorType(getCanonicalType(vecType), NumElts, - VectorType::NotAltiVec); + Canonical = getVectorType(getCanonicalType(vecType), NumElts, VecKind); // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } VectorType *New = new (*this, TypeAlignment) - VectorType(vecType, NumElts, Canonical, AltiVecSpec); + VectorType(vecType, NumElts, Canonical, VecKind); VectorTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); @@ -1566,16 +1786,14 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, /// getExtVectorType - Return the unique reference to an extended vector type of /// the specified element type and size. VectorType must be a built-in type. -QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { - BuiltinType *baseType; - - baseType = dyn_cast(getCanonicalType(vecType).getTypePtr()); - assert(baseType != 0 && "getExtVectorType(): Expecting a built-in type"); +QualType +ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const { + assert(vecType->isBuiltinType()); // Check if we've already instantiated a vector of this type. llvm::FoldingSetNodeID ID; VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, - VectorType::NotAltiVec); + VectorType::GenericVector); void *InsertPos = 0; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -1588,7 +1806,7 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } ExtVectorType *New = new (*this, TypeAlignment) ExtVectorType(vecType, NumElts, Canonical); @@ -1597,9 +1815,10 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { return QualType(New, 0); } -QualType ASTContext::getDependentSizedExtVectorType(QualType vecType, - Expr *SizeExpr, - SourceLocation AttrLoc) { +QualType +ASTContext::getDependentSizedExtVectorType(QualType vecType, + Expr *SizeExpr, + SourceLocation AttrLoc) const { llvm::FoldingSetNodeID ID; DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType), SizeExpr); @@ -1640,8 +1859,9 @@ QualType ASTContext::getDependentSizedExtVectorType(QualType vecType, /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// -QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, - const FunctionType::ExtInfo &Info) { +QualType +ASTContext::getFunctionNoProtoType(QualType ResultTy, + const FunctionType::ExtInfo &Info) const { const CallingConv CallConv = Info.getCC(); // Unique functions, to guarantee there is only one function of a particular // structure. @@ -1663,7 +1883,7 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, // Get the new insert position for the node we care about. FunctionNoProtoType *NewIP = FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } FunctionNoProtoType *New = new (*this, TypeAlignment) @@ -1675,19 +1895,14 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, /// getFunctionType - Return a normal function type with a typed argument /// list. isVariadic indicates whether the argument list includes '...'. -QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, - unsigned NumArgs, bool isVariadic, - unsigned TypeQuals, bool hasExceptionSpec, - bool hasAnyExceptionSpec, unsigned NumExs, - const QualType *ExArray, - const FunctionType::ExtInfo &Info) { - const CallingConv CallConv= Info.getCC(); +QualType +ASTContext::getFunctionType(QualType ResultTy, + const QualType *ArgArray, unsigned NumArgs, + const FunctionProtoType::ExtProtoInfo &EPI) const { // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; - FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic, - TypeQuals, hasExceptionSpec, hasAnyExceptionSpec, - NumExs, ExArray, Info); + FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI); void *InsertPos = 0; if (FunctionProtoType *FTP = @@ -1695,11 +1910,13 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, return QualType(FTP, 0); // Determine whether the type being created is already canonical or not. - bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical(); + bool isCanonical = !EPI.HasExceptionSpec && ResultTy.isCanonical(); for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; + const CallingConv CallConv = EPI.ExtInfo.getCC(); + // If this type isn't canonical, get the canonical version of it. // The exception spec is not part of the canonical type. QualType Canonical; @@ -1709,28 +1926,33 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, for (unsigned i = 0; i != NumArgs; ++i) CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); + FunctionProtoType::ExtProtoInfo CanonicalEPI = EPI; + if (CanonicalEPI.HasExceptionSpec) { + CanonicalEPI.HasExceptionSpec = false; + CanonicalEPI.HasAnyExceptionSpec = false; + CanonicalEPI.NumExceptions = 0; + } + CanonicalEPI.ExtInfo + = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); + Canonical = getFunctionType(getCanonicalType(ResultTy), CanonicalArgs.data(), NumArgs, - isVariadic, TypeQuals, false, - false, 0, 0, - Info.withCallingConv(getCanonicalCallConv(CallConv))); + CanonicalEPI); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; } // FunctionProtoType objects are allocated with extra bytes after them // for two variable size arrays (for parameter and exception types) at the // end of them. - FunctionProtoType *FTP = - (FunctionProtoType*)Allocate(sizeof(FunctionProtoType) + - NumArgs*sizeof(QualType) + - NumExs*sizeof(QualType), TypeAlignment); - new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, isVariadic, - TypeQuals, hasExceptionSpec, hasAnyExceptionSpec, - ExArray, NumExs, Canonical, Info); + size_t Size = sizeof(FunctionProtoType) + + NumArgs * sizeof(QualType) + + EPI.NumExceptions * sizeof(QualType); + FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); + new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, EPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); @@ -1752,7 +1974,7 @@ static bool NeedsInjectedClassNameType(const RecordDecl *D) { /// getInjectedClassNameType - Return the unique reference to the /// injected class name type for the specified templated declaration. QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl, - QualType TST) { + QualType TST) const { assert(NeedsInjectedClassNameType(Decl)); if (Decl->TypeForDecl) { assert(isa(Decl->TypeForDecl)); @@ -1761,16 +1983,17 @@ QualType ASTContext::getInjectedClassNameType(CXXRecordDecl *Decl, Decl->TypeForDecl = PrevDecl->TypeForDecl; assert(isa(Decl->TypeForDecl)); } else { - Decl->TypeForDecl = + Type *newType = new (*this, TypeAlignment) InjectedClassNameType(Decl, TST); - Types.push_back(Decl->TypeForDecl); + Decl->TypeForDecl = newType; + Types.push_back(newType); } return QualType(Decl->TypeForDecl, 0); } /// getTypeDeclType - Return the unique reference to the type for the /// specified type declaration. -QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { +QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { assert(Decl && "Passed null for Decl param"); assert(!Decl->TypeForDecl && "TypeForDecl present in slow case"); @@ -1791,56 +2014,81 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) { return getEnumType(Enum); } else if (const UnresolvedUsingTypenameDecl *Using = dyn_cast(Decl)) { - Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using); + Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using); + Decl->TypeForDecl = newType; + Types.push_back(newType); } else llvm_unreachable("TypeDecl without a type?"); - Types.push_back(Decl->TypeForDecl); return QualType(Decl->TypeForDecl, 0); } /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. QualType -ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) { +ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); if (Canonical.isNull()) Canonical = getCanonicalType(Decl->getUnderlyingType()); - Decl->TypeForDecl = new(*this, TypeAlignment) + TypedefType *newType = new(*this, TypeAlignment) TypedefType(Type::Typedef, Decl, Canonical); - Types.push_back(Decl->TypeForDecl); - return QualType(Decl->TypeForDecl, 0); + Decl->TypeForDecl = newType; + Types.push_back(newType); + return QualType(newType, 0); } -QualType ASTContext::getRecordType(const RecordDecl *Decl) { +QualType ASTContext::getRecordType(const RecordDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); if (const RecordDecl *PrevDecl = Decl->getPreviousDeclaration()) if (PrevDecl->TypeForDecl) return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); - Decl->TypeForDecl = new (*this, TypeAlignment) RecordType(Decl); - Types.push_back(Decl->TypeForDecl); - return QualType(Decl->TypeForDecl, 0); + RecordType *newType = new (*this, TypeAlignment) RecordType(Decl); + Decl->TypeForDecl = newType; + Types.push_back(newType); + return QualType(newType, 0); } -QualType ASTContext::getEnumType(const EnumDecl *Decl) { +QualType ASTContext::getEnumType(const EnumDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); if (const EnumDecl *PrevDecl = Decl->getPreviousDeclaration()) if (PrevDecl->TypeForDecl) return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); - Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Decl); - Types.push_back(Decl->TypeForDecl); - return QualType(Decl->TypeForDecl, 0); + EnumType *newType = new (*this, TypeAlignment) EnumType(Decl); + Decl->TypeForDecl = newType; + Types.push_back(newType); + return QualType(newType, 0); } +QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, + QualType modifiedType, + QualType equivalentType) { + llvm::FoldingSetNodeID id; + AttributedType::Profile(id, attrKind, modifiedType, equivalentType); + + void *insertPos = 0; + AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos); + if (type) return QualType(type, 0); + + QualType canon = getCanonicalType(equivalentType); + type = new (*this, TypeAlignment) + AttributedType(canon, attrKind, modifiedType, equivalentType); + + Types.push_back(type); + AttributedTypes.InsertNode(type, insertPos); + + return QualType(type, 0); +} + + /// \brief Retrieve a substitution-result type. QualType ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, - QualType Replacement) { + QualType Replacement) const { assert(Replacement.isCanonical() && "replacement types must always be canonical"); @@ -1860,12 +2108,48 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, return QualType(SubstParm, 0); } +/// \brief Retrieve a +QualType ASTContext::getSubstTemplateTypeParmPackType( + const TemplateTypeParmType *Parm, + const TemplateArgument &ArgPack) { +#ifndef NDEBUG + for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(), + PEnd = ArgPack.pack_end(); + P != PEnd; ++P) { + assert(P->getKind() == TemplateArgument::Type &&"Pack contains a non-type"); + assert(P->getAsType().isCanonical() && "Pack contains non-canonical type"); + } +#endif + + llvm::FoldingSetNodeID ID; + SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack); + void *InsertPos = 0; + if (SubstTemplateTypeParmPackType *SubstParm + = SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(SubstParm, 0); + + QualType Canon; + if (!Parm->isCanonicalUnqualified()) { + Canon = getCanonicalType(QualType(Parm, 0)); + Canon = getSubstTemplateTypeParmPackType(cast(Canon), + ArgPack); + SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos); + } + + SubstTemplateTypeParmPackType *SubstParm + = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon, + ArgPack); + Types.push_back(SubstParm); + SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); + return QualType(SubstParm, 0); +} + /// \brief Retrieve the template type parameter type for a template /// parameter or parameter pack with the given depth, index, and (optionally) /// name. QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) { + IdentifierInfo *Name) const { llvm::FoldingSetNodeID ID; TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, Name); void *InsertPos = 0; @@ -1898,7 +2182,7 @@ TypeSourceInfo * ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, SourceLocation NameLoc, const TemplateArgumentListInfo &Args, - QualType CanonType) { + QualType CanonType) const { QualType TST = getTemplateSpecializationType(Name, Args, CanonType); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); @@ -1915,7 +2199,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, - QualType Canon) { + QualType Canon) const { unsigned NumArgs = Args.size(); llvm::SmallVector ArgVec; @@ -1931,7 +2215,7 @@ QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon) { + QualType Canon) const { if (!Canon.isNull()) Canon = getCanonicalType(Canon); else @@ -1955,7 +2239,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, QualType ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, - unsigned NumArgs) { + unsigned NumArgs) const { // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); llvm::SmallVector CanonArgs; @@ -1993,7 +2277,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - QualType NamedType) { + QualType NamedType) const { llvm::FoldingSetNodeID ID; ElaboratedType::Profile(ID, Keyword, NNS, NamedType); @@ -2016,10 +2300,34 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, return QualType(T, 0); } +QualType +ASTContext::getParenType(QualType InnerType) const { + llvm::FoldingSetNodeID ID; + ParenType::Profile(ID, InnerType); + + void *InsertPos = 0; + ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); + if (T) + return QualType(T, 0); + + QualType Canon = InnerType; + if (!Canon.isCanonical()) { + Canon = getCanonicalType(InnerType); + ParenType *CheckT = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!CheckT && "Paren canonical type broken"); + (void)CheckT; + } + + T = new (*this) ParenType(InnerType, Canon); + Types.push_back(T); + ParenTypes.InsertNode(T, InsertPos); + return QualType(T, 0); +} + QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - QualType Canon) { + QualType Canon) const { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); if (Canon.isNull()) { @@ -2052,7 +2360,7 @@ ASTContext::getDependentTemplateSpecializationType( ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - const TemplateArgumentListInfo &Args) { + const TemplateArgumentListInfo &Args) const { // TODO: avoid this copy llvm::SmallVector ArgCopy; for (unsigned I = 0, E = Args.size(); I != E; ++I) @@ -2068,7 +2376,7 @@ ASTContext::getDependentTemplateSpecializationType( NestedNameSpecifier *NNS, const IdentifierInfo *Name, unsigned NumArgs, - const TemplateArgument *Args) { + const TemplateArgument *Args) const { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; @@ -2114,6 +2422,33 @@ ASTContext::getDependentTemplateSpecializationType( return QualType(T, 0); } +QualType ASTContext::getPackExpansionType(QualType Pattern, + llvm::Optional NumExpansions) { + llvm::FoldingSetNodeID ID; + PackExpansionType::Profile(ID, Pattern, NumExpansions); + + assert(Pattern->containsUnexpandedParameterPack() && + "Pack expansions must expand one or more parameter packs"); + void *InsertPos = 0; + PackExpansionType *T + = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); + if (T) + return QualType(T, 0); + + QualType Canon; + if (!Pattern.isCanonical()) { + Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions); + + // Find the insert position again. + PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); + } + + T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions); + Types.push_back(T); + PackExpansionTypes.InsertNode(T, InsertPos); + return QualType(T, 0); +} + /// CmpProtocolNames - Comparison predicate for sorting protocols /// alphabetically. static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, @@ -2145,7 +2480,7 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, QualType ASTContext::getObjCObjectType(QualType BaseType, ObjCProtocolDecl * const *Protocols, - unsigned NumProtocols) { + unsigned NumProtocols) const { // If the base type is an interface and there aren't any protocols // to add, then the interface type will do just fine. if (!NumProtocols && isa(BaseType)) @@ -2193,7 +2528,7 @@ QualType ASTContext::getObjCObjectType(QualType BaseType, /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for /// the given object type. -QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) { +QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const { llvm::FoldingSetNodeID ID; ObjCObjectPointerType::Profile(ID, ObjectT); @@ -2223,7 +2558,7 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) { /// 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) { +QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); @@ -2240,7 +2575,7 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl) { /// multiple declarations that refer to "typeof(x)" all contain different /// DeclRefExpr's. This doesn't effect the type checker, since it operates /// on canonical type's (which are always unique). -QualType ASTContext::getTypeOfExprType(Expr *tofExpr) { +QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { TypeOfExprType *toe; if (tofExpr->isTypeDependent()) { llvm::FoldingSetNodeID ID; @@ -2275,7 +2610,7 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) { /// memory savings. Since typeof(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::getTypeOfType(QualType tofType) { +QualType ASTContext::getTypeOfType(QualType tofType) const { QualType Canonical = getCanonicalType(tofType); TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical); Types.push_back(tot); @@ -2284,7 +2619,7 @@ QualType ASTContext::getTypeOfType(QualType tofType) { /// 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, ASTContext &Context) { +static QualType getDecltypeForExpr(const Expr *e, const ASTContext &Context) { if (e->isTypeDependent()) return Context.DependentTy; @@ -2308,7 +2643,7 @@ static QualType getDecltypeForExpr(const Expr *e, ASTContext &Context) { // 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(Context) == Expr::LV_Valid) + if (e->isLValue()) T = Context.getLValueReferenceType(T); return T; @@ -2319,7 +2654,7 @@ static QualType getDecltypeForExpr(const Expr *e, ASTContext &Context) { /// 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) { +QualType ASTContext::getDecltypeType(Expr *e) const { DecltypeType *dt; if (e->isTypeDependent()) { llvm::FoldingSetNodeID ID; @@ -2348,9 +2683,17 @@ QualType ASTContext::getDecltypeType(Expr *e) { return QualType(dt, 0); } +/// getAutoType - Unlike many "get" functions, we don't unique +/// AutoType AST's. +QualType ASTContext::getAutoType(QualType DeducedType) const { + AutoType *at = new (*this, TypeAlignment) AutoType(DeducedType); + Types.push_back(at); + return QualType(at, 0); +} + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. -QualType ASTContext::getTagDeclType(const TagDecl *Decl) { +QualType ASTContext::getTagDeclType(const TagDecl *Decl) const { assert (Decl); // FIXME: What is the design on getTagDeclType when it requires casting // away const? mutable? @@ -2388,12 +2731,12 @@ QualType ASTContext::getPointerDiffType() const { // Type Operators //===----------------------------------------------------------------------===// -CanQualType ASTContext::getCanonicalParamType(QualType T) { +CanQualType ASTContext::getCanonicalParamType(QualType T) const { // Push qualifiers into arrays, and then discard any remaining // qualifiers. T = getCanonicalType(T); + T = getVariableArrayDecayedType(T); const Type *Ty = T.getTypePtr(); - QualType Result; if (isa(Ty)) { Result = getArrayDecayedType(QualType(Ty,0)); @@ -2406,97 +2749,59 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) { return CanQualType::CreateUnsafe(Result); } -/// getCanonicalType - Return the canonical (structural) type corresponding to -/// the specified potentially non-canonical type. The non-canonical version -/// of a type may have many "decorated" versions of types. Decorators can -/// include typedefs, 'typeof' operators, etc. The returned type is guaranteed -/// to be free of any of these, allowing two canonical types to be compared -/// for exact equality with a simple pointer comparison. -CanQualType ASTContext::getCanonicalType(QualType T) { - QualifierCollector Quals; - const Type *Ptr = Quals.strip(T); - QualType CanType = Ptr->getCanonicalTypeInternal(); - - // The canonical internal type will be the canonical type *except* - // that we push type qualifiers down through array types. - - // If there are no new qualifiers to push down, stop here. - if (!Quals.hasQualifiers()) - return CanQualType::CreateUnsafe(CanType); - - // If the type qualifiers are on an array type, get the canonical - // type of the array with the qualifiers applied to the element - // type. - ArrayType *AT = dyn_cast(CanType); - if (!AT) - return CanQualType::CreateUnsafe(getQualifiedType(CanType, Quals)); - - // Get the canonical version of the element with the extra qualifiers on it. - // This can recursively sink qualifiers through multiple levels of arrays. - QualType NewEltTy = getQualifiedType(AT->getElementType(), Quals); - NewEltTy = getCanonicalType(NewEltTy); - - if (ConstantArrayType *CAT = dyn_cast(AT)) - return CanQualType::CreateUnsafe( - getConstantArrayType(NewEltTy, CAT->getSize(), - CAT->getSizeModifier(), - CAT->getIndexTypeCVRQualifiers())); - if (IncompleteArrayType *IAT = dyn_cast(AT)) - return CanQualType::CreateUnsafe( - getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(), - IAT->getIndexTypeCVRQualifiers())); - - if (DependentSizedArrayType *DSAT = dyn_cast(AT)) - return CanQualType::CreateUnsafe( - getDependentSizedArrayType(NewEltTy, - DSAT->getSizeExpr() ? - DSAT->getSizeExpr()->Retain() : 0, - DSAT->getSizeModifier(), - DSAT->getIndexTypeCVRQualifiers(), - DSAT->getBracketsRange())->getCanonicalTypeInternal()); - - VariableArrayType *VAT = cast(AT); - return CanQualType::CreateUnsafe(getVariableArrayType(NewEltTy, - VAT->getSizeExpr() ? - VAT->getSizeExpr()->Retain() : 0, - VAT->getSizeModifier(), - VAT->getIndexTypeCVRQualifiers(), - VAT->getBracketsRange())); -} -QualType ASTContext::getUnqualifiedArrayType(QualType T, - Qualifiers &Quals) { - Quals = T.getQualifiers(); - const ArrayType *AT = getAsArrayType(T); +QualType ASTContext::getUnqualifiedArrayType(QualType type, + Qualifiers &quals) { + SplitQualType splitType = type.getSplitUnqualifiedType(); + + // FIXME: getSplitUnqualifiedType() actually walks all the way to + // the unqualified desugared type and then drops it on the floor. + // We then have to strip that sugar back off with + // getUnqualifiedDesugaredType(), which is silly. + const ArrayType *AT = + dyn_cast(splitType.first->getUnqualifiedDesugaredType()); + + // If we don't have an array, just use the results in splitType. if (!AT) { - return T.getUnqualifiedType(); + quals = splitType.second; + return QualType(splitType.first, 0); } - QualType Elt = AT->getElementType(); - QualType UnqualElt = getUnqualifiedArrayType(Elt, Quals); - if (Elt == UnqualElt) - return T; + // Otherwise, recurse on the array's element type. + QualType elementType = AT->getElementType(); + QualType unqualElementType = getUnqualifiedArrayType(elementType, quals); + + // If that didn't change the element type, AT has no qualifiers, so we + // 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); + } + + // Otherwise, add in the qualifiers from the outermost type, then + // build the type back up. + quals.addConsistentQualifiers(splitType.second); if (const ConstantArrayType *CAT = dyn_cast(AT)) { - return getConstantArrayType(UnqualElt, CAT->getSize(), + return getConstantArrayType(unqualElementType, CAT->getSize(), CAT->getSizeModifier(), 0); } if (const IncompleteArrayType *IAT = dyn_cast(AT)) { - return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0); + return getIncompleteArrayType(unqualElementType, IAT->getSizeModifier(), 0); } if (const VariableArrayType *VAT = dyn_cast(AT)) { - return getVariableArrayType(UnqualElt, - VAT->getSizeExpr() ? - VAT->getSizeExpr()->Retain() : 0, + return getVariableArrayType(unqualElementType, + VAT->getSizeExpr(), VAT->getSizeModifier(), VAT->getIndexTypeCVRQualifiers(), VAT->getBracketsRange()); } const DependentSizedArrayType *DSAT = cast(AT); - return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(), + return getDependentSizedArrayType(unqualElementType, DSAT->getSizeExpr(), DSAT->getSizeModifier(), 0, SourceRange()); } @@ -2543,8 +2848,9 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { return false; } -DeclarationNameInfo ASTContext::getNameForTemplate(TemplateName Name, - SourceLocation NameLoc) { +DeclarationNameInfo +ASTContext::getNameForTemplate(TemplateName Name, + SourceLocation NameLoc) const { if (TemplateDecl *TD = Name.getAsTemplateDecl()) // DNInfo work in progress: CHECKME: what about DNLoc? return DeclarationNameInfo(TD->getDeclName(), NameLoc); @@ -2570,7 +2876,7 @@ DeclarationNameInfo ASTContext::getNameForTemplate(TemplateName Name, return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc); } -TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { +TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const { if (TemplateDecl *Template = Name.getAsTemplateDecl()) { if (TemplateTemplateParmDecl *TTP = dyn_cast(Template)) @@ -2580,6 +2886,15 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) { return TemplateName(cast(Template->getCanonicalDecl())); } + if (SubstTemplateTemplateParmPackStorage *SubstPack + = Name.getAsSubstTemplateTemplateParmPack()) { + TemplateTemplateParmDecl *CanonParam + = getCanonicalTemplateTemplateParmDecl(SubstPack->getParameterPack()); + TemplateArgument CanonArgPack + = getCanonicalTemplateArgument(SubstPack->getArgumentPack()); + return getSubstTemplateTemplateParmPack(CanonParam, CanonArgPack); + } + assert(!Name.getAsOverloadedTemplate()); DependentTemplateName *DTN = Name.getAsDependentTemplateName(); @@ -2594,7 +2909,7 @@ bool ASTContext::hasSameTemplateName(TemplateName X, TemplateName Y) { } TemplateArgument -ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { +ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { switch (Arg.getKind()) { case TemplateArgument::Null: return Arg; @@ -2607,7 +2922,12 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { case TemplateArgument::Template: return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate())); - + + case TemplateArgument::TemplateExpansion: + return TemplateArgument(getCanonicalTemplateName( + Arg.getAsTemplateOrTemplatePattern()), + Arg.getNumTemplateExpansions()); + case TemplateArgument::Integral: return TemplateArgument(*Arg.getAsIntegral(), getCanonicalType(Arg.getIntegralType())); @@ -2616,17 +2936,18 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { return TemplateArgument(getCanonicalType(Arg.getAsType())); case TemplateArgument::Pack: { - // FIXME: Allocate in ASTContext - TemplateArgument *CanonArgs = new TemplateArgument[Arg.pack_size()]; + if (Arg.pack_size() == 0) + return Arg; + + TemplateArgument *CanonArgs + = new (*this) TemplateArgument[Arg.pack_size()]; unsigned Idx = 0; for (TemplateArgument::pack_iterator A = Arg.pack_begin(), AEnd = Arg.pack_end(); A != AEnd; (void)++A, ++Idx) CanonArgs[Idx] = getCanonicalTemplateArgument(*A); - TemplateArgument Result; - Result.setArgumentPack(CanonArgs, Arg.pack_size(), false); - return Result; + return TemplateArgument(CanonArgs, Arg.pack_size()); } } @@ -2636,7 +2957,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) { } NestedNameSpecifier * -ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) { +ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { if (!NNS) return 0; @@ -2655,9 +2976,35 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: { QualType T = getCanonicalType(QualType(NNS->getAsType(), 0)); - return NestedNameSpecifier::Create(*this, 0, - NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate, - T.getTypePtr()); + + // If we have some kind of dependent-named type (e.g., "typename T::type"), + // break it apart into its prefix and identifier, then reconsititute those + // as the canonical nested-name-specifier. This is required to canonicalize + // a dependent nested-name-specifier involving typedefs of dependent-name + // types, e.g., + // typedef typename T::type T1; + // typedef typename T1::type T2; + if (const DependentNameType *DNT = T->getAs()) { + NestedNameSpecifier *Prefix + = getCanonicalNestedNameSpecifier(DNT->getQualifier()); + return NestedNameSpecifier::Create(*this, Prefix, + const_cast(DNT->getIdentifier())); + } + + // Do the same thing as above, but with dependent-named specializations. + if (const DependentTemplateSpecializationType *DTST + = T->getAs()) { + NestedNameSpecifier *Prefix + = getCanonicalNestedNameSpecifier(DTST->getQualifier()); + TemplateName Name + = getDependentTemplateName(Prefix, DTST->getIdentifier()); + T = getTemplateSpecializationType(Name, + DTST->getArgs(), DTST->getNumArgs()); + T = getCanonicalType(T); + } + + return NestedNameSpecifier::Create(*this, 0, false, + const_cast(T.getTypePtr())); } case NestedNameSpecifier::Global: @@ -2670,7 +3017,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) { } -const ArrayType *ASTContext::getAsArrayType(QualType T) { +const ArrayType *ASTContext::getAsArrayType(QualType T) const { // Handle the non-qualified case efficiently. if (!T.hasLocalQualifiers()) { // Handle the common positive case fast. @@ -2679,8 +3026,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { } // Handle the common negative case fast. - QualType CType = T->getCanonicalTypeInternal(); - if (!isa(CType)) + if (!isa(T.getCanonicalType())) return 0; // Apply any qualifiers from the array type to the element type. This @@ -2691,19 +3037,17 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { // sugar such as a typedef in the way. If we have type qualifiers on the type // we must propagate them down into the element type. - QualifierCollector Qs; - const Type *Ty = Qs.strip(T.getDesugaredType()); + SplitQualType split = T.getSplitDesugaredType(); + Qualifiers qs = split.second; // If we have a simple case, just return now. - const ArrayType *ATy = dyn_cast(Ty); - if (ATy == 0 || Qs.empty()) + const ArrayType *ATy = dyn_cast(split.first); + if (ATy == 0 || qs.empty()) return ATy; // Otherwise, we have an array and we have qualifiers on it. Push the // qualifiers into the array element type and return a new array type. - // Get the canonical version of the element with the extra qualifiers on it. - // This can recursively sink qualifiers through multiple levels of arrays. - QualType NewEltTy = getQualifiedType(ATy->getElementType(), Qs); + QualType NewEltTy = getQualifiedType(ATy->getElementType(), qs); if (const ConstantArrayType *CAT = dyn_cast(ATy)) return cast(getConstantArrayType(NewEltTy, CAT->getSize(), @@ -2718,29 +3062,26 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { = dyn_cast(ATy)) return cast( getDependentSizedArrayType(NewEltTy, - DSAT->getSizeExpr() ? - DSAT->getSizeExpr()->Retain() : 0, + DSAT->getSizeExpr(), DSAT->getSizeModifier(), DSAT->getIndexTypeCVRQualifiers(), DSAT->getBracketsRange())); const VariableArrayType *VAT = cast(ATy); return cast(getVariableArrayType(NewEltTy, - VAT->getSizeExpr() ? - VAT->getSizeExpr()->Retain() : 0, + VAT->getSizeExpr(), VAT->getSizeModifier(), VAT->getIndexTypeCVRQualifiers(), VAT->getBracketsRange())); } - /// getArrayDecayedType - Return the properly qualified result of decaying the /// specified array type to a pointer. This operation is non-trivial when /// handling typedefs etc. The canonical type of "T" must be an array type, /// this returns a pointer to a properly qualified element of the array. /// /// See C99 6.7.5.3p7 and C99 6.3.2.1p3. -QualType ASTContext::getArrayDecayedType(QualType Ty) { +QualType ASTContext::getArrayDecayedType(QualType Ty) const { // Get the element type with 'getAsArrayType' so that we don't lose any // typedefs in the element type of the array. This also handles propagation // of type qualifiers from the array type into the element type if present @@ -2754,20 +3095,22 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) { return getQualifiedType(PtrTy, PrettyArrayType->getIndexTypeQualifiers()); } -QualType ASTContext::getBaseElementType(QualType QT) { - QualifierCollector Qs; - while (const ArrayType *AT = getAsArrayType(QualType(Qs.strip(QT), 0))) - QT = AT->getElementType(); - return Qs.apply(QT); +QualType ASTContext::getBaseElementType(const ArrayType *array) const { + return getBaseElementType(array->getElementType()); } -QualType ASTContext::getBaseElementType(const ArrayType *AT) { - QualType ElemTy = AT->getElementType(); +QualType ASTContext::getBaseElementType(QualType type) const { + Qualifiers qs; + while (true) { + SplitQualType split = type.getSplitDesugaredType(); + const ArrayType *array = split.first->getAsArrayTypeUnsafe(); + if (!array) break; - if (const ArrayType *AT = getAsArrayType(ElemTy)) - return getBaseElementType(AT); + type = array->getElementType(); + qs.addConsistentQualifiers(split.second); + } - return ElemTy; + return getQualifiedType(type, qs); } /// getConstantArrayElementCount - Returns number of constant array elements. @@ -2825,7 +3168,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, /// point types, ignoring the domain of the type (i.e. 'double' == /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If /// LHS < RHS, return -1. -int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) { +int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const { FloatingRank LHSR = getFloatingRank(LHS); FloatingRank RHSR = getFloatingRank(RHS); @@ -2839,12 +3182,13 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) { /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This /// routine will assert if passed a built-in type that isn't an integer or enum, /// or if it is not canonicalized. -unsigned ASTContext::getIntegerRank(Type *T) { +unsigned ASTContext::getIntegerRank(const Type *T) const { assert(T->isCanonicalUnqualified() && "T should be canonicalized"); - if (EnumType* ET = dyn_cast(T)) + if (const EnumType* ET = dyn_cast(T)) T = ET->getDecl()->getPromotionType().getTypePtr(); - if (T->isSpecificBuiltinType(BuiltinType::WChar)) + if (T->isSpecificBuiltinType(BuiltinType::WChar_S) || + T->isSpecificBuiltinType(BuiltinType::WChar_U)) T = getFromTargetType(Target.getWCharType()).getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Char16)) @@ -2885,7 +3229,7 @@ unsigned ASTContext::getIntegerRank(Type *T) { /// /// \returns the type this bit-field will promote to, or NULL if no /// promotion occurs. -QualType ASTContext::isPromotableBitField(Expr *E) { +QualType ASTContext::isPromotableBitField(Expr *E) const { if (E->isTypeDependent() || E->isValueDependent()) return QualType(); @@ -2917,7 +3261,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) { /// getPromotedIntegerType - Returns the type that Promotable will /// promote to: C99 6.3.1.1p2, assuming that Promotable is a promotable /// integer type. -QualType ASTContext::getPromotedIntegerType(QualType Promotable) { +QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { assert(!Promotable.isNull()); assert(Promotable->isPromotableIntegerType()); if (const EnumType *ET = Promotable->getAs()) @@ -2933,9 +3277,9 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) { /// getIntegerTypeOrder - Returns the highest ranked integer type: /// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If /// LHS < RHS, return -1. -int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) { - Type *LHSC = getCanonicalType(LHS).getTypePtr(); - Type *RHSC = getCanonicalType(RHS).getTypePtr(); +int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { + const Type *LHSC = getCanonicalType(LHS).getTypePtr(); + const Type *RHSC = getCanonicalType(RHS).getTypePtr(); if (LHSC == RHSC) return 0; bool LHSUnsigned = LHSC->isUnsignedIntegerType(); @@ -2972,7 +3316,7 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) { } static RecordDecl * -CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, +CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) { if (Ctx.getLangOptions().CPlusPlus) return CXXRecordDecl::Create(Ctx, TK, DC, L, Id); @@ -2981,7 +3325,7 @@ CreateRecordDecl(ASTContext &Ctx, RecordDecl::TagKind TK, DeclContext *DC, } // getCFConstantStringType - Return the type used for constant CFStrings. -QualType ASTContext::getCFConstantStringType() { +QualType ASTContext::getCFConstantStringType() const { if (!CFConstantStringTypeDecl) { CFConstantStringTypeDecl = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), @@ -3023,7 +3367,7 @@ void ASTContext::setCFConstantStringType(QualType T) { } // getNSConstantStringType - Return the type used for constant NSStrings. -QualType ASTContext::getNSConstantStringType() { +QualType ASTContext::getNSConstantStringType() const { if (!NSConstantStringTypeDecl) { NSConstantStringTypeDecl = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), @@ -3062,7 +3406,7 @@ void ASTContext::setNSConstantStringType(QualType T) { NSConstantStringTypeDecl = Rec->getDecl(); } -QualType ASTContext::getObjCFastEnumerationStateType() { +QualType ASTContext::getObjCFastEnumerationStateType() const { if (!ObjCFastEnumerationStateTypeDecl) { ObjCFastEnumerationStateTypeDecl = CreateRecordDecl(*this, TTK_Struct, TUDecl, SourceLocation(), @@ -3087,10 +3431,6 @@ QualType ASTContext::getObjCFastEnumerationStateType() { Field->setAccess(AS_public); ObjCFastEnumerationStateTypeDecl->addDecl(Field); } - if (getLangOptions().CPlusPlus) - if (CXXRecordDecl *CXXRD = - dyn_cast(ObjCFastEnumerationStateTypeDecl)) - CXXRD->setEmpty(false); ObjCFastEnumerationStateTypeDecl->completeDefinition(); } @@ -3098,7 +3438,7 @@ QualType ASTContext::getObjCFastEnumerationStateType() { return getTagDeclType(ObjCFastEnumerationStateTypeDecl); } -QualType ASTContext::getBlockDescriptorType() { +QualType ASTContext::getBlockDescriptorType() const { if (BlockDescriptorType) return getTagDeclType(BlockDescriptorType); @@ -3143,7 +3483,7 @@ void ASTContext::setBlockDescriptorType(QualType T) { BlockDescriptorType = Rec->getDecl(); } -QualType ASTContext::getBlockDescriptorExtendedType() { +QualType ASTContext::getBlockDescriptorExtendedType() const { if (BlockDescriptorExtendedType) return getTagDeclType(BlockDescriptorExtendedType); @@ -3192,17 +3532,25 @@ void ASTContext::setBlockDescriptorExtendedType(QualType T) { BlockDescriptorExtendedType = Rec->getDecl(); } -bool ASTContext::BlockRequiresCopying(QualType Ty) { +bool ASTContext::BlockRequiresCopying(QualType Ty) const { if (Ty->isBlockPointerType()) return true; if (isObjCNSObjectType(Ty)) return true; if (Ty->isObjCObjectPointerType()) return true; + if (getLangOptions().CPlusPlus) { + if (const RecordType *RT = Ty->getAs()) { + CXXRecordDecl *RD = cast(RT->getDecl()); + return RD->hasConstCopyConstructor(*this); + + } + } return false; } -QualType ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) { +QualType +ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const { // type = struct __Block_byref_1_X { // void *__isa; // struct __Block_byref_1_X *__forwarding; @@ -3264,7 +3612,7 @@ QualType ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) { QualType ASTContext::getBlockParmType( bool BlockHasCopyDispose, - llvm::SmallVectorImpl &Layout) { + llvm::SmallVectorImpl &Layout) const { // FIXME: Move up llvm::SmallString<36> Name; @@ -3351,7 +3699,7 @@ static bool isTypeTypedefedAsBOOL(QualType T) { /// getObjCEncodingTypeSize returns size of type for objective-c encoding /// purpose. -CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) { +CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const { CharUnits sz = getTypeSizeInChars(type); // Make all integer and enum types at least as large as an int @@ -3368,10 +3716,11 @@ std::string charUnitsToString(const CharUnits &CU) { return llvm::itostr(CU.getQuantity()); } -/// getObjCEncodingForBlockDecl - Return the encoded type for this block +/// getObjCEncodingForBlock - Return the encoded type for this block /// declaration. -void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr, - std::string& S) { +std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { + std::string S; + const BlockDecl *Decl = Expr->getBlockDecl(); QualType BlockTy = Expr->getType()->getAs()->getPointeeType(); @@ -3414,12 +3763,50 @@ void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr, S += charUnitsToString(ParmOffset); ParmOffset += getObjCEncodingTypeSize(PType); } + + return S; +} + +void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, + std::string& S) { + // Encode result type. + getObjCEncodingForType(Decl->getResultType(), S); + CharUnits ParmOffset; + // Compute size of all parameters. + for (FunctionDecl::param_const_iterator PI = Decl->param_begin(), + E = Decl->param_end(); PI != E; ++PI) { + QualType PType = (*PI)->getType(); + CharUnits sz = getObjCEncodingTypeSize(PType); + assert (sz.isPositive() && + "getObjCEncodingForMethodDecl - Incomplete param type"); + ParmOffset += sz; + } + S += charUnitsToString(ParmOffset); + ParmOffset = CharUnits::Zero(); + + // Argument types. + for (FunctionDecl::param_const_iterator PI = Decl->param_begin(), + E = Decl->param_end(); PI != E; ++PI) { + ParmVarDecl *PVDecl = *PI; + QualType PType = PVDecl->getOriginalType(); + if (const ArrayType *AT = + dyn_cast(PType->getCanonicalTypeInternal())) { + // Use array's original type only if it has known number of + // elements. + if (!isa(AT)) + PType = PVDecl->getType(); + } else if (PType->isFunctionType()) + PType = PVDecl->getType(); + getObjCEncodingForType(PType, S); + S += charUnitsToString(ParmOffset); + ParmOffset += getObjCEncodingTypeSize(PType); + } } /// getObjCEncodingForMethodDecl - Return the encoded type for this method /// declaration. void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, - std::string& S) { + std::string& S) const { // FIXME: This is not very efficient. // Encode type qualifer, 'in', 'inout', etc. for the return type. getObjCEncodingForTypeQualifier(Decl->getObjCDeclQualifier(), S); @@ -3495,7 +3882,7 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, /// @endcode void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, const Decl *Container, - std::string& S) { + std::string& S) const { // Collect information from the property implementation decl(s). bool Dynamic = false; ObjCPropertyImplDecl *SynthesizePID = 0; @@ -3588,19 +3975,17 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const { if (isa(PointeeTy.getTypePtr())) { if (const BuiltinType *BT = PointeeTy->getAs()) { - if (BT->getKind() == BuiltinType::ULong && - ((const_cast(this))->getIntWidth(PointeeTy) == 32)) + if (BT->getKind() == BuiltinType::ULong && getIntWidth(PointeeTy) == 32) PointeeTy = UnsignedIntTy; else - if (BT->getKind() == BuiltinType::Long && - ((const_cast(this))->getIntWidth(PointeeTy) == 32)) + if (BT->getKind() == BuiltinType::Long && getIntWidth(PointeeTy) == 32) PointeeTy = IntTy; } } } void ASTContext::getObjCEncodingForType(QualType T, std::string& S, - const FieldDecl *Field) { + const FieldDecl *Field) const { // We follow the behavior of gcc, expanding structures which are // directly pointed to, and expanding embedded structures. Note that // these rules are sufficient to prevent recursive encoding of the @@ -3619,31 +4004,29 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { case BuiltinType::UShort: return 'S'; case BuiltinType::UInt: return 'I'; case BuiltinType::ULong: - return - (const_cast(C))->getIntWidth(T) == 32 ? 'L' : 'Q'; + return C->getIntWidth(T) == 32 ? 'L' : 'Q'; case BuiltinType::UInt128: return 'T'; case BuiltinType::ULongLong: return 'Q'; case BuiltinType::Char_S: case BuiltinType::SChar: return 'c'; case BuiltinType::Short: return 's'; - case BuiltinType::WChar: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: case BuiltinType::Int: return 'i'; case BuiltinType::Long: - return - (const_cast(C))->getIntWidth(T) == 32 ? 'l' : 'q'; + return C->getIntWidth(T) == 32 ? 'l' : 'q'; case BuiltinType::LongLong: return 'q'; case BuiltinType::Int128: return 't'; case BuiltinType::Float: return 'f'; case BuiltinType::Double: return 'd'; - case BuiltinType::LongDouble: return 'd'; + case BuiltinType::LongDouble: return 'D'; } } -static void EncodeBitField(const ASTContext *Context, std::string& S, +static void EncodeBitField(const ASTContext *Ctx, std::string& S, QualType T, const FieldDecl *FD) { const Expr *E = FD->getBitWidth(); assert(E && "bitfield width not there - getObjCEncodingForTypeImpl"); - ASTContext *Ctx = const_cast(Context); S += 'b'; // The NeXT runtime encodes bit fields as b followed by the number of bits. // The GNU runtime requires more information; bitfields are encoded as b, @@ -3674,7 +4057,10 @@ static void EncodeBitField(const ASTContext *Context, std::string& S, break; } S += llvm::utostr(RL.getFieldOffset(i)); - S += ObjCEncodingForPrimitiveKind(Context, T); + if (T->isEnumeralType()) + S += 'i'; + else + S += ObjCEncodingForPrimitiveKind(Ctx, T); } unsigned N = E->EvaluateAsInt(*Ctx).getZExtValue(); S += llvm::utostr(N); @@ -3686,7 +4072,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool ExpandStructures, const FieldDecl *FD, bool OutermostType, - bool EncodingProperty) { + bool EncodingProperty) const { if (T->getAs()) { if (FD && FD->isBitField()) return EncodeBitField(this, S, T, FD); @@ -3811,8 +4197,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); std::string TemplateArgsStr = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), + TemplateArgs.data(), + TemplateArgs.size(), (*this).PrintingPolicy); S += TemplateArgsStr; @@ -3846,7 +4232,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += RDecl->isUnion() ? ')' : '}'; return; } - + if (T->isEnumeralType()) { if (FD && FD->isBitField()) EncodeBitField(this, S, T, FD); @@ -3949,7 +4335,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // TODO: maybe there should be a mangling for these if (T->getAs()) return; - + + if (T->isVectorType()) { + // This matches gcc's encoding, even though technically it is + // insufficient. + // FIXME. We should do a better job than gcc. + return; + } + assert(0 && "@encode for type not implemented!"); } @@ -4000,8 +4393,9 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { /// \brief Retrieve the template name that corresponds to a non-empty /// lookup. -TemplateName ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { +TemplateName +ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, + UnresolvedSetIterator End) const { unsigned size = End - Begin; assert(size > 1 && "set is not overloaded!"); @@ -4023,9 +4417,10 @@ TemplateName ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, /// \brief Retrieve the template name that represents a qualified /// template name such as \c std::vector. -TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, - bool TemplateKeyword, - TemplateDecl *Template) { +TemplateName +ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, + bool TemplateKeyword, + TemplateDecl *Template) const { // FIXME: Canonicalization? llvm::FoldingSetNodeID ID; QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); @@ -4043,8 +4438,9 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, /// \brief Retrieve the template name that represents a dependent /// template name such as \c MetaFun::template apply. -TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, - const IdentifierInfo *Name) { +TemplateName +ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, + const IdentifierInfo *Name) const { assert((!NNS || NNS->isDependent()) && "Nested name specifier must be dependent"); @@ -4078,7 +4474,7 @@ TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, /// template name such as \c MetaFun::template operator+. TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, - OverloadedOperatorKind Operator) { + OverloadedOperatorKind Operator) const { assert((!NNS || NNS->isDependent()) && "Nested name specifier must be dependent"); @@ -4109,6 +4505,27 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, return TemplateName(QTN); } +TemplateName +ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, + const TemplateArgument &ArgPack) const { + ASTContext &Self = const_cast(*this); + llvm::FoldingSetNodeID ID; + SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack); + + void *InsertPos = 0; + SubstTemplateTemplateParmPackStorage *Subst + = SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos); + + if (!Subst) { + Subst = new (*this) SubstTemplateTemplateParmPackStorage(Self, Param, + ArgPack.pack_size(), + ArgPack.pack_begin()); + SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos); + } + + return TemplateName(Subst); +} + /// getFromTargetType - Given one of the integer types provided by /// TargetInfo, produce the corresponding type. The unsigned @p Type /// is actually a value of type @c TargetInfo::IntType. @@ -4139,7 +4556,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { /// FIXME: Move to Type. /// bool ASTContext::isObjCNSObjectType(QualType Ty) const { - if (TypedefType *TDT = dyn_cast(Ty)) { + if (const TypedefType *TDT = dyn_cast(Ty)) { if (TypedefDecl *TD = TDT->getDecl()) if (TD->getAttr()) return true; @@ -4150,24 +4567,30 @@ bool ASTContext::isObjCNSObjectType(QualType Ty) const { /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's /// garbage collection attribute. /// -Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const { - Qualifiers::GC GCAttrs = Qualifiers::GCNone; - if (getLangOptions().ObjC1 && - getLangOptions().getGCMode() != LangOptions::NonGC) { - GCAttrs = Ty.getObjCGCAttr(); - // Default behavious under objective-c's gc is for objective-c pointers - // (or pointers to them) be treated as though they were declared - // as __strong. - if (GCAttrs == Qualifiers::GCNone) { - if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) - GCAttrs = Qualifiers::Strong; - else if (Ty->isPointerType()) - return getObjCGCAttrKind(Ty->getAs()->getPointeeType()); - } - // Non-pointers have none gc'able attribute regardless of the attribute - // set on them. - else if (!Ty->isAnyPointerType() && !Ty->isBlockPointerType()) - return Qualifiers::GCNone; +Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const { + if (getLangOptions().getGCMode() == LangOptions::NonGC) + return Qualifiers::GCNone; + + assert(getLangOptions().ObjC1); + Qualifiers::GC GCAttrs = Ty.getObjCGCAttr(); + + // Default behaviour under objective-C's gc is for ObjC pointers + // (or pointers to them) be treated as though they were declared + // as __strong. + if (GCAttrs == Qualifiers::GCNone) { + if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) + return Qualifiers::Strong; + else if (Ty->isPointerType()) + return getObjCGCAttrKind(Ty->getAs()->getPointeeType()); + } else { + // It's not valid to set GC attributes on anything that isn't a + // pointer. +#ifndef NDEBUG + QualType CT = Ty->getCanonicalTypeInternal(); + while (const ArrayType *AT = dyn_cast(CT)) + CT = AT->getElementType(); + assert(CT->isAnyPointerType() || CT->isBlockPointerType()); +#endif } return GCAttrs; } @@ -4193,15 +4616,16 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, if (hasSameUnqualifiedType(FirstVec, SecondVec)) return true; - // AltiVec vectors types are identical to equivalent GCC vector types + // Treat Neon vector types and most AltiVec vector types as if they are the + // equivalent GCC vector types. const VectorType *First = FirstVec->getAs(); const VectorType *Second = SecondVec->getAs(); - if ((((First->getAltiVecSpecific() == VectorType::AltiVec) && - (Second->getAltiVecSpecific() == VectorType::NotAltiVec)) || - ((First->getAltiVecSpecific() == VectorType::NotAltiVec) && - (Second->getAltiVecSpecific() == VectorType::AltiVec))) && + if (First->getNumElements() == Second->getNumElements() && hasSameType(First->getElementType(), Second->getElementType()) && - (First->getNumElements() == Second->getNumElements())) + First->getVectorKind() != VectorType::AltiVecPixel && + First->getVectorKind() != VectorType::AltiVecBool && + Second->getVectorKind() != VectorType::AltiVecPixel && + Second->getVectorKind() != VectorType::AltiVecBool) return true; return false; @@ -4213,8 +4637,9 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, /// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the /// inheritance hierarchy of 'rProto'. -bool ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, - ObjCProtocolDecl *rProto) { +bool +ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, + ObjCProtocolDecl *rProto) const { if (lProto == rProto) return true; for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), @@ -4336,33 +4761,17 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, if (const ObjCObjectPointerType *lhsOPT = lhs->getAsObjCInterfacePointerType()) { - if (lhsOPT->qual_empty()) { - bool match = false; - if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(), - E = rhsQID->qual_end(); I != E; ++I) { - // when comparing an id

on rhs with a static type on lhs, - // static class must implement all of id's protocols directly or - // indirectly through its super class. - if (lhsID->ClassImplementsProtocol(*I, true)) { - match = true; - break; - } - } - if (!match) - return false; - } - return true; - } - // Both the right and left sides have qualifiers. + // If both the right and left sides have qualifiers. for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(), E = lhsOPT->qual_end(); I != E; ++I) { ObjCProtocolDecl *lhsProto = *I; bool match = false; - // when comparing an id

on lhs with a static type on rhs, + // when comparing an id

on rhs with a static type on lhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. + // First, lhs protocols in the qualifier list must be found, direct + // or indirect in rhs's qualifier list or it is a mismatch. for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), E = rhsQID->qual_end(); J != E; ++J) { ObjCProtocolDecl *rhsProto = *J; @@ -4375,6 +4784,35 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, if (!match) return false; } + + // Static class's protocols, or its super class or category protocols + // must be found, direct or indirect in rhs's qualifier list or it is a mismatch. + if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) { + llvm::SmallPtrSet LHSInheritedProtocols; + CollectInheritedProtocols(lhsID, LHSInheritedProtocols); + // This is rather dubious but matches gcc's behavior. If lhs has + // no type qualifier and its class has no static protocol(s) + // assume that it is mismatch. + if (LHSInheritedProtocols.empty() && lhsOPT->qual_empty()) + return false; + for (llvm::SmallPtrSet::iterator I = + LHSInheritedProtocols.begin(), + E = LHSInheritedProtocols.end(); I != E; ++I) { + bool match = false; + ObjCProtocolDecl *lhsProto = (*I); + for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), + E = rhsQID->qual_end(); J != E; ++J) { + ObjCProtocolDecl *rhsProto = *J; + if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || + (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { + match = true; + break; + } + } + if (!match) + return false; + } + } return true; } return false; @@ -4600,6 +5038,49 @@ bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) { return !mergeTypes(LHS, RHS, true).isNull(); } +/// mergeTransparentUnionType - if T is a transparent union type and a member +/// of T is compatible with SubType, return the merged type, else return +/// QualType() +QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, + bool OfBlockPointer, + bool Unqualified) { + if (const RecordType *UT = T->getAsUnionType()) { + RecordDecl *UD = UT->getDecl(); + if (UD->hasAttr()) { + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { + QualType ET = it->getType().getUnqualifiedType(); + QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified); + if (!MT.isNull()) + return MT; + } + } + } + + return QualType(); +} + +/// mergeFunctionArgumentTypes - merge two types which appear as function +/// argument types +QualType ASTContext::mergeFunctionArgumentTypes(QualType lhs, QualType rhs, + bool OfBlockPointer, + bool Unqualified) { + // GNU extension: two types are compatible if they appear as a function + // argument, one of the types is a transparent union type and the other + // type is compatible with a union member + QualType lmerge = mergeTransparentUnionType(lhs, rhs, OfBlockPointer, + Unqualified); + if (!lmerge.isNull()) + return lmerge; + + QualType rmerge = mergeTransparentUnionType(rhs, lhs, OfBlockPointer, + Unqualified); + if (!rmerge.isNull()) + return rmerge; + + return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified); +} + QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, bool OfBlockPointer, bool Unqualified) { @@ -4612,12 +5093,17 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // Check return type QualType retType; - if (OfBlockPointer) - retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true, - Unqualified); + if (OfBlockPointer) { + QualType RHS = rbase->getResultType(); + QualType LHS = lbase->getResultType(); + bool UnqualifiedResult = Unqualified; + if (!UnqualifiedResult) + UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers()); + retType = mergeTypes(RHS, LHS, true, UnqualifiedResult); + } else - retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), - false, Unqualified); + retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false, + Unqualified); if (retType.isNull()) return QualType(); if (Unqualified) @@ -4634,26 +5120,33 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, allLTypes = false; if (getCanonicalType(retType) != RRetType) allRTypes = false; + // FIXME: double check this // FIXME: should we error if lbase->getRegParmAttr() != 0 && // rbase->getRegParmAttr() != 0 && // lbase->getRegParmAttr() != rbase->getRegParmAttr()? FunctionType::ExtInfo lbaseInfo = lbase->getExtInfo(); FunctionType::ExtInfo rbaseInfo = rbase->getExtInfo(); - unsigned RegParm = lbaseInfo.getRegParm() == 0 ? rbaseInfo.getRegParm() : - lbaseInfo.getRegParm(); + + // Compatible functions must have compatible calling conventions + if (!isSameCallConv(lbaseInfo.getCC(), rbaseInfo.getCC())) + return QualType(); + + // Regparm is part of the calling convention. + if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm()) + return QualType(); + + // It's noreturn if either type is. + // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); - if (NoReturn != lbaseInfo.getNoReturn() || - RegParm != lbaseInfo.getRegParm()) + if (NoReturn != lbaseInfo.getNoReturn()) allLTypes = false; - if (NoReturn != rbaseInfo.getNoReturn() || - RegParm != rbaseInfo.getRegParm()) + if (NoReturn != rbaseInfo.getNoReturn()) allRTypes = false; - CallingConv lcc = lbaseInfo.getCC(); - CallingConv rcc = rbaseInfo.getCC(); - // Compatible functions must have compatible calling conventions - if (!isSameCallConv(lcc, rcc)) - return QualType(); + + FunctionType::ExtInfo einfo(NoReturn, + lbaseInfo.getRegParm(), + lbaseInfo.getCC()); if (lproto && rproto) { // two C99 style function prototypes assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() && @@ -4677,8 +5170,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, for (unsigned i = 0; i < lproto_nargs; i++) { QualType largtype = lproto->getArgType(i).getUnqualifiedType(); QualType rargtype = rproto->getArgType(i).getUnqualifiedType(); - QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer, - Unqualified); + QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype, + OfBlockPointer, + Unqualified); if (argtype.isNull()) return QualType(); if (Unqualified) @@ -4697,10 +5191,10 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, } if (allLTypes) return lhs; if (allRTypes) return rhs; - return getFunctionType(retType, types.begin(), types.size(), - lproto->isVariadic(), lproto->getTypeQuals(), - false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, RegParm, lcc)); + + FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo(); + EPI.ExtInfo = einfo; + return getFunctionType(retType, types.begin(), types.size(), EPI); } if (lproto) allRTypes = false; @@ -4731,17 +5225,16 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (allLTypes) return lhs; if (allRTypes) return rhs; + + FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); + EPI.ExtInfo = einfo; return getFunctionType(retType, proto->arg_type_begin(), - proto->getNumArgs(), proto->isVariadic(), - proto->getTypeQuals(), - false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, RegParm, lcc)); + proto->getNumArgs(), EPI); } if (allLTypes) return lhs; if (allRTypes) return rhs; - FunctionType::ExtInfo Info(NoReturn, RegParm, lcc); - return getFunctionNoProtoType(retType, Info); + return getFunctionNoProtoType(retType, einfo); } QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, @@ -5020,16 +5513,11 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { // In either case, use OldReturnType to build the new function type. const FunctionType *F = LHS->getAs(); if (const FunctionProtoType *FPT = cast(F)) { - FunctionType::ExtInfo Info = getFunctionExtInfo(LHS); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType = getFunctionType(OldReturnType, FPT->arg_type_begin(), - FPT->getNumArgs(), FPT->isVariadic(), - FPT->getTypeQuals(), - FPT->hasExceptionSpec(), - FPT->hasAnyExceptionSpec(), - FPT->getNumExceptions(), - FPT->exception_begin(), - Info); + FPT->getNumArgs(), EPI); return ResultType; } } @@ -5080,11 +5568,11 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { // Integer Predicates //===----------------------------------------------------------------------===// -unsigned ASTContext::getIntWidth(QualType T) { +unsigned ASTContext::getIntWidth(QualType T) const { + if (const EnumType *ET = dyn_cast(T)) + T = ET->getDecl()->getIntegerType(); if (T->isBooleanType()) return 1; - if (EnumType *ET = dyn_cast(T)) - T = ET->getDecl()->getIntegerType(); // For builtin types, just use the standard type sizing method return (unsigned)getTypeSize(T); } @@ -5095,7 +5583,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) { // Turn <4 x signed int> -> <4 x unsigned int> if (const VectorType *VTy = T->getAs()) return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()), - VTy->getNumElements(), VTy->getAltiVecSpecific()); + VTy->getNumElements(), VTy->getVectorKind()); // For enums, we return the unsigned version of the base type. if (const EnumType *ETy = T->getAs()) @@ -5127,25 +5615,38 @@ ExternalASTSource::~ExternalASTSource() { } void ExternalASTSource::PrintStats() { } +ASTMutationListener::~ASTMutationListener() { } + //===----------------------------------------------------------------------===// // Builtin Type Computation //===----------------------------------------------------------------------===// /// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the -/// pointer over the consumed characters. This returns the resultant type. -static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, +/// pointer over the consumed characters. This returns the resultant type. If +/// AllowTypeModifiers is false then modifier like * are not parsed, just basic +/// types. This allows "v2i*" to be parsed as a pointer to a v2i instead of +/// a vector of "i*". +/// +/// RequiresICE is filled in on return to indicate whether the value is required +/// to be an Integer Constant Expression. +static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, ASTContext::GetBuiltinTypeError &Error, - bool AllowTypeModifiers = true) { + bool &RequiresICE, + bool AllowTypeModifiers) { // Modifiers. int HowLong = 0; bool Signed = false, Unsigned = false; - - // Read the modifiers first. + RequiresICE = false; + + // Read the prefixed modifiers first. bool Done = false; while (!Done) { switch (*Str++) { default: Done = true; --Str; break; + case 'I': + RequiresICE = true; + break; case 'S': assert(!Unsigned && "Can't use both 'S' and 'U' modifiers!"); assert(!Signed && "Can't use 'S' modifier multiple times!"); @@ -5223,6 +5724,12 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, case 'F': Type = Context.getCFConstantStringType(); break; + case 'G': + Type = Context.getObjCIdType(); + break; + case 'H': + Type = Context.getObjCSelType(); + break; case 'a': Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); @@ -5238,27 +5745,30 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, // it to be a __va_list_tag*. Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); - if (Type->isArrayType()) { + if (Type->isArrayType()) Type = Context.getArrayDecayedType(Type); - } else { + else Type = Context.getLValueReferenceType(Type); - } break; case 'V': { char *End; unsigned NumElements = strtoul(Str, &End, 10); assert(End != Str && "Missing vector size"); - Str = End; - QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false); - // FIXME: Don't know what to do about AltiVec. + QualType ElementType = DecodeTypeFromStr(Str, Context, Error, + RequiresICE, false); + assert(!RequiresICE && "Can't require vector ICE"); + + // TODO: No way to make AltiVec vectors in builtins yet. Type = Context.getVectorType(ElementType, NumElements, - VectorType::NotAltiVec); + VectorType::GenericVector); break; } case 'X': { - QualType ElementType = DecodeTypeFromStr(Str, Context, Error, false); + QualType ElementType = DecodeTypeFromStr(Str, Context, Error, RequiresICE, + false); + assert(!RequiresICE && "Can't require complex ICE"); Type = Context.getComplexType(ElementType); break; } @@ -5282,59 +5792,70 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, break; } - if (!AllowTypeModifiers) - return Type; - - Done = false; + // If there are modifiers and if we're allowed to parse them, go for it. + Done = !AllowTypeModifiers; while (!Done) { switch (char c = *Str++) { - default: Done = true; --Str; break; - case '*': - case '&': - { - // Both pointers and references can have their pointee types - // qualified with an address space. - char *End; - unsigned AddrSpace = strtoul(Str, &End, 10); - if (End != Str && AddrSpace != 0) { - Type = Context.getAddrSpaceQualType(Type, AddrSpace); - Str = End; - } - } - if (c == '*') - Type = Context.getPointerType(Type); - else - Type = Context.getLValueReferenceType(Type); - break; - // FIXME: There's no way to have a built-in with an rvalue ref arg. - case 'C': - Type = Type.withConst(); - break; - case 'D': - Type = Context.getVolatileType(Type); - break; + default: Done = true; --Str; break; + case '*': + case '&': { + // Both pointers and references can have their pointee types + // qualified with an address space. + char *End; + unsigned AddrSpace = strtoul(Str, &End, 10); + if (End != Str && AddrSpace != 0) { + Type = Context.getAddrSpaceQualType(Type, AddrSpace); + Str = End; + } + if (c == '*') + Type = Context.getPointerType(Type); + else + Type = Context.getLValueReferenceType(Type); + break; + } + // FIXME: There's no way to have a built-in with an rvalue ref arg. + case 'C': + Type = Type.withConst(); + break; + case 'D': + Type = Context.getVolatileType(Type); + break; } } + + assert((!RequiresICE || Type->isIntegralOrEnumerationType()) && + "Integer constant 'I' type must be an integer"); return Type; } /// GetBuiltinType - Return the type for the specified builtin. -QualType ASTContext::GetBuiltinType(unsigned id, - GetBuiltinTypeError &Error) { - const char *TypeStr = BuiltinInfo.GetTypeString(id); +QualType ASTContext::GetBuiltinType(unsigned Id, + GetBuiltinTypeError &Error, + unsigned *IntegerConstantArgs) const { + const char *TypeStr = BuiltinInfo.GetTypeString(Id); llvm::SmallVector ArgTypes; + bool RequiresICE = false; Error = GE_None; - QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error); + QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error, + RequiresICE, true); if (Error != GE_None) return QualType(); + + assert(!RequiresICE && "Result of intrinsic cannot be required to be an ICE"); + while (TypeStr[0] && TypeStr[0] != '.') { - QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error); + QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true); if (Error != GE_None) return QualType(); + // If this argument is required to be an IntegerConstantExpression and the + // caller cares, fill in the bitmask we return. + if (RequiresICE && IntegerConstantArgs) + *IntegerConstantArgs |= 1 << ArgTypes.size(); + // Do array -> pointer decay. The builtin should use the decayed type. if (Ty->isArrayType()) Ty = getArrayDecayedType(Ty); @@ -5345,164 +5866,26 @@ QualType ASTContext::GetBuiltinType(unsigned id, assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); - // handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);". - if (ArgTypes.size() == 0 && TypeStr[0] == '.') - return getFunctionNoProtoType(ResType); - - // FIXME: Should we create noreturn types? - return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), - TypeStr[0] == '.', 0, false, false, 0, 0, - FunctionType::ExtInfo()); -} - -QualType -ASTContext::UsualArithmeticConversionsType(QualType lhs, QualType rhs) { - // Perform the usual unary conversions. We do this early so that - // integral promotions to "int" can allow us to exit early, in the - // lhs == rhs check. Also, for conversion purposes, we ignore any - // qualifiers. For example, "const float" and "float" are - // equivalent. - if (lhs->isPromotableIntegerType()) - lhs = getPromotedIntegerType(lhs); - else - lhs = lhs.getUnqualifiedType(); - if (rhs->isPromotableIntegerType()) - rhs = getPromotedIntegerType(rhs); - else - rhs = rhs.getUnqualifiedType(); + FunctionType::ExtInfo EI; + if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true); - // If both types are identical, no conversion is needed. - if (lhs == rhs) - return lhs; + bool Variadic = (TypeStr[0] == '.'); - // If either side is a non-arithmetic type (e.g. a pointer), we are done. - // The caller can deal with this (e.g. pointer + int). - if (!lhs->isArithmeticType() || !rhs->isArithmeticType()) - return lhs; + // We really shouldn't be making a no-proto type here, especially in C++. + if (ArgTypes.empty() && Variadic) + return getFunctionNoProtoType(ResType, EI); - // At this point, we have two different arithmetic types. + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = EI; + EPI.Variadic = Variadic; - // Handle complex types first (C99 6.3.1.8p1). - if (lhs->isComplexType() || rhs->isComplexType()) { - // if we have an integer operand, the result is the complex type. - if (rhs->isIntegerType() || rhs->isComplexIntegerType()) { - // convert the rhs to the lhs complex type. - return lhs; - } - if (lhs->isIntegerType() || lhs->isComplexIntegerType()) { - // convert the lhs to the rhs complex type. - return rhs; - } - // This handles complex/complex, complex/float, or float/complex. - // When both operands are complex, the shorter operand is converted to the - // type of the longer, and that is the type of the result. This corresponds - // to what is done when combining two real floating-point operands. - // The fun begins when size promotion occur across type domains. - // From H&S 6.3.4: When one operand is complex and the other is a real - // floating-point type, the less precise type is converted, within it's - // real or complex domain, to the precision of the other type. For example, - // when combining a "long double" with a "double _Complex", the - // "double _Complex" is promoted to "long double _Complex". - int result = getFloatingTypeOrder(lhs, rhs); - - if (result > 0) { // The left side is bigger, convert rhs. - rhs = getFloatingTypeOfSizeWithinDomain(lhs, rhs); - } else if (result < 0) { // The right side is bigger, convert lhs. - lhs = getFloatingTypeOfSizeWithinDomain(rhs, lhs); - } - // At this point, lhs and rhs have the same rank/size. Now, make sure the - // domains match. This is a requirement for our implementation, C99 - // does not require this promotion. - if (lhs != rhs) { // Domains don't match, we have complex/float mix. - if (lhs->isRealFloatingType()) { // handle "double, _Complex double". - return rhs; - } else { // handle "_Complex double, double". - return lhs; - } - } - return lhs; // The domain/size match exactly. - } - // Now handle "real" floating types (i.e. float, double, long double). - if (lhs->isRealFloatingType() || rhs->isRealFloatingType()) { - // if we have an integer operand, the result is the real floating type. - if (rhs->isIntegerType()) { - // convert rhs to the lhs floating point type. - return lhs; - } - if (rhs->isComplexIntegerType()) { - // convert rhs to the complex floating point type. - return getComplexType(lhs); - } - if (lhs->isIntegerType()) { - // convert lhs to the rhs floating point type. - return rhs; - } - if (lhs->isComplexIntegerType()) { - // convert lhs to the complex floating point type. - return getComplexType(rhs); - } - // We have two real floating types, float/complex combos were handled above. - // Convert the smaller operand to the bigger result. - int result = getFloatingTypeOrder(lhs, rhs); - if (result > 0) // convert the rhs - return lhs; - assert(result < 0 && "illegal float comparison"); - return rhs; // convert the lhs - } - if (lhs->isComplexIntegerType() || rhs->isComplexIntegerType()) { - // Handle GCC complex int extension. - const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType(); - const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType(); - - if (lhsComplexInt && rhsComplexInt) { - if (getIntegerTypeOrder(lhsComplexInt->getElementType(), - rhsComplexInt->getElementType()) >= 0) - return lhs; // convert the rhs - return rhs; - } else if (lhsComplexInt && rhs->isIntegerType()) { - // convert the rhs to the lhs complex type. - return lhs; - } else if (rhsComplexInt && lhs->isIntegerType()) { - // convert the lhs to the rhs complex type. - return rhs; - } - } - // Finally, we have two differing integer types. - // The rules for this case are in C99 6.3.1.8 - int compare = getIntegerTypeOrder(lhs, rhs); - bool lhsSigned = lhs->hasSignedIntegerRepresentation(), - rhsSigned = rhs->hasSignedIntegerRepresentation(); - QualType destType; - if (lhsSigned == rhsSigned) { - // Same signedness; use the higher-ranked type - destType = compare >= 0 ? lhs : rhs; - } else if (compare != (lhsSigned ? 1 : -1)) { - // The unsigned type has greater than or equal rank to the - // signed type, so use the unsigned type - destType = lhsSigned ? rhs : lhs; - } else if (getIntWidth(lhs) != getIntWidth(rhs)) { - // The two types are different widths; if we are here, that - // means the signed type is larger than the unsigned type, so - // use the signed type. - destType = lhsSigned ? lhs : rhs; - } else { - // The signed type is higher-ranked than the unsigned type, - // but isn't actually any bigger (like unsigned int and long - // on most 32-bit systems). Use the unsigned type corresponding - // to the signed type. - destType = getCorrespondingUnsignedType(lhsSigned ? lhs : rhs); - } - return destType; + return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI); } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { GVALinkage External = GVA_StrongExternal; Linkage L = FD->getLinkage(); - if (L == ExternalLinkage && getLangOptions().CPlusPlus && - FD->getType()->getLinkage() == UniqueExternalLinkage) - L = UniqueExternalLinkage; - switch (L) { case NoLinkage: case InternalLinkage: @@ -5663,4 +6046,26 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { return true; } +CallingConv ASTContext::getDefaultMethodCallConv() { + // Pass through to the C++ ABI object + return ABI->getDefaultMethodCallConv(); +} + +bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { + // Pass through to the C++ ABI object + return ABI->isNearlyEmpty(RD); +} + +MangleContext *ASTContext::createMangleContext() { + switch (Target.getCXXABI()) { + case CXXABI_ARM: + case CXXABI_Itanium: + return createItaniumMangleContext(*this, getDiagnostics()); + case CXXABI_Microsoft: + return createMicrosoftMangleContext(*this, getDiagnostics()); + } + assert(0 && "Unsupported ABI"); + return 0; +} + CXXABI::~CXXABI() {} diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 23f323d0286a..5bf8a38199b6 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -28,14 +28,26 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { const Type *Ty = QC.strip(QT); // Don't aka just because we saw an elaborated type... - if (isa(Ty)) { - QT = cast(Ty)->desugar(); + if (const ElaboratedType *ET = dyn_cast(Ty)) { + QT = ET->desugar(); continue; } - - // ...or a substituted template type parameter. - if (isa(Ty)) { - QT = cast(Ty)->desugar(); + // ... or a paren type ... + if (const ParenType *PT = dyn_cast(Ty)) { + QT = PT->desugar(); + continue; + } + // ...or a substituted template type parameter ... + if (const SubstTemplateTypeParmType *ST = + dyn_cast(Ty)) { + QT = ST->desugar(); + continue; + } + // ... or an auto type. + if (const AutoType *AT = dyn_cast(Ty)) { + if (!AT->isSugared()) + break; + QT = AT->desugar(); continue; } @@ -81,10 +93,10 @@ break; \ break; // Don't desugar through the primary typedef of an anonymous type. - if (isa(Underlying) && isa(QT)) - if (cast(Underlying)->getDecl()->getTypedefForAnonDecl() == - cast(QT)->getDecl()) - break; + if (const TagType *UTT = Underlying->getAs()) + if (const TypedefType *QTT = dyn_cast(QT)) + if (UTT->getDecl()->getTypedefForAnonDecl() == QTT->getDecl()) + break; // Record that we actually looked through an opaque type here. ShouldAKA = true; @@ -94,14 +106,17 @@ break; \ // If we have a pointer-like type, desugar the pointee as well. // FIXME: Handle other pointer-like types. if (const PointerType *Ty = QT->getAs()) { - QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), - ShouldAKA)); + QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), + ShouldAKA)); } else if (const LValueReferenceType *Ty = QT->getAs()) { - QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), - ShouldAKA)); + QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), + ShouldAKA)); + } else if (const RValueReferenceType *Ty = QT->getAs()) { + QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(), + ShouldAKA)); } - return QC.apply(QT); + return QC.apply(Context, QT); } /// \brief Convert the given type to a string suitable for printing as part of @@ -151,13 +166,10 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, bool ShouldAKA = false; QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); if (ShouldAKA) { - std::string D = DesugaredTy.getAsString(Context.PrintingPolicy); - if (D != S) { - S = "'" + S + "' (aka '"; - S += D; - S += "')"; - return S; - } + S = "'" + S + "' (aka '"; + S += DesugaredTy.getAsString(Context.PrintingPolicy); + S += "')"; + return S; } } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 2edd09c067e9..65c0a3bb619f 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -41,41 +41,42 @@ namespace { using StmtVisitor::Visit; // Importing types - QualType VisitType(Type *T); - QualType VisitBuiltinType(BuiltinType *T); - QualType VisitComplexType(ComplexType *T); - QualType VisitPointerType(PointerType *T); - QualType VisitBlockPointerType(BlockPointerType *T); - QualType VisitLValueReferenceType(LValueReferenceType *T); - QualType VisitRValueReferenceType(RValueReferenceType *T); - QualType VisitMemberPointerType(MemberPointerType *T); - QualType VisitConstantArrayType(ConstantArrayType *T); - QualType VisitIncompleteArrayType(IncompleteArrayType *T); - QualType VisitVariableArrayType(VariableArrayType *T); + QualType VisitType(const Type *T); + QualType VisitBuiltinType(const BuiltinType *T); + QualType VisitComplexType(const ComplexType *T); + QualType VisitPointerType(const PointerType *T); + QualType VisitBlockPointerType(const BlockPointerType *T); + QualType VisitLValueReferenceType(const LValueReferenceType *T); + QualType VisitRValueReferenceType(const RValueReferenceType *T); + QualType VisitMemberPointerType(const MemberPointerType *T); + QualType VisitConstantArrayType(const ConstantArrayType *T); + QualType VisitIncompleteArrayType(const IncompleteArrayType *T); + QualType VisitVariableArrayType(const VariableArrayType *T); // FIXME: DependentSizedArrayType // FIXME: DependentSizedExtVectorType - QualType VisitVectorType(VectorType *T); - QualType VisitExtVectorType(ExtVectorType *T); - QualType VisitFunctionNoProtoType(FunctionNoProtoType *T); - QualType VisitFunctionProtoType(FunctionProtoType *T); + QualType VisitVectorType(const VectorType *T); + QualType VisitExtVectorType(const ExtVectorType *T); + QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T); + QualType VisitFunctionProtoType(const FunctionProtoType *T); // FIXME: UnresolvedUsingType - QualType VisitTypedefType(TypedefType *T); - QualType VisitTypeOfExprType(TypeOfExprType *T); + QualType VisitTypedefType(const TypedefType *T); + QualType VisitTypeOfExprType(const TypeOfExprType *T); // FIXME: DependentTypeOfExprType - QualType VisitTypeOfType(TypeOfType *T); - QualType VisitDecltypeType(DecltypeType *T); + QualType VisitTypeOfType(const TypeOfType *T); + QualType VisitDecltypeType(const DecltypeType *T); + QualType VisitAutoType(const AutoType *T); // FIXME: DependentDecltypeType - QualType VisitRecordType(RecordType *T); - QualType VisitEnumType(EnumType *T); + QualType VisitRecordType(const RecordType *T); + QualType VisitEnumType(const EnumType *T); // FIXME: TemplateTypeParmType // FIXME: SubstTemplateTypeParmType - // FIXME: TemplateSpecializationType - QualType VisitElaboratedType(ElaboratedType *T); + QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); + QualType VisitElaboratedType(const ElaboratedType *T); // FIXME: DependentNameType // FIXME: DependentTemplateSpecializationType - QualType VisitObjCInterfaceType(ObjCInterfaceType *T); - QualType VisitObjCObjectType(ObjCObjectType *T); - QualType VisitObjCObjectPointerType(ObjCObjectPointerType *T); + QualType VisitObjCInterfaceType(const ObjCInterfaceType *T); + QualType VisitObjCObjectType(const ObjCObjectType *T); + QualType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); // Importing declarations bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, @@ -83,9 +84,17 @@ namespace { SourceLocation &Loc); void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); - void ImportDeclContext(DeclContext *FromDC); + void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); + bool ImportDefinition(RecordDecl *From, RecordDecl *To); + TemplateParameterList *ImportTemplateParameterList( + TemplateParameterList *Params); + TemplateArgument ImportTemplateArgument(const TemplateArgument &From); + bool ImportTemplateArguments(const TemplateArgument *FromArgs, + unsigned NumFromArgs, + llvm::SmallVectorImpl &ToArgs); bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord); bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord); + bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitTypedefDecl(TypedefDecl *D); @@ -98,6 +107,7 @@ namespace { Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D); Decl *VisitCXXConversionDecl(CXXConversionDecl *D); Decl *VisitFieldDecl(FieldDecl *D); + Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D); Decl *VisitObjCIvarDecl(ObjCIvarDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -106,9 +116,18 @@ namespace { Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); + Decl *VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); + 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); + Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); + Decl *VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D); // Importing statements Stmt *VisitStmt(Stmt *S); @@ -137,9 +156,6 @@ namespace { /// \brief AST contexts for which we are checking structural equivalence. ASTContext &C1, &C2; - /// \brief Diagnostic object used to emit diagnostics. - Diagnostic &Diags; - /// \brief The set of "tentative" equivalences between two canonical /// declarations, mapping from a declaration in the first context to the /// declaration in the second context that we believe to be equivalent. @@ -158,10 +174,9 @@ namespace { bool StrictTypeSpelling; StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2, - Diagnostic &Diags, llvm::DenseSet > &NonEquivalentDecls, bool StrictTypeSpelling = false) - : C1(C1), C2(C2), Diags(Diags), NonEquivalentDecls(NonEquivalentDecls), + : C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls), StrictTypeSpelling(StrictTypeSpelling) { } /// \brief Determine whether the two declarations are structurally @@ -179,11 +194,11 @@ namespace { public: DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, C1.getSourceManager()), DiagID); + return C1.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, C2.getSourceManager()), DiagID); + return C2.getDiagnostics().Report(Loc, DiagID); } }; } @@ -200,9 +215,9 @@ static bool IsSameValue(const llvm::APInt &I1, const llvm::APInt &I2) { return I1 == I2; if (I1.getBitWidth() > I2.getBitWidth()) - return I1 == llvm::APInt(I2).zext(I1.getBitWidth()); + return I1 == I2.zext(I1.getBitWidth()); - return llvm::APInt(I1).zext(I2.getBitWidth()) == I2; + return I1.zext(I2.getBitWidth()) == I2; } /// \brief Determine if two APSInts have the same value, zero- or sign-extending @@ -213,9 +228,9 @@ static bool IsSameValue(const llvm::APSInt &I1, const llvm::APSInt &I2) { // Check for a bit-width mismatch. if (I1.getBitWidth() > I2.getBitWidth()) - return IsSameValue(I1, llvm::APSInt(I2).extend(I1.getBitWidth())); + return IsSameValue(I1, I2.extend(I1.getBitWidth())); else if (I2.getBitWidth() > I1.getBitWidth()) - return IsSameValue(llvm::APSInt(I1).extend(I2.getBitWidth()), I2); + return IsSameValue(I1.extend(I2.getBitWidth()), I2); // We have a signedness mismatch. Turn the signed value into an unsigned // value. @@ -263,7 +278,54 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, const TemplateArgument &Arg1, const TemplateArgument &Arg2) { - // FIXME: Implement! + if (Arg1.getKind() != Arg2.getKind()) + return false; + + switch (Arg1.getKind()) { + case TemplateArgument::Null: + return true; + + case TemplateArgument::Type: + return Context.IsStructurallyEquivalent(Arg1.getAsType(), Arg2.getAsType()); + + case TemplateArgument::Integral: + if (!Context.IsStructurallyEquivalent(Arg1.getIntegralType(), + Arg2.getIntegralType())) + return false; + + return IsSameValue(*Arg1.getAsIntegral(), *Arg2.getAsIntegral()); + + case TemplateArgument::Declaration: + return Context.IsStructurallyEquivalent(Arg1.getAsDecl(), Arg2.getAsDecl()); + + case TemplateArgument::Template: + return IsStructurallyEquivalent(Context, + Arg1.getAsTemplate(), + Arg2.getAsTemplate()); + + case TemplateArgument::TemplateExpansion: + return IsStructurallyEquivalent(Context, + Arg1.getAsTemplateOrTemplatePattern(), + Arg2.getAsTemplateOrTemplatePattern()); + + case TemplateArgument::Expression: + return IsStructurallyEquivalent(Context, + Arg1.getAsExpr(), Arg2.getAsExpr()); + + case TemplateArgument::Pack: + if (Arg1.pack_size() != Arg2.pack_size()) + return false; + + for (unsigned I = 0, N = Arg1.pack_size(); I != N; ++I) + if (!IsStructurallyEquivalent(Context, + Arg1.pack_begin()[I], + Arg2.pack_begin()[I])) + return false; + + return true; + } + + llvm_unreachable("Invalid template argument kind"); return true; } @@ -441,7 +503,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; if (Vec1->getNumElements() != Vec2->getNumElements()) return false; - if (Vec1->getAltiVecSpecific() != Vec2->getAltiVecSpecific()) + if (Vec1->getVectorKind() != Vec2->getVectorKind()) return false; break; } @@ -496,7 +558,25 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + + case Type::Attributed: + if (!IsStructurallyEquivalent(Context, + cast(T1)->getModifiedType(), + cast(T2)->getModifiedType())) + return false; + if (!IsStructurallyEquivalent(Context, + cast(T1)->getEquivalentType(), + cast(T2)->getEquivalentType())) + return false; + break; + case Type::Paren: + if (!IsStructurallyEquivalent(Context, + cast(T1)->getInnerType(), + cast(T2)->getInnerType())) + return false; + break; + case Type::Typedef: if (!IsStructurallyEquivalent(Context, cast(T1)->getDecl(), @@ -525,6 +605,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::Auto: + if (!IsStructurallyEquivalent(Context, + cast(T1)->getDeducedType(), + cast(T2)->getDeducedType())) + return false; + break; + case Type::Record: case Type::Enum: if (!IsStructurallyEquivalent(Context, @@ -563,6 +650,21 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, break; } + case Type::SubstTemplateTypeParmPack: { + const SubstTemplateTypeParmPackType *Subst1 + = cast(T1); + const SubstTemplateTypeParmPackType *Subst2 + = cast(T2); + if (!IsStructurallyEquivalent(Context, + QualType(Subst1->getReplacedParameter(), 0), + QualType(Subst2->getReplacedParameter(), 0))) + return false; + if (!IsStructurallyEquivalent(Context, + Subst1->getArgumentPack(), + Subst2->getArgumentPack())) + return false; + break; + } case Type::TemplateSpecialization: { const TemplateSpecializationType *Spec1 = cast(T1); @@ -644,7 +746,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, } break; } - + + case Type::PackExpansion: + if (!IsStructurallyEquivalent(Context, + cast(T1)->getPattern(), + cast(T2)->getPattern())) + return false; + break; + case Type::ObjCInterface: { const ObjCInterfaceType *Iface1 = cast(T1); const ObjCInterfaceType *Iface2 = cast(T2); @@ -698,6 +807,33 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; } + // If both declarations are class template specializations, we know + // the ODR applies, so check the template and template arguments. + ClassTemplateSpecializationDecl *Spec1 + = dyn_cast(D1); + ClassTemplateSpecializationDecl *Spec2 + = dyn_cast(D2); + if (Spec1 && Spec2) { + // Check that the specialized templates are the same. + if (!IsStructurallyEquivalent(Context, Spec1->getSpecializedTemplate(), + Spec2->getSpecializedTemplate())) + return false; + + // Check that the template arguments are the same. + if (Spec1->getTemplateArgs().size() != Spec2->getTemplateArgs().size()) + return false; + + for (unsigned I = 0, N = Spec1->getTemplateArgs().size(); I != N; ++I) + if (!IsStructurallyEquivalent(Context, + Spec1->getTemplateArgs().get(I), + Spec2->getTemplateArgs().get(I))) + return false; + } + // If one is a class template specialization and the other is not, these + // structures are diferent. + else if (Spec1 || Spec2) + return false; + // Compare the definitions of these two records. If either or both are // incomplete, we assume that they are equivalent. D1 = D1->getDefinition(); @@ -709,11 +845,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (CXXRecordDecl *D2CXX = dyn_cast(D2)) { if (D1CXX->getNumBases() != D2CXX->getNumBases()) { Context.Diag2(D2->getLocation(), diag::warn_odr_tag_type_inconsistent) - << Context.C2.getTypeDeclType(D2); + << Context.C2.getTypeDeclType(D2); Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases) - << D2CXX->getNumBases(); + << D2CXX->getNumBases(); Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases) - << D1CXX->getNumBases(); + << D1CXX->getNumBases(); return false; } @@ -892,7 +1028,112 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TemplateParameterList *Params1, + TemplateParameterList *Params2) { + if (Params1->size() != Params2->size()) { + Context.Diag2(Params2->getTemplateLoc(), + diag::err_odr_different_num_template_parameters) + << Params1->size() << Params2->size(); + Context.Diag1(Params1->getTemplateLoc(), + diag::note_odr_template_parameter_list); + return false; + } + for (unsigned I = 0, N = Params1->size(); I != N; ++I) { + if (Params1->getParam(I)->getKind() != Params2->getParam(I)->getKind()) { + Context.Diag2(Params2->getParam(I)->getLocation(), + diag::err_odr_different_template_parameter_kind); + Context.Diag1(Params1->getParam(I)->getLocation(), + diag::note_odr_template_parameter_here); + return false; + } + + if (!Context.IsStructurallyEquivalent(Params1->getParam(I), + Params2->getParam(I))) { + + return false; + } + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TemplateTypeParmDecl *D1, + TemplateTypeParmDecl *D2) { + if (D1->isParameterPack() != D2->isParameterPack()) { + Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + << D2->isParameterPack(); + Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) + << D1->isParameterPack(); + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + NonTypeTemplateParmDecl *D1, + NonTypeTemplateParmDecl *D2) { + // FIXME: Enable once we have variadic templates. +#if 0 + if (D1->isParameterPack() != D2->isParameterPack()) { + Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + << D2->isParameterPack(); + Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) + << D1->isParameterPack(); + return false; + } +#endif + + // Check types. + if (!Context.IsStructurallyEquivalent(D1->getType(), D2->getType())) { + Context.Diag2(D2->getLocation(), + diag::err_odr_non_type_parameter_type_inconsistent) + << D2->getType() << D1->getType(); + Context.Diag1(D1->getLocation(), diag::note_odr_value_here) + << D1->getType(); + return false; + } + + return true; +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + TemplateTemplateParmDecl *D1, + TemplateTemplateParmDecl *D2) { + // FIXME: Enable once we have variadic templates. +#if 0 + if (D1->isParameterPack() != D2->isParameterPack()) { + Context.Diag2(D2->getLocation(), diag::err_odr_parameter_pack_non_pack) + << D2->isParameterPack(); + Context.Diag1(D1->getLocation(), diag::note_odr_parameter_pack_non_pack) + << D1->isParameterPack(); + return false; + } +#endif + + // Check template parameter lists. + return IsStructurallyEquivalent(Context, D1->getTemplateParameters(), + D2->getTemplateParameters()); +} + +static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, + ClassTemplateDecl *D1, + ClassTemplateDecl *D2) { + // Check template parameters. + if (!IsStructurallyEquivalent(Context, + D1->getTemplateParameters(), + D2->getTemplateParameters())) + return false; + + // Check the templated declaration. + return Context.IsStructurallyEquivalent(D1->getTemplatedDecl(), + D2->getTemplatedDecl()); +} + /// \brief Determine structural equivalence of two declarations. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, Decl *D1, Decl *D2) { @@ -988,8 +1229,47 @@ bool StructuralEquivalenceContext::Finish() { // Typedef/non-typedef mismatch. Equivalent = false; } - } - + } else if (ClassTemplateDecl *ClassTemplate1 + = dyn_cast(D1)) { + if (ClassTemplateDecl *ClassTemplate2 = dyn_cast(D2)) { + if (!::IsStructurallyEquivalent(ClassTemplate1->getIdentifier(), + ClassTemplate2->getIdentifier()) || + !::IsStructurallyEquivalent(*this, ClassTemplate1, ClassTemplate2)) + Equivalent = false; + } else { + // Class template/non-class-template mismatch. + Equivalent = false; + } + } else if (TemplateTypeParmDecl *TTP1= dyn_cast(D1)) { + if (TemplateTypeParmDecl *TTP2 = dyn_cast(D2)) { + if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } + } else if (NonTypeTemplateParmDecl *NTTP1 + = dyn_cast(D1)) { + if (NonTypeTemplateParmDecl *NTTP2 + = dyn_cast(D2)) { + if (!::IsStructurallyEquivalent(*this, NTTP1, NTTP2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } + } else if (TemplateTemplateParmDecl *TTP1 + = dyn_cast(D1)) { + if (TemplateTemplateParmDecl *TTP2 + = dyn_cast(D2)) { + if (!::IsStructurallyEquivalent(*this, TTP1, TTP2)) + Equivalent = false; + } else { + // Kind mismatch. + Equivalent = false; + } + } + if (!Equivalent) { // Note that these two declarations are not equivalent (and we already // know about it). @@ -1007,13 +1287,13 @@ bool StructuralEquivalenceContext::Finish() { // Import Types //---------------------------------------------------------------------------- -QualType ASTNodeImporter::VisitType(Type *T) { +QualType ASTNodeImporter::VisitType(const Type *T) { Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node) << T->getTypeClassName(); return QualType(); } -QualType ASTNodeImporter::VisitBuiltinType(BuiltinType *T) { +QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { case BuiltinType::Void: return Importer.getToContext().VoidTy; case BuiltinType::Bool: return Importer.getToContext().BoolTy; @@ -1054,7 +1334,8 @@ QualType ASTNodeImporter::VisitBuiltinType(BuiltinType *T) { return Importer.getToContext().CharTy; case BuiltinType::SChar: return Importer.getToContext().SignedCharTy; - case BuiltinType::WChar: + 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; @@ -1074,9 +1355,6 @@ QualType ASTNodeImporter::VisitBuiltinType(BuiltinType *T) { case BuiltinType::Overload: return Importer.getToContext().OverloadTy; case BuiltinType::Dependent: return Importer.getToContext().DependentTy; - case BuiltinType::UndeducedAuto: - // FIXME: Make sure that the "to" context supports C++0x! - return Importer.getToContext().UndeducedAutoTy; case BuiltinType::ObjCId: // FIXME: Make sure that the "to" context supports Objective-C! @@ -1092,7 +1370,7 @@ QualType ASTNodeImporter::VisitBuiltinType(BuiltinType *T) { return QualType(); } -QualType ASTNodeImporter::VisitComplexType(ComplexType *T) { +QualType ASTNodeImporter::VisitComplexType(const ComplexType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) return QualType(); @@ -1100,7 +1378,7 @@ QualType ASTNodeImporter::VisitComplexType(ComplexType *T) { return Importer.getToContext().getComplexType(ToElementType); } -QualType ASTNodeImporter::VisitPointerType(PointerType *T) { +QualType ASTNodeImporter::VisitPointerType(const PointerType *T) { QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) return QualType(); @@ -1108,7 +1386,7 @@ QualType ASTNodeImporter::VisitPointerType(PointerType *T) { return Importer.getToContext().getPointerType(ToPointeeType); } -QualType ASTNodeImporter::VisitBlockPointerType(BlockPointerType *T) { +QualType ASTNodeImporter::VisitBlockPointerType(const BlockPointerType *T) { // FIXME: Check for blocks support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) @@ -1117,7 +1395,8 @@ QualType ASTNodeImporter::VisitBlockPointerType(BlockPointerType *T) { return Importer.getToContext().getBlockPointerType(ToPointeeType); } -QualType ASTNodeImporter::VisitLValueReferenceType(LValueReferenceType *T) { +QualType +ASTNodeImporter::VisitLValueReferenceType(const LValueReferenceType *T) { // FIXME: Check for C++ support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten()); if (ToPointeeType.isNull()) @@ -1126,7 +1405,8 @@ QualType ASTNodeImporter::VisitLValueReferenceType(LValueReferenceType *T) { return Importer.getToContext().getLValueReferenceType(ToPointeeType); } -QualType ASTNodeImporter::VisitRValueReferenceType(RValueReferenceType *T) { +QualType +ASTNodeImporter::VisitRValueReferenceType(const RValueReferenceType *T) { // FIXME: Check for C++0x support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeTypeAsWritten()); if (ToPointeeType.isNull()) @@ -1135,7 +1415,7 @@ QualType ASTNodeImporter::VisitRValueReferenceType(RValueReferenceType *T) { return Importer.getToContext().getRValueReferenceType(ToPointeeType); } -QualType ASTNodeImporter::VisitMemberPointerType(MemberPointerType *T) { +QualType ASTNodeImporter::VisitMemberPointerType(const MemberPointerType *T) { // FIXME: Check for C++ support in "to" context. QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) @@ -1146,7 +1426,7 @@ QualType ASTNodeImporter::VisitMemberPointerType(MemberPointerType *T) { ClassType.getTypePtr()); } -QualType ASTNodeImporter::VisitConstantArrayType(ConstantArrayType *T) { +QualType ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) return QualType(); @@ -1157,7 +1437,8 @@ QualType ASTNodeImporter::VisitConstantArrayType(ConstantArrayType *T) { T->getIndexTypeCVRQualifiers()); } -QualType ASTNodeImporter::VisitIncompleteArrayType(IncompleteArrayType *T) { +QualType +ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) return QualType(); @@ -1167,7 +1448,7 @@ QualType ASTNodeImporter::VisitIncompleteArrayType(IncompleteArrayType *T) { T->getIndexTypeCVRQualifiers()); } -QualType ASTNodeImporter::VisitVariableArrayType(VariableArrayType *T) { +QualType ASTNodeImporter::VisitVariableArrayType(const VariableArrayType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) return QualType(); @@ -1183,17 +1464,17 @@ QualType ASTNodeImporter::VisitVariableArrayType(VariableArrayType *T) { Brackets); } -QualType ASTNodeImporter::VisitVectorType(VectorType *T) { +QualType ASTNodeImporter::VisitVectorType(const VectorType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) return QualType(); return Importer.getToContext().getVectorType(ToElementType, T->getNumElements(), - T->getAltiVecSpecific()); + T->getVectorKind()); } -QualType ASTNodeImporter::VisitExtVectorType(ExtVectorType *T) { +QualType ASTNodeImporter::VisitExtVectorType(const ExtVectorType *T) { QualType ToElementType = Importer.Import(T->getElementType()); if (ToElementType.isNull()) return QualType(); @@ -1202,7 +1483,8 @@ QualType ASTNodeImporter::VisitExtVectorType(ExtVectorType *T) { T->getNumElements()); } -QualType ASTNodeImporter::VisitFunctionNoProtoType(FunctionNoProtoType *T) { +QualType +ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { // FIXME: What happens if we're importing a function without a prototype // into C++? Should we make it variadic? QualType ToResultType = Importer.Import(T->getResultType()); @@ -1213,7 +1495,7 @@ QualType ASTNodeImporter::VisitFunctionNoProtoType(FunctionNoProtoType *T) { T->getExtInfo()); } -QualType ASTNodeImporter::VisitFunctionProtoType(FunctionProtoType *T) { +QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { QualType ToResultType = Importer.Import(T->getResultType()); if (ToResultType.isNull()) return QualType(); @@ -1239,19 +1521,15 @@ QualType ASTNodeImporter::VisitFunctionProtoType(FunctionProtoType *T) { return QualType(); ExceptionTypes.push_back(ExceptionType); } + + FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo(); + EPI.Exceptions = ExceptionTypes.data(); return Importer.getToContext().getFunctionType(ToResultType, ArgTypes.data(), - ArgTypes.size(), - T->isVariadic(), - T->getTypeQuals(), - T->hasExceptionSpec(), - T->hasAnyExceptionSpec(), - ExceptionTypes.size(), - ExceptionTypes.data(), - T->getExtInfo()); + ArgTypes.size(), EPI); } -QualType ASTNodeImporter::VisitTypedefType(TypedefType *T) { +QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { TypedefDecl *ToDecl = dyn_cast_or_null(Importer.Import(T->getDecl())); if (!ToDecl) @@ -1260,7 +1538,7 @@ QualType ASTNodeImporter::VisitTypedefType(TypedefType *T) { return Importer.getToContext().getTypeDeclType(ToDecl); } -QualType ASTNodeImporter::VisitTypeOfExprType(TypeOfExprType *T) { +QualType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { Expr *ToExpr = Importer.Import(T->getUnderlyingExpr()); if (!ToExpr) return QualType(); @@ -1268,7 +1546,7 @@ QualType ASTNodeImporter::VisitTypeOfExprType(TypeOfExprType *T) { return Importer.getToContext().getTypeOfExprType(ToExpr); } -QualType ASTNodeImporter::VisitTypeOfType(TypeOfType *T) { +QualType ASTNodeImporter::VisitTypeOfType(const TypeOfType *T) { QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType()); if (ToUnderlyingType.isNull()) return QualType(); @@ -1276,7 +1554,8 @@ QualType ASTNodeImporter::VisitTypeOfType(TypeOfType *T) { return Importer.getToContext().getTypeOfType(ToUnderlyingType); } -QualType ASTNodeImporter::VisitDecltypeType(DecltypeType *T) { +QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) { + // FIXME: Make sure that the "to" context supports C++0x! Expr *ToExpr = Importer.Import(T->getUnderlyingExpr()); if (!ToExpr) return QualType(); @@ -1284,7 +1563,20 @@ QualType ASTNodeImporter::VisitDecltypeType(DecltypeType *T) { return Importer.getToContext().getDecltypeType(ToExpr); } -QualType ASTNodeImporter::VisitRecordType(RecordType *T) { +QualType ASTNodeImporter::VisitAutoType(const AutoType *T) { + // FIXME: Make sure that the "to" context supports C++0x! + QualType FromDeduced = T->getDeducedType(); + QualType ToDeduced; + if (!FromDeduced.isNull()) { + ToDeduced = Importer.Import(FromDeduced); + if (ToDeduced.isNull()) + return QualType(); + } + + return Importer.getToContext().getAutoType(ToDeduced); +} + +QualType ASTNodeImporter::VisitRecordType(const RecordType *T) { RecordDecl *ToDecl = dyn_cast_or_null(Importer.Import(T->getDecl())); if (!ToDecl) @@ -1293,7 +1585,7 @@ QualType ASTNodeImporter::VisitRecordType(RecordType *T) { return Importer.getToContext().getTagDeclType(ToDecl); } -QualType ASTNodeImporter::VisitEnumType(EnumType *T) { +QualType ASTNodeImporter::VisitEnumType(const EnumType *T) { EnumDecl *ToDecl = dyn_cast_or_null(Importer.Import(T->getDecl())); if (!ToDecl) @@ -1302,7 +1594,31 @@ QualType ASTNodeImporter::VisitEnumType(EnumType *T) { return Importer.getToContext().getTagDeclType(ToDecl); } -QualType ASTNodeImporter::VisitElaboratedType(ElaboratedType *T) { +QualType ASTNodeImporter::VisitTemplateSpecializationType( + const TemplateSpecializationType *T) { + TemplateName ToTemplate = Importer.Import(T->getTemplateName()); + if (ToTemplate.isNull()) + return QualType(); + + llvm::SmallVector ToTemplateArgs; + if (ImportTemplateArguments(T->getArgs(), T->getNumArgs(), ToTemplateArgs)) + return QualType(); + + QualType ToCanonType; + if (!QualType(T, 0).isCanonical()) { + QualType FromCanonType + = Importer.getFromContext().getCanonicalType(QualType(T, 0)); + ToCanonType =Importer.Import(FromCanonType); + if (ToCanonType.isNull()) + return QualType(); + } + return Importer.getToContext().getTemplateSpecializationType(ToTemplate, + ToTemplateArgs.data(), + ToTemplateArgs.size(), + ToCanonType); +} + +QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { NestedNameSpecifier *ToQualifier = 0; // Note: the qualifier in an ElaboratedType is optional. if (T->getQualifier()) { @@ -1319,7 +1635,7 @@ QualType ASTNodeImporter::VisitElaboratedType(ElaboratedType *T) { ToQualifier, ToNamedType); } -QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { +QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { ObjCInterfaceDecl *Class = dyn_cast_or_null(Importer.Import(T->getDecl())); if (!Class) @@ -1328,7 +1644,7 @@ QualType ASTNodeImporter::VisitObjCInterfaceType(ObjCInterfaceType *T) { return Importer.getToContext().getObjCInterfaceType(Class); } -QualType ASTNodeImporter::VisitObjCObjectType(ObjCObjectType *T) { +QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { QualType ToBaseType = Importer.Import(T->getBaseType()); if (ToBaseType.isNull()) return QualType(); @@ -1349,7 +1665,8 @@ QualType ASTNodeImporter::VisitObjCObjectType(ObjCObjectType *T) { Protocols.size()); } -QualType ASTNodeImporter::VisitObjCObjectPointerType(ObjCObjectPointerType *T) { +QualType +ASTNodeImporter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) { QualType ToPointeeType = Importer.Import(T->getPointeeType()); if (ToPointeeType.isNull()) return QualType(); @@ -1420,7 +1737,15 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, } } -void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC) { +void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { + if (Importer.isMinimalImport() && !ForceImport) { + if (DeclContext *ToDC = Importer.ImportContext(FromDC)) { + ToDC->setHasExternalLexicalStorage(); + ToDC->setHasExternalVisibleStorage(); + } + return; + } + for (DeclContext::decl_iterator From = FromDC->decls_begin(), FromEnd = FromDC->decls_end(); From != FromEnd; @@ -1428,11 +1753,151 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC) { Importer.Import(*From); } +bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) { + if (To->getDefinition()) + return false; + + To->startDefinition(); + + // Add base classes. + if (CXXRecordDecl *ToCXX = dyn_cast(To)) { + CXXRecordDecl *FromCXX = cast(From); + + llvm::SmallVector Bases; + for (CXXRecordDecl::base_class_iterator + Base1 = FromCXX->bases_begin(), + FromBaseEnd = FromCXX->bases_end(); + Base1 != FromBaseEnd; + ++Base1) { + QualType T = Importer.Import(Base1->getType()); + if (T.isNull()) + return true; + + SourceLocation EllipsisLoc; + if (Base1->isPackExpansion()) + EllipsisLoc = Importer.Import(Base1->getEllipsisLoc()); + + Bases.push_back( + new (Importer.getToContext()) + CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), + Base1->isVirtual(), + Base1->isBaseOfClass(), + Base1->getAccessSpecifierAsWritten(), + Importer.Import(Base1->getTypeSourceInfo()), + EllipsisLoc)); + } + if (!Bases.empty()) + ToCXX->setBases(Bases.data(), Bases.size()); + } + + ImportDeclContext(From); + To->completeDefinition(); + return false; +} + +TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( + TemplateParameterList *Params) { + llvm::SmallVector ToParams; + ToParams.reserve(Params->size()); + for (TemplateParameterList::iterator P = Params->begin(), + PEnd = Params->end(); + P != PEnd; ++P) { + Decl *To = Importer.Import(*P); + if (!To) + return 0; + + ToParams.push_back(cast(To)); + } + + return TemplateParameterList::Create(Importer.getToContext(), + Importer.Import(Params->getTemplateLoc()), + Importer.Import(Params->getLAngleLoc()), + ToParams.data(), ToParams.size(), + Importer.Import(Params->getRAngleLoc())); +} + +TemplateArgument +ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) { + switch (From.getKind()) { + case TemplateArgument::Null: + return TemplateArgument(); + + case TemplateArgument::Type: { + QualType ToType = Importer.Import(From.getAsType()); + if (ToType.isNull()) + return TemplateArgument(); + return TemplateArgument(ToType); + } + + case TemplateArgument::Integral: { + QualType ToType = Importer.Import(From.getIntegralType()); + if (ToType.isNull()) + return TemplateArgument(); + return TemplateArgument(*From.getAsIntegral(), ToType); + } + + case TemplateArgument::Declaration: + if (Decl *To = Importer.Import(From.getAsDecl())) + return TemplateArgument(To); + return TemplateArgument(); + + case TemplateArgument::Template: { + TemplateName ToTemplate = Importer.Import(From.getAsTemplate()); + if (ToTemplate.isNull()) + return TemplateArgument(); + + return TemplateArgument(ToTemplate); + } + + case TemplateArgument::TemplateExpansion: { + TemplateName ToTemplate + = Importer.Import(From.getAsTemplateOrTemplatePattern()); + if (ToTemplate.isNull()) + return TemplateArgument(); + + return TemplateArgument(ToTemplate, From.getNumTemplateExpansions()); + } + + case TemplateArgument::Expression: + if (Expr *ToExpr = Importer.Import(From.getAsExpr())) + return TemplateArgument(ToExpr); + return TemplateArgument(); + + case TemplateArgument::Pack: { + llvm::SmallVector ToPack; + ToPack.reserve(From.pack_size()); + if (ImportTemplateArguments(From.pack_begin(), From.pack_size(), ToPack)) + return TemplateArgument(); + + TemplateArgument *ToArgs + = new (Importer.getToContext()) TemplateArgument[ToPack.size()]; + std::copy(ToPack.begin(), ToPack.end(), ToArgs); + return TemplateArgument(ToArgs, ToPack.size()); + } + } + + llvm_unreachable("Invalid template argument kind"); + return TemplateArgument(); +} + +bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs, + unsigned NumFromArgs, + llvm::SmallVectorImpl &ToArgs) { + for (unsigned I = 0; I != NumFromArgs; ++I) { + TemplateArgument To = ImportTemplateArgument(FromArgs[I]); + if (To.isNull() && !FromArgs[I].isNull()) + return true; + + ToArgs.push_back(To); + } + + return false; +} + bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getDiags(), Importer.getNonEquivalentDecls()); return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); } @@ -1440,11 +1905,18 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getDiags(), Importer.getNonEquivalentDecls()); return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } +bool ASTNodeImporter::IsStructuralMatch(ClassTemplateDecl *From, + ClassTemplateDecl *To) { + StructuralEquivalenceContext Ctx(Importer.getFromContext(), + Importer.getToContext(), + Importer.getNonEquivalentDecls()); + return Ctx.IsStructurallyEquivalent(From, To); +} + Decl *ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); @@ -1620,9 +2092,10 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Create the enum declaration. EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getTagKeywordLoc()), - 0); + Name.getAsIdentifierInfo(), + Importer.Import(D->getTagKeywordLoc()), 0, + D->isScoped(), D->isScopedUsingClassTag(), + D->isFixed()); // Import the qualifier, if any. if (D->getQualifier()) { NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); @@ -1764,38 +2237,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Importer.Imported(D, D2); - if (D->isDefinition()) { - D2->startDefinition(); - - // Add base classes. - if (CXXRecordDecl *D2CXX = dyn_cast(D2)) { - CXXRecordDecl *D1CXX = cast(D); - - llvm::SmallVector Bases; - for (CXXRecordDecl::base_class_iterator - Base1 = D1CXX->bases_begin(), - FromBaseEnd = D1CXX->bases_end(); - Base1 != FromBaseEnd; - ++Base1) { - QualType T = Importer.Import(Base1->getType()); - if (T.isNull()) - return 0; - - Bases.push_back( - new (Importer.getToContext()) - CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), - Base1->isVirtual(), - Base1->isBaseOfClass(), - Base1->getAccessSpecifierAsWritten(), - Importer.Import(Base1->getTypeSourceInfo()))); - } - if (!Bases.empty()) - D2CXX->setBases(Bases.data(), Bases.size()); - } - - ImportDeclContext(D); - D2->completeDefinition(); - } + if (D->isDefinition() && ImportDefinition(D, D2)) + return 0; return D2; } @@ -1939,7 +2382,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } else if (isa(D)) { ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), cast(DC), - NameInfo, T, + NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit()); } else if (CXXConversionDecl *FromConversion @@ -1949,6 +2392,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { NameInfo, T, TInfo, D->isInlineSpecified(), FromConversion->isExplicit()); + } else if (CXXMethodDecl *Method = dyn_cast(D)) { + ToFunction = CXXMethodDecl::Create(Importer.getToContext(), + cast(DC), + NameInfo, T, TInfo, + Method->isStatic(), + Method->getStorageClassAsWritten(), + Method->isInlineSpecified()); } else { ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, NameInfo, T, TInfo, D->getStorageClass(), @@ -1965,8 +2415,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { } ToFunction->setAccess(D->getAccess()); ToFunction->setLexicalDeclContext(LexicalDC); + ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); + ToFunction->setTrivial(D->isTrivial()); + ToFunction->setPure(D->isPure()); Importer.Imported(D, ToFunction); - LexicalDC->addDecl(ToFunction); // Set the parameters. for (unsigned I = 0, N = Parameters.size(); I != N; ++I) { @@ -1976,7 +2428,10 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ToFunction->setParams(Parameters.data(), Parameters.size()); // FIXME: Other bits to merge? - + + // Add this function to the lexical context. + LexicalDC->addDecl(ToFunction); + return ToFunction; } @@ -2024,6 +2479,42 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { return ToField; } +Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + // Import the major distinguishing characteristics of a variable. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + return 0; + + // Import the type. + QualType T = Importer.Import(D->getType()); + if (T.isNull()) + return 0; + + NamedDecl **NamedChain = + new (Importer.getToContext())NamedDecl*[D->getChainingSize()]; + + unsigned i = 0; + for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), + PE = D->chain_end(); PI != PE; ++PI) { + Decl* D = Importer.Import(*PI); + if (!D) + return 0; + NamedChain[i++] = cast(D); + } + + IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( + Importer.getToContext(), DC, + Loc, Name.getAsIdentifierInfo(), T, + NamedChain, D->getChainingSize()); + ToIndirectField->setAccess(D->getAccess()); + ToIndirectField->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToIndirectField); + LexicalDC->addDecl(ToIndirectField); + return ToIndirectField; +} + Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // Import the major distinguishing characteristics of an ivar. DeclContext *DC, *LexicalDC; @@ -2434,7 +2925,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { // If we have an implementation, import it as well. if (D->getImplementation()) { ObjCCategoryImplDecl *Impl - = cast(Importer.Import(D->getImplementation())); + = cast_or_null( + Importer.Import(D->getImplementation())); if (!Impl) return 0; @@ -2615,8 +3107,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { // If we have an @implementation, import it as well. if (D->getImplementation()) { - ObjCImplementationDecl *Impl - = cast(Importer.Import(D->getImplementation())); + ObjCImplementationDecl *Impl = cast_or_null( + Importer.Import(D->getImplementation())); if (!Impl) return 0; @@ -2626,6 +3118,114 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { return ToIface; } +Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { + ObjCCategoryDecl *Category = cast_or_null( + Importer.Import(D->getCategoryDecl())); + if (!Category) + return 0; + + ObjCCategoryImplDecl *ToImpl = Category->getImplementation(); + if (!ToImpl) { + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return 0; + + ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Importer.Import(D->getIdentifier()), + Category->getClassInterface()); + + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return 0; + + ToImpl->setLexicalDeclContext(LexicalDC); + } + + LexicalDC->addDecl(ToImpl); + Category->setImplementation(ToImpl); + } + + Importer.Imported(D, ToImpl); + ImportDeclContext(D); + return ToImpl; +} + +Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { + // Find the corresponding interface. + ObjCInterfaceDecl *Iface = cast_or_null( + Importer.Import(D->getClassInterface())); + if (!Iface) + return 0; + + // Import the superclass, if any. + ObjCInterfaceDecl *Super = 0; + if (D->getSuperClass()) { + Super = cast_or_null( + Importer.Import(D->getSuperClass())); + if (!Super) + return 0; + } + + ObjCImplementationDecl *Impl = Iface->getImplementation(); + if (!Impl) { + // We haven't imported an implementation yet. Create a new @implementation + // now. + Impl = ObjCImplementationDecl::Create(Importer.getToContext(), + Importer.ImportContext(D->getDeclContext()), + Importer.Import(D->getLocation()), + Iface, Super); + + if (D->getDeclContext() != D->getLexicalDeclContext()) { + DeclContext *LexicalDC + = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return 0; + Impl->setLexicalDeclContext(LexicalDC); + } + + // Associate the implementation with the class it implements. + Iface->setImplementation(Impl); + Importer.Imported(D, Iface->getImplementation()); + } else { + Importer.Imported(D, Iface->getImplementation()); + + // Verify that the existing @implementation has the same superclass. + if ((Super && !Impl->getSuperClass()) || + (!Super && Impl->getSuperClass()) || + (Super && Impl->getSuperClass() && + Super->getCanonicalDecl() != Impl->getSuperClass())) { + Importer.ToDiag(Impl->getLocation(), + diag::err_odr_objc_superclass_inconsistent) + << Iface->getDeclName(); + // FIXME: It would be nice to have the location of the superclass + // below. + if (Impl->getSuperClass()) + Importer.ToDiag(Impl->getLocation(), + diag::note_odr_objc_superclass) + << Impl->getSuperClass()->getDeclName(); + else + Importer.ToDiag(Impl->getLocation(), + diag::note_odr_objc_missing_superclass); + if (D->getSuperClass()) + Importer.FromDiag(D->getLocation(), + diag::note_odr_objc_superclass) + << D->getSuperClass()->getDeclName(); + else + Importer.FromDiag(D->getLocation(), + diag::note_odr_objc_missing_superclass); + return 0; + } + } + + // Import all of the members of this @implementation. + ImportDeclContext(D); + + return Impl; +} + Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Import the major distinguishing characteristics of an @property. DeclContext *DC, *LexicalDC; @@ -2688,6 +3288,87 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { return ToProperty; } +Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *Property = cast_or_null( + Importer.Import(D->getPropertyDecl())); + if (!Property) + return 0; + + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return 0; + + // Import the lexical declaration context. + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return 0; + } + + ObjCImplDecl *InImpl = dyn_cast(LexicalDC); + if (!InImpl) + return 0; + + // Import the ivar (for an @synthesize). + ObjCIvarDecl *Ivar = 0; + if (D->getPropertyIvarDecl()) { + Ivar = cast_or_null( + Importer.Import(D->getPropertyIvarDecl())); + if (!Ivar) + return 0; + } + + ObjCPropertyImplDecl *ToImpl + = InImpl->FindPropertyImplDecl(Property->getIdentifier()); + if (!ToImpl) { + ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getLocStart()), + Importer.Import(D->getLocation()), + Property, + D->getPropertyImplementation(), + Ivar, + Importer.Import(D->getPropertyIvarDeclLoc())); + ToImpl->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToImpl); + LexicalDC->addDecl(ToImpl); + } else { + // Check that we have the same kind of property implementation (@synthesize + // vs. @dynamic). + if (D->getPropertyImplementation() != ToImpl->getPropertyImplementation()) { + Importer.ToDiag(ToImpl->getLocation(), + diag::err_odr_objc_property_impl_kind_inconsistent) + << Property->getDeclName() + << (ToImpl->getPropertyImplementation() + == ObjCPropertyImplDecl::Dynamic); + Importer.FromDiag(D->getLocation(), + diag::note_odr_objc_property_impl_kind) + << D->getPropertyDecl()->getDeclName() + << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); + return 0; + } + + // For @synthesize, check that we have the same + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize && + Ivar != ToImpl->getPropertyIvarDecl()) { + Importer.ToDiag(ToImpl->getPropertyIvarDeclLoc(), + diag::err_odr_objc_synthesize_ivar_inconsistent) + << Property->getDeclName() + << ToImpl->getPropertyIvarDecl()->getDeclName() + << Ivar->getDeclName(); + Importer.FromDiag(D->getPropertyIvarDeclLoc(), + diag::note_odr_objc_synthesize_ivar_here) + << D->getPropertyIvarDecl()->getDeclName(); + return 0; + } + + // Merge the existing implementation with the new implementation. + Importer.Imported(D, ToImpl); + } + + return ToImpl; +} + Decl * ASTNodeImporter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { // Import the context of this declaration. @@ -2772,6 +3453,275 @@ Decl *ASTNodeImporter::VisitObjCClassDecl(ObjCClassDecl *D) { 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 + // is created. + + // FIXME: Import default argument. + return TemplateTypeParmDecl::Create(Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getLocation()), + D->getDepth(), + D->getIndex(), + Importer.Import(D->getIdentifier()), + D->wasDeclaredWithTypename(), + D->isParameterPack()); +} + +Decl * +ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { + // Import the name of this declaration. + DeclarationName Name = Importer.Import(D->getDeclName()); + if (D->getDeclName() && !Name) + return 0; + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + // Import the type of this declaration. + QualType T = Importer.Import(D->getType()); + if (T.isNull()) + return 0; + + // Import type-source information. + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); + if (D->getTypeSourceInfo() && !TInfo) + return 0; + + // FIXME: Import default argument. + + return NonTypeTemplateParmDecl::Create(Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Loc, D->getDepth(), D->getPosition(), + Name.getAsIdentifierInfo(), + T, D->isParameterPack(), TInfo); +} + +Decl * +ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { + // Import the name of this declaration. + DeclarationName Name = Importer.Import(D->getDeclName()); + if (D->getDeclName() && !Name) + return 0; + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + // Import template parameters. + TemplateParameterList *TemplateParams + = ImportTemplateParameterList(D->getTemplateParameters()); + if (!TemplateParams) + return 0; + + // FIXME: Import default argument. + + return TemplateTemplateParmDecl::Create(Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Loc, D->getDepth(), D->getPosition(), + D->isParameterPack(), + Name.getAsIdentifierInfo(), + TemplateParams); +} + +Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { + // If this record 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. + CXXRecordDecl *Definition + = cast_or_null(D->getTemplatedDecl()->getDefinition()); + if (Definition && Definition != D->getTemplatedDecl()) { + Decl *ImportedDef + = Importer.Import(Definition->getDescribedClassTemplate()); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + + // Import the major distinguishing characteristics of this class template. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) + return 0; + + // We may already have a template of the same name; try to find and match it. + if (!DC->isFunctionOrMethod()) { + llvm::SmallVector ConflictingDecls; + for (DeclContext::lookup_result Lookup = DC->lookup(Name); + Lookup.first != Lookup.second; + ++Lookup.first) { + if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + continue; + + Decl *Found = *Lookup.first; + if (ClassTemplateDecl *FoundTemplate + = dyn_cast(Found)) { + if (IsStructuralMatch(D, FoundTemplate)) { + // The class templates structurally match; call it the same template. + // FIXME: We may be filling in a forward declaration here. Handle + // this case! + Importer.Imported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.Imported(D, FoundTemplate); + } + } + + ConflictingDecls.push_back(*Lookup.first); + } + + if (!ConflictingDecls.empty()) { + Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary, + ConflictingDecls.data(), + ConflictingDecls.size()); + } + + if (!Name) + return 0; + } + + CXXRecordDecl *DTemplated = D->getTemplatedDecl(); + + // Create the declaration that is being templated. + CXXRecordDecl *D2Templated = CXXRecordDecl::Create(Importer.getToContext(), + DTemplated->getTagKind(), + DC, + Importer.Import(DTemplated->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(DTemplated->getTagKeywordLoc())); + D2Templated->setAccess(DTemplated->getAccess()); + + + // Import the qualifier, if any. + if (DTemplated->getQualifier()) { + NestedNameSpecifier *NNS = Importer.Import(DTemplated->getQualifier()); + SourceRange NNSRange = Importer.Import(DTemplated->getQualifierRange()); + D2Templated->setQualifierInfo(NNS, NNSRange); + } + D2Templated->setLexicalDeclContext(LexicalDC); + + // Create the class template declaration itself. + TemplateParameterList *TemplateParams + = ImportTemplateParameterList(D->getTemplateParameters()); + if (!TemplateParams) + return 0; + + ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, + Loc, Name, TemplateParams, + D2Templated, + /*PrevDecl=*/0); + D2Templated->setDescribedClassTemplate(D2); + + D2->setAccess(D->getAccess()); + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDecl(D2); + + // Note the relationship between the class templates. + Importer.Imported(D, D2); + Importer.Imported(DTemplated, D2Templated); + + if (DTemplated->isDefinition() && !D2Templated->isDefinition()) { + // FIXME: Import definition! + } + + return D2; +} + +Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + // If this record 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. + TagDecl *Definition = D->getDefinition(); + if (Definition && Definition != D) { + Decl *ImportedDef = Importer.Import(Definition); + if (!ImportedDef) + return 0; + + return Importer.Imported(D, ImportedDef); + } + + ClassTemplateDecl *ClassTemplate + = cast_or_null(Importer.Import( + D->getSpecializedTemplate())); + if (!ClassTemplate) + return 0; + + // Import the context of this declaration. + DeclContext *DC = ClassTemplate->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()); + + // Import template arguments. + llvm::SmallVector TemplateArgs; + if (ImportTemplateArguments(D->getTemplateArgs().data(), + D->getTemplateArgs().size(), + TemplateArgs)) + return 0; + + // Try to find an existing specialization with these template arguments. + void *InsertPos = 0; + ClassTemplateSpecializationDecl *D2 + = ClassTemplate->findSpecialization(TemplateArgs.data(), + TemplateArgs.size(), InsertPos); + if (D2) { + // We already have a class template specialization with these template + // arguments. + + // FIXME: Check for specialization vs. instantiation errors. + + if (RecordDecl *FoundDef = D2->getDefinition()) { + if (!D->isDefinition() || IsStructuralMatch(D, FoundDef)) { + // The record types structurally match, or the "from" translation + // unit only had a forward declaration anyway; call it the same + // function. + return Importer.Imported(D, FoundDef); + } + } + } else { + // Create a new specialization. + D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), + D->getTagKind(), DC, + Loc, ClassTemplate, + TemplateArgs.data(), + TemplateArgs.size(), + /*PrevDecl=*/0); + D2->setSpecializationKind(D->getSpecializationKind()); + + // Add this specialization to the class template. + ClassTemplate->AddSpecialization(D2, InsertPos); + + // Import the qualifier, if any. + if (D->getQualifier()) { + NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); + SourceRange NNSRange = Importer.Import(D->getQualifierRange()); + D2->setQualifierInfo(NNS, NNSRange); + } + + + // Add the specialization to this context. + D2->setLexicalDeclContext(LexicalDC); + LexicalDC->addDecl(D2); + } + Importer.Imported(D, D2); + + if (D->isDefinition() && ImportDefinition(D, D2)) + return 0; + + return D2; +} + //---------------------------------------------------------------------------- // Import Statements //---------------------------------------------------------------------------- @@ -2811,7 +3761,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Importer.Import(E->getQualifierRange()), ToD, Importer.Import(E->getLocation()), - T, + T, E->getValueKind(), /*FIXME:TemplateArgs=*/0); } @@ -2856,7 +3806,8 @@ Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { return 0; return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(), - T, + T, E->getValueKind(), + E->getObjectKind(), Importer.Import(E->getOperatorLoc())); } @@ -2898,7 +3849,8 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { return 0; return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(), - T, + T, E->getValueKind(), + E->getObjectKind(), Importer.Import(E->getOperatorLoc())); } @@ -2925,7 +3877,9 @@ Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { return new (Importer.getToContext()) CompoundAssignOperator(LHS, RHS, E->getOpcode(), - T, CompLHSType, CompResultType, + T, E->getValueKind(), + E->getObjectKind(), + CompLHSType, CompResultType, Importer.Import(E->getOperatorLoc())); } @@ -2970,18 +3924,20 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { if (ImportCastPath(E, BasePath)) return 0; - return CStyleCastExpr::Create(Importer.getToContext(), T, E->getCastKind(), + return CStyleCastExpr::Create(Importer.getToContext(), T, + E->getValueKind(), E->getCastKind(), SubExpr, &BasePath, TInfo, Importer.Import(E->getLParenLoc()), Importer.Import(E->getRParenLoc())); } -ASTImporter::ASTImporter(Diagnostic &Diags, - ASTContext &ToContext, FileManager &ToFileManager, - ASTContext &FromContext, FileManager &FromFileManager) +ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, + ASTContext &FromContext, FileManager &FromFileManager, + bool MinimalImport) : ToContext(ToContext), FromContext(FromContext), ToFileManager(ToFileManager), FromFileManager(FromFileManager), - Diags(Diags) { + Minimal(MinimalImport) +{ ImportedDecls[FromContext.getTranslationUnitDecl()] = ToContext.getTranslationUnitDecl(); } @@ -2991,23 +3947,25 @@ ASTImporter::~ASTImporter() { } QualType ASTImporter::Import(QualType FromT) { if (FromT.isNull()) return QualType(); + + const Type *fromTy = FromT.getTypePtr(); // Check whether we've already imported this type. - llvm::DenseMap::iterator Pos - = ImportedTypes.find(FromT.getTypePtr()); + llvm::DenseMap::iterator Pos + = ImportedTypes.find(fromTy); if (Pos != ImportedTypes.end()) - return ToContext.getQualifiedType(Pos->second, FromT.getQualifiers()); + return ToContext.getQualifiedType(Pos->second, FromT.getLocalQualifiers()); // Import the type ASTNodeImporter Importer(*this); - QualType ToT = Importer.Visit(FromT.getTypePtr()); + QualType ToT = Importer.Visit(fromTy); if (ToT.isNull()) return ToT; // Record the imported type. - ImportedTypes[FromT.getTypePtr()] = ToT.getTypePtr(); + ImportedTypes[fromTy] = ToT.getTypePtr(); - return ToContext.getQualifiedType(ToT, FromT.getQualifiers()); + return ToContext.getQualifiedType(ToT, FromT.getLocalQualifiers()); } TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { @@ -3109,6 +4067,82 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { return 0; } +TemplateName ASTImporter::Import(TemplateName From) { + switch (From.getKind()) { + case TemplateName::Template: + if (TemplateDecl *ToTemplate + = cast_or_null(Import(From.getAsTemplateDecl()))) + return TemplateName(ToTemplate); + + return TemplateName(); + + case TemplateName::OverloadedTemplate: { + OverloadedTemplateStorage *FromStorage = From.getAsOverloadedTemplate(); + UnresolvedSet<2> ToTemplates; + for (OverloadedTemplateStorage::iterator I = FromStorage->begin(), + E = FromStorage->end(); + I != E; ++I) { + if (NamedDecl *To = cast_or_null(Import(*I))) + ToTemplates.addDecl(To); + else + return TemplateName(); + } + return ToContext.getOverloadedTemplateName(ToTemplates.begin(), + ToTemplates.end()); + } + + case TemplateName::QualifiedTemplate: { + QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName(); + NestedNameSpecifier *Qualifier = Import(QTN->getQualifier()); + if (!Qualifier) + return TemplateName(); + + if (TemplateDecl *ToTemplate + = cast_or_null(Import(From.getAsTemplateDecl()))) + return ToContext.getQualifiedTemplateName(Qualifier, + QTN->hasTemplateKeyword(), + ToTemplate); + + return TemplateName(); + } + + case TemplateName::DependentTemplate: { + DependentTemplateName *DTN = From.getAsDependentTemplateName(); + NestedNameSpecifier *Qualifier = Import(DTN->getQualifier()); + if (!Qualifier) + return TemplateName(); + + if (DTN->isIdentifier()) { + return ToContext.getDependentTemplateName(Qualifier, + Import(DTN->getIdentifier())); + } + + return ToContext.getDependentTemplateName(Qualifier, DTN->getOperator()); + } + + case TemplateName::SubstTemplateTemplateParmPack: { + SubstTemplateTemplateParmPackStorage *SubstPack + = From.getAsSubstTemplateTemplateParmPack(); + TemplateTemplateParmDecl *Param + = cast_or_null( + Import(SubstPack->getParameterPack())); + if (!Param) + return TemplateName(); + + ASTNodeImporter Importer(*this); + TemplateArgument ArgPack + = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); + if (ArgPack.isNull()) + return TemplateName(); + + return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack); + } + } + + llvm_unreachable("Invalid template name kind"); + return TemplateName(); +} + SourceLocation ASTImporter::Import(SourceLocation FromLoc) { if (FromLoc.isInvalid()) return SourceLocation(); @@ -3130,8 +4164,8 @@ SourceRange ASTImporter::Import(SourceRange FromRange) { } FileID ASTImporter::Import(FileID FromID) { - llvm::DenseMap::iterator Pos - = ImportedFileIDs.find(FromID.getHashValue()); + llvm::DenseMap::iterator Pos + = ImportedFileIDs.find(FromID); if (Pos != ImportedFileIDs.end()) return Pos->second; @@ -3156,7 +4190,8 @@ FileID ASTImporter::Import(FileID FromID) { FromSLoc.getFile().getFileCharacteristic()); } else { // FIXME: We want to re-use the existing MemoryBuffer! - const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags(), FromSM); + const llvm::MemoryBuffer * + FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM); llvm::MemoryBuffer *ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); @@ -3164,10 +4199,21 @@ FileID ASTImporter::Import(FileID FromID) { } - ImportedFileIDs[FromID.getHashValue()] = ToID; + ImportedFileIDs[FromID] = ToID; return ToID; } +void ASTImporter::ImportDefinition(Decl *From) { + Decl *To = Import(From); + if (!To) + return; + + if (DeclContext *FromDC = cast(From)) { + ASTNodeImporter Importer(*this); + Importer.ImportDeclContext(FromDC, true); + } +} + DeclarationName ASTImporter::Import(DeclarationName FromName) { if (!FromName) return DeclarationName(); @@ -3225,7 +4271,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { return DeclarationName(); } -IdentifierInfo *ASTImporter::Import(IdentifierInfo *FromId) { +IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { if (!FromId) return 0; @@ -3252,13 +4298,11 @@ DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name, } DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, ToContext.getSourceManager()), - DiagID); + return ToContext.getDiagnostics().Report(Loc, DiagID); } DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, FromContext.getSourceManager()), - DiagID); + return FromContext.getDiagnostics().Report(Loc, DiagID); } Decl *ASTImporter::Imported(Decl *From, Decl *To) { @@ -3267,12 +4311,11 @@ Decl *ASTImporter::Imported(Decl *From, Decl *To) { } bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) { - llvm::DenseMap::iterator Pos + llvm::DenseMap::iterator Pos = ImportedTypes.find(From.getTypePtr()); if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To)) return true; - StructuralEquivalenceContext Ctx(FromContext, ToContext, Diags, - NonEquivalentDecls); + StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls); return Ctx.IsStructurallyEquivalent(From, To); } diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 82a81ec42411..9fe18407a839 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -1,4 +1,6 @@ -set(LLVM_NO_RTTI 1) +set(LLVM_LINK_COMPONENTS support) + +set(LLVM_USED_LIBS clangBasic) add_clang_library(clangAST APValue.cpp @@ -17,14 +19,17 @@ add_clang_library(clangAST DeclObjC.cpp DeclPrinter.cpp DeclTemplate.cpp + DumpXML.cpp Expr.cpp ExprClassification.cpp ExprConstant.cpp ExprCXX.cpp - FullExpr.cpp InheritViz.cpp ItaniumCXXABI.cpp + ItaniumMangle.cpp + Mangle.cpp MicrosoftCXXABI.cpp + MicrosoftMangle.cpp NestedNameSpecifier.cpp ParentMap.cpp RecordLayout.cpp diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h index 4b38d7afb6a4..943c43e79198 100644 --- a/lib/AST/CXXABI.h +++ b/lib/AST/CXXABI.h @@ -15,6 +15,8 @@ #ifndef LLVM_CLANG_AST_CXXABI_H #define LLVM_CLANG_AST_CXXABI_H +#include "clang/AST/Type.h" + namespace clang { class ASTContext; @@ -28,6 +30,13 @@ public: /// Returns the size of a member pointer in multiples of the target /// pointer size. virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0; + + /// Returns the default calling convention for C++ methods. + virtual CallingConv getDefaultMethodCallConv() const = 0; + + // Returns whether the given class is nearly empty, with just virtual pointers + // and no data except possibly virtual bases. + virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0; }; /// Creates an instance of a C++ ABI class. diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index c563c37d58f4..ca9ec18b3997 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// #include "clang/AST/CXXInheritance.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/DeclCXX.h" #include #include @@ -75,18 +76,21 @@ void CXXBasePaths::swap(CXXBasePaths &Other) { std::swap(DetectedVirtual, Other.DetectedVirtual); } -bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base) const { +bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const { CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, /*DetectVirtual=*/false); return isDerivedFrom(Base, Paths); } -bool CXXRecordDecl::isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const { +bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, + CXXBasePaths &Paths) const { if (getCanonicalDecl() == Base->getCanonicalDecl()) return false; Paths.setOrigin(const_cast(this)); - return lookupInBases(&FindBaseClass, Base->getCanonicalDecl(), Paths); + return lookupInBases(&FindBaseClass, + const_cast(Base->getCanonicalDecl()), + Paths); } bool CXXRecordDecl::isVirtuallyDerivedFrom(CXXRecordDecl *Base) const { @@ -662,3 +666,50 @@ CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { } } } + +static void +AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, + CXXIndirectPrimaryBaseSet& Bases) { + // If the record has a virtual primary base class, add it to our set. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + if (Layout.isPrimaryBaseVirtual()) + Bases.insert(Layout.getPrimaryBase()); + + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + assert(!I->getType()->isDependentType() && + "Cannot get indirect primary bases for class with dependent bases."); + + const CXXRecordDecl *BaseDecl = + cast(I->getType()->getAs()->getDecl()); + + // Only bases with virtual bases participate in computing the + // indirect primary virtual base classes. + if (BaseDecl->getNumVBases()) + AddIndirectPrimaryBases(BaseDecl, Context, Bases); + } + +} + +void +CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { + ASTContext &Context = getASTContext(); + + if (!getNumVBases()) + return; + + for (CXXRecordDecl::base_class_const_iterator I = bases_begin(), + E = bases_end(); I != E; ++I) { + assert(!I->getType()->isDependentType() && + "Cannot get indirect primary bases for class with dependent bases."); + + const CXXRecordDecl *BaseDecl = + cast(I->getType()->getAs()->getDecl()); + + // Only bases with virtual bases participate in computing the + // indirect primary virtual base classes. + if (BaseDecl->getNumVBases()) + AddIndirectPrimaryBases(BaseDecl, Context, Bases); + } +} + diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index b7be02d74533..56db8c7e330b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Specifiers.h" @@ -32,35 +33,140 @@ using namespace clang; // NamedDecl Implementation //===----------------------------------------------------------------------===// +static const VisibilityAttr *GetExplicitVisibility(const Decl *d) { + // Use the most recent declaration of a variable. + if (const VarDecl *var = dyn_cast(d)) + return var->getMostRecentDeclaration()->getAttr(); + + // Use the most recent declaration of a function, and also handle + // function template specializations. + if (const FunctionDecl *fn = dyn_cast(d)) { + if (const VisibilityAttr *attr + = fn->getMostRecentDeclaration()->getAttr()) + return attr; + + // If the function is a specialization of a template with an + // explicit visibility attribute, use that. + if (FunctionTemplateSpecializationInfo *templateInfo + = fn->getTemplateSpecializationInfo()) + return templateInfo->getTemplate()->getTemplatedDecl() + ->getAttr(); + + return 0; + } + + // Otherwise, just check the declaration itself first. + if (const VisibilityAttr *attr = d->getAttr()) + return attr; + + // If there wasn't explicit visibility there, and this is a + // specialization of a class template, check for visibility + // on the pattern. + if (const ClassTemplateSpecializationDecl *spec + = dyn_cast(d)) + return spec->getSpecializedTemplate()->getTemplatedDecl() + ->getAttr(); + + return 0; +} + +static Visibility GetVisibilityFromAttr(const VisibilityAttr *A) { + switch (A->getVisibility()) { + case VisibilityAttr::Default: + return DefaultVisibility; + case VisibilityAttr::Hidden: + return HiddenVisibility; + case VisibilityAttr::Protected: + return ProtectedVisibility; + } + return DefaultVisibility; +} + +typedef NamedDecl::LinkageInfo LinkageInfo; +typedef std::pair 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. +struct LVFlags { + bool ConsiderGlobalVisibility; + bool ConsiderVisibilityAttributes; + + LVFlags() : ConsiderGlobalVisibility(true), + ConsiderVisibilityAttributes(true) { + } + + /// \brief Returns a set of flags that is only useful for computing the + /// linkage, not the visibility, of a declaration. + static LVFlags CreateOnlyDeclLinkage() { + LVFlags F; + F.ConsiderGlobalVisibility = false; + F.ConsiderVisibilityAttributes = false; + return F; + } + + /// Returns a set of flags, otherwise based on these, which ignores + /// off all sources of visibility except template arguments. + LVFlags onlyTemplateVisibility() const { + LVFlags F = *this; + F.ConsiderGlobalVisibility = false; + F.ConsiderVisibilityAttributes = false; + return F; + } +}; +} // end anonymous namespace + /// \brief Get the most restrictive linkage for the types in the given /// template parameter list. -static Linkage -getLinkageForTemplateParameterList(const TemplateParameterList *Params) { - Linkage L = ExternalLinkage; +static LVPair +getLVForTemplateParameterList(const TemplateParameterList *Params) { + LVPair LV(ExternalLinkage, DefaultVisibility); for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { - if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*P)) + if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*P)) { + if (NTTP->isExpandedParameterPack()) { + for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) { + QualType T = NTTP->getExpansionType(I); + if (!T->isDependentType()) + LV = merge(LV, T->getLinkageAndVisibility()); + } + continue; + } + if (!NTTP->getType()->isDependentType()) { - L = minLinkage(L, NTTP->getType()->getLinkage()); + LV = merge(LV, NTTP->getType()->getLinkageAndVisibility()); continue; } + } if (TemplateTemplateParmDecl *TTP = dyn_cast(*P)) { - L = minLinkage(L, - getLinkageForTemplateParameterList(TTP->getTemplateParameters())); + LV = merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters())); } } - return L; + return LV; } +/// getLVForDecl - Get the linkage and visibility for the given declaration. +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 Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args, - unsigned NumArgs) { - Linkage L = ExternalLinkage; +static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args, + unsigned NumArgs, + LVFlags &F) { + LVPair LV(ExternalLinkage, DefaultVisibility); for (unsigned I = 0; I != NumArgs; ++I) { switch (Args[I].getKind()) { @@ -70,40 +176,43 @@ static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args, break; case TemplateArgument::Type: - L = minLinkage(L, Args[I].getAsType()->getLinkage()); + LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility()); break; case TemplateArgument::Declaration: - if (NamedDecl *ND = dyn_cast(Args[I].getAsDecl())) - L = minLinkage(L, ND->getLinkage()); - if (ValueDecl *VD = dyn_cast(Args[I].getAsDecl())) - L = minLinkage(L, VD->getType()->getLinkage()); + // The decl can validly be null as the representation of nullptr + // arguments, valid only in C++0x. + if (Decl *D = Args[I].getAsDecl()) { + if (NamedDecl *ND = dyn_cast(D)) + LV = merge(LV, getLVForDecl(ND, F)); + } break; case TemplateArgument::Template: - if (TemplateDecl *Template - = Args[I].getAsTemplate().getAsTemplateDecl()) - L = minLinkage(L, Template->getLinkage()); + case TemplateArgument::TemplateExpansion: + if (TemplateDecl *Template + = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + LV = merge(LV, getLVForDecl(Template, F)); break; case TemplateArgument::Pack: - L = minLinkage(L, - getLinkageForTemplateArgumentList(Args[I].pack_begin(), - Args[I].pack_size())); + LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(), + Args[I].pack_size(), + F)); break; } } - return L; + return LV; } -static Linkage -getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) { - return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(), - TArgs.flat_size()); +static LVPair +getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, + LVFlags &F) { + return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F); } -static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { +static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { assert(D->getDeclContext()->getRedeclContext()->isFileContext() && "Not a name having namespace scope"); ASTContext &Context = D->getASTContext(); @@ -117,7 +226,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { if (const VarDecl *Var = dyn_cast(D)) { // Explicitly declared static. if (Var->getStorageClass() == SC_Static) - return InternalLinkage; + return LinkageInfo::internal(); // - an object or reference that is explicitly declared const // and neither explicitly declared extern nor previously @@ -135,7 +244,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { FoundExtern = true; if (!FoundExtern) - return InternalLinkage; + return LinkageInfo::internal(); } } else if (isa(D) || isa(D)) { // C++ [temp]p4: @@ -150,23 +259,88 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { // Explicitly declared static. if (Function->getStorageClass() == SC_Static) - return InternalLinkage; + return LinkageInfo(InternalLinkage, DefaultVisibility, false); } else if (const FieldDecl *Field = dyn_cast(D)) { // - a data member of an anonymous union. if (cast(Field->getDeclContext())->isAnonymousStructOrUnion()) - return InternalLinkage; + return LinkageInfo::internal(); + } + + if (D->isInAnonymousNamespace()) + return LinkageInfo::uniqueExternal(); + + // Set up the defaults. + + // C99 6.2.2p5: + // If the declaration of an identifier for an object has file + // scope and no storage-class specifier, its linkage is + // external. + LinkageInfo LV; + + if (F.ConsiderVisibilityAttributes) { + if (const VisibilityAttr *VA = GetExplicitVisibility(D)) { + LV.setVisibility(GetVisibilityFromAttr(VA), true); + F.ConsiderGlobalVisibility = false; + } else { + // If we're declared in a namespace with a visibility attribute, + // use that namespace's visibility, but don't call it explicit. + for (const DeclContext *DC = D->getDeclContext(); + !isa(DC); + DC = DC->getParent()) { + if (!isa(DC)) continue; + if (const VisibilityAttr *VA = + cast(DC)->getAttr()) { + LV.setVisibility(GetVisibilityFromAttr(VA), false); + F.ConsiderGlobalVisibility = false; + break; + } + } + } } // C++ [basic.link]p4: - + // A name having namespace scope has external linkage if it is the // name of // // - an object or reference, unless it has internal linkage; or if (const VarDecl *Var = dyn_cast(D)) { + // GCC applies the following optimization to variables and static + // data members, but not to functions: + // + // Modify the variable's LV by the LV of its type unless this is + // C or extern "C". This follows from [basic.link]p9: + // A type without linkage shall not be used as the type of a + // variable or function with external linkage unless + // - the entity has C language linkage, or + // - the entity is declared within an unnamed namespace, or + // - the entity is not used or is defined in the same + // translation unit. + // and [basic.link]p10: + // ...the types specified by all declarations referring to a + // given variable or function shall be identical... + // C does not have an equivalent rule. + // + // Ignore this if we've got an explicit attribute; the user + // probably knows what they're doing. + // + // 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) + return LinkageInfo::uniqueExternal(); + if (!LV.visibilityExplicit()) + LV.mergeVisibility(TypeLV.second); + } + + if (Var->getStorageClass() == SC_PrivateExtern) + LV.setVisibility(HiddenVisibility, true); + if (!Context.getLangOptions().CPlusPlus && (Var->getStorageClass() == SC_Extern || Var->getStorageClass() == SC_PrivateExtern)) { + // C99 6.2.2p4: // For an identifier declared with the storage-class specifier // extern in a scope in which a prior declaration of that @@ -177,23 +351,22 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { // is visible, or if the prior declaration specifies no // linkage, then the identifier has external linkage. if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) { - if (Linkage L = PrevVar->getLinkage()) - return L; + LinkageInfo PrevLV = getLVForDecl(PrevVar, F); + if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); + LV.mergeVisibility(PrevLV); } } - // C99 6.2.2p5: - // If the declaration of an identifier for an object has file - // scope and no storage-class specifier, its linkage is - // external. - if (Var->isInAnonymousNamespace()) - return UniqueExternalLinkage; + // - a function, unless it has internal linkage; or + } else if (const FunctionDecl *Function = dyn_cast(D)) { + // In theory, we can modify the function's LV by the LV of its + // type unless it has C linkage (see comment above about variables + // for justification). In practice, GCC doesn't do this, so it's + // just too painful to make work. - return ExternalLinkage; - } + if (Function->getStorageClass() == SC_PrivateExtern) + LV.setVisibility(HiddenVisibility, true); - // - a function, unless it has internal linkage; or - if (const FunctionDecl *Function = dyn_cast(D)) { // C99 6.2.2p5: // If the declaration of an identifier for a function has no // storage-class specifier, its linkage is determined exactly @@ -213,141 +386,300 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) { // is visible, or if the prior declaration specifies no // linkage, then the identifier has external linkage. if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) { - if (Linkage L = PrevFunc->getLinkage()) - return L; + LinkageInfo PrevLV = getLVForDecl(PrevFunc, F); + if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); + LV.mergeVisibility(PrevLV); } } - if (Function->isInAnonymousNamespace()) - return UniqueExternalLinkage; + // In C++, then if the type of the function uses a type with + // 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() && + Function->getType()->getLinkage() == UniqueExternalLinkage) + return LinkageInfo::uniqueExternal(); if (FunctionTemplateSpecializationInfo *SpecInfo = Function->getTemplateSpecializationInfo()) { - Linkage L = SpecInfo->getTemplate()->getLinkage(); + LV.merge(getLVForDecl(SpecInfo->getTemplate(), + F.onlyTemplateVisibility())); const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments; - L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs)); - return L; + LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); } - return ExternalLinkage; - } - // - a named class (Clause 9), or an unnamed class defined in a // typedef declaration in which the class has the typedef name // for linkage purposes (7.1.3); or // - a named enumeration (7.2), or an unnamed enumeration // defined in a typedef declaration in which the enumeration // has the typedef name for linkage purposes (7.1.3); or - if (const TagDecl *Tag = dyn_cast(D)) - if (Tag->getDeclName() || Tag->getTypedefForAnonDecl()) { - if (Tag->isInAnonymousNamespace()) - return UniqueExternalLinkage; - - // If this is a class template specialization, consider the - // linkage of the template and template arguments. - if (const ClassTemplateSpecializationDecl *Spec - = dyn_cast(Tag)) { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - Linkage L = getLinkageForTemplateArgumentList(TemplateArgs); - return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage()); - } + } else if (const TagDecl *Tag = dyn_cast(D)) { + // Unnamed tags have no linkage. + if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) + return LinkageInfo::none(); + + // If this is a class template specialization, consider the + // linkage of the template and template arguments. + if (const ClassTemplateSpecializationDecl *Spec + = dyn_cast(Tag)) { + // From the template. + LV.merge(getLVForDecl(Spec->getSpecializedTemplate(), + F.onlyTemplateVisibility())); - return ExternalLinkage; + // The arguments at which the template was instantiated. + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + LV.merge(getLVForTemplateArgumentList(TemplateArgs, F)); } + // Consider -fvisibility unless the type has C linkage. + if (F.ConsiderGlobalVisibility) + F.ConsiderGlobalVisibility = + (Context.getLangOptions().CPlusPlus && + !Tag->getDeclContext()->isExternCContext()); + // - an enumerator belonging to an enumeration with external linkage; - if (isa(D)) { - Linkage L = cast(D->getDeclContext())->getLinkage(); - if (isExternalLinkage(L)) - return L; - } + } else if (isa(D)) { + LinkageInfo EnumLV = getLVForDecl(cast(D->getDeclContext()), F); + if (!isExternalLinkage(EnumLV.linkage())) + return LinkageInfo::none(); + LV.merge(EnumLV); // - a template, unless it is a function template that has // internal linkage (Clause 14); - if (const TemplateDecl *Template = dyn_cast(D)) { - if (D->isInAnonymousNamespace()) - return UniqueExternalLinkage; - - return getLinkageForTemplateParameterList( - Template->getTemplateParameters()); - } + } else if (const TemplateDecl *Template = dyn_cast(D)) { + LV.merge(getLVForTemplateParameterList(Template->getTemplateParameters())); // - a namespace (7.3), unless it is declared within an unnamed // namespace. - if (isa(D) && !D->isInAnonymousNamespace()) - return ExternalLinkage; + } else if (isa(D) && !D->isInAnonymousNamespace()) { + return LV; + + // By extension, we assign external linkage to Objective-C + // interfaces. + } else if (isa(D)) { + // fallout - return NoLinkage; + // Everything not covered here has no linkage. + } else { + return LinkageInfo::none(); + } + + // If we ended up with non-external linkage, visibility should + // always be default. + 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; } -static Linkage getLinkageForClassMember(const NamedDecl *D) { +static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { + // Only certain class members have linkage. Note that fields don't + // really have linkage, but it's convenient to say they do for the + // purposes of calculating linkage of pointer-to-data-member + // template arguments. if (!(isa(D) || isa(D) || + isa(D) || (isa(D) && (D->getDeclName() || cast(D)->getTypedefForAnonDecl())))) - return NoLinkage; + return LinkageInfo::none(); + + LinkageInfo LV; - // Class members only have linkage if their class has external linkage. - Linkage L = cast(D->getDeclContext())->getLinkage(); - if (!isExternalLinkage(L)) return NoLinkage; + // The flags we're going to use to compute the class's visibility. + LVFlags ClassF = F; + + // If we have an explicit visibility attribute, merge that in. + if (F.ConsiderVisibilityAttributes) { + if (const VisibilityAttr *VA = GetExplicitVisibility(D)) { + LV.mergeVisibility(GetVisibilityFromAttr(VA), true); + + // Ignore global visibility later, but not this attribute. + F.ConsiderGlobalVisibility = false; + + // Ignore both global visibility and attributes when computing our + // parent's visibility. + ClassF = F.onlyTemplateVisibility(); + } + } + + // Class members only have linkage if their class has external + // linkage. + LV.merge(getLVForDecl(cast(D->getDeclContext()), ClassF)); + if (!isExternalLinkage(LV.linkage())) + return LinkageInfo::none(); // If the class already has unique-external linkage, we can't improve. - if (L == UniqueExternalLinkage) return UniqueExternalLinkage; + if (LV.linkage() == UniqueExternalLinkage) + return LinkageInfo::uniqueExternal(); - // If this is a method template specialization, use the linkage for - // the template parameters and arguments. if (const CXXMethodDecl *MD = dyn_cast(D)) { - if (FunctionTemplateSpecializationInfo *SpecInfo + // If the type of the function uses a type with unique-external + // linkage, it's not legally usable from outside this translation unit. + if (MD->getType()->getLinkage() == UniqueExternalLinkage) + return LinkageInfo::uniqueExternal(); + + TemplateSpecializationKind TSK = TSK_Undeclared; + + // If this is a method template specialization, use the linkage for + // the template parameters and arguments. + if (FunctionTemplateSpecializationInfo *Spec = MD->getTemplateSpecializationInfo()) { - Linkage ArgLinkage = - getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments); - Linkage ParamLinkage = - getLinkageForTemplateParameterList( - SpecInfo->getTemplate()->getTemplateParameters()); - return minLinkage(ArgLinkage, ParamLinkage); + LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F)); + LV.merge(getLVForTemplateParameterList( + Spec->getTemplate()->getTemplateParameters())); + + TSK = Spec->getTemplateSpecializationKind(); + } else if (MemberSpecializationInfo *MSI = + MD->getMemberSpecializationInfo()) { + TSK = MSI->getTemplateSpecializationKind(); + } + + // If we're paying attention to global visibility, apply + // -finline-visibility-hidden if this is an inline method. + // + // Note that ConsiderGlobalVisibility doesn't yet have information + // about whether containing classes have visibility attributes, + // and that's intentional. + if (TSK != TSK_ExplicitInstantiationDeclaration && + F.ConsiderGlobalVisibility && + MD->getASTContext().getLangOptions().InlineVisibilityHidden) { + // InlineVisibilityHidden only applies to definitions, and + // isInlined() only gives meaningful answers on definitions + // anyway. + const FunctionDecl *Def = 0; + if (MD->hasBody(Def) && Def->isInlined()) + LV.setVisibility(HiddenVisibility); + } + + // Note that in contrast to basically every other situation, we + // *do* apply -fvisibility to method declarations. + + } else if (const CXXRecordDecl *RD = dyn_cast(D)) { + if (const ClassTemplateSpecializationDecl *Spec + = dyn_cast(RD)) { + // Merge template argument/parameter information for member + // class template specializations. + LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F)); + LV.merge(getLVForTemplateParameterList( + Spec->getSpecializedTemplate()->getTemplateParameters())); } - // Similarly for member class template specializations. - } else if (const ClassTemplateSpecializationDecl *Spec - = dyn_cast(D)) { - Linkage ArgLinkage = - getLinkageForTemplateArgumentList(Spec->getTemplateArgs()); - Linkage ParamLinkage = - getLinkageForTemplateParameterList( - Spec->getSpecializedTemplate()->getTemplateParameters()); - return minLinkage(ArgLinkage, ParamLinkage); + // Static data members. + } else if (const VarDecl *VD = dyn_cast(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) + LV.mergeLinkage(UniqueExternalLinkage); + if (!LV.visibilityExplicit()) + LV.mergeVisibility(TypeLV.second); } - return ExternalLinkage; + F.ConsiderGlobalVisibility &= !LV.visibilityExplicit(); + + // Apply -fvisibility if desired. + if (F.ConsiderGlobalVisibility && LV.visibility() != HiddenVisibility) { + LV.mergeVisibility(D->getASTContext().getLangOptions().getVisibilityMode()); + } + + return LV; +} + +static void clearLinkageForClass(const CXXRecordDecl *record) { + for (CXXRecordDecl::decl_iterator + i = record->decls_begin(), e = record->decls_end(); i != e; ++i) { + Decl *child = *i; + if (isa(child)) + cast(child)->ClearLinkageCache(); + } +} + +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 + // when computing linkage for parent contexts. + + HasCachedLinkage = 0; + + // If we're changing the linkage of a class, we need to reset the + // linkage of child declarations, too. + if (const CXXRecordDecl *record = dyn_cast(this)) + clearLinkageForClass(record); + + if (ClassTemplateDecl *temp = + dyn_cast(const_cast(this))) { + // Clear linkage for the template pattern. + CXXRecordDecl *record = temp->getTemplatedDecl(); + record->HasCachedLinkage = 0; + clearLinkageForClass(record); + + // We need to clear linkage for specializations, too. + for (ClassTemplateDecl::spec_iterator + i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) + i->ClearLinkageCache(); + } + + // Clear cached linkage for function template decls, too. + if (FunctionTemplateDecl *temp = + dyn_cast(const_cast(this))) + for (FunctionTemplateDecl::spec_iterator + i = temp->spec_begin(), e = temp->spec_end(); i != e; ++i) + i->ClearLinkageCache(); + } Linkage NamedDecl::getLinkage() const { + if (HasCachedLinkage) { + assert(Linkage(CachedLinkage) == + getLVForDecl(this, LVFlags::CreateOnlyDeclLinkage()).linkage()); + return Linkage(CachedLinkage); + } + + CachedLinkage = getLVForDecl(this, + LVFlags::CreateOnlyDeclLinkage()).linkage(); + HasCachedLinkage = 1; + return Linkage(CachedLinkage); +} +LinkageInfo NamedDecl::getLinkageAndVisibility() const { + LinkageInfo LI = getLVForDecl(this, LVFlags()); + assert(!HasCachedLinkage || Linkage(CachedLinkage) == LI.linkage()); + HasCachedLinkage = 1; + CachedLinkage = LI.linkage(); + return LI; +} + +static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { // Objective-C: treat all Objective-C declarations as having external // linkage. - switch (getKind()) { + switch (D->getKind()) { default: break; + case Decl::TemplateTemplateParm: // count these as external + case Decl::NonTypeTemplateParm: case Decl::ObjCAtDefsField: case Decl::ObjCCategory: case Decl::ObjCCategoryImpl: - case Decl::ObjCClass: case Decl::ObjCCompatibleAlias: case Decl::ObjCForwardProtocol: case Decl::ObjCImplementation: - case Decl::ObjCInterface: - case Decl::ObjCIvar: case Decl::ObjCMethod: case Decl::ObjCProperty: case Decl::ObjCPropertyImpl: case Decl::ObjCProtocol: - return ExternalLinkage; + return LinkageInfo::external(); } // Handle linkage for namespace-scope names. - if (getDeclContext()->getRedeclContext()->isFileContext()) - if (Linkage L = getLinkageForNamespaceScopeDecl(this)) - return L; + if (D->getDeclContext()->getRedeclContext()->isFileContext()) + return getLVForNamespaceScopeDecl(D, Flags); // C++ [basic.link]p5: // In addition, a member function, static data member, a named @@ -356,8 +688,8 @@ Linkage NamedDecl::getLinkage() const { // that the class or enumeration has the typedef name for linkage // purposes (7.1.3), has external linkage if the name of the class // has external linkage. - if (getDeclContext()->isRecord()) - return getLinkageForClassMember(this); + if (D->getDeclContext()->isRecord()) + return getLVForClassMember(D, Flags); // C++ [basic.link]p6: // The name of a function declared in block scope and the name of @@ -370,36 +702,54 @@ Linkage NamedDecl::getLinkage() const { // one such matching entity, the program is ill-formed. Otherwise, // if no matching entity is found, the block scope entity receives // external linkage. - if (getLexicalDeclContext()->isFunctionOrMethod()) { - if (const FunctionDecl *Function = dyn_cast(this)) { - if (Function->getPreviousDeclaration()) - if (Linkage L = Function->getPreviousDeclaration()->getLinkage()) - return L; - + if (D->getLexicalDeclContext()->isFunctionOrMethod()) { + if (const FunctionDecl *Function = dyn_cast(D)) { if (Function->isInAnonymousNamespace()) - return UniqueExternalLinkage; + return LinkageInfo::uniqueExternal(); - return ExternalLinkage; + LinkageInfo LV; + if (Flags.ConsiderVisibilityAttributes) { + if (const VisibilityAttr *VA = GetExplicitVisibility(Function)) + LV.setVisibility(GetVisibilityFromAttr(VA)); + } + + if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) { + LinkageInfo PrevLV = getLVForDecl(Prev, Flags); + if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); + LV.mergeVisibility(PrevLV); + } + + return LV; } - if (const VarDecl *Var = dyn_cast(this)) + if (const VarDecl *Var = dyn_cast(D)) if (Var->getStorageClass() == SC_Extern || Var->getStorageClass() == SC_PrivateExtern) { - if (Var->getPreviousDeclaration()) - if (Linkage L = Var->getPreviousDeclaration()->getLinkage()) - return L; - if (Var->isInAnonymousNamespace()) - return UniqueExternalLinkage; + return LinkageInfo::uniqueExternal(); + + LinkageInfo LV; + if (Var->getStorageClass() == SC_PrivateExtern) + LV.setVisibility(HiddenVisibility); + else if (Flags.ConsiderVisibilityAttributes) { + if (const VisibilityAttr *VA = GetExplicitVisibility(Var)) + LV.setVisibility(GetVisibilityFromAttr(VA)); + } + + if (const VarDecl *Prev = Var->getPreviousDeclaration()) { + LinkageInfo PrevLV = getLVForDecl(Prev, Flags); + if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage()); + LV.mergeVisibility(PrevLV); + } - return ExternalLinkage; + return LV; } } // C++ [basic.link]p6: // Names not covered by these rules have no linkage. - return NoLinkage; - } + return LinkageInfo::none(); +} std::string NamedDecl::getQualifiedNameAsString() const { return getQualifiedNameAsString(getASTContext().getLangOptions()); @@ -430,8 +780,8 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); std::string TemplateArgsStr = TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), + TemplateArgs.data(), + TemplateArgs.size(), P); OS << Spec->getName() << TemplateArgsStr; } else if (const NamespaceDecl *ND = dyn_cast(*I)) { @@ -514,6 +864,10 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { return cast(this)->getTargetDecl() == cast(OldD)->getTargetDecl(); + if (isa(this) && isa(OldD)) + return cast(this)->getTargetNestedNameDecl() == + cast(OldD)->getTargetNestedNameDecl(); + // 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. @@ -545,7 +899,7 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa(D)) D = cast(D)->getTargetDecl(); - if (isa(D)) + if (isa(D) || isa(D)) return true; if (isa(D)) return cast(D)->isInstance(); @@ -655,6 +1009,14 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten); } +void VarDecl::setStorageClass(StorageClass SC) { + assert(isLegalForVariable(SC)); + if (getStorageClass() != SC) + ClearLinkageCache(); + + SClass = SC; +} + SourceLocation VarDecl::getInnerLocStart() const { SourceLocation Start = getTypeSpecStartLoc(); if (Start.isInvalid()) @@ -785,6 +1147,17 @@ VarDecl *VarDecl::getDefinition() { return 0; } +VarDecl::DefinitionKind VarDecl::hasDefinition() 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()); + + return Kind; +} + const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { redecl_iterator I = redecls_begin(), E = redecls_end(); while (I != E && !I->getInit()) @@ -883,15 +1256,14 @@ Expr *ParmVarDecl::getDefaultArg() { "Default argument is not yet instantiated!"); Expr *Arg = getInit(); - if (CXXExprWithTemporaries *E = dyn_cast_or_null(Arg)) + if (ExprWithCleanups *E = dyn_cast_or_null(Arg)) return E->getSubExpr(); return Arg; } unsigned ParmVarDecl::getNumDefaultArgTemporaries() const { - if (const CXXExprWithTemporaries *E = - dyn_cast(getInit())) + if (const ExprWithCleanups *E = dyn_cast(getInit())) return E->getNumTemporaries(); return 0; @@ -901,7 +1273,7 @@ CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) { assert(getNumDefaultArgTemporaries() && "Default arguments does not have any temporaries!"); - CXXExprWithTemporaries *E = cast(getInit()); + ExprWithCleanups *E = cast(getInit()); return E->getTemporary(i); } @@ -915,6 +1287,10 @@ SourceRange ParmVarDecl::getDefaultArgRange() const { return SourceRange(); } +bool ParmVarDecl::isParameterPack() const { + return isa(getType()); +} + //===----------------------------------------------------------------------===// // FunctionDecl Implementation //===----------------------------------------------------------------------===// @@ -926,8 +1302,8 @@ void FunctionDecl::getNameForDiagnostic(std::string &S, const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); if (TemplateArgs) S += TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs->getFlatArgumentList(), - TemplateArgs->flat_size(), + TemplateArgs->data(), + TemplateArgs->size(), Policy); } @@ -966,6 +1342,13 @@ void FunctionDecl::setBody(Stmt *B) { EndRangeLoc = B->getLocEnd(); } +void FunctionDecl::setPure(bool P) { + IsPure = P; + if (P) + if (CXXRecordDecl *Parent = dyn_cast(getDeclContext())) + Parent->markedVirtualFunctionPure(); +} + bool FunctionDecl::isMain() const { ASTContext &Context = getASTContext(); return !Context.getLangOptions().Freestanding && @@ -994,7 +1377,7 @@ bool FunctionDecl::isExternC() const { break; } - return false; + return isMain(); } bool FunctionDecl::isGlobal() const { @@ -1027,6 +1410,9 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); FunTmpl->setPreviousDeclaration(PrevFunTmpl); } + + if (PrevDecl->IsInline) + IsInline = true; } const FunctionDecl *FunctionDecl::getCanonicalDecl() const { @@ -1037,6 +1423,14 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDeclaration(); } +void FunctionDecl::setStorageClass(StorageClass SC) { + assert(isLegalForFunction(SC)); + if (getStorageClass() != SC) + ClearLinkageCache(); + + SClass = SC; +} + /// \brief Returns a value indicating whether this function /// corresponds to a builtin function. /// @@ -1083,7 +1477,7 @@ unsigned FunctionDecl::getBuiltinID() const { /// getNumParams - Return the number of parameters this function must have -/// based on its FunctionType. This is the length of the PararmInfo array +/// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. unsigned FunctionDecl::getNumParams() const { const FunctionType *FT = getType()->getAs(); @@ -1093,13 +1487,14 @@ unsigned FunctionDecl::getNumParams() const { } -void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { +void FunctionDecl::setParams(ASTContext &C, + ParmVarDecl **NewParamInfo, unsigned NumParams) { assert(ParamInfo == 0 && "Already has param info!"); assert(NumParams == getNumParams() && "Parameter count mismatch!"); // Zero params -> null pointer. if (NumParams) { - void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams); + void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); ParamInfo = new (Mem) ParmVarDecl*[NumParams]; memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); @@ -1113,25 +1508,40 @@ void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { /// 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++). +/// arguments (in C++) or the last parameter is a parameter pack. unsigned FunctionDecl::getMinRequiredArguments() const { - unsigned NumRequiredArgs = getNumParams(); - while (NumRequiredArgs > 0 - && getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) + if (!getASTContext().getLangOptions().CPlusPlus) + return getNumParams(); + + unsigned NumRequiredArgs = getNumParams(); + + // If the last parameter is a parameter pack, we don't need an argument for + // it. + if (NumRequiredArgs > 0 && + getParamDecl(NumRequiredArgs - 1)->isParameterPack()) + --NumRequiredArgs; + + // If this parameter has a default argument, we don't need an argument for + // it. + while (NumRequiredArgs > 0 && + getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) --NumRequiredArgs; + // We might have parameter packs before the end. These can't be deduced, + // but they can still handle multiple arguments. + unsigned ArgIdx = NumRequiredArgs; + while (ArgIdx > 0) { + if (getParamDecl(ArgIdx - 1)->isParameterPack()) + NumRequiredArgs = ArgIdx; + + --ArgIdx; + } + return NumRequiredArgs; } bool FunctionDecl::isInlined() const { - // FIXME: This is not enough. Consider: - // - // inline void f(); - // void f() { } - // - // f is inlined, but does not have inline specified. - // To fix this we should add an 'inline' flag to FunctionDecl. - if (isInlineSpecified()) + if (IsInline) return true; if (isa(this)) { @@ -1185,20 +1595,22 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { ASTContext &Context = getASTContext(); if (!Context.getLangOptions().C99 || hasAttr()) { - // GNU inline semantics. Based on a number of examples, we came up with the - // following heuristic: if the "inline" keyword is present on a - // declaration of the function but "extern" is not present on that - // declaration, then the symbol is externally visible. Otherwise, the GNU - // "extern inline" semantics applies and the symbol is not externally - // visible. + // If it's not the case that both 'inline' and 'extern' are + // specified on the definition, then this inline definition is + // externally visible. + if (!(isInlineSpecified() && getStorageClassAsWritten() == SC_Extern)) + return true; + + // If any declaration is 'inline' but not 'extern', then this definition + // is externally visible. for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); Redecl != RedeclEnd; ++Redecl) { - if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern) + if (Redecl->isInlineSpecified() && + Redecl->getStorageClassAsWritten() != SC_Extern) return true; - } + } - // GNU "extern inline" semantics; no externally visible symbol. return false; } @@ -1271,12 +1683,13 @@ MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { } void -FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD, +FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, + FunctionDecl *FD, TemplateSpecializationKind TSK) { assert(TemplateOrSpecialization.isNull() && "Member function is already a specialization"); MemberSpecializationInfo *Info - = new (getASTContext()) MemberSpecializationInfo(FD, TSK); + = new (C) MemberSpecializationInfo(FD, TSK); TemplateOrSpecialization = Info; } @@ -1362,7 +1775,8 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { } void -FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, +FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, + FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, TemplateSpecializationKind TSK, @@ -1373,14 +1787,10 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization.dyn_cast(); if (!Info) - Info = new (getASTContext()) FunctionTemplateSpecializationInfo; - - Info->Function = this; - Info->Template.setPointer(Template); - Info->Template.setInt(TSK - 1); - Info->TemplateArguments = TemplateArgs; - Info->TemplateArgumentsAsWritten = TemplateArgsAsWritten; - Info->PointOfInstantiation = PointOfInstantiation; + Info = FunctionTemplateSpecializationInfo::Create(C, this, Template, TSK, + TemplateArgs, + TemplateArgsAsWritten, + PointOfInstantiation); TemplateOrSpecialization = Info; // Insert this function template specialization into the set of known @@ -1400,28 +1810,6 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, } } -void -FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, - unsigned NumTemplateArgs, - const TemplateArgument *TemplateArgs, - TemplateSpecializationKind TSK, - unsigned NumTemplateArgsAsWritten, - TemplateArgumentLoc *TemplateArgsAsWritten, - SourceLocation LAngleLoc, - SourceLocation RAngleLoc, - SourceLocation PointOfInstantiation) { - ASTContext &Ctx = getASTContext(); - TemplateArgumentList *TemplArgs - = new (Ctx) TemplateArgumentList(Ctx, TemplateArgs, NumTemplateArgs); - TemplateArgumentListInfo *TemplArgsInfo - = new (Ctx) TemplateArgumentListInfo(LAngleLoc, RAngleLoc); - for (unsigned i=0; i != NumTemplateArgsAsWritten; ++i) - TemplArgsInfo->addArgument(TemplateArgsAsWritten[i]); - - setFunctionTemplateSpecialization(Template, TemplArgs, /*InsertPos=*/0, TSK, - TemplArgsInfo, PointOfInstantiation); -} - void FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context, const UnresolvedSetImpl &Templates, @@ -1533,8 +1921,8 @@ bool FunctionDecl::isOutOfLine() const { // FieldDecl Implementation //===----------------------------------------------------------------------===// -FieldDecl *FieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, +FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) { return new (C) FieldDecl(Decl::Field, DC, L, Id, T, TInfo, BW, Mutable); } @@ -1549,6 +1937,25 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; } +unsigned FieldDecl::getFieldIndex() const { + if (CachedFieldIndex) return CachedFieldIndex - 1; + + unsigned index = 0; + RecordDecl::field_iterator + i = getParent()->field_begin(), e = getParent()->field_end(); + while (true) { + assert(i != e && "failed to find field in parent!"); + if (*i == this) + break; + + ++i; + ++index; + } + + CachedFieldIndex = index + 1; + return index; +} + //===----------------------------------------------------------------------===// // TagDecl Implementation //===----------------------------------------------------------------------===// @@ -1569,7 +1976,8 @@ TagDecl* TagDecl::getCanonicalDecl() { void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; if (TypeForDecl) - TypeForDecl->ClearLinkageCache(); + const_cast(TypeForDecl)->ClearLinkageCache(); + ClearLinkageCache(); } void TagDecl::startDefinition() { @@ -1591,11 +1999,16 @@ void TagDecl::completeDefinition() { IsDefinition = true; IsBeingDefined = false; + + if (ASTMutationListener *L = getASTMutationListener()) + L->CompletedTagDefinition(this); } TagDecl* TagDecl::getDefinition() const { if (isDefinition()) return const_cast(this); + if (const CXXRecordDecl *CXXRD = dyn_cast(this)) + return CXXRD->getDefinition(); for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); R != REnd; ++R) @@ -1631,14 +2044,17 @@ void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, - EnumDecl *PrevDecl) { - EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL); + EnumDecl *PrevDecl, bool IsScoped, + bool IsScopedUsingClassTag, bool IsFixed) { + EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL, + IsScoped, IsScopedUsingClassTag, IsFixed); C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) { - return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation()); + return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation(), + false, false, false); } void EnumDecl::completeDefinition(QualType NewType, @@ -1646,7 +2062,8 @@ void EnumDecl::completeDefinition(QualType NewType, unsigned NumPositiveBits, unsigned NumNegativeBits) { assert(!isDefinition() && "Cannot redefine enums!"); - IntegerType = NewType; + if (!IntegerType) + IntegerType = NewType.getTypePtr(); PromotionType = NewPromotionType; setNumPositiveBits(NumPositiveBits); setNumNegativeBits(NumNegativeBits); @@ -1664,10 +2081,11 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; + LoadedFieldsFromExternalStorage = false; assert(classof(static_cast(this)) && "Invalid Kind!"); } -RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, +RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, RecordDecl* PrevDecl) { @@ -1676,7 +2094,7 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, return R; } -RecordDecl *RecordDecl::Create(ASTContext &C, EmptyShell Empty) { +RecordDecl *RecordDecl::Create(const ASTContext &C, EmptyShell Empty) { return new (C) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), 0, 0, SourceLocation()); } @@ -1686,6 +2104,13 @@ bool RecordDecl::isInjectedClassName() const { cast(getDeclContext())->getDeclName() == getDeclName(); } +RecordDecl::field_iterator RecordDecl::field_begin() const { + if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage) + LoadFieldsFromExternalStorage(); + + return field_iterator(decl_iterator(FirstDecl)); +} + /// completeDefinition - Notes that the definition of this type is now /// complete. void RecordDecl::completeDefinition() { @@ -1693,15 +2118,29 @@ void RecordDecl::completeDefinition() { TagDecl::completeDefinition(); } -ValueDecl *RecordDecl::getAnonymousStructOrUnionObject() { - // Force the decl chain to come into existence properly. - if (!getNextDeclInContext()) getParent()->decls_begin(); +void RecordDecl::LoadFieldsFromExternalStorage() const { + ExternalASTSource *Source = getASTContext().getExternalSource(); + assert(hasExternalLexicalStorage() && Source && "No external storage?"); + + // Notify that we have a RecordDecl doing some initialization. + ExternalASTSource::Deserializing TheFields(Source); - assert(isAnonymousStructOrUnion()); - ValueDecl *D = cast(getNextDeclInContext()); - assert(D->getType()->isRecordType()); - assert(D->getType()->getAs()->getDecl() == this); - return D; + llvm::SmallVector Decls; + if (Source->FindExternalLexicalDeclsBy(this, Decls)) + return; + +#ifndef NDEBUG + // Check that all decls we got were FieldDecls. + for (unsigned i=0, e=Decls.size(); i != e; ++i) + assert(isa(Decls[i])); +#endif + + LoadedFieldsFromExternalStorage = true; + + if (Decls.empty()) + return; + + llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls); } //===----------------------------------------------------------------------===// @@ -1721,10 +2160,31 @@ void BlockDecl::setParams(ParmVarDecl **NewParamInfo, } } -unsigned BlockDecl::getNumParams() const { - return NumParams; +void BlockDecl::setCaptures(ASTContext &Context, + const Capture *begin, + const Capture *end, + bool capturesCXXThis) { + CapturesCXXThis = capturesCXXThis; + + if (begin == end) { + NumCaptures = 0; + Captures = 0; + return; + } + + NumCaptures = end - begin; + + // Avoid new Capture[] because we don't want to provide a default + // constructor. + size_t allocationSize = NumCaptures * sizeof(Capture); + void *buffer = Context.Allocate(allocationSize, /*alignment*/sizeof(void*)); + memcpy(buffer, begin, allocationSize); + Captures = static_cast(buffer); } +SourceRange BlockDecl::getSourceRange() const { + return SourceRange(getLocation(), Body? Body->getLocEnd() : getLocation()); +} //===----------------------------------------------------------------------===// // Other Decl Allocation/Deallocation Method Implementations @@ -1734,11 +2194,22 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { return new (C) TranslationUnitDecl(C); } +LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *II) { + return new (C) LabelDecl(DC, L, II, 0); +} + + NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) { return new (C) NamespaceDecl(DC, L, Id); } +NamespaceDecl *NamespaceDecl::getNextNamespace() { + return dyn_cast_or_null( + NextNamespace.get(getASTContext().getExternalSource())); +} + ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T) { return new (C) ImplicitParamDecl(ImplicitParam, DC, L, Id, T); @@ -1748,9 +2219,10 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, - bool isInline, bool hasWrittenPrototype) { + bool isInlineSpecified, + bool hasWrittenPrototype) { FunctionDecl *New = new (C) FunctionDecl(Function, DC, NameInfo, T, TInfo, - S, SCAsWritten, isInline); + S, SCAsWritten, isInlineSpecified); New->HasWrittenPrototype = hasWrittenPrototype; return New; } @@ -1766,6 +2238,13 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, return new (C) EnumConstantDecl(CD, L, Id, T, E, V); } +IndirectFieldDecl * +IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, NamedDecl **CH, + unsigned CHS) { + return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); +} + SourceRange EnumConstantDecl::getSourceRange() const { SourceLocation End = getLocation(); if (Init) diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 0b958fe82b09..be379d522dd4 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -24,6 +24,7 @@ #include "clang/AST/Type.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/ASTMutationListener.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include @@ -109,10 +110,22 @@ void Decl::add(Kind k) { bool Decl::isTemplateParameterPack() const { if (const TemplateTypeParmDecl *TTP = dyn_cast(this)) return TTP->isParameterPack(); - + if (const NonTypeTemplateParmDecl *NTTP + = dyn_cast(this)) + return NTTP->isParameterPack(); + if (const TemplateTemplateParmDecl *TTP + = dyn_cast(this)) + return TTP->isParameterPack(); return false; } +bool Decl::isParameterPack() const { + if (const ParmVarDecl *Parm = dyn_cast(this)) + return Parm->isParameterPack(); + + return isTemplateParameterPack(); +} + bool Decl::isFunctionOrFunctionTemplate() const { if (const UsingShadowDecl *UD = dyn_cast(this)) return UD->getTargetDecl()->isFunctionOrFunctionTemplate(); @@ -210,6 +223,10 @@ ASTContext &Decl::getASTContext() const { return getTranslationUnitDecl()->getASTContext(); } +ASTMutationListener *Decl::getASTMutationListener() const { + return getASTContext().getASTMutationListener(); +} + bool Decl::isUsed(bool CheckUsedAttr) const { if (Used) return true; @@ -243,6 +260,10 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case ObjCMethod: case ObjCProperty: return IDNS_Ordinary; + case Label: + return IDNS_Label; + case IndirectField: + return IDNS_Ordinary | IDNS_Member; case ObjCCompatibleAlias: case ObjCInterface: @@ -416,27 +437,34 @@ SourceLocation Decl::getBodyRBrace() const { return SourceLocation(); } -#ifndef NDEBUG void Decl::CheckAccessDeclContext() const { - // FIXME: Disable this until rdar://8146294 "access specifier for inner class - // templates is not set or checked" is fixed. - return; +#ifndef NDEBUG // Suppress this check if any of the following hold: // 1. this is the translation unit (and thus has no parent) // 2. this is a template parameter (and thus doesn't belong to its context) - // 3. the context is not a record - // 4. it's invalid + // 3. this is a non-type template parameter + // 4. the context is not a record + // 5. it's invalid + // 6. it's a C++0x static_assert. if (isa(this) || isa(this) || + isa(this) || !isa(getDeclContext()) || - isInvalidDecl()) + isInvalidDecl() || + isa(this) || + // FIXME: a ParmVarDecl can have ClassTemplateSpecialization + // as DeclContext (?). + isa(this) || + // FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have + // AS_none as access specifier. + isa(this)) return; assert(Access != AS_none && "Access specifier is AS_none inside a record decl"); +#endif } -#endif //===----------------------------------------------------------------------===// // DeclContext Implementation @@ -509,15 +537,24 @@ bool DeclContext::isDependentContext() const { bool DeclContext::isTransparentContext() const { if (DeclKind == Decl::Enum) - return true; // FIXME: Check for C++0x scoped enums + return !cast(this)->isScoped(); else if (DeclKind == Decl::LinkageSpec) return true; - else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord) - return cast(this)->isAnonymousStructOrUnion(); return false; } +bool DeclContext::isExternCContext() const { + const DeclContext *DC = this; + while (DC->DeclKind != Decl::TranslationUnit) { + if (DC->DeclKind == Decl::LinkageSpec) + return cast(DC)->getLanguage() + == LinkageSpecDecl::lang_c; + DC = DC->getParent(); + } + return false; +} + bool DeclContext::Encloses(const DeclContext *DC) const { if (getPrimaryContext() != this) return getPrimaryContext()->Encloses(DC); @@ -592,6 +629,24 @@ DeclContext *DeclContext::getNextContext() { } } +std::pair +DeclContext::BuildDeclChain(const llvm::SmallVectorImpl &Decls) { + // Build up a chain of declarations via the Decl::NextDeclInContext field. + Decl *FirstNewDecl = 0; + Decl *PrevDecl = 0; + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + Decl *D = Decls[I]; + if (PrevDecl) + PrevDecl->NextDeclInContext = D; + else + FirstNewDecl = D; + + PrevDecl = D; + } + + return std::make_pair(FirstNewDecl, PrevDecl); +} + /// \brief Load the declarations within this lexical storage from an /// external source. void @@ -612,26 +667,22 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { if (Decls.empty()) return; - // Resolve all of the declaration IDs into declarations, building up - // a chain of declarations via the Decl::NextDeclInContext field. - Decl *FirstNewDecl = 0; - Decl *PrevDecl = 0; - for (unsigned I = 0, N = Decls.size(); I != N; ++I) { - Decl *D = Decls[I]; - if (PrevDecl) - PrevDecl->NextDeclInContext = D; - else - FirstNewDecl = D; - - PrevDecl = D; - } + // We may have already loaded just the fields of this record, in which case + // don't add the decls, just replace the FirstDecl/LastDecl chain. + if (const RecordDecl *RD = dyn_cast(this)) + if (RD->LoadedFieldsFromExternalStorage) { + llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls); + return; + } // Splice the newly-read declarations into the beginning of the list // of declarations. - PrevDecl->NextDeclInContext = FirstDecl; - FirstDecl = FirstNewDecl; + Decl *ExternalFirst, *ExternalLast; + llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls); + ExternalLast->NextDeclInContext = FirstDecl; + FirstDecl = ExternalFirst; if (!LastDecl) - LastDecl = PrevDecl; + LastDecl = ExternalLast; } DeclContext::lookup_result @@ -771,6 +822,11 @@ void DeclContext::addHiddenDecl(Decl *D) { } else { FirstDecl = LastDecl = D; } + + // Notify a C++ record declaration that we've added a member, so it can + // update it's class-specific state. + if (CXXRecordDecl *Record = dyn_cast(this)) + Record->addedMember(D); } void DeclContext::addDecl(Decl *D) { @@ -911,6 +967,12 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) { // parent context, too. This operation is recursive. if (isTransparentContext() || isInlineNamespace()) getParent()->makeDeclVisibleInContext(D, Recoverable); + + Decl *DCAsDecl = cast(this); + // Notify that a decl was made visible unless it's a Tag being defined. + if (!(isa(DCAsDecl) && cast(DCAsDecl)->isBeingDefined())) + if (ASTMutationListener *L = DCAsDecl->getASTMutationListener()) + L->AddedVisibleDecl(this, D); } void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index f2f0694826c6..fba73f59d563 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -14,6 +14,8 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/IdentifierTable.h" @@ -34,8 +36,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) HasTrivialDestructor(true), ComputedVisibleConversions(false), DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), DeclaredCopyAssignment(false), DeclaredDestructor(false), - Bases(0), NumBases(0), VBases(0), NumVBases(0), - Definition(D), FirstFriend(0) { + NumBases(0), NumVBases(0), Bases(), VBases(), + Definition(D), FirstFriend(0) { } CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -46,9 +48,9 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0), TemplateOrInstantiation() { } -CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL, +CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, + DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, SourceLocation TKL, CXXRecordDecl* PrevDecl, bool DelayTypeCreation) { CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id, @@ -60,7 +62,7 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, return R; } -CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, EmptyShell Empty) { +CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, EmptyShell Empty) { return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), 0, 0, SourceLocation()); } @@ -75,8 +77,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // no base classes [...]. data().Aggregate = false; - if (data().Bases) - C.Deallocate(data().Bases); + if (!data().Bases.isOffset() && data().NumBases > 0) + C.Deallocate(data().getBases()); // The set of seen virtual base types. llvm::SmallPtrSet SeenVBaseTypes; @@ -87,7 +89,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().Bases = new(C) CXXBaseSpecifier [NumBases]; data().NumBases = NumBases; for (unsigned i = 0; i < NumBases; ++i) { - data().Bases[i] = *Bases[i]; + data().getBases()[i] = *Bases[i]; // Keep track of inherited vbases for this base class. const CXXBaseSpecifier *Base = Bases[i]; QualType BaseType = Base->getType(); @@ -97,6 +99,25 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, CXXRecordDecl *BaseClassDecl = cast(BaseType->getAs()->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()) + data().Empty = false; + + // C++ [class.virtual]p1: + // A class that declares or inherits a virtual function is called a + // polymorphic class. + if (BaseClassDecl->isPolymorphic()) + data().Polymorphic = true; + // Now go through all virtual bases of this base and add them. for (CXXRecordDecl::base_class_iterator VBase = BaseClassDecl->vbases_begin(), @@ -110,8 +131,50 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, // Add this base if it's not already in the list. if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) VBases.push_back(Base); + + // C++0x [meta.unary.prop] is_empty: + // T is a class type, but not a union type, with ... no virtual base + // classes + data().Empty = false; + + // C++ [class.ctor]p5: + // A constructor is trivial if its class has no virtual base classes. + data().HasTrivialConstructor = false; + + // C++ [class.copy]p6: + // A copy constructor is trivial if its class has no virtual base + // classes. + data().HasTrivialCopyConstructor = false; + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if its class has no virtual + // base classes. + data().HasTrivialCopyAssignment = false; + } else { + // C++ [class.ctor]p5: + // A constructor is trivial if all the direct base classes of its + // class have trivial constructors. + if (!BaseClassDecl->hasTrivialConstructor()) + data().HasTrivialConstructor = false; + + // C++ [class.copy]p6: + // A copy constructor is trivial if all the direct base classes of its + // class have trivial copy constructors. + if (!BaseClassDecl->hasTrivialCopyConstructor()) + data().HasTrivialCopyConstructor = false; + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if all the direct base classes + // of its class have trivial copy assignment operators. + if (!BaseClassDecl->hasTrivialCopyAssignment()) + data().HasTrivialCopyAssignment = false; } - + + // C++ [class.ctor]p3: + // A destructor is trivial if all the direct base classes of its class + // have trivial destructors. + if (!BaseClassDecl->hasTrivialDestructor()) + data().HasTrivialDestructor = false; } if (VBases.empty()) @@ -130,10 +193,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, CXXRecordDecl *VBaseClassDecl = cast( VBaseTypeInfo->getType()->getAs()->getDecl()); - data().VBases[I] = + data().getVBases()[I] = CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true, VBaseClassDecl->getTagKind() == TTK_Class, - VBases[I]->getAccessSpecifier(), VBaseTypeInfo); + VBases[I]->getAccessSpecifier(), VBaseTypeInfo, + SourceLocation()); } } @@ -150,7 +214,7 @@ bool CXXRecordDecl::hasAnyDependentBases() const { return !forallBases(SawBase, 0); } -bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { +bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const { return getCopyConstructor(Context, Qualifiers::Const) != 0; } @@ -177,7 +241,7 @@ GetBestOverloadCandidateSimple( return Cands[Best].first; } -CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, +CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context, unsigned TypeQuals) const{ QualType ClassType = Context.getTypeDeclType(const_cast(this)); @@ -258,84 +322,268 @@ CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { return GetBestOverloadCandidateSimple(Found); } -void -CXXRecordDecl::addedConstructor(ASTContext &Context, - CXXConstructorDecl *ConDecl) { - assert(!ConDecl->isImplicit() && "addedConstructor - not for implicit decl"); - // Note that we have a user-declared constructor. - data().UserDeclaredConstructor = true; - - // Note that we have no need of an implicitly-declared default constructor. - data().DeclaredDefaultConstructor = true; +void CXXRecordDecl::markedVirtualFunctionPure() { + // C++ [class.abstract]p2: + // A class is abstract if it has at least one pure virtual function. + data().Abstract = true; +} + +void CXXRecordDecl::addedMember(Decl *D) { + // Ignore friends and invalid declarations. + if (D->getFriendObjectKind() || D->isInvalidDecl()) + return; - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class (clause 9) with no - // user-declared constructors (12.1) [...]. - data().Aggregate = false; + FunctionTemplateDecl *FunTmpl = dyn_cast(D); + if (FunTmpl) + D = FunTmpl->getTemplatedDecl(); + + if (CXXMethodDecl *Method = dyn_cast(D)) { + if (Method->isVirtual()) { + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class with [...] no virtual functions. + data().Aggregate = false; + + // C++ [class]p4: + // A POD-struct is an aggregate class... + data().PlainOldData = false; + + // Virtual functions make the class non-empty. + // FIXME: Standard ref? + data().Empty = false; + + // C++ [class.virtual]p1: + // A class that declares or inherits a virtual function is called a + // polymorphic class. + data().Polymorphic = true; + + // None of the special member functions are trivial. + data().HasTrivialConstructor = false; + data().HasTrivialCopyConstructor = false; + data().HasTrivialCopyAssignment = false; + // FIXME: Destructor? + } + } + + if (D->isImplicit()) { + // Notify that an implicit member was added after the definition + // was completed. + if (!isBeingDefined()) + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXImplicitMember(data().Definition, D); + + if (CXXConstructorDecl *Constructor = dyn_cast(D)) { + // If this is the implicit default constructor, note that we have now + // declared it. + if (Constructor->isDefaultConstructor()) + data().DeclaredDefaultConstructor = true; + // If this is the implicit copy constructor, note that we have now + // declared it. + else if (Constructor->isCopyConstructor()) + data().DeclaredCopyConstructor = true; + return; + } - // C++ [class]p4: - // A POD-struct is an aggregate class [...] - data().PlainOldData = false; + if (isa(D)) { + data().DeclaredDestructor = true; + return; + } + + if (CXXMethodDecl *Method = dyn_cast(D)) { + // If this is the implicit copy constructor, note that we have now + // declared it. + // FIXME: Move constructors + if (Method->getOverloadedOperator() == OO_Equal) + data().DeclaredCopyAssignment = true; + return; + } - // C++ [class.ctor]p5: - // A constructor is trivial if it is an implicitly-declared default - // constructor. - // FIXME: C++0x: don't do this for "= default" default constructors. - data().HasTrivialConstructor = false; - - // Note when we have a user-declared copy constructor, which will - // suppress the implicit declaration of a copy constructor. - if (ConDecl->isCopyConstructor()) { - data().UserDeclaredCopyConstructor = true; - data().DeclaredCopyConstructor = true; + // Any other implicit declarations are handled like normal declarations. + } + + // Handle (user-declared) constructors. + if (CXXConstructorDecl *Constructor = dyn_cast(D)) { + // Note that we have a user-declared constructor. + data().UserDeclaredConstructor = true; + + // Note that we have no need of an implicitly-declared default constructor. + data().DeclaredDefaultConstructor = true; - // C++ [class.copy]p6: - // A copy constructor is trivial if it is implicitly declared. - // FIXME: C++0x: don't do this for "= default" copy constructors. - data().HasTrivialCopyConstructor = false; + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class (clause 9) with no + // user-declared constructors (12.1) [...]. + data().Aggregate = false; + + // C++ [class]p4: + // A POD-struct is an aggregate class [...] + data().PlainOldData = false; + + // C++ [class.ctor]p5: + // A constructor is trivial if it is an implicitly-declared default + // constructor. + // FIXME: C++0x: don't do this for "= default" default constructors. + data().HasTrivialConstructor = false; + + // Note when we have a user-declared copy constructor, which will + // suppress the implicit declaration of a copy constructor. + if (!FunTmpl && Constructor->isCopyConstructor()) { + data().UserDeclaredCopyConstructor = true; + data().DeclaredCopyConstructor = true; + + // C++ [class.copy]p6: + // A copy constructor is trivial if it is implicitly declared. + // FIXME: C++0x: don't do this for "= default" copy constructors. + data().HasTrivialCopyConstructor = false; + } + return; } -} -void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, - CXXMethodDecl *OpDecl) { - // We're interested specifically in copy assignment operators. - const FunctionProtoType *FnType = OpDecl->getType()->getAs(); - assert(FnType && "Overloaded operator has no proto function type."); - assert(FnType->getNumArgs() == 1 && !FnType->isVariadic()); - - // Copy assignment operators must be non-templates. - if (OpDecl->getPrimaryTemplate() || OpDecl->getDescribedFunctionTemplate()) + // Handle (user-declared) destructors. + if (isa(D)) { + data().DeclaredDestructor = true; + data().UserDeclaredDestructor = true; + + // C++ [class]p4: + // A POD-struct is an aggregate class that has [...] no user-defined + // destructor. + data().PlainOldData = false; + + // C++ [class.dtor]p3: + // A destructor is trivial if it is an implicitly-declared destructor and + // [...]. + // + // FIXME: C++0x: don't do this for "= default" destructors + data().HasTrivialDestructor = false; + return; + } - QualType ArgType = FnType->getArgType(0); - if (const LValueReferenceType *Ref = ArgType->getAs()) - ArgType = Ref->getPointeeType(); - - ArgType = ArgType.getUnqualifiedType(); - QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( - const_cast(this))); + // Handle (user-declared) member functions. + if (CXXMethodDecl *Method = dyn_cast(D)) { + if (Method->getOverloadedOperator() == OO_Equal) { + // We're interested specifically in copy assignment operators. + const FunctionProtoType *FnType + = Method->getType()->getAs(); + assert(FnType && "Overloaded operator has no proto function type."); + assert(FnType->getNumArgs() == 1 && !FnType->isVariadic()); + + // Copy assignment operators must be non-templates. + if (Method->getPrimaryTemplate() || FunTmpl) + return; + + ASTContext &Context = getASTContext(); + QualType ArgType = FnType->getArgType(0); + if (const LValueReferenceType *Ref =ArgType->getAs()) + ArgType = Ref->getPointeeType(); + + ArgType = ArgType.getUnqualifiedType(); + QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( + const_cast(this))); + + if (!Context.hasSameUnqualifiedType(ClassType, ArgType)) + return; + + // This is a copy assignment operator. + // FIXME: Move assignment operators. + + // Suppress the implicit declaration of a copy constructor. + data().UserDeclaredCopyAssignment = true; + data().DeclaredCopyAssignment = true; + + // C++ [class.copy]p11: + // A copy assignment operator is trivial if it is implicitly declared. + // FIXME: C++0x: don't do this for "= default" copy operators. + data().HasTrivialCopyAssignment = false; + + // C++ [class]p4: + // A POD-struct is an aggregate class that [...] has no user-defined copy + // assignment operator [...]. + data().PlainOldData = false; + } + + // Keep the list of conversion functions up-to-date. + if (CXXConversionDecl *Conversion = dyn_cast(D)) { + // We don't record specializations. + if (Conversion->getPrimaryTemplate()) + return; + + // FIXME: We intentionally don't use the decl's access here because it + // hasn't been set yet. That's really just a misdesign in Sema. - if (!Context.hasSameUnqualifiedType(ClassType, ArgType)) + if (FunTmpl) { + if (FunTmpl->getPreviousDeclaration()) + data().Conversions.replace(FunTmpl->getPreviousDeclaration(), + FunTmpl); + else + data().Conversions.addDecl(FunTmpl); + } else { + if (Conversion->getPreviousDeclaration()) + data().Conversions.replace(Conversion->getPreviousDeclaration(), + Conversion); + else + data().Conversions.addDecl(Conversion); + } + } + return; - - // This is a copy assignment operator. - // Note on the decl that it is a copy assignment operator. - OpDecl->setCopyAssignment(true); - - // Suppress the implicit declaration of a copy constructor. - data().UserDeclaredCopyAssignment = true; - data().DeclaredCopyAssignment = true; + } - // C++ [class.copy]p11: - // A copy assignment operator is trivial if it is implicitly declared. - // FIXME: C++0x: don't do this for "= default" copy operators. - data().HasTrivialCopyAssignment = false; - - // C++ [class]p4: - // A POD-struct is an aggregate class that [...] has no user-defined copy - // assignment operator [...]. - data().PlainOldData = false; + // Handle non-static data members. + if (FieldDecl *Field = dyn_cast(D)) { + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class (clause 9) with [...] no + // private or protected non-static data members (clause 11). + // + // A POD must be an aggregate. + if (D->getAccess() == AS_private || D->getAccess() == AS_protected) { + data().Aggregate = false; + data().PlainOldData = false; + } + + // C++ [class]p9: + // A POD struct is a class that is both a trivial class and a + // standard-layout class, and has no non-static data members of type + // non-POD struct, non-POD union (or array of such types). + ASTContext &Context = getASTContext(); + QualType T = Context.getBaseElementType(Field->getType()); + if (!T->isPODType()) + data().PlainOldData = false; + if (T->isReferenceType()) + data().HasTrivialConstructor = false; + + if (const RecordType *RecordTy = T->getAs()) { + CXXRecordDecl* FieldRec = cast(RecordTy->getDecl()); + if (FieldRec->getDefinition()) { + if (!FieldRec->hasTrivialConstructor()) + data().HasTrivialConstructor = false; + if (!FieldRec->hasTrivialCopyConstructor()) + data().HasTrivialCopyConstructor = false; + if (!FieldRec->hasTrivialCopyAssignment()) + data().HasTrivialCopyAssignment = false; + if (!FieldRec->hasTrivialDestructor()) + data().HasTrivialDestructor = false; + } + } + + // If this is not a zero-length bit-field, then the class is not empty. + if (data().Empty) { + if (!Field->getBitWidth()) + data().Empty = false; + else if (!Field->getBitWidth()->isTypeDependent() && + !Field->getBitWidth()->isValueDependent()) { + llvm::APSInt Bits; + if (Field->getBitWidth()->isIntegerConstantExpr(Bits, Context)) + if (!!Bits) + data().Empty = false; + } + } + } + + // Handle using declarations of conversion functions. + if (UsingShadowDecl *Shadow = dyn_cast(D)) + if (Shadow->getDeclName().getNameKind() + == DeclarationName::CXXConversionFunctionName) + data().Conversions.addDecl(Shadow, Shadow->getAccess()); } static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { @@ -479,20 +727,6 @@ const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() { return &data().VisibleConversions; } -#ifndef NDEBUG -void CXXRecordDecl::CheckConversionFunction(NamedDecl *ConvDecl) { - assert(ConvDecl->getDeclContext() == this && - "conversion function does not belong to this record"); - - ConvDecl = ConvDecl->getUnderlyingDecl(); - if (FunctionTemplateDecl *Temp = dyn_cast(ConvDecl)) { - assert(isa(Temp->getTemplatedDecl())); - } else { - assert(isa(ConvDecl)); - } -} -#endif - void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { // This operation is O(N) but extremely rare. Sema only uses it to // remove UsingShadowDecls in a class that were followed by a direct @@ -518,17 +752,6 @@ void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { llvm_unreachable("conversion not found in set!"); } -void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) { - Method->setVirtualAsWritten(true); - setAggregate(false); - setPOD(false); - setEmpty(false); - setPolymorphic(true); - setHasTrivialConstructor(false); - setHasTrivialCopyConstructor(false); - setHasTrivialCopyAssignment(false); -} - CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) return cast(MSInfo->getInstantiatedFrom()); @@ -577,28 +800,6 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(false && "Not a class template or member class specialization"); } -CXXConstructorDecl * -CXXRecordDecl::getDefaultConstructor() { - ASTContext &Context = getASTContext(); - QualType ClassType = Context.getTypeDeclType(this); - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ClassType.getUnqualifiedType())); - - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = lookup(ConstructorName); - Con != ConEnd; ++Con) { - // FIXME: In C++0x, a constructor template can be a default constructor. - if (isa(*Con)) - continue; - - CXXConstructorDecl *Constructor = cast(*Con); - if (Constructor->isDefaultConstructor()) - return Constructor; - } - return 0; -} - CXXDestructorDecl *CXXRecordDecl::getDestructor() const { ASTContext &Context = getASTContext(); QualType ClassType = Context.getTypeDeclType(this); @@ -618,6 +819,69 @@ CXXDestructorDecl *CXXRecordDecl::getDestructor() const { return Dtor; } +void CXXRecordDecl::completeDefinition() { + completeDefinition(0); +} + +void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { + RecordDecl::completeDefinition(); + + // If the class may be abstract (but hasn't been marked as such), check for + // any pure final overriders. + if (mayBeAbstract()) { + CXXFinalOverriderMap MyFinalOverriders; + if (!FinalOverriders) { + getFinalOverriders(MyFinalOverriders); + FinalOverriders = &MyFinalOverriders; + } + + bool Done = false; + for (CXXFinalOverriderMap::iterator M = FinalOverriders->begin(), + MEnd = FinalOverriders->end(); + M != MEnd && !Done; ++M) { + for (OverridingMethods::iterator SO = M->second.begin(), + SOEnd = M->second.end(); + SO != SOEnd && !Done; ++SO) { + assert(SO->second.size() > 0 && + "All virtual functions have overridding virtual functions"); + + // C++ [class.abstract]p4: + // A class is abstract if it contains or inherits at least one + // pure virtual function for which the final overrider is pure + // virtual. + if (SO->second.front().Method->isPure()) { + data().Abstract = true; + Done = true; + break; + } + } + } + } + + // Set access bits correctly on the directly-declared conversions. + for (UnresolvedSetIterator I = data().Conversions.begin(), + E = data().Conversions.end(); + I != E; ++I) + data().Conversions.setAccess(I, (*I)->getAccess()); +} + +bool CXXRecordDecl::mayBeAbstract() const { + if (data().Abstract || isInvalidDecl() || !data().Polymorphic || + isDependentContext()) + return false; + + for (CXXRecordDecl::base_class_const_iterator B = bases_begin(), + BEnd = bases_end(); + B != BEnd; ++B) { + CXXRecordDecl *BaseDecl + = cast(B->getType()->getAs()->getDecl()); + if (BaseDecl->isAbstract()) + return true; + } + + return false; +} + CXXMethodDecl * CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, @@ -735,85 +999,90 @@ bool CXXMethodDecl::hasInlineBody() const { return CheckFn->hasBody(fn) && !fn->isOutOfLine(); } -CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(ASTContext &Context, - TypeSourceInfo *TInfo, bool IsVirtual, - SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0), +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) { } -CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(ASTContext &Context, - FieldDecl *Member, SourceLocation MemberLoc, - SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), - AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), +CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, + FieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, Expr *Init, + SourceLocation R) + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsVirtual(false), + IsWritten(false), SourceOrderOrNumArrayIndices(0) +{ +} + +CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, + IndirectFieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, Expr *Init, + SourceLocation R) + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { } -CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(ASTContext &Context, - FieldDecl *Member, SourceLocation MemberLoc, - SourceLocation L, Expr *Init, SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) - : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), - AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), +CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context, + FieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices) + : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), + LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) { VarDecl **MyIndices = reinterpret_cast (this + 1); memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *)); } -CXXBaseOrMemberInitializer * -CXXBaseOrMemberInitializer::Create(ASTContext &Context, - FieldDecl *Member, - SourceLocation MemberLoc, - SourceLocation L, - Expr *Init, - SourceLocation R, - VarDecl **Indices, - unsigned NumIndices) { - void *Mem = Context.Allocate(sizeof(CXXBaseOrMemberInitializer) + +CXXCtorInitializer *CXXCtorInitializer::Create(ASTContext &Context, + FieldDecl *Member, + SourceLocation MemberLoc, + SourceLocation L, Expr *Init, + SourceLocation R, + VarDecl **Indices, + unsigned NumIndices) { + void *Mem = Context.Allocate(sizeof(CXXCtorInitializer) + sizeof(VarDecl *) * NumIndices, - llvm::alignof()); - return new (Mem) CXXBaseOrMemberInitializer(Context, Member, MemberLoc, - L, Init, R, Indices, NumIndices); + llvm::alignOf()); + return new (Mem) CXXCtorInitializer(Context, Member, MemberLoc, L, Init, R, + Indices, NumIndices); } -TypeLoc CXXBaseOrMemberInitializer::getBaseClassLoc() const { +TypeLoc CXXCtorInitializer::getBaseClassLoc() const { if (isBaseInitializer()) - return BaseOrMember.get()->getTypeLoc(); + return Initializee.get()->getTypeLoc(); else return TypeLoc(); } -Type *CXXBaseOrMemberInitializer::getBaseClass() { - if (isBaseInitializer()) - return BaseOrMember.get()->getType().getTypePtr(); - else - return 0; -} - -const Type *CXXBaseOrMemberInitializer::getBaseClass() const { +const Type *CXXCtorInitializer::getBaseClass() const { if (isBaseInitializer()) - return BaseOrMember.get()->getType().getTypePtr(); + return Initializee.get()->getType().getTypePtr(); else return 0; } -SourceLocation CXXBaseOrMemberInitializer::getSourceLocation() const { - if (isMemberInitializer()) +SourceLocation CXXCtorInitializer::getSourceLocation() const { + if (isAnyMemberInitializer()) return getMemberLocation(); return getBaseClassLoc().getLocalSourceRange().getBegin(); } -SourceRange CXXBaseOrMemberInitializer::getSourceRange() const { +SourceRange CXXCtorInitializer::getSourceRange() const { return SourceRange(getSourceLocation(), getRParenLoc()); } @@ -847,25 +1116,40 @@ bool CXXConstructorDecl::isDefaultConstructor() const { bool CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const { + return isCopyOrMoveConstructor(TypeQuals) && + getParamDecl(0)->getType()->isLValueReferenceType(); +} + +bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const { + return isCopyOrMoveConstructor(TypeQuals) && + getParamDecl(0)->getType()->isRValueReferenceType(); +} + +/// \brief Determine whether this is a copy or move constructor. +bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const { // C++ [class.copy]p2: // A non-template constructor for class X is a copy constructor // if its first parameter is of type X&, const X&, volatile X& or // const volatile X&, and either there are no other parameters // or else all other parameters have default arguments (8.3.6). + // C++0x [class.copy]p3: + // A non-template constructor for class X is a move constructor if its + // first parameter is of type X&&, const X&&, volatile X&&, or + // const volatile X&&, and either there are no other parameters or else + // all other parameters have default arguments. if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || (getPrimaryTemplate() != 0) || (getDescribedFunctionTemplate() != 0)) return false; - + const ParmVarDecl *Param = getParamDecl(0); - - // Do we have a reference type? Rvalue references don't count. - const LValueReferenceType *ParamRefType = - Param->getType()->getAs(); + + // Do we have a reference type? + const ReferenceType *ParamRefType = Param->getType()->getAs(); if (!ParamRefType) return false; - + // Is it a reference to our class type? ASTContext &Context = getASTContext(); @@ -875,12 +1159,12 @@ CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const { = Context.getCanonicalType(Context.getTagDeclType(getParent())); if (PointeeType.getUnqualifiedType() != ClassTy) return false; - + // FIXME: other qualifiers? - - // We have a copy constructor. + + // We have a copy or move constructor. TypeQuals = PointeeType.getCVRQualifiers(); - return true; + return true; } bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { @@ -899,7 +1183,7 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { (getNumParams() > 1 && getParamDecl(1)->hasDefaultArg()); } -bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { +bool CXXConstructorDecl::isSpecializationCopyingObject() const { if ((getNumParams() < 1) || (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || (getPrimaryTemplate() == 0) || @@ -911,12 +1195,6 @@ bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { ASTContext &Context = getASTContext(); CanQualType ParamType = Context.getCanonicalType(Param->getType()); - // Strip off the lvalue reference, if any. - if (CanQual ParamRefType - = ParamType->getAs()) - ParamType = ParamRefType->getPointeeType(); - - // Is it the same as our our class type? CanQualType ClassTy = Context.getCanonicalType(Context.getTagDeclType(getParent())); @@ -926,21 +1204,38 @@ bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { return true; } +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()) + return 0; + + return cast(*It); +} + +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); +} + CXXDestructorDecl * CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) { return new (C) CXXDestructorDecl(0, DeclarationNameInfo(), - QualType(), false, false); + QualType(), 0, false, false); } CXXDestructorDecl * CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, - QualType T, bool isInline, + QualType T, TypeSourceInfo *TInfo, + bool isInline, bool isImplicitlyDeclared) { assert(NameInfo.getName().getNameKind() == DeclarationName::CXXDestructorName && "Name must refer to a destructor"); - return new (C) CXXDestructorDecl(RD, NameInfo, T, isInline, + return new (C) CXXDestructorDecl(RD, NameInfo, T, TInfo, isInline, isImplicitlyDeclared); } @@ -1004,6 +1299,44 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, Qualifier, IdentLoc, Namespace); } +UsingDecl *UsingShadowDecl::getUsingDecl() const { + const UsingShadowDecl *Shadow = this; + while (const UsingShadowDecl *NextShadow = + dyn_cast(Shadow->UsingOrNextShadow)) + Shadow = NextShadow; + return cast(Shadow->UsingOrNextShadow); +} + +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; +} + +void UsingDecl::removeShadowDecl(UsingShadowDecl *S) { + assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() && + "declaration not in set"); + assert(S->getUsingDecl() == this); + + // Remove S from the shadow decl chain. This is O(n) but hopefully rare. + + if (FirstUsingShadow == S) { + FirstUsingShadow = dyn_cast(S->UsingOrNextShadow); + S->UsingOrNextShadow = this; + return; + } + + UsingShadowDecl *Prev = FirstUsingShadow; + while (Prev->UsingOrNextShadow != S) + Prev = cast(Prev->UsingOrNextShadow); + Prev->UsingOrNextShadow = S->UsingOrNextShadow; + S->UsingOrNextShadow = this; +} + UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceRange NNR, SourceLocation UL, NestedNameSpecifier* TargetNNS, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index d952cc36ef1d..45f5188d4043 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -153,6 +153,9 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { ObjCPropertyDecl * ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass( IdentifierInfo *PropertyId) const { + if (ExternallyCompleted) + LoadExternalDefinition(); + if (ObjCPropertyDecl *PD = ObjCPropertyDecl::findPropertyDecl(cast(this), PropertyId)) return PD; @@ -171,6 +174,9 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList( ObjCProtocolDecl *const* ExtList, unsigned ExtNum, ASTContext &C) { + if (ExternallyCompleted) + LoadExternalDefinition(); + if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) { AllReferencedProtocols.set(ExtList, ExtNum, C); return; @@ -270,6 +276,9 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, const ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; + if (ExternallyCompleted) + LoadExternalDefinition(); + while (ClassDecl != NULL) { if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) return MethodDecl; @@ -302,14 +311,16 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, return NULL; } -ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateInstanceMethod( - const Selector &Sel) { +ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod( + const Selector &Sel, + bool Instance) { ObjCMethodDecl *Method = 0; if (ObjCImplementationDecl *ImpDecl = getImplementation()) - Method = ImpDecl->getInstanceMethod(Sel); + Method = Instance ? ImpDecl->getInstanceMethod(Sel) + : ImpDecl->getClassMethod(Sel); if (!Method && getSuperClass()) - return getSuperClass()->lookupPrivateInstanceMethod(Sel); + return getSuperClass()->lookupPrivateMethod(Sel, Instance); return Method; } @@ -443,11 +454,29 @@ ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, : ObjCContainerDecl(ObjCInterface, DC, atLoc, Id), TypeForDecl(0), SuperClass(0), CategoryList(0), IvarList(0), - ForwardDecl(FD), InternalInterface(isInternal), + ForwardDecl(FD), InternalInterface(isInternal), ExternallyCompleted(false), ClassLoc(CLoc) { } +void ObjCInterfaceDecl::LoadExternalDefinition() const { + assert(ExternallyCompleted && "Class is not externally completed"); + ExternallyCompleted = false; + getASTContext().getExternalSource()->CompleteType( + const_cast(this)); +} + +void ObjCInterfaceDecl::setExternallyCompleted() { + assert(getASTContext().getExternalSource() && + "Class can't be externally completed without an external source"); + assert(!ForwardDecl && + "Forward declarations can't be externally completed"); + ExternallyCompleted = true; +} + ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { + if (ExternallyCompleted) + LoadExternalDefinition(); + return getASTContext().getObjCImplementation( const_cast(this)); } @@ -506,6 +535,9 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { /// ObjCCategoryDecl * ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const { + if (ExternallyCompleted) + LoadExternalDefinition(); + for (ObjCCategoryDecl *Category = getCategoryList(); Category; Category = Category->getNextClassCategory()) if (Category->getIdentifier() == CategoryId) @@ -711,7 +743,7 @@ ObjCClassDecl::ObjCClassDecl(DeclContext *DC, SourceLocation L, void ObjCClassDecl::setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, const SourceLocation *Locs, unsigned Num) { ForwardDecls = (ObjCClassRef*) C.Allocate(sizeof(ObjCClassRef)*Num, - llvm::alignof()); + llvm::alignOf()); for (unsigned i = 0; i < Num; ++i) new (&ForwardDecls[i]) ObjCClassRef(List[i], Locs[i]); @@ -896,7 +928,6 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T); } - //===----------------------------------------------------------------------===// // ObjCPropertyImplDecl //===----------------------------------------------------------------------===// @@ -907,8 +938,16 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, SourceLocation L, ObjCPropertyDecl *property, Kind PK, - ObjCIvarDecl *ivar) { - return new (C) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar); + ObjCIvarDecl *ivar, + SourceLocation ivarLoc) { + return new (C) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, + ivarLoc); } +SourceRange ObjCPropertyImplDecl::getSourceRange() const { + SourceLocation EndLoc = getLocation(); + if (IvarLoc.isValid()) + EndLoc = IvarLoc; + return SourceRange(AtLoc, EndLoc); +} diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index f18d2f0215dd..77b42574709f 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -51,6 +51,7 @@ namespace { void VisitFunctionDecl(FunctionDecl *D); void VisitFieldDecl(FieldDecl *D); void VisitVarDecl(VarDecl *D); + void VisitLabelDecl(LabelDecl *D); void VisitParmVarDecl(ParmVarDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); void VisitNamespaceDecl(NamespaceDecl *D); @@ -307,9 +308,26 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { } void DeclPrinter::VisitEnumDecl(EnumDecl *D) { - Out << "enum " << D << " {\n"; - VisitDeclContext(D); - Indent() << "}"; + Out << "enum "; + if (D->isScoped()) { + if (D->isScopedUsingClassTag()) + Out << "class "; + else + Out << "struct "; + } + Out << D; + + if (D->isFixed()) { + std::string Underlying; + D->getIntegerType().getAsStringInternal(Underlying, Policy); + Out << " : " << Underlying; + } + + if (D->isDefinition()) { + Out << " {\n"; + VisitDeclContext(D); + Indent() << "}"; + } } void DeclPrinter::VisitRecordDecl(RecordDecl *D) { @@ -349,9 +367,15 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; std::string Proto = D->getNameInfo().getAsString(); - if (isa(D->getType().getTypePtr())) { - const FunctionType *AFT = D->getType()->getAs(); + QualType Ty = D->getType(); + while (const ParenType *PT = dyn_cast(Ty)) { + Proto = '(' + Proto + ')'; + Ty = PT->getInnerType(); + } + + if (isa(Ty)) { + const FunctionType *AFT = Ty->getAs(); const FunctionProtoType *FT = 0; if (D->hasWrittenPrototype()) FT = dyn_cast(AFT); @@ -379,6 +403,16 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto += ")"; + if (FT && FT->getTypeQuals()) { + unsigned TypeQuals = FT->getTypeQuals(); + if (TypeQuals & Qualifiers::Const) + Proto += " const"; + if (TypeQuals & Qualifiers::Volatile) + Proto += " volatile"; + if (TypeQuals & Qualifiers::Restrict) + Proto += " restrict"; + } + if (FT && FT->hasExceptionSpec()) { Proto += " throw("; if (FT->hasAnyExceptionSpec()) @@ -399,18 +433,18 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (D->hasAttr()) Proto += " __attribute((noreturn))"; if (CXXConstructorDecl *CDecl = dyn_cast(D)) { - if (CDecl->getNumBaseOrMemberInitializers() > 0) { + if (CDecl->getNumCtorInitializers() > 0) { Proto += " : "; Out << Proto; Proto.clear(); for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(), E = CDecl->init_end(); B != E; ++B) { - CXXBaseOrMemberInitializer * BMInitializer = (*B); + CXXCtorInitializer * BMInitializer = (*B); if (B != CDecl->init_begin()) Out << ", "; - if (BMInitializer->isMemberInitializer()) { - FieldDecl *FD = BMInitializer->getMember(); + if (BMInitializer->isAnyMemberInitializer()) { + FieldDecl *FD = BMInitializer->getAnyMember(); Out << FD; } else { Out << QualType(BMInitializer->getBaseClass(), @@ -422,8 +456,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { // Nothing to print } else { Expr *Init = BMInitializer->getInit(); - if (CXXExprWithTemporaries *Tmp - = dyn_cast(Init)) + if (ExprWithCleanups *Tmp = dyn_cast(Init)) Init = Tmp->getSubExpr(); Init = Init->IgnoreParens(); @@ -461,7 +494,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { else AFT->getResultType().getAsStringInternal(Proto, Policy); } else { - D->getType().getAsStringInternal(Proto, Policy); + Ty.getAsStringInternal(Proto, Policy); } Out << Proto; @@ -505,6 +538,11 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { } } +void DeclPrinter::VisitLabelDecl(LabelDecl *D) { + Out << D->getNameAsString() << ":"; +} + + void DeclPrinter::VisitVarDecl(VarDecl *D) { if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None) Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " "; @@ -518,12 +556,15 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { T = Parm->getOriginalType(); T.getAsStringInternal(Name, Policy); Out << Name; - if (D->getInit()) { + if (Expr *Init = D->getInit()) { if (D->hasCXXDirectInitializer()) Out << "("; - else - Out << " = "; - D->getInit()->printPretty(Out, Context, 0, Policy, Indentation); + else { + CXXConstructExpr *CCE = dyn_cast(Init); + if (!CCE || CCE->getConstructor()->isCopyConstructor()) + Out << " = "; + } + Init->printPretty(Out, Context, 0, Policy, Indentation); if (D->hasCXXDirectInitializer()) Out << ")"; } @@ -646,6 +687,9 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { dyn_cast(Param)) { Out << NTTP->getType().getAsString(Policy); + if (NTTP->isParameterPack() && !isa(NTTP->getType())) + Out << "..."; + if (IdentifierInfo *Name = NTTP->getIdentifier()) { Out << ' '; Out << Name->getName(); @@ -661,8 +705,11 @@ void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { Out << "> "; - if (isa(D)) { - Out << "class " << D->getName(); + if (TemplateTemplateParmDecl *TTP = dyn_cast(D)) { + Out << "class "; + if (TTP->isParameterPack()) + Out << "..."; + Out << D->getName(); } else { Visit(D->getTemplatedDecl()); } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index e69338a7730d..a73deeab3a61 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -14,10 +14,13 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ASTContext.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" +#include using namespace clang; //===----------------------------------------------------------------------===// @@ -35,7 +38,7 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, } TemplateParameterList * -TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc, +TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, NamedDecl **Params, unsigned NumParams, SourceLocation RAngleLoc) { unsigned Size = sizeof(TemplateParameterList) @@ -47,24 +50,33 @@ TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc, } unsigned TemplateParameterList::getMinRequiredArguments() const { - unsigned NumRequiredArgs = size(); - iterator Param = const_cast(this)->end(), - ParamBegin = const_cast(this)->begin(); - while (Param != ParamBegin) { - --Param; - - if (!(*Param)->isTemplateParameterPack() && - !(isa(*Param) && - cast(*Param)->hasDefaultArgument()) && - !(isa(*Param) && - cast(*Param)->hasDefaultArgument()) && - !(isa(*Param) && - cast(*Param)->hasDefaultArgument())) + unsigned NumRequiredArgs = 0; + for (iterator P = const_cast(this)->begin(), + PEnd = const_cast(this)->end(); + P != PEnd; ++P) { + if ((*P)->isTemplateParameterPack()) { + if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*P)) + if (NTTP->isExpandedParameterPack()) { + NumRequiredArgs += NTTP->getNumExpansionTypes(); + continue; + } + break; - - --NumRequiredArgs; + } + + if (TemplateTypeParmDecl *TTP = dyn_cast(*P)) { + if (TTP->hasDefaultArgument()) + break; + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(*P)) { + if (NTTP->hasDefaultArgument()) + break; + } else if (cast(*P)->hasDefaultArgument()) + break; + + ++NumRequiredArgs; } - + return NumRequiredArgs; } @@ -92,7 +104,7 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() { RedeclarableTemplateDecl *First = getCanonicalDecl(); if (First->CommonOrPrev.isNull()) { - CommonBase *CommonPtr = First->newCommon(); + CommonBase *CommonPtr = First->newCommon(getASTContext()); First->CommonOrPrev = CommonPtr; CommonPtr->Latest = First; } @@ -156,9 +168,10 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); } -RedeclarableTemplateDecl::CommonBase *FunctionTemplateDecl::newCommon() { - Common *CommonPtr = new (getASTContext()) Common; - getASTContext().AddDeallocation(DeallocateCommon, CommonPtr); +RedeclarableTemplateDecl::CommonBase * +FunctionTemplateDecl::newCommon(ASTContext &C) { + Common *CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; } @@ -188,9 +201,33 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, return New; } -RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() { - Common *CommonPtr = new (getASTContext()) Common; - getASTContext().AddDeallocation(DeallocateCommon, CommonPtr); +void ClassTemplateDecl::LoadLazySpecializations() { + Common *CommonPtr = getCommonPtr(); + if (CommonPtr->LazySpecializations) { + ASTContext &Context = getASTContext(); + uint32_t *Specs = CommonPtr->LazySpecializations; + CommonPtr->LazySpecializations = 0; + for (uint32_t I = 0, N = *Specs++; I != N; ++I) + (void)Context.getExternalSource()->GetExternalDecl(Specs[I]); + } +} + +llvm::FoldingSet & +ClassTemplateDecl::getSpecializations() { + LoadLazySpecializations(); + return getCommonPtr()->Specializations; +} + +llvm::FoldingSet & +ClassTemplateDecl::getPartialSpecializations() { + LoadLazySpecializations(); + return getCommonPtr()->PartialSpecializations; +} + +RedeclarableTemplateDecl::CommonBase * +ClassTemplateDecl::newCommon(ASTContext &C) { + Common *CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; } @@ -200,6 +237,13 @@ ClassTemplateDecl::findSpecialization(const TemplateArgument *Args, return findSpecializationImpl(getSpecializations(), Args, NumArgs, InsertPos); } +void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, + void *InsertPos) { + getSpecializations().InsertNode(D, InsertPos); + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXTemplateSpecialization(this, D); +} + ClassTemplatePartialSpecializationDecl * ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, @@ -208,6 +252,14 @@ ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, InsertPos); } +void ClassTemplateDecl::AddPartialSpecialization( + ClassTemplatePartialSpecializationDecl *D, + void *InsertPos) { + getPartialSpecializations().InsertNode(D, InsertPos); + if (ASTMutationListener *L = getASTMutationListener()) + L->AddedCXXTemplateSpecialization(this, D); +} + void ClassTemplateDecl::getPartialSpecializations( llvm::SmallVectorImpl &PS) { llvm::FoldingSet &PartialSpecs @@ -258,10 +310,13 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { if (!CommonPtr->InjectedClassNameType.isNull()) return CommonPtr->InjectedClassNameType; - // FIXME: n2800 14.6.1p1 should say how the template arguments - // corresponding to template parameter packs should be pack - // expansions. We already say that in 14.6.2.1p2, so it would be - // better to fix that redundancy. + // C++0x [temp.dep.type]p2: + // The template argument list of a primary template is a template argument + // list in which the nth template argument has the value of the nth template + // parameter of the class template. If the nth template parameter is a + // template parameter pack (14.5.3), the nth template argument is a pack + // expansion (14.5.3) whose pattern is the name of the template parameter + // pack. ASTContext &Context = getASTContext(); TemplateParameterList *Params = getTemplateParameters(); llvm::SmallVector TemplateArgs; @@ -269,19 +324,38 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { for (TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); Param != ParamEnd; ++Param) { - if (isa(*Param)) { - QualType ParamType = Context.getTypeDeclType(cast(*Param)); - TemplateArgs.push_back(TemplateArgument(ParamType)); + TemplateArgument Arg; + if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { + QualType ArgType = Context.getTypeDeclType(TTP); + if (TTP->isParameterPack()) + ArgType = Context.getPackExpansionType(ArgType, + llvm::Optional()); + + Arg = TemplateArgument(ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast(*Param)) { Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType().getNonLValueExprType(Context), + Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation()); - TemplateArgs.push_back(TemplateArgument(E)); + + if (NTTP->isParameterPack()) + E = new (Context) PackExpansionExpr(Context.DependentTy, E, + NTTP->getLocation(), + llvm::Optional()); + Arg = TemplateArgument(E); } else { TemplateTemplateParmDecl *TTP = cast(*Param); - TemplateArgs.push_back(TemplateArgument(TemplateName(TTP))); + if (TTP->isParameterPack()) + Arg = TemplateArgument(TemplateName(TTP), llvm::Optional()); + else + Arg = TemplateArgument(TemplateName(TTP)); } + + if ((*Param)->isTemplateParameterPack()) + Arg = TemplateArgument::CreatePackCopy(Context, &Arg, 1); + + TemplateArgs.push_back(Arg); } CommonPtr->InjectedClassNameType @@ -296,7 +370,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { //===----------------------------------------------------------------------===// TemplateTypeParmDecl * -TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, +TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack) { @@ -305,7 +379,7 @@ TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC, } TemplateTypeParmDecl * -TemplateTypeParmDecl::Create(ASTContext &C, EmptyShell Empty) { +TemplateTypeParmDecl::Create(const ASTContext &C, EmptyShell Empty) { return new (C) TemplateTypeParmDecl(0, SourceLocation(), 0, false, QualType(), false); } @@ -326,12 +400,62 @@ unsigned TemplateTypeParmDecl::getIndex() const { // NonTypeTemplateParmDecl Method Implementations //===----------------------------------------------------------------------===// +NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, + SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, + QualType T, + TypeSourceInfo *TInfo, + const QualType *ExpandedTypes, + unsigned NumExpandedTypes, + TypeSourceInfo **ExpandedTInfos) + : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo), + TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), + ParameterPack(true), ExpandedParameterPack(true), + NumExpandedTypes(NumExpandedTypes) +{ + if (ExpandedTypes && ExpandedTInfos) { + void **TypesAndInfos = reinterpret_cast(this + 1); + for (unsigned I = 0; I != NumExpandedTypes; ++I) { + TypesAndInfos[2*I] = ExpandedTypes[I].getAsOpaquePtr(); + TypesAndInfos[2*I + 1] = ExpandedTInfos[I]; + } + } +} + NonTypeTemplateParmDecl * -NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, +NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo) { - return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo); + bool ParameterPack, TypeSourceInfo *TInfo) { + return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, ParameterPack, + TInfo); +} + +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, + const QualType *ExpandedTypes, + unsigned NumExpandedTypes, + TypeSourceInfo **ExpandedTInfos) { + unsigned Size = sizeof(NonTypeTemplateParmDecl) + + NumExpandedTypes * 2 * sizeof(void*); + void *Mem = C.Allocate(Size); + return new (Mem) NonTypeTemplateParmDecl(DC, L, D, P, Id, T, TInfo, + ExpandedTypes, NumExpandedTypes, + ExpandedTInfos); +} + +SourceLocation NonTypeTemplateParmDecl::getInnerLocStart() const { + SourceLocation Start = getTypeSpecStartLoc(); + if (Start.isInvalid()) + Start = getLocation(); + return Start; +} + +SourceRange NonTypeTemplateParmDecl::getSourceRange() const { + return SourceRange(getOuterLocStart(), getLocation()); } SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { @@ -345,128 +469,29 @@ SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { //===----------------------------------------------------------------------===// TemplateTemplateParmDecl * -TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC, +TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, unsigned P, - IdentifierInfo *Id, + bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) { - return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params); -} - -//===----------------------------------------------------------------------===// -// TemplateArgumentListBuilder Implementation -//===----------------------------------------------------------------------===// - -void TemplateArgumentListBuilder::Append(const TemplateArgument &Arg) { - assert((Arg.getKind() != TemplateArgument::Type || - Arg.getAsType().isCanonical()) && "Type must be canonical!"); - assert(FlatArgs.size() < MaxFlatArgs && "Argument list builder is full!"); - assert(!StructuredArgs && - "Can't append arguments when an argument pack has been added!"); - - FlatArgs.push_back(Arg); -} - -void TemplateArgumentListBuilder::BeginPack() { - assert(!AddingToPack && "Already adding to pack!"); - assert(!StructuredArgs && "Argument list already contains a pack!"); - - AddingToPack = true; - PackBeginIndex = FlatArgs.size(); -} - -void TemplateArgumentListBuilder::EndPack() { - assert(AddingToPack && "Not adding to pack!"); - assert(!StructuredArgs && "Argument list already contains a pack!"); - - AddingToPack = false; - - // FIXME: This is a memory leak! - StructuredArgs = new TemplateArgument[MaxStructuredArgs]; - - // First copy the flat entries over to the list (if any) - for (unsigned I = 0; I != PackBeginIndex; ++I) { - NumStructuredArgs++; - StructuredArgs[I] = FlatArgs[I]; - } - - // Next, set the pack. - TemplateArgument *PackArgs = 0; - unsigned NumPackArgs = NumFlatArgs - PackBeginIndex; - // FIXME: NumPackArgs shouldn't be negative here??? - if (NumPackArgs) - PackArgs = FlatArgs.data()+PackBeginIndex; - - StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs, - /*CopyArgs=*/false); + return new (C) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id, + Params); } //===----------------------------------------------------------------------===// // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// -TemplateArgumentList::TemplateArgumentList(ASTContext &Context, - TemplateArgumentListBuilder &Builder, - bool TakeArgs) - : FlatArguments(Builder.getFlatArguments(), TakeArgs), - NumFlatArguments(Builder.flatSize()), - StructuredArguments(Builder.getStructuredArguments(), TakeArgs), - NumStructuredArguments(Builder.structuredSize()) { - - if (!TakeArgs) - return; - - // If this does take ownership of the arguments, then we have to new them - // and copy over. - TemplateArgument *NewArgs = - new (Context) TemplateArgument[Builder.flatSize()]; - std::copy(Builder.getFlatArguments(), - Builder.getFlatArguments()+Builder.flatSize(), NewArgs); - FlatArguments.setPointer(NewArgs); - - // Just reuse the structured and flat arguments array if possible. - if (Builder.getStructuredArguments() == Builder.getFlatArguments()) { - StructuredArguments.setPointer(NewArgs); - StructuredArguments.setInt(0); - } else { - TemplateArgument *NewSArgs = - new (Context) TemplateArgument[Builder.flatSize()]; - std::copy(Builder.getFlatArguments(), - Builder.getFlatArguments()+Builder.flatSize(), NewSArgs); - StructuredArguments.setPointer(NewSArgs); - } -} - -TemplateArgumentList::TemplateArgumentList(ASTContext &Context, - const TemplateArgument *Args, - unsigned NumArgs) - : NumFlatArguments(0), NumStructuredArguments(0) { - init(Context, Args, NumArgs); -} - -/// Produces a shallow copy of the given template argument list. This -/// assumes that the input argument list outlives it. This takes the list as -/// a pointer to avoid looking like a copy constructor, since this really -/// really isn't safe to use that way. -TemplateArgumentList::TemplateArgumentList(const TemplateArgumentList *Other) - : FlatArguments(Other->FlatArguments.getPointer(), false), - NumFlatArguments(Other->flat_size()), - StructuredArguments(Other->StructuredArguments.getPointer(), false), - NumStructuredArguments(Other->NumStructuredArguments) { } - -void TemplateArgumentList::init(ASTContext &Context, - const TemplateArgument *Args, - unsigned NumArgs) { -assert(NumFlatArguments == 0 && NumStructuredArguments == 0 && - "Already initialized!"); - -NumFlatArguments = NumStructuredArguments = NumArgs; -TemplateArgument *NewArgs = new (Context) TemplateArgument[NumArgs]; -std::copy(Args, Args+NumArgs, NewArgs); -FlatArguments.setPointer(NewArgs); -FlatArguments.setInt(1); // Owns the pointer. - -// Just reuse the flat arguments array. -StructuredArguments.setPointer(NewArgs); -StructuredArguments.setInt(0); // Doesn't own the pointer. +TemplateArgumentList * +TemplateArgumentList::CreateCopy(ASTContext &Context, + const TemplateArgument *Args, + unsigned NumArgs) { + std::size_t Size = sizeof(TemplateArgumentList) + + NumArgs * sizeof(TemplateArgument); + void *Mem = Context.Allocate(Size); + TemplateArgument *StoredArgs + = reinterpret_cast( + static_cast(Mem) + 1); + std::uninitialized_copy(Args, Args + NumArgs, StoredArgs); + return new (Mem) TemplateArgumentList(StoredArgs, NumArgs, true); } //===----------------------------------------------------------------------===// @@ -476,14 +501,15 @@ ClassTemplateSpecializationDecl:: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl) : CXXRecordDecl(DK, TK, DC, L, SpecializedTemplate->getIdentifier(), PrevDecl), SpecializedTemplate(SpecializedTemplate), ExplicitInfo(0), - TemplateArgs(Context, Builder, /*TakeArgs=*/true), + TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args, NumArgs)), SpecializationKind(TSK_Undeclared) { } @@ -497,14 +523,15 @@ ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, ClassTemplateSpecializationDecl *PrevDecl) { ClassTemplateSpecializationDecl *Result = new (Context)ClassTemplateSpecializationDecl(Context, ClassTemplateSpecialization, TK, DC, L, SpecializedTemplate, - Builder, + Args, NumArgs, PrevDecl); Context.getTypeDeclType(Result, PrevDecl); return Result; @@ -524,8 +551,8 @@ ClassTemplateSpecializationDecl::getNameForDiagnostic(std::string &S, const TemplateArgumentList &TemplateArgs = getTemplateArgs(); S += TemplateSpecializationType::PrintTemplateArgumentList( - TemplateArgs.getFlatArgumentList(), - TemplateArgs.flat_size(), + TemplateArgs.data(), + TemplateArgs.size(), Policy); } @@ -545,7 +572,8 @@ ClassTemplatePartialSpecializationDecl:: Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - TemplateArgumentListBuilder &Builder, + const TemplateArgument *Args, + unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl, @@ -559,7 +587,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, = new (Context)ClassTemplatePartialSpecializationDecl(Context, TK, DC, L, Params, SpecializedTemplate, - Builder, + Args, NumArgs, ClonedArgs, N, PrevDecl, SequenceNumber); @@ -575,19 +603,6 @@ ClassTemplatePartialSpecializationDecl::Create(ASTContext &Context, return new (Context)ClassTemplatePartialSpecializationDecl(); } -void ClassTemplatePartialSpecializationDecl:: -initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos) { - assert(ArgsAsWritten == 0 && "ArgsAsWritten already set"); - unsigned N = ArgInfos.size(); - TemplateArgumentLoc *ClonedArgs - = new (getASTContext()) TemplateArgumentLoc[N]; - for (unsigned I = 0; I != N; ++I) - ClonedArgs[I] = ArgInfos[I]; - - ArgsAsWritten = ClonedArgs; - NumArgsAsWritten = N; -} - //===----------------------------------------------------------------------===// // FriendTemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 860a0b276a79..cef54e97c93a 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -93,10 +94,8 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { Selector RHSSelector = RHS.getObjCSelector(); unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { - IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I); - IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I); - - switch (LHSId->getName().compare(RHSId->getName())) { + switch (LHSSelector.getNameForSlot(I).compare( + RHSSelector.getNameForSlot(I))) { case -1: return true; case 1: return false; default: break; @@ -385,7 +384,7 @@ void DeclarationName::dump() const { llvm::errs() << '\n'; } -DeclarationNameTable::DeclarationNameTable(ASTContext &C) : Ctx(C) { +DeclarationNameTable::DeclarationNameTable(const ASTContext &C) : Ctx(C) { CXXSpecialNamesImpl = new llvm::FoldingSet; CXXLiteralOperatorNames = new llvm::FoldingSet; @@ -512,6 +511,28 @@ DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { } } +bool DeclarationNameInfo::containsUnexpandedParameterPack() const { + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + return false; + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + if (TypeSourceInfo *TInfo = LocInfo.NamedType.TInfo) + return TInfo->getType()->containsUnexpandedParameterPack(); + + return Name.getCXXNameType()->containsUnexpandedParameterPack(); + } + llvm_unreachable("All name kinds handled."); +} + std::string DeclarationNameInfo::getAsString() const { std::string Result; llvm::raw_string_ostream OS(Result); diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp new file mode 100644 index 000000000000..9d828fcfb85a --- /dev/null +++ b/lib/AST/DumpXML.cpp @@ -0,0 +1,1028 @@ +//===--- DumpXML.cpp - Detailed XML dumping ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Decl::dumpXML() method, a debugging tool to +// print a detailed graph of an AST in an unspecified XML format. +// +// There is no guarantee of stability for this format. +// +//===----------------------------------------------------------------------===// + +// Only pay for this in code size in assertions-enabled builds. + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeLocVisitor.h" +#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" + +using namespace clang; + +#ifndef NDEBUG + +namespace { + +enum NodeState { + NS_Attrs, NS_LazyChildren, NS_Children +}; + +struct Node { + llvm::StringRef Name; + NodeState State; + Node(llvm::StringRef name) : Name(name), State(NS_Attrs) {} + + bool isDoneWithAttrs() const { return State != NS_Attrs; } +}; + +template struct XMLDeclVisitor { +#define DISPATCH(NAME, CLASS) \ + static_cast(this)->NAME(static_cast(D)) + + 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); \ + static_cast(this)->completeAttrs(); \ + DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \ + DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \ + break; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + } + } + +#define DECL(DERIVED, BASE) \ + void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \ + DISPATCH(dispatch##BASE##Attrs, BASE); \ + DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \ + } \ + void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \ + void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \ + DISPATCH(dispatch##BASE##Children, BASE); \ + DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \ + } \ + void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \ + void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \ + DISPATCH(dispatch##BASE##AsContext, BASE); \ + DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \ + } \ + void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {} +#include "clang/AST/DeclNodes.inc" + + void dispatchDeclAttrs(Decl *D) { + DISPATCH(visitDeclAttrs, Decl); + } + void visitDeclAttrs(Decl *D) {} + + void dispatchDeclChildren(Decl *D) { + DISPATCH(visitDeclChildren, Decl); + } + void visitDeclChildren(Decl *D) {} + + void dispatchDeclAsContext(Decl *D) { + DISPATCH(visitDeclAsContext, Decl); + } + void visitDeclAsContext(Decl *D) {} + +#undef DISPATCH +}; + +template struct XMLTypeVisitor { +#define DISPATCH(NAME, CLASS) \ + static_cast(this)->NAME(static_cast(T)) + + 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); \ + static_cast(this)->completeAttrs(); \ + DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \ + break; +#define ABSTRACT_TYPE(DERIVED, BASE) +#include "clang/AST/TypeNodes.def" + } + } + +#define TYPE(DERIVED, BASE) \ + void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \ + DISPATCH(dispatch##BASE##Attrs, BASE); \ + DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \ + } \ + void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \ + void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \ + DISPATCH(dispatch##BASE##Children, BASE); \ + DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \ + } \ + void visit##DERIVED##TypeChildren(DERIVED##Type *T) {} +#include "clang/AST/TypeNodes.def" + + void dispatchTypeAttrs(Type *T) { + DISPATCH(visitTypeAttrs, Type); + } + void visitTypeAttrs(Type *T) {} + + void dispatchTypeChildren(Type *T) { + DISPATCH(visitTypeChildren, Type); + } + void visitTypeChildren(Type *T) {} + +#undef DISPATCH +}; + +static llvm::StringRef getTypeKindName(Type *T) { + switch (T->getTypeClass()) { +#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type"; +#define ABSTRACT_TYPE(DERIVED, BASE) +#include "clang/AST/TypeNodes.def" + } + + llvm_unreachable("unknown type kind!"); + return "unknown_type"; +} + +struct XMLDumper : public XMLDeclVisitor, + public XMLTypeVisitor { + llvm::raw_ostream &out; + ASTContext &Context; + llvm::SmallVector Stack; + unsigned Indent; + explicit XMLDumper(llvm::raw_ostream &OS, ASTContext &context) + : out(OS), Context(context), Indent(0) {} + + void indent() { + for (unsigned I = Indent; I; --I) + out << ' '; + } + + /// Push a new node on the stack. + void push(llvm::StringRef name) { + if (!Stack.empty()) { + assert(Stack.back().isDoneWithAttrs()); + if (Stack.back().State == NS_LazyChildren) { + Stack.back().State = NS_Children; + out << ">\n"; + } + Indent++; + indent(); + } + Stack.push_back(Node(name)); + out << '<' << name; + } + + /// Set the given attribute to the given value. + void set(llvm::StringRef attr, llvm::StringRef value) { + assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); + out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation + } + + /// Finish attributes. + void completeAttrs() { + assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); + Stack.back().State = NS_LazyChildren; + } + + /// Pop a node. + void pop() { + assert(!Stack.empty() && Stack.back().isDoneWithAttrs()); + if (Stack.back().State == NS_LazyChildren) { + out << "/>\n"; + } else { + indent(); + out << "\n"; + } + if (Stack.size() > 1) Indent--; + Stack.pop_back(); + } + + //---- General utilities -------------------------------------------// + + void setPointer(llvm::StringRef prop, const void *p) { + llvm::SmallString<10> buffer; + llvm::raw_svector_ostream os(buffer); + os << p; + os.flush(); + set(prop, buffer); + } + + void setPointer(void *p) { + setPointer("ptr", p); + } + + void setInteger(llvm::StringRef prop, const llvm::APSInt &v) { + set(prop, v.toString(10)); + } + + void setInteger(llvm::StringRef prop, unsigned n) { + llvm::SmallString<10> buffer; + llvm::raw_svector_ostream os(buffer); + os << n; + os.flush(); + set(prop, buffer); + } + + void setFlag(llvm::StringRef prop, bool flag) { + if (flag) set(prop, "true"); + } + + void setName(DeclarationName Name) { + if (!Name) + return set("name", ""); + + // Common case. + if (Name.isIdentifier()) + return set("name", Name.getAsIdentifierInfo()->getName()); + + set("name", Name.getAsString()); + } + + class TemporaryContainer { + XMLDumper &Dumper; + public: + TemporaryContainer(XMLDumper &dumper, llvm::StringRef name) + : Dumper(dumper) { + Dumper.push(name); + Dumper.completeAttrs(); + } + + ~TemporaryContainer() { + Dumper.pop(); + } + }; + + void visitTemplateParameters(TemplateParameterList *L) { + push("template_parameters"); + completeAttrs(); + for (TemplateParameterList::iterator + I = L->begin(), E = L->end(); I != E; ++I) + dispatch(*I); + pop(); + } + + void visitTemplateArguments(const TemplateArgumentList &L) { + push("template_arguments"); + completeAttrs(); + for (unsigned I = 0, E = L.size(); I != E; ++I) + dispatch(L[I]); + pop(); + } + + /// Visits a reference to the given declaration. + void visitDeclRef(Decl *D) { + push(D->getDeclKindName()); + setPointer("ref", D); + completeAttrs(); + pop(); + } + void visitDeclRef(llvm::StringRef Name, Decl *D) { + TemporaryContainer C(*this, Name); + if (D) visitDeclRef(D); + } + + void dispatch(const TemplateArgument &A) { + switch (A.getKind()) { + case TemplateArgument::Null: { + TemporaryContainer C(*this, "null"); + break; + } + case TemplateArgument::Type: { + dispatch(A.getAsType()); + break; + } + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + // FIXME: Implement! + break; + + case TemplateArgument::Declaration: { + visitDeclRef(A.getAsDecl()); + break; + } + case TemplateArgument::Integral: { + push("integer"); + setInteger("value", *A.getAsIntegral()); + completeAttrs(); + pop(); + break; + } + case TemplateArgument::Expression: { + dispatch(A.getAsExpr()); + break; + } + case TemplateArgument::Pack: { + for (TemplateArgument::pack_iterator P = A.pack_begin(), + PEnd = A.pack_end(); + P != PEnd; ++P) + dispatch(*P); + break; + } + } + } + + void dispatch(const TemplateArgumentLoc &A) { + dispatch(A.getArgument()); + } + + //---- Declarations ------------------------------------------------// + // Calls are made in this order: + // # Enter a new node. + // push("FieldDecl") + // + // # In this phase, attributes are set on the node. + // visitDeclAttrs(D) + // visitNamedDeclAttrs(D) + // ... + // visitFieldDeclAttrs(D) + // + // # No more attributes after this point. + // completeAttrs() + // + // # Create "header" child nodes, i.e. those which logically + // # belong to the declaration itself. + // visitDeclChildren(D) + // visitNamedDeclChildren(D) + // ... + // visitFieldDeclChildren(D) + // + // # Create nodes for the lexical children. + // visitDeclAsContext(D) + // visitNamedDeclAsContext(D) + // ... + // visitFieldDeclAsContext(D) + // + // # Finish the node. + // pop(); + void dispatch(Decl *D) { + push(D->getDeclKindName()); + XMLDeclVisitor::dispatch(D); + pop(); + } + void visitDeclAttrs(Decl *D) { + setPointer(D); + } + + /// Visit all the lexical decls in the given context. + void visitDeclContext(DeclContext *DC) { + for (DeclContext::decl_iterator + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) + dispatch(*I); + + // FIXME: point out visible declarations not in lexical context? + } + + /// Set the "access" attribute on the current node according to the + /// given specifier. + void setAccess(AccessSpecifier AS) { + switch (AS) { + case AS_public: return set("access", "public"); + case AS_protected: return set("access", "protected"); + case AS_private: return set("access", "private"); + case AS_none: llvm_unreachable("explicit forbidden access"); + } + } + + template void visitRedeclarableAttrs(T *D) { + if (T *Prev = D->getPreviousDeclaration()) + setPointer("previous", Prev); + } + + + // TranslationUnitDecl + void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) { + visitDeclContext(D); + } + + // LinkageSpecDecl + void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { + llvm::StringRef lang = ""; + switch (D->getLanguage()) { + case LinkageSpecDecl::lang_c: lang = "C"; break; + case LinkageSpecDecl::lang_cxx: lang = "C++"; break; + } + set("lang", lang); + } + void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) { + visitDeclContext(D); + } + + // NamespaceDecl + void visitNamespaceDeclAttrs(NamespaceDecl *D) { + setFlag("inline", D->isInline()); + if (!D->isOriginalNamespace()) + setPointer("original", D->getOriginalNamespace()); + } + void visitNamespaceDeclAsContext(NamespaceDecl *D) { + visitDeclContext(D); + } + + // NamedDecl + void visitNamedDeclAttrs(NamedDecl *D) { + setName(D->getDeclName()); + } + + // ValueDecl + void visitValueDeclChildren(ValueDecl *D) { + dispatch(D->getType()); + } + + // DeclaratorDecl + void visitDeclaratorDeclChildren(DeclaratorDecl *D) { + //dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + + // VarDecl + void visitVarDeclAttrs(VarDecl *D) { + visitRedeclarableAttrs(D); + if (D->getStorageClass() != SC_None) + set("storage", + VarDecl::getStorageClassSpecifierString(D->getStorageClass())); + setFlag("directinit", D->hasCXXDirectInitializer()); + setFlag("nrvo", D->isNRVOVariable()); + // TODO: instantiation, etc. + } + void visitVarDeclChildren(VarDecl *D) { + if (D->hasInit()) dispatch(D->getInit()); + } + + // ParmVarDecl? + + // FunctionDecl + void visitFunctionDeclAttrs(FunctionDecl *D) { + visitRedeclarableAttrs(D); + setFlag("pure", D->isPure()); + setFlag("trivial", D->isTrivial()); + setFlag("returnzero", D->hasImplicitReturnZero()); + setFlag("prototype", D->hasWrittenPrototype()); + setFlag("deleted", D->isDeleted()); + if (D->getStorageClass() != SC_None) + set("storage", + VarDecl::getStorageClassSpecifierString(D->getStorageClass())); + setFlag("inline", D->isInlineSpecified()); + // TODO: instantiation, etc. + } + void visitFunctionDeclChildren(FunctionDecl *D) { + for (FunctionDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + dispatch(*I); + if (D->isThisDeclarationADefinition()) + dispatch(D->getBody()); + } + + // CXXMethodDecl ? + // CXXConstructorDecl ? + // CXXDestructorDecl ? + // CXXConversionDecl ? + + void dispatch(CXXCtorInitializer *Init) { + // TODO + } + + // FieldDecl + void visitFieldDeclAttrs(FieldDecl *D) { + setFlag("mutable", D->isMutable()); + } + void visitFieldDeclChildren(FieldDecl *D) { + if (D->isBitField()) { + TemporaryContainer C(*this, "bitwidth"); + dispatch(D->getBitWidth()); + } + // TODO: C++0x member initializer + } + + // EnumConstantDecl + void visitEnumConstantDeclChildren(EnumConstantDecl *D) { + // value in any case? + if (D->getInitExpr()) dispatch(D->getInitExpr()); + } + + // IndirectFieldDecl + void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) { + for (IndirectFieldDecl::chain_iterator + I = D->chain_begin(), E = D->chain_end(); I != E; ++I) { + NamedDecl *VD = const_cast(*I); + push(isa(VD) ? "variable" : "field"); + setPointer("ptr", VD); + completeAttrs(); + pop(); + } + } + + // TypeDecl + void visitTypeDeclAttrs(TypeDecl *D) { + setPointer("typeptr", D->getTypeForDecl()); + } + + // TypedefDecl + void visitTypedefDeclAttrs(TypedefDecl *D) { + visitRedeclarableAttrs(D); + } + void visitTypedefDeclChildren(TypedefDecl *D) { + dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + + // TagDecl + void visitTagDeclAttrs(TagDecl *D) { + visitRedeclarableAttrs(D); + } + void visitTagDeclAsContext(TagDecl *D) { + visitDeclContext(D); + } + + // EnumDecl + void visitEnumDeclAttrs(EnumDecl *D) { + setFlag("scoped", D->isScoped()); + setFlag("fixed", D->isFixed()); + } + void visitEnumDeclChildren(EnumDecl *D) { + { + TemporaryContainer C(*this, "promotion_type"); + dispatch(D->getPromotionType()); + } + { + TemporaryContainer C(*this, "integer_type"); + dispatch(D->getIntegerType()); + } + } + + // RecordDecl ? + + void visitCXXRecordDeclChildren(CXXRecordDecl *D) { + if (!D->isThisDeclarationADefinition()) return; + + for (CXXRecordDecl::base_class_iterator + I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { + push("base"); + setAccess(I->getAccessSpecifier()); + completeAttrs(); + dispatch(I->getTypeSourceInfo()->getTypeLoc()); + pop(); + } + } + + // ClassTemplateSpecializationDecl ? + + // FileScopeAsmDecl ? + + // BlockDecl + void visitBlockDeclAttrs(BlockDecl *D) { + setFlag("variadic", D->isVariadic()); + } + void visitBlockDeclChildren(BlockDecl *D) { + for (FunctionDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + dispatch(*I); + dispatch(D->getBody()); + } + + // AccessSpecDecl + void visitAccessSpecDeclAttrs(AccessSpecDecl *D) { + setAccess(D->getAccess()); + } + + // TemplateDecl + void visitTemplateDeclChildren(TemplateDecl *D) { + visitTemplateParameters(D->getTemplateParameters()); + dispatch(D->getTemplatedDecl()); + } + + // FunctionTemplateDecl + void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) { + visitRedeclarableAttrs(D); + } + void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) { + // Mention all the specializations which don't have explicit + // declarations elsewhere. + for (FunctionTemplateDecl::spec_iterator + I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { + FunctionTemplateSpecializationInfo *Info + = I->getTemplateSpecializationInfo(); + + bool Unknown = false; + switch (Info->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: Unknown = false; break; + case TSK_Undeclared: Unknown = true; break; + + // These will be covered at their respective sites. + case TSK_ExplicitSpecialization: continue; + case TSK_ExplicitInstantiationDeclaration: continue; + case TSK_ExplicitInstantiationDefinition: continue; + } + + TemporaryContainer C(*this, + Unknown ? "uninstantiated" : "instantiation"); + visitTemplateArguments(*Info->TemplateArguments); + dispatch(Info->Function); + } + } + + // ClasTemplateDecl + void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) { + visitRedeclarableAttrs(D); + } + void visitClassTemplateDeclChildren(ClassTemplateDecl *D) { + // Mention all the specializations which don't have explicit + // declarations elsewhere. + for (ClassTemplateDecl::spec_iterator + I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { + + bool Unknown = false; + switch (I->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: Unknown = false; break; + case TSK_Undeclared: Unknown = true; break; + + // These will be covered at their respective sites. + case TSK_ExplicitSpecialization: continue; + case TSK_ExplicitInstantiationDeclaration: continue; + case TSK_ExplicitInstantiationDefinition: continue; + } + + TemporaryContainer C(*this, + Unknown ? "uninstantiated" : "instantiation"); + visitTemplateArguments(I->getTemplateArgs()); + dispatch(*I); + } + } + + // TemplateTypeParmDecl + void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) { + setInteger("depth", D->getDepth()); + setInteger("index", D->getIndex()); + } + void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + dispatch(D->getDefaultArgumentInfo()->getTypeLoc()); + // parameter pack? + } + + // NonTypeTemplateParmDecl + void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) { + setInteger("depth", D->getDepth()); + setInteger("index", D->getIndex()); + } + void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + dispatch(D->getDefaultArgument()); + // parameter pack? + } + + // TemplateTemplateParmDecl + void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) { + setInteger("depth", D->getDepth()); + setInteger("index", D->getIndex()); + } + void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + dispatch(D->getDefaultArgument()); + // parameter pack? + } + + // FriendDecl + void visitFriendDeclChildren(FriendDecl *D) { + if (TypeSourceInfo *T = D->getFriendType()) + dispatch(T->getTypeLoc()); + else + dispatch(D->getFriendDecl()); + } + + // UsingDirectiveDecl ? + // UsingDecl ? + // UsingShadowDecl ? + // NamespaceAliasDecl ? + // UnresolvedUsingValueDecl ? + // UnresolvedUsingTypenameDecl ? + // StaticAssertDecl ? + + // ObjCImplDecl + void visitObjCImplDeclChildren(ObjCImplDecl *D) { + visitDeclRef(D->getClassInterface()); + } + void visitObjCImplDeclAsContext(ObjCImplDecl *D) { + visitDeclContext(D); + } + + // ObjCClassDecl + void visitObjCClassDeclChildren(ObjCClassDecl *D) { + for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I) + visitDeclRef(I->getInterface()); + } + + // ObjCInterfaceDecl + void visitCategoryList(ObjCCategoryDecl *D) { + if (!D) return; + + TemporaryContainer C(*this, "categories"); + for (; D; D = D->getNextClassCategory()) + visitDeclRef(D); + } + void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { + setPointer("typeptr", D->getTypeForDecl()); + setFlag("forward_decl", D->isForwardDecl()); + setFlag("implicit_interface", D->isImplicitInterfaceDecl()); + } + void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { + visitDeclRef("super", D->getSuperClass()); + visitDeclRef("implementation", D->getImplementation()); + if (D->protocol_begin() != D->protocol_end()) { + TemporaryContainer C(*this, "protocols"); + for (ObjCInterfaceDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) + visitDeclRef(*I); + } + visitCategoryList(D->getCategoryList()); + } + void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) { + visitDeclContext(D); + } + + // ObjCCategoryDecl + void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) { + setFlag("extension", D->IsClassExtension()); + setFlag("synth_bitfield", D->hasSynthBitfield()); + } + void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) { + visitDeclRef("interface", D->getClassInterface()); + visitDeclRef("implementation", D->getImplementation()); + if (D->protocol_begin() != D->protocol_end()) { + TemporaryContainer C(*this, "protocols"); + for (ObjCCategoryDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) + visitDeclRef(*I); + } + } + void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) { + visitDeclContext(D); + } + + // ObjCCategoryImplDecl + void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) { + set("identifier", D->getName()); + } + void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) { + visitDeclRef(D->getCategoryDecl()); + } + + // ObjCImplementationDecl + void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) { + setFlag("synth_bitfield", D->hasSynthBitfield()); + set("identifier", D->getName()); + } + void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) { + visitDeclRef("super", D->getSuperClass()); + if (D->init_begin() != D->init_end()) { + TemporaryContainer C(*this, "initializers"); + for (ObjCImplementationDecl::init_iterator + I = D->init_begin(), E = D->init_end(); I != E; ++I) + dispatch(*I); + } + } + + // 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->protocol_begin() != D->protocol_end()) { + TemporaryContainer C(*this, "protocols"); + for (ObjCInterfaceDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) + visitDeclRef(*I); + } + } + void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) { + visitDeclContext(D); + } + + // ObjCMethodDecl + void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) { + // decl qualifier? + // implementation control? + + setFlag("instance", D->isInstanceMethod()); + setFlag("variadic", D->isVariadic()); + setFlag("synthesized", D->isSynthesized()); + setFlag("defined", D->isDefined()); + } + void visitObjCMethodDeclChildren(ObjCMethodDecl *D) { + dispatch(D->getResultType()); + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + dispatch(*I); + if (D->isThisDeclarationADefinition()) + dispatch(D->getBody()); + } + + // ObjCIvarDecl + void setAccessControl(llvm::StringRef prop, ObjCIvarDecl::AccessControl AC) { + switch (AC) { + case ObjCIvarDecl::None: return set(prop, "none"); + case ObjCIvarDecl::Private: return set(prop, "private"); + case ObjCIvarDecl::Protected: return set(prop, "protected"); + case ObjCIvarDecl::Public: return set(prop, "public"); + case ObjCIvarDecl::Package: return set(prop, "package"); + } + } + void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) { + setFlag("synthesize", D->getSynthesize()); + setAccessControl("access", D->getAccessControl()); + } + + // ObjCCompatibleAliasDecl + void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) { + visitDeclRef(D->getClassInterface()); + } + + // FIXME: ObjCPropertyDecl + // FIXME: ObjCPropertyImplDecl + + //---- Types -----------------------------------------------------// + void dispatch(TypeLoc TL) { + dispatch(TL.getType()); // for now + } + + void dispatch(QualType T) { + if (T.hasLocalQualifiers()) { + push("QualType"); + Qualifiers Qs = T.getLocalQualifiers(); + setFlag("const", Qs.hasConst()); + setFlag("volatile", Qs.hasVolatile()); + setFlag("restrict", Qs.hasRestrict()); + if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace()); + if (Qs.hasObjCGCAttr()) { + switch (Qs.getObjCGCAttr()) { + case Qualifiers::Weak: set("gc", "weak"); break; + case Qualifiers::Strong: set("gc", "strong"); break; + case Qualifiers::GCNone: llvm_unreachable("explicit none"); + } + } + + completeAttrs(); + dispatch(QualType(T.getTypePtr(), 0)); + pop(); + return; + } + + Type *Ty = const_cast(T.getTypePtr()); + push(getTypeKindName(Ty)); + XMLTypeVisitor::dispatch(const_cast(T.getTypePtr())); + pop(); + } + + void setCallingConv(CallingConv CC) { + switch (CC) { + case CC_Default: return; + case CC_C: return set("cc", "cdecl"); + case CC_X86FastCall: return set("cc", "x86_fastcall"); + case CC_X86StdCall: return set("cc", "x86_stdcall"); + case CC_X86ThisCall: return set("cc", "x86_thiscall"); + case CC_X86Pascal: return set("cc", "x86_pascal"); + } + } + + void visitTypeAttrs(Type *D) { + setPointer(D); + setFlag("dependent", D->isDependentType()); + setFlag("variably_modified", D->isVariablyModifiedType()); + + setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr()); + } + + void visitPointerTypeChildren(PointerType *T) { + dispatch(T->getPointeeType()); + } + void visitReferenceTypeChildren(ReferenceType *T) { + dispatch(T->getPointeeType()); + } + void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) { + dispatch(T->getPointeeType()); + } + void visitBlockPointerTypeChildren(BlockPointerType *T) { + dispatch(T->getPointeeType()); + } + + // Types that just wrap declarations. + void visitTagTypeChildren(TagType *T) { + visitDeclRef(T->getDecl()); + } + void visitTypedefTypeChildren(TypedefType *T) { + visitDeclRef(T->getDecl()); + } + void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) { + visitDeclRef(T->getDecl()); + } + void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) { + visitDeclRef(T->getDecl()); + } + void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) { + visitDeclRef(T->getDecl()); + } + + void visitFunctionTypeAttrs(FunctionType *T) { + setFlag("noreturn", T->getNoReturnAttr()); + setCallingConv(T->getCallConv()); + if (T->getRegParmType()) setInteger("regparm", T->getRegParmType()); + } + void visitFunctionTypeChildren(FunctionType *T) { + dispatch(T->getResultType()); + } + + void visitFunctionProtoTypeAttrs(FunctionProtoType *T) { + setFlag("const", T->getTypeQuals() & Qualifiers::Const); + setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile); + setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict); + } + void visitFunctionProtoTypeChildren(FunctionProtoType *T) { + push("parameters"); + setFlag("variadic", T->isVariadic()); + completeAttrs(); + for (FunctionProtoType::arg_type_iterator + I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I) + dispatch(*I); + pop(); + + if (T->hasExceptionSpec()) { + push("exception_specifiers"); + setFlag("any", T->hasAnyExceptionSpec()); + completeAttrs(); + for (FunctionProtoType::exception_iterator + I = T->exception_begin(), E = T->exception_end(); I != E; ++I) + dispatch(*I); + pop(); + } + } + + void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) { + if (const RecordType *RT = T->getAs()) + visitDeclRef(RT->getDecl()); + + // TODO: TemplateName + + push("template_arguments"); + completeAttrs(); + for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) + dispatch(T->getArg(I)); + pop(); + } + + //---- Statements ------------------------------------------------// + void dispatch(Stmt *S) { + // FIXME: this is not really XML at all + push("Stmt"); + out << ">\n"; + Stack.back().State = NS_Children; // explicitly become non-lazy + S->dump(out, Context.getSourceManager()); + out << '\n'; + pop(); + } +}; +} + +void Decl::dumpXML() const { + dumpXML(llvm::errs()); +} + +void Decl::dumpXML(llvm::raw_ostream &out) const { + XMLDumper(out, getASTContext()).dispatch(const_cast(this)); +} + +#else /* ifndef NDEBUG */ + +void Decl::dumpXML() const {} +void Decl::dumpXML(llvm::raw_ostream &out) const {} + +#endif diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 5feef1c80332..391b26ab48ea 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -20,15 +20,16 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Lex/LiteralSupport.h" +#include "clang/Lex/Lexer.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include using namespace clang; -void Expr::ANCHOR() {} // key function for Expr class. - /// isKnownToHaveBooleanValue - Return true if this is an integer expression /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in @@ -90,6 +91,42 @@ bool Expr::isKnownToHaveBooleanValue() const { return false; } +// Amusing macro metaprogramming hack: check whether a class provides +// a more specific implementation of getExprLoc(). +namespace { + /// This implementation is used when a class provides a custom + /// implementation of getExprLoc. + template + SourceLocation getExprLocImpl(const Expr *expr, + SourceLocation (T::*v)() const) { + return static_cast(expr)->getExprLoc(); + } + + /// This implementation is used when a class doesn't provide + /// a custom implementation of getExprLoc. Overload resolution + /// should pick it over the implementation above because it's + /// more specialized according to function template partial ordering. + template + SourceLocation getExprLocImpl(const Expr *expr, + SourceLocation (Expr::*v)() const) { + return static_cast(expr)->getSourceRange().getBegin(); + } +} + +SourceLocation Expr::getExprLoc() const { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: llvm_unreachable(#type " is not an Expr"); break; +#define EXPR(type, base) \ + case Stmt::type##Class: return getExprLocImpl(this, &type::getExprLoc); +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("unknown statement kind"); + return SourceLocation(); +} + //===----------------------------------------------------------------------===// // Primary Expressions. //===----------------------------------------------------------------------===// @@ -105,6 +142,25 @@ void ExplicitTemplateArgumentList::initializeFrom( new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); } +void ExplicitTemplateArgumentList::initializeFrom( + const TemplateArgumentListInfo &Info, + bool &Dependent, + bool &ContainsUnexpandedParameterPack) { + LAngleLoc = Info.getLAngleLoc(); + RAngleLoc = Info.getRAngleLoc(); + NumTemplateArgs = Info.size(); + + TemplateArgumentLoc *ArgBuffer = getTemplateArgs(); + for (unsigned i = 0; i != NumTemplateArgs; ++i) { + Dependent = Dependent || Info[i].getArgument().isDependent(); + ContainsUnexpandedParameterPack + = ContainsUnexpandedParameterPack || + Info[i].getArgument().containsUnexpandedParameterPack(); + + new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); + } +} + void ExplicitTemplateArgumentList::copyInto( TemplateArgumentListInfo &Info) const { Info.setLAngleLoc(LAngleLoc); @@ -123,11 +179,14 @@ std::size_t ExplicitTemplateArgumentList::sizeFor( return sizeFor(Info.size()); } -void DeclRefExpr::computeDependence() { +/// \brief Compute the type- and value-dependence of a declaration reference +/// based on the declaration being referenced. +static void computeDeclRefDependence(NamedDecl *D, QualType T, + bool &TypeDependent, + bool &ValueDependent) { TypeDependent = false; ValueDependent = false; - NamedDecl *D = getDecl(); // (TD) C++ [temp.dep.expr]p3: // An id-expression is type-dependent if it contains: @@ -136,63 +195,93 @@ void DeclRefExpr::computeDependence() { // // (VD) C++ [temp.dep.constexpr]p2: // An identifier is value-dependent if it is: - + // (TD) - an identifier that was declared with dependent type // (VD) - a name declared with a dependent type, - if (getType()->isDependentType()) { + if (T->isDependentType()) { TypeDependent = true; ValueDependent = true; + return; } + // (TD) - a conversion-function-id that specifies a dependent type - else if (D->getDeclName().getNameKind() - == DeclarationName::CXXConversionFunctionName && + if (D->getDeclName().getNameKind() + == DeclarationName::CXXConversionFunctionName && D->getDeclName().getCXXNameType()->isDependentType()) { TypeDependent = true; ValueDependent = true; - } - // (TD) - a template-id that is dependent, - else if (hasExplicitTemplateArgs() && - TemplateSpecializationType::anyDependentTemplateArguments( - getTemplateArgs(), - getNumTemplateArgs())) { - TypeDependent = true; - ValueDependent = true; + return; } // (VD) - the name of a non-type template parameter, - else if (isa(D)) + if (isa(D)) { ValueDependent = true; + return; + } + // (VD) - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent. - else if (VarDecl *Var = dyn_cast(D)) { + if (VarDecl *Var = dyn_cast(D)) { if (Var->getType()->isIntegralOrEnumerationType() && Var->getType().getCVRQualifiers() == Qualifiers::Const) { if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) ValueDependent = 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()) ValueDependent = true; - } + + return; + } + // (VD) - FIXME: Missing from the standard: // - a member function or a static data member of the current // instantiation - else if (isa(D) && D->getDeclContext()->isDependentContext()) + if (isa(D) && D->getDeclContext()->isDependentContext()) { ValueDependent = true; - // (TD) - a nested-name-specifier or a qualified-id that names a - // member of an unknown specialization. - // (handled by DependentScopeDeclRefExpr) + return; + } +} + +void DeclRefExpr::computeDependence() { + bool TypeDependent = false; + bool ValueDependent = false; + computeDeclRefDependence(getDecl(), getType(), TypeDependent, ValueDependent); + + // (TD) C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains: + // + // and + // + // (VD) C++ [temp.dep.constexpr]p2: + // An identifier is value-dependent if it is: + if (!TypeDependent && !ValueDependent && + hasExplicitTemplateArgs() && + TemplateSpecializationType::anyDependentTemplateArguments( + getTemplateArgs(), + getNumTemplateArgs())) { + TypeDependent = true; + ValueDependent = true; + } + + ExprBits.TypeDependent = TypeDependent; + ExprBits.ValueDependent = ValueDependent; + + // Is the declaration a parameter pack? + if (getDecl()->isParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; } DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, - QualType T) - : Expr(DeclRefExprClass, T, false, false), + QualType T, ExprValueKind VK) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), DecoratedD(D, (Qualifier? HasQualifierFlag : 0) | (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), @@ -213,8 +302,8 @@ DeclRefExpr::DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, ValueDecl *D, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, - QualType T) - : Expr(DeclRefExprClass, T, false, false), + QualType T, ExprValueKind VK) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), DecoratedD(D, (Qualifier? HasQualifierFlag : 0) | (TemplateArgs ? HasExplicitTemplateArgumentListFlag : 0)), @@ -237,10 +326,11 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, ValueDecl *D, SourceLocation NameLoc, QualType T, + ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs) { return Create(Context, Qualifier, QualifierRange, D, DeclarationNameInfo(D->getDeclName(), NameLoc), - T, TemplateArgs); + T, VK, TemplateArgs); } DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, @@ -249,6 +339,7 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, ValueDecl *D, const DeclarationNameInfo &NameInfo, QualType T, + ExprValueKind VK, const TemplateArgumentListInfo *TemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (Qualifier != 0) @@ -257,21 +348,23 @@ DeclRefExpr *DeclRefExpr::Create(ASTContext &Context, if (TemplateArgs) Size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); - void *Mem = Context.Allocate(Size, llvm::alignof()); + void *Mem = Context.Allocate(Size, llvm::alignOf()); return new (Mem) DeclRefExpr(Qualifier, QualifierRange, D, NameInfo, - TemplateArgs, T); + TemplateArgs, T, VK); } -DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, bool HasQualifier, +DeclRefExpr *DeclRefExpr::CreateEmpty(ASTContext &Context, + bool HasQualifier, + bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { std::size_t Size = sizeof(DeclRefExpr); if (HasQualifier) Size += sizeof(NameQualifier); - if (NumTemplateArgs) + if (HasExplicitTemplateArgs) Size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); - void *Mem = Context.Allocate(Size, llvm::alignof()); + void *Mem = Context.Allocate(Size, llvm::alignOf()); return new (Mem) DeclRefExpr(EmptyShell()); } @@ -432,7 +525,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData, // any concatenated string tokens. void *Mem = C.Allocate(sizeof(StringLiteral)+ sizeof(SourceLocation)*(NumStrs-1), - llvm::alignof()); + llvm::alignOf()); StringLiteral *SL = new (Mem) StringLiteral(Ty); // OPTIMIZE: could allocate this appended to the StringLiteral. @@ -452,7 +545,7 @@ StringLiteral *StringLiteral::Create(ASTContext &C, const char *StrData, StringLiteral *StringLiteral::CreateEmpty(ASTContext &C, unsigned NumStrs) { void *Mem = C.Allocate(sizeof(StringLiteral)+ sizeof(SourceLocation)*(NumStrs-1), - llvm::alignof()); + llvm::alignOf()); StringLiteral *SL = new (Mem) StringLiteral(QualType()); SL->StrData = 0; SL->ByteLength = 0; @@ -467,6 +560,72 @@ void StringLiteral::setString(ASTContext &C, llvm::StringRef Str) { ByteLength = Str.size(); } +/// getLocationOfByte - Return a source location that points to the specified +/// byte of this string literal. +/// +/// Strings are amazingly complex. They can be formed from multiple tokens and +/// can have escape sequences in them in addition to the usual trigraph and +/// escaped newline business. This routine handles this complexity. +/// +SourceLocation StringLiteral:: +getLocationOfByte(unsigned ByteNo, const SourceManager &SM, + const LangOptions &Features, const TargetInfo &Target) const { + assert(!isWide() && "This doesn't work for wide strings yet"); + + // Loop over all of the tokens in this string until we find the one that + // contains the byte we're looking for. + unsigned TokNo = 0; + while (1) { + assert(TokNo < getNumConcatenated() && "Invalid byte number!"); + SourceLocation StrTokLoc = getStrTokenLoc(TokNo); + + // Get the spelling of the string so that we can get the data that makes up + // the string literal, not the identifier for the macro it is potentially + // expanded through. + SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc); + + // Re-lex the token to get its length and original spelling. + std::pair LocInfo =SM.getDecomposedLoc(StrTokSpellingLoc); + bool Invalid = false; + llvm::StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); + if (Invalid) + return StrTokSpellingLoc; + + const char *StrData = Buffer.data()+LocInfo.second; + + // Create a langops struct and enable trigraphs. This is sufficient for + // relexing tokens. + LangOptions LangOpts; + LangOpts.Trigraphs = true; + + // Create a lexer starting at the beginning of this token. + Lexer TheLexer(StrTokSpellingLoc, Features, Buffer.begin(), StrData, + Buffer.end()); + Token TheTok; + TheLexer.LexFromRawLexer(TheTok); + + // Use the StringLiteralParser to compute the length of the string in bytes. + StringLiteralParser SLP(&TheTok, 1, SM, Features, Target); + unsigned TokNumBytes = SLP.GetStringLength(); + + // If the byte is in this token, return the location of the byte. + if (ByteNo < TokNumBytes || + (ByteNo == TokNumBytes && TokNo == getNumConcatenated())) { + unsigned Offset = SLP.getOffsetOfStringByte(TheTok, ByteNo); + + // Now that we know the offset of the token in the spelling, use the + // preprocessor to get the offset in the original source. + return Lexer::AdvanceToTokenCharacter(StrTokLoc, Offset, SM, Features); + } + + // Move to the next string token. + ++TokNo; + ByteNo -= TokNumBytes; + } +} + + + /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it /// corresponds to, e.g. "sizeof" or "[pre]++". const char *UnaryOperator::getOpcodeStr(Opcode Op) { @@ -522,43 +681,82 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { // Postfix Operators. //===----------------------------------------------------------------------===// -CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, Expr **args, - unsigned numargs, QualType t, SourceLocation rparenloc) - : Expr(SC, t, - fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs), - fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)), +CallExpr::CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, + Expr **args, unsigned numargs, QualType t, ExprValueKind VK, + SourceLocation rparenloc) + : Expr(SC, t, VK, OK_Ordinary, + fn->isTypeDependent(), + fn->isValueDependent(), + fn->containsUnexpandedParameterPack()), NumArgs(numargs) { - SubExprs = new (C) Stmt*[numargs+1]; + SubExprs = new (C) Stmt*[numargs+PREARGS_START+NumPreArgs]; SubExprs[FN] = fn; - for (unsigned i = 0; i != numargs; ++i) - SubExprs[i+ARGS_START] = args[i]; + for (unsigned i = 0; i != numargs; ++i) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i+PREARGS_START+NumPreArgs] = args[i]; + } + CallExprBits.NumPreArgs = NumPreArgs; RParenLoc = rparenloc; } CallExpr::CallExpr(ASTContext& C, Expr *fn, Expr **args, unsigned numargs, - QualType t, SourceLocation rparenloc) - : Expr(CallExprClass, t, - fn->isTypeDependent() || hasAnyTypeDependentArguments(args, numargs), - fn->isValueDependent() || hasAnyValueDependentArguments(args,numargs)), + QualType t, ExprValueKind VK, SourceLocation rparenloc) + : Expr(CallExprClass, t, VK, OK_Ordinary, + fn->isTypeDependent(), + fn->isValueDependent(), + fn->containsUnexpandedParameterPack()), NumArgs(numargs) { - SubExprs = new (C) Stmt*[numargs+1]; + SubExprs = new (C) Stmt*[numargs+PREARGS_START]; SubExprs[FN] = fn; - for (unsigned i = 0; i != numargs; ++i) - SubExprs[i+ARGS_START] = args[i]; + for (unsigned i = 0; i != numargs; ++i) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i+PREARGS_START] = args[i]; + } + CallExprBits.NumPreArgs = 0; RParenLoc = rparenloc; } CallExpr::CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), SubExprs(0), NumArgs(0) { - SubExprs = new (C) Stmt*[1]; + // FIXME: Why do we allocate this? + SubExprs = new (C) Stmt*[PREARGS_START]; + CallExprBits.NumPreArgs = 0; +} + +CallExpr::CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, + EmptyShell Empty) + : Expr(SC, Empty), SubExprs(0), NumArgs(0) { + // FIXME: Why do we allocate this? + SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs]; + CallExprBits.NumPreArgs = NumPreArgs; } Decl *CallExpr::getCalleeDecl() { Expr *CEE = getCallee()->IgnoreParenCasts(); + // If we're calling a dereference, look at the pointer instead. + if (BinaryOperator *BO = dyn_cast(CEE)) { + if (BO->isPtrMemOp()) + CEE = BO->getRHS()->IgnoreParenCasts(); + } else if (UnaryOperator *UO = dyn_cast(CEE)) { + if (UO->getOpcode() == UO_Deref) + CEE = UO->getSubExpr()->IgnoreParenCasts(); + } if (DeclRefExpr *DRE = dyn_cast(CEE)) return DRE->getDecl(); if (MemberExpr *ME = dyn_cast(CEE)) @@ -585,12 +783,14 @@ void CallExpr::setNumArgs(ASTContext& C, unsigned NumArgs) { } // Otherwise, we are growing the # arguments. New an bigger argument array. - Stmt **NewSubExprs = new (C) Stmt*[NumArgs+1]; + unsigned NumPreArgs = getNumPreArgs(); + Stmt **NewSubExprs = new (C) Stmt*[NumArgs+PREARGS_START+NumPreArgs]; // Copy over args. - for (unsigned i = 0; i != getNumArgs()+ARGS_START; ++i) + for (unsigned i = 0; i != getNumArgs()+PREARGS_START+NumPreArgs; ++i) NewSubExprs[i] = SubExprs[i]; // Null out new args. - for (unsigned i = getNumArgs()+ARGS_START; i != NumArgs+ARGS_START; ++i) + for (unsigned i = getNumArgs()+PREARGS_START+NumPreArgs; + i != NumArgs+PREARGS_START+NumPreArgs; ++i) NewSubExprs[i] = 0; if (SubExprs) C.Deallocate(SubExprs); @@ -600,7 +800,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(ASTContext &Context) const { +unsigned CallExpr::isBuiltinCall(const ASTContext &Context) 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. @@ -663,10 +863,10 @@ OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type, OffsetOfNode* compsPtr, unsigned numComps, Expr** exprsPtr, unsigned numExprs, SourceLocation RParenLoc) - : Expr(OffsetOfExprClass, type, /*TypeDependent=*/false, - /*ValueDependent=*/tsi->getType()->isDependentType() || - hasAnyTypeDependentArguments(exprsPtr, numExprs) || - hasAnyValueDependentArguments(exprsPtr, numExprs)), + : Expr(OffsetOfExprClass, type, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, + /*ValueDependent=*/tsi->getType()->isDependentType(), + tsi->getType()->containsUnexpandedParameterPack()), OperatorLoc(OperatorLoc), RParenLoc(RParenLoc), TSInfo(tsi), NumComps(numComps), NumExprs(numExprs) { @@ -675,6 +875,11 @@ OffsetOfExpr::OffsetOfExpr(ASTContext &C, QualType type, } for(unsigned i = 0; i < numExprs; ++i) { + if (exprsPtr[i]->isTypeDependent() || exprsPtr[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (exprsPtr[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + setIndexExpr(i, exprsPtr[i]); } } @@ -694,7 +899,9 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, DeclAccessPair founddecl, DeclarationNameInfo nameinfo, const TemplateArgumentListInfo *targs, - QualType ty) { + QualType ty, + ExprValueKind vk, + ExprObjectKind ok) { std::size_t Size = sizeof(MemberExpr); bool hasQualOrFound = (qual != 0 || @@ -706,8 +913,9 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, if (targs) Size += ExplicitTemplateArgumentList::sizeFor(*targs); - void *Mem = C.Allocate(Size, llvm::alignof()); - MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, ty); + void *Mem = C.Allocate(Size, llvm::alignOf()); + MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, nameinfo, + ty, vk, ok); if (hasQualOrFound) { if (qual && qual->isDependent()) { @@ -732,12 +940,16 @@ MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow, const char *CastExpr::getCastKindName() const { switch (getCastKind()) { - case CK_Unknown: - return "Unknown"; + case CK_Dependent: + return "Dependent"; case CK_BitCast: return "BitCast"; case CK_LValueBitCast: return "LValueBitCast"; + case CK_LValueToRValue: + return "LValueToRValue"; + case CK_GetObjCProperty: + return "GetObjCProperty"; case CK_NoOp: return "NoOp"; case CK_BaseToDerived: @@ -756,6 +968,8 @@ const char *CastExpr::getCastKindName() const { return "FunctionToPointerDecay"; case CK_NullToMemberPointer: return "NullToMemberPointer"; + case CK_NullToPointer: + return "NullToPointer"; case CK_BaseToDerivedMemberPointer: return "BaseToDerivedMemberPointer"; case CK_DerivedToBaseMemberPointer: @@ -768,18 +982,24 @@ const char *CastExpr::getCastKindName() const { return "IntegralToPointer"; case CK_PointerToIntegral: return "PointerToIntegral"; + case CK_PointerToBoolean: + return "PointerToBoolean"; case CK_ToVoid: return "ToVoid"; case CK_VectorSplat: return "VectorSplat"; case CK_IntegralCast: return "IntegralCast"; + case CK_IntegralToBoolean: + return "IntegralToBoolean"; case CK_IntegralToFloating: return "IntegralToFloating"; case CK_FloatingToIntegral: return "FloatingToIntegral"; case CK_FloatingCast: return "FloatingCast"; + case CK_FloatingToBoolean: + return "FloatingToBoolean"; case CK_MemberPointerToBoolean: return "MemberPointerToBoolean"; case CK_AnyPointerToObjCPointerCast: @@ -788,9 +1008,29 @@ const char *CastExpr::getCastKindName() const { return "AnyPointerToBlockPointerCast"; case CK_ObjCObjectLValueCast: return "ObjCObjectLValueCast"; + case CK_FloatingRealToComplex: + return "FloatingRealToComplex"; + case CK_FloatingComplexToReal: + return "FloatingComplexToReal"; + case CK_FloatingComplexToBoolean: + return "FloatingComplexToBoolean"; + case CK_FloatingComplexCast: + return "FloatingComplexCast"; + case CK_FloatingComplexToIntegralComplex: + return "FloatingComplexToIntegralComplex"; + case CK_IntegralRealToComplex: + return "IntegralRealToComplex"; + case CK_IntegralComplexToReal: + return "IntegralComplexToReal"; + case CK_IntegralComplexToBoolean: + return "IntegralComplexToBoolean"; + case CK_IntegralComplexCast: + return "IntegralComplexCast"; + case CK_IntegralComplexToFloatingComplex: + return "IntegralComplexToFloatingComplex"; } - assert(0 && "Unhandled cast kind!"); + llvm_unreachable("Unhandled cast kind!"); return 0; } @@ -859,7 +1099,7 @@ ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C, CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T, - CastKind K, Expr *Op, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R) { @@ -867,7 +1107,7 @@ CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T, void *Buffer = C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CStyleCastExpr *E = - new (Buffer) CStyleCastExpr(T, K, Op, PathSize, WrittenTy, L, R); + new (Buffer) CStyleCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, R); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -984,16 +1224,19 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) { InitListExpr::InitListExpr(ASTContext &C, SourceLocation lbraceloc, Expr **initExprs, unsigned numInits, SourceLocation rbraceloc) - : Expr(InitListExprClass, QualType(), false, false), + : Expr(InitListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, + false), InitExprs(C, numInits), LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0), UnionFieldInit(0), HadArrayRangeDesignator(false) { for (unsigned I = 0; I != numInits; ++I) { if (initExprs[I]->isTypeDependent()) - TypeDependent = true; + ExprBits.TypeDependent = true; if (initExprs[I]->isValueDependent()) - ValueDependent = true; + ExprBits.ValueDependent = true; + if (initExprs[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; } InitExprs.insert(C, InitExprs.end(), initExprs, initExprs+numInits); @@ -1020,6 +1263,35 @@ Expr *InitListExpr::updateInit(ASTContext &C, unsigned Init, Expr *expr) { return Result; } +SourceRange InitListExpr::getSourceRange() const { + if (SyntacticForm) + return SyntacticForm->getSourceRange(); + SourceLocation Beg = LBraceLoc, End = RBraceLoc; + if (Beg.isInvalid()) { + // Find the first non-null initializer. + for (InitExprsTy::const_iterator I = InitExprs.begin(), + E = InitExprs.end(); + I != E; ++I) { + if (Stmt *S = *I) { + Beg = S->getLocStart(); + break; + } + } + } + if (End.isInvalid()) { + // Find the first non-null initializer from the end. + for (InitExprsTy::const_reverse_iterator I = InitExprs.rbegin(), + E = InitExprs.rend(); + I != E; ++I) { + if (Stmt *S = *I) { + End = S->getSourceRange().getEnd(); + break; + } + } + } + return SourceRange(Beg, End); +} + /// getFunctionType - Return the underlying function type for this block. /// const FunctionType *BlockExpr::getFunctionType() const { @@ -1195,21 +1467,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return false; } - case ObjCImplicitSetterGetterRefExprClass: { // Dot syntax for message send. -#if 0 - const ObjCImplicitSetterGetterRefExpr *Ref = - cast(this); - // FIXME: We really want the location of the '.' here. - Loc = Ref->getLocation(); - R1 = SourceRange(Ref->getLocation(), Ref->getLocation()); - if (Ref->getBase()) - R2 = Ref->getBase()->getSourceRange(); -#else + case ObjCPropertyRefExprClass: Loc = getExprLoc(); R1 = getSourceRange(); -#endif 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. @@ -1217,9 +1479,13 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // however, if the result of the stmt expr is dead, we don't want to emit a // warning. const CompoundStmt *CS = cast(this)->getSubStmt(); - if (!CS->body_empty()) + if (!CS->body_empty()) { if (const Expr *E = dyn_cast(CS->body_back())) return E->isUnusedResultAWarning(Loc, R1, R2, Ctx); + if (const LabelStmt *Label = dyn_cast(CS->body_back())) + if (const Expr *E = dyn_cast(Label->getSubStmt())) + return E->isUnusedResultAWarning(Loc, R1, R2, Ctx); + } if (getType()->isVoidType()) return false; @@ -1268,8 +1534,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case CXXBindTemporaryExprClass: return (cast(this) ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); - case CXXExprWithTemporariesClass: - return (cast(this) + case ExprWithCleanupsClass: + return (cast(this) ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Ctx)); } } @@ -1311,12 +1577,254 @@ bool Expr::isOBJCGCCandidate(ASTContext &Ctx) const { return cast(this)->getBase()->isOBJCGCCandidate(Ctx); } } + +bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { + if (isTypeDependent()) + return false; + return ClassifyLValue(Ctx) == Expr::LV_MemberFunction; +} + +static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1, + Expr::CanThrowResult CT2) { + // CanThrowResult constants are ordered so that the maximum is the correct + // merge result. + return CT1 > CT2 ? CT1 : CT2; +} + +static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) { + Expr *E = const_cast(CE); + Expr::CanThrowResult R = Expr::CT_Cannot; + for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I) { + R = MergeCanThrow(R, cast(*I)->CanThrow(C)); + } + return R; +} + +static Expr::CanThrowResult CanCalleeThrow(const Decl *D, + bool NullThrows = true) { + if (!D) + return NullThrows ? Expr::CT_Can : Expr::CT_Cannot; + + // See if we can get a function type from the decl somehow. + const ValueDecl *VD = dyn_cast(D); + if (!VD) // If we have no clue what we're calling, assume the worst. + return Expr::CT_Can; + + // As an extension, we assume that __attribute__((nothrow)) functions don't + // throw. + if (isa(D) && D->hasAttr()) + return Expr::CT_Cannot; + + QualType T = VD->getType(); + const FunctionProtoType *FT; + if ((FT = T->getAs())) { + } else if (const PointerType *PT = T->getAs()) + FT = PT->getPointeeType()->getAs(); + else if (const ReferenceType *RT = T->getAs()) + FT = RT->getPointeeType()->getAs(); + else if (const MemberPointerType *MT = T->getAs()) + FT = MT->getPointeeType()->getAs(); + else if (const BlockPointerType *BT = T->getAs()) + FT = BT->getPointeeType()->getAs(); + + if (!FT) + return Expr::CT_Can; + + return FT->hasEmptyExceptionSpec() ? Expr::CT_Cannot : Expr::CT_Can; +} + +static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr *DC) { + if (DC->isTypeDependent()) + return Expr::CT_Dependent; + + if (!DC->getTypeAsWritten()->isReferenceType()) + return Expr::CT_Cannot; + + return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can : Expr::CT_Cannot; +} + +static Expr::CanThrowResult CanTypeidThrow(ASTContext &C, + const CXXTypeidExpr *DC) { + if (DC->isTypeOperand()) + return Expr::CT_Cannot; + + Expr *Op = DC->getExprOperand(); + if (Op->isTypeDependent()) + return Expr::CT_Dependent; + + const RecordType *RT = Op->getType()->getAs(); + if (!RT) + return Expr::CT_Cannot; + + if (!cast(RT->getDecl())->isPolymorphic()) + return Expr::CT_Cannot; + + if (Op->Classify(C).isPRValue()) + return Expr::CT_Cannot; + + return Expr::CT_Can; +} + +Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { + // C++ [expr.unary.noexcept]p3: + // [Can throw] if in a potentially-evaluated context the expression would + // contain: + switch (getStmtClass()) { + case CXXThrowExprClass: + // - a potentially evaluated throw-expression + return CT_Can; + + case CXXDynamicCastExprClass: { + // - a potentially evaluated dynamic_cast expression dynamic_cast(v), + // where T is a reference type, that requires a run-time check + CanThrowResult CT = CanDynamicCastThrow(cast(this)); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXTypeidExprClass: + // - a potentially evaluated typeid expression applied to a glvalue + // expression whose type is a polymorphic class type + return CanTypeidThrow(C, cast(this)); + + // - a potentially evaluated call to a function, member function, function + // pointer, or member function pointer that does not have a non-throwing + // exception-specification + case CallExprClass: + case CXXOperatorCallExprClass: + case CXXMemberCallExprClass: { + CanThrowResult CT = CanCalleeThrow(cast(this)->getCalleeDecl()); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXConstructExprClass: + case CXXTemporaryObjectExprClass: { + CanThrowResult CT = CanCalleeThrow( + cast(this)->getConstructor()); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXNewExprClass: { + CanThrowResult CT = MergeCanThrow( + CanCalleeThrow(cast(this)->getOperatorNew()), + CanCalleeThrow(cast(this)->getConstructor(), + /*NullThrows*/false)); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXDeleteExprClass: { + CanThrowResult CT = CanCalleeThrow( + cast(this)->getOperatorDelete()); + if (CT == CT_Can) + return CT; + const Expr *Arg = cast(this)->getArgument(); + // Unwrap exactly one implicit cast, which converts all pointers to void*. + if (const ImplicitCastExpr *Cast = dyn_cast(Arg)) + Arg = Cast->getSubExpr(); + if (const PointerType *PT = Arg->getType()->getAs()) { + if (const RecordType *RT = PT->getPointeeType()->getAs()) { + CanThrowResult CT2 = CanCalleeThrow( + cast(RT->getDecl())->getDestructor()); + if (CT2 == CT_Can) + return CT2; + CT = MergeCanThrow(CT, CT2); + } + } + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXBindTemporaryExprClass: { + // The bound temporary has to be destroyed again, which might throw. + CanThrowResult CT = CanCalleeThrow( + cast(this)->getTemporary()->getDestructor()); + if (CT == CT_Can) + return CT; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + // ObjC message sends are like function calls, but never have exception + // specs. + case ObjCMessageExprClass: + case ObjCPropertyRefExprClass: + 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 CXXDefaultArgExprClass: + case ExprWithCleanupsClass: + case ObjCIvarRefExprClass: + case ObjCIsaExprClass: + case ShuffleVectorExprClass: + return CanSubExprsThrow(C, this); + + // Some might be dependent for other reasons. + case UnaryOperatorClass: + case ArraySubscriptExprClass: + case ImplicitCastExprClass: + case CStyleCastExprClass: + case CXXStaticCastExprClass: + case CXXFunctionalCastExprClass: + case BinaryOperatorClass: + case CompoundAssignOperatorClass: { + CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot; + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms. + case StmtExprClass: + return CT_Can; + + case ChooseExprClass: + if (isTypeDependent() || isValueDependent()) + return CT_Dependent; + return cast(this)->getChosenSubExpr(C)->CanThrow(C); + + // Some expressions are always dependent. + case DependentScopeDeclRefExprClass: + case CXXUnresolvedConstructExprClass: + case CXXDependentScopeMemberExprClass: + return CT_Dependent; + + default: + // All other expressions don't have subexpressions, or else they are + // unevaluated. + return CT_Cannot; + } +} + Expr* Expr::IgnoreParens() { Expr* E = this; - while (ParenExpr* P = dyn_cast(E)) - E = P->getSubExpr(); - - return E; + while (true) { + if (ParenExpr* P = dyn_cast(E)) { + E = P->getSubExpr(); + continue; + } + if (UnaryOperator* P = dyn_cast(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; + } } /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr @@ -1324,24 +1832,68 @@ Expr* Expr::IgnoreParens() { Expr *Expr::IgnoreParenCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast(E)) + if (ParenExpr* P = dyn_cast(E)) { E = P->getSubExpr(); - else if (CastExpr *P = dyn_cast(E)) + continue; + } + if (CastExpr *P = dyn_cast(E)) { E = P->getSubExpr(); - else - return E; + continue; + } + if (UnaryOperator* P = dyn_cast(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; } } +/// IgnoreParenLValueCasts - Ignore parentheses and lvalue-to-rvalue +/// casts. This is intended purely as a temporary workaround for code +/// that hasn't yet been rewritten to do the right thing about those +/// casts, and may disappear along with the last internal use. +Expr *Expr::IgnoreParenLValueCasts() { + Expr *E = this; + while (true) { + if (ParenExpr *P = dyn_cast(E)) { + E = P->getSubExpr(); + continue; + } else if (CastExpr *P = dyn_cast(E)) { + if (P->getCastKind() == CK_LValueToRValue) { + E = P->getSubExpr(); + continue; + } + } else if (UnaryOperator* P = dyn_cast(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + break; + } + return E; +} + Expr *Expr::IgnoreParenImpCasts() { Expr *E = this; while (true) { - if (ParenExpr *P = dyn_cast(E)) + if (ParenExpr *P = dyn_cast(E)) { E = P->getSubExpr(); - else if (ImplicitCastExpr *P = dyn_cast(E)) + continue; + } + if (ImplicitCastExpr *P = dyn_cast(E)) { E = P->getSubExpr(); - else - return E; + continue; + } + if (UnaryOperator* P = dyn_cast(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; } } @@ -1366,9 +1918,9 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { continue; } - if ((E->getType()->isPointerType() || + if ((E->getType()->isPointerType() || E->getType()->isIntegralType(Ctx)) && - (SE->getType()->isPointerType() || + (SE->getType()->isPointerType() || SE->getType()->isIntegralType(Ctx)) && Ctx.getTypeSize(E->getType()) == Ctx.getTypeSize(SE->getType())) { E = SE; @@ -1376,6 +1928,13 @@ Expr *Expr::IgnoreParenNoopCasts(ASTContext &Ctx) { } } + if (UnaryOperator* P = dyn_cast(E)) { + if (P->getOpcode() == UO_Extension) { + E = P->getSubExpr(); + continue; + } + } + return E; } } @@ -1390,7 +1949,7 @@ bool Expr::isDefaultArgument() const { /// \brief Skip over any no-op casts and any temporary-binding /// expressions. -static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) { +static const Expr *skipTemporaryBindingsNoOpCastsAndParens(const Expr *E) { while (const ImplicitCastExpr *ICE = dyn_cast(E)) { if (ICE->getCastKind() == CK_NoOp) E = ICE->getSubExpr(); @@ -1407,50 +1966,48 @@ static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) { else break; } - - return E; -} -const Expr *Expr::getTemporaryObject() const { - const Expr *E = skipTemporaryBindingsAndNoOpCasts(this); + return E->IgnoreParens(); +} - // A cast can produce a temporary object. The object's construction - // is represented as a CXXConstructExpr. - if (const CastExpr *Cast = dyn_cast(E)) { - // Only user-defined and constructor conversions can produce - // temporary objects. - if (Cast->getCastKind() != CK_ConstructorConversion && - Cast->getCastKind() != CK_UserDefinedConversion) - return 0; +/// isTemporaryObject - Determines if this expression produces a +/// temporary of the given class type. +bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { + if (!C.hasSameUnqualifiedType(getType(), C.getTypeDeclType(TempTy))) + return false; - // Strip off temporary bindings and no-op casts. - const Expr *Sub = skipTemporaryBindingsAndNoOpCasts(Cast->getSubExpr()); + const Expr *E = skipTemporaryBindingsNoOpCastsAndParens(this); - // If this is a constructor conversion, see if we have an object - // construction. - if (Cast->getCastKind() == CK_ConstructorConversion) - return dyn_cast(Sub); + // Temporaries are by definition pr-values of class type. + if (!E->Classify(C).isPRValue()) { + // In this context, property reference is a message call and is pr-value. + if (!isa(E)) + return false; + } - // If this is a user-defined conversion, see if we have a call to - // a function that itself returns a temporary object. - if (Cast->getCastKind() == CK_UserDefinedConversion) - if (const CallExpr *CE = dyn_cast(Sub)) - if (CE->getCallReturnType()->isRecordType()) - return CE; + // Black-list a few cases which yield pr-values of class type that don't + // refer to temporaries of that type: - return 0; + // - implicit derived-to-base conversions + if (isa(E)) { + switch (cast(E)->getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + return false; + default: + break; + } } - // A call returning a class type returns a temporary. - if (const CallExpr *CE = dyn_cast(E)) { - if (CE->getCallReturnType()->isRecordType()) - return CE; + // - member expressions (all) + if (isa(E)) + return false; - return 0; - } + // - opaque values (all) + if (isa(E)) + return false; - // Explicit temporary object constructors create temporaries. - return dyn_cast(E); + return true; } /// hasAnyTypeDependentArguments - Determines if any of the expressions @@ -1533,6 +2090,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case ParenExprClass: return cast(this)->getSubExpr() ->isConstantInitializer(Ctx, IsForRef); + case ChooseExprClass: + return cast(this)->getChosenSubExpr(Ctx) + ->isConstantInitializer(Ctx, IsForRef); case UnaryOperatorClass: { const UnaryOperator* Exp = cast(this); if (Exp->getOpcode() == UO_Extension) @@ -1572,11 +2132,14 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { return isEvaluatable(Ctx); } -/// isNullPointerConstant - C99 6.3.2.3p3 - Return true if this is either an -/// integer constant expression with the value zero, or if this is one that is -/// cast to void*. -bool Expr::isNullPointerConstant(ASTContext &Ctx, - NullPointerConstantValueDependence NPC) const { +/// 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 +/// value zero, casts of zero to void*, nullptr (C++0X), or __null +/// (a GNU extension). +Expr::NullPointerConstantKind +Expr::isNullPointerConstant(ASTContext &Ctx, + NullPointerConstantValueDependence NPC) const { if (isValueDependent()) { switch (NPC) { case NPC_NeverValueDependent: @@ -1584,10 +2147,13 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, // If the unthinkable happens, fall through to the safest alternative. case NPC_ValueDependentIsNull: - return isTypeDependent() || getType()->isIntegralType(Ctx); + if (isTypeDependent() || getType()->isIntegralType(Ctx)) + return NPCK_ZeroInteger; + else + return NPCK_NotNull; case NPC_ValueDependentIsNotNull: - return false; + return NPCK_NotNull; } } @@ -1616,30 +2182,61 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx, return DefaultArg->getExpr()->isNullPointerConstant(Ctx, NPC); } else if (isa(this)) { // The GNU __null extension is always a null pointer constant. - return true; + return NPCK_GNUNull; } // C++0x nullptr_t is always a null pointer constant. if (getType()->isNullPtrType()) - return true; - + return NPCK_CXX0X_nullptr; + + if (const RecordType *UT = getType()->getAsUnionType()) + if (UT && UT->getDecl()->hasAttr()) + if (const CompoundLiteralExpr *CLE = dyn_cast(this)){ + const Expr *InitExpr = CLE->getInitializer(); + if (const InitListExpr *ILE = dyn_cast(InitExpr)) + return ILE->getInit(0)->isNullPointerConstant(Ctx, NPC); + } // This expression must be an integer type. if (!getType()->isIntegerType() || (Ctx.getLangOptions().CPlusPlus && getType()->isEnumeralType())) - return false; + return NPCK_NotNull; // If we have an integer constant expression, we need to *evaluate* it and // test for the value 0. llvm::APSInt Result; - return isIntegerConstantExpr(Result, Ctx) && Result == 0; + bool IsNull = isIntegerConstantExpr(Result, Ctx) && Result == 0; + + return (IsNull ? NPCK_ZeroInteger : NPCK_NotNull); +} + +/// \brief If this expression is an l-value for an Objective C +/// property, find the underlying property reference expression. +const ObjCPropertyRefExpr *Expr::getObjCProperty() const { + const Expr *E = this; + while (true) { + assert((E->getValueKind() == VK_LValue && + E->getObjectKind() == OK_ObjCProperty) && + "expression is not a property reference"); + E = E->IgnoreParenCasts(); + if (const BinaryOperator *BO = dyn_cast(E)) { + if (BO->getOpcode() == BO_Comma) { + E = BO->getRHS(); + continue; + } + } + + break; + } + + return cast(E); } FieldDecl *Expr::getBitField() { Expr *E = this->IgnoreParens(); while (ImplicitCastExpr *ICE = dyn_cast(E)) { - if (ICE->getValueKind() != VK_RValue && - ICE->getCastKind() == CK_NoOp) + if (ICE->getCastKind() == CK_LValueToRValue || + (ICE->getValueKind() != VK_RValue && ICE->getCastKind() == CK_NoOp)) E = ICE->getSubExpr()->IgnoreParens(); else break; @@ -1650,6 +2247,11 @@ FieldDecl *Expr::getBitField() { if (Field->isBitField()) return Field; + if (DeclRefExpr *DeclRef = dyn_cast(E)) + if (FieldDecl *Field = dyn_cast(DeclRef->getDecl())) + if (Field->isBitField()) + return Field; + if (BinaryOperator *BinOp = dyn_cast(E)) if (BinOp->isAssignmentOp() && BinOp->getLHS()) return BinOp->getLHS()->getBitField(); @@ -1741,21 +2343,24 @@ void ExtVectorElementExpr::getEncodedElementAccess( } ObjCMessageExpr::ObjCMessageExpr(QualType T, + ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) - : Expr(ObjCMessageExprClass, T, /*TypeDependent=*/false, - /*ValueDependent=*/false), + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass), HasMethod(Method != 0), SuperLoc(SuperLoc), SelectorOrMethod(reinterpret_cast(Method? Method : Sel.getAsOpaquePtr())), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { setReceiverPointer(SuperType.getAsOpaquePtr()); if (NumArgs) @@ -1763,88 +2368,115 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T, } ObjCMessageExpr::ObjCMessageExpr(QualType T, + ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, - Selector Sel, + Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) - : Expr(ObjCMessageExprClass, T, T->isDependentType(), - (T->isDependentType() || - hasAnyValueDependentArguments(Args, NumArgs))), + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), + T->isDependentType(), T->containsUnexpandedParameterPack()), NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0), SelectorOrMethod(reinterpret_cast(Method? Method : Sel.getAsOpaquePtr())), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { setReceiverPointer(Receiver); - if (NumArgs) - memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); + Expr **MyArgs = getArgs(); + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + MyArgs[I] = Args[I]; + } } ObjCMessageExpr::ObjCMessageExpr(QualType T, + ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) - : Expr(ObjCMessageExprClass, T, Receiver->isTypeDependent(), - (Receiver->isTypeDependent() || - hasAnyValueDependentArguments(Args, NumArgs))), + : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(), + Receiver->isTypeDependent(), + Receiver->containsUnexpandedParameterPack()), NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0), SelectorOrMethod(reinterpret_cast(Method? Method : Sel.getAsOpaquePtr())), - LBracLoc(LBracLoc), RBracLoc(RBracLoc) + SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) { setReceiverPointer(Receiver); - if (NumArgs) - memcpy(getArgs(), Args, NumArgs * sizeof(Expr *)); + Expr **MyArgs = getArgs(); + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (Args[I]->isValueDependent()) + ExprBits.ValueDependent = true; + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + MyArgs[I] = Args[I]; + } } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + NumArgs * sizeof(Expr *); void *Mem = Context.Allocate(Size, llvm::AlignOf::Alignment); - return new (Mem) ObjCMessageExpr(T, LBracLoc, SuperLoc, IsInstanceSuper, - SuperType, Sel, Method, Args, NumArgs, + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, SuperLoc, IsInstanceSuper, + SuperType, Sel, SelLoc, Method, Args,NumArgs, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + NumArgs * sizeof(Expr *); void *Mem = Context.Allocate(Size, llvm::AlignOf::Alignment); - return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args, - NumArgs, RBracLoc); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc, + Method, Args, NumArgs, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::Create(ASTContext &Context, QualType T, + ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, - Selector Sel, + Selector Sel, + SourceLocation SelLoc, ObjCMethodDecl *Method, Expr **Args, unsigned NumArgs, SourceLocation RBracLoc) { unsigned Size = sizeof(ObjCMessageExpr) + sizeof(void *) + NumArgs * sizeof(Expr *); void *Mem = Context.Allocate(Size, llvm::AlignOf::Alignment); - return new (Mem) ObjCMessageExpr(T, LBracLoc, Receiver, Sel, Method, Args, - NumArgs, RBracLoc); + return new (Mem) ObjCMessageExpr(T, VK, LBracLoc, Receiver, Sel, SelLoc, + Method, Args, NumArgs, RBracLoc); } ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, @@ -1854,7 +2486,23 @@ ObjCMessageExpr *ObjCMessageExpr::CreateEmpty(ASTContext &Context, void *Mem = Context.Allocate(Size, llvm::AlignOf::Alignment); return new (Mem) ObjCMessageExpr(EmptyShell(), NumArgs); } - + +SourceRange ObjCMessageExpr::getReceiverRange() const { + switch (getReceiverKind()) { + case Instance: + return getInstanceReceiver()->getSourceRange(); + + case Class: + return getClassReceiverTypeInfo()->getTypeLoc().getSourceRange(); + + case SuperInstance: + case SuperClass: + return getSuperLoc(); + } + + return SourceLocation(); +} + Selector ObjCMessageExpr::getSelector() const { if (HasMethod) return reinterpret_cast(SelectorOrMethod) @@ -1883,19 +2531,40 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const { break; case SuperClass: - if (const ObjCObjectPointerType *Iface - = getSuperType()->getAs()) - return Iface->getInterfaceDecl(); + if (const ObjCObjectType *Iface + = getSuperType()->getAs()) + return Iface->getInterface(); break; } return 0; } -bool ChooseExpr::isConditionTrue(ASTContext &C) const { +bool ChooseExpr::isConditionTrue(const ASTContext &C) const { return getCond()->EvaluateAsInt(C) != 0; } +ShuffleVectorExpr::ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr, + QualType Type, SourceLocation BLoc, + SourceLocation RP) + : Expr(ShuffleVectorExprClass, Type, VK_RValue, OK_Ordinary, + Type->isDependentType(), Type->isDependentType(), + Type->containsUnexpandedParameterPack()), + BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) +{ + SubExprs = new (C) Stmt*[nexpr]; + for (unsigned i = 0; i < nexpr; i++) { + if (args[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + SubExprs[i] = args[i]; + } +} + void ShuffleVectorExpr::setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs) { if (SubExprs) C.Deallocate(SubExprs); @@ -1926,13 +2595,15 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumIndexExprs, Expr *Init) : Expr(DesignatedInitExprClass, Ty, - Init->isTypeDependent(), Init->isValueDependent()), + Init->getValueKind(), Init->getObjectKind(), + Init->isTypeDependent(), Init->isValueDependent(), + Init->containsUnexpandedParameterPack()), EqualOrColonLoc(EqualOrColonLoc), GNUSyntax(GNUSyntax), NumDesignators(NumDesignators), NumSubExprs(NumIndexExprs + 1) { this->Designators = new (C) Designator[NumDesignators]; // Record the initializer itself. - child_iterator Child = child_begin(); + child_range Child = children(); *Child++ = Init; // Copy the designators and their subexpressions, computing @@ -1944,8 +2615,12 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, if (this->Designators[I].isArrayDesignator()) { // Compute type- and value-dependence. Expr *Index = IndexExprs[IndexIdx]; - ValueDependent = ValueDependent || - Index->isTypeDependent() || Index->isValueDependent(); + if (Index->isTypeDependent() || Index->isValueDependent()) + ExprBits.ValueDependent = true; + + // Propagate unexpanded parameter packs. + if (Index->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; // Copy the index expressions into permanent storage. *Child++ = IndexExprs[IndexIdx++]; @@ -1953,9 +2628,14 @@ DesignatedInitExpr::DesignatedInitExpr(ASTContext &C, QualType Ty, // Compute type- and value-dependence. Expr *Start = IndexExprs[IndexIdx]; Expr *End = IndexExprs[IndexIdx + 1]; - ValueDependent = ValueDependent || - Start->isTypeDependent() || Start->isValueDependent() || - End->isTypeDependent() || End->isValueDependent(); + if (Start->isTypeDependent() || Start->isValueDependent() || + End->isTypeDependent() || End->isValueDependent()) + ExprBits.ValueDependent = true; + + // Propagate unexpanded parameter packs. + if (Start->containsUnexpandedParameterPack() || + End->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; // Copy the start/end expressions into permanent storage. *Child++ = IndexExprs[IndexIdx++]; @@ -2066,14 +2746,30 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx, ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, unsigned nexprs, SourceLocation rparenloc) -: Expr(ParenListExprClass, QualType(), - hasAnyTypeDependentArguments(exprs, nexprs), - hasAnyValueDependentArguments(exprs, nexprs)), - NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, + false, false, false), + NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { Exprs = new (C) Stmt*[nexprs]; - for (unsigned i = 0; i != nexprs; ++i) + for (unsigned i = 0; i != nexprs; ++i) { + if (exprs[i]->isTypeDependent()) + ExprBits.TypeDependent = true; + if (exprs[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (exprs[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + Exprs[i] = exprs[i]; + } +} + +const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { + if (const ExprWithCleanups *ewc = dyn_cast(e)) + e = ewc->getSubExpr(); + e = cast(e)->getArg(0); + while (const ImplicitCastExpr *ice = dyn_cast(e)) + e = ice->getSubExpr(); + return cast(e); } //===----------------------------------------------------------------------===// @@ -2093,257 +2789,43 @@ const Expr* ConstExprIterator::operator->() const { return cast(*I); } // Child Iterators for iterating over subexpressions/substatements //===----------------------------------------------------------------------===// -// DeclRefExpr -Stmt::child_iterator DeclRefExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator DeclRefExpr::child_end() { return child_iterator(); } - -// ObjCIvarRefExpr -Stmt::child_iterator ObjCIvarRefExpr::child_begin() { return &Base; } -Stmt::child_iterator ObjCIvarRefExpr::child_end() { return &Base+1; } - -// ObjCPropertyRefExpr -Stmt::child_iterator ObjCPropertyRefExpr::child_begin() { return &Base; } -Stmt::child_iterator ObjCPropertyRefExpr::child_end() { return &Base+1; } - -// ObjCImplicitSetterGetterRefExpr -Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_begin() { - // If this is accessing a class member, skip that entry. - if (Base) return &Base; - return &Base+1; -} -Stmt::child_iterator ObjCImplicitSetterGetterRefExpr::child_end() { - return &Base+1; -} - -// ObjCSuperExpr -Stmt::child_iterator ObjCSuperExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator ObjCSuperExpr::child_end() { return child_iterator(); } - -// ObjCIsaExpr -Stmt::child_iterator ObjCIsaExpr::child_begin() { return &Base; } -Stmt::child_iterator ObjCIsaExpr::child_end() { return &Base+1; } - -// PredefinedExpr -Stmt::child_iterator PredefinedExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator PredefinedExpr::child_end() { return child_iterator(); } - -// IntegerLiteral -Stmt::child_iterator IntegerLiteral::child_begin() { return child_iterator(); } -Stmt::child_iterator IntegerLiteral::child_end() { return child_iterator(); } - -// CharacterLiteral -Stmt::child_iterator CharacterLiteral::child_begin() { return child_iterator();} -Stmt::child_iterator CharacterLiteral::child_end() { return child_iterator(); } - -// FloatingLiteral -Stmt::child_iterator FloatingLiteral::child_begin() { return child_iterator(); } -Stmt::child_iterator FloatingLiteral::child_end() { return child_iterator(); } - -// ImaginaryLiteral -Stmt::child_iterator ImaginaryLiteral::child_begin() { return &Val; } -Stmt::child_iterator ImaginaryLiteral::child_end() { return &Val+1; } - -// StringLiteral -Stmt::child_iterator StringLiteral::child_begin() { return child_iterator(); } -Stmt::child_iterator StringLiteral::child_end() { return child_iterator(); } - -// ParenExpr -Stmt::child_iterator ParenExpr::child_begin() { return &Val; } -Stmt::child_iterator ParenExpr::child_end() { return &Val+1; } - -// UnaryOperator -Stmt::child_iterator UnaryOperator::child_begin() { return &Val; } -Stmt::child_iterator UnaryOperator::child_end() { return &Val+1; } - -// OffsetOfExpr -Stmt::child_iterator OffsetOfExpr::child_begin() { - return reinterpret_cast (reinterpret_cast (this + 1) - + NumComps); -} -Stmt::child_iterator OffsetOfExpr::child_end() { - return child_iterator(&*child_begin() + NumExprs); -} - // SizeOfAlignOfExpr -Stmt::child_iterator SizeOfAlignOfExpr::child_begin() { +Stmt::child_range SizeOfAlignOfExpr::children() { // If this is of a type and the type is a VLA type (and not a typedef), the // size expression of the VLA needs to be treated as an executable expression. // Why isn't this weirdness documented better in StmtIterator? if (isArgumentType()) { - if (VariableArrayType* T = dyn_cast( + if (const VariableArrayType* T = dyn_cast( getArgumentType().getTypePtr())) - return child_iterator(T); - return child_iterator(); + return child_range(child_iterator(T), child_iterator()); + return child_range(); } - return child_iterator(&Argument.Ex); -} -Stmt::child_iterator SizeOfAlignOfExpr::child_end() { - if (isArgumentType()) - return child_iterator(); - return child_iterator(&Argument.Ex + 1); -} - -// ArraySubscriptExpr -Stmt::child_iterator ArraySubscriptExpr::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator ArraySubscriptExpr::child_end() { - return &SubExprs[0]+END_EXPR; -} - -// CallExpr -Stmt::child_iterator CallExpr::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator CallExpr::child_end() { - return &SubExprs[0]+NumArgs+ARGS_START; -} - -// MemberExpr -Stmt::child_iterator MemberExpr::child_begin() { return &Base; } -Stmt::child_iterator MemberExpr::child_end() { return &Base+1; } - -// ExtVectorElementExpr -Stmt::child_iterator ExtVectorElementExpr::child_begin() { return &Base; } -Stmt::child_iterator ExtVectorElementExpr::child_end() { return &Base+1; } - -// CompoundLiteralExpr -Stmt::child_iterator CompoundLiteralExpr::child_begin() { return &Init; } -Stmt::child_iterator CompoundLiteralExpr::child_end() { return &Init+1; } - -// CastExpr -Stmt::child_iterator CastExpr::child_begin() { return &Op; } -Stmt::child_iterator CastExpr::child_end() { return &Op+1; } - -// BinaryOperator -Stmt::child_iterator BinaryOperator::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator BinaryOperator::child_end() { - return &SubExprs[0]+END_EXPR; -} - -// ConditionalOperator -Stmt::child_iterator ConditionalOperator::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator ConditionalOperator::child_end() { - return &SubExprs[0]+END_EXPR; -} - -// AddrLabelExpr -Stmt::child_iterator AddrLabelExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator AddrLabelExpr::child_end() { return child_iterator(); } - -// StmtExpr -Stmt::child_iterator StmtExpr::child_begin() { return &SubStmt; } -Stmt::child_iterator StmtExpr::child_end() { return &SubStmt+1; } - -// TypesCompatibleExpr -Stmt::child_iterator TypesCompatibleExpr::child_begin() { - return child_iterator(); -} - -Stmt::child_iterator TypesCompatibleExpr::child_end() { - return child_iterator(); -} - -// ChooseExpr -Stmt::child_iterator ChooseExpr::child_begin() { return &SubExprs[0]; } -Stmt::child_iterator ChooseExpr::child_end() { return &SubExprs[0]+END_EXPR; } - -// GNUNullExpr -Stmt::child_iterator GNUNullExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator GNUNullExpr::child_end() { return child_iterator(); } - -// ShuffleVectorExpr -Stmt::child_iterator ShuffleVectorExpr::child_begin() { - return &SubExprs[0]; -} -Stmt::child_iterator ShuffleVectorExpr::child_end() { - return &SubExprs[0]+NumExprs; -} - -// VAArgExpr -Stmt::child_iterator VAArgExpr::child_begin() { return &Val; } -Stmt::child_iterator VAArgExpr::child_end() { return &Val+1; } - -// InitListExpr -Stmt::child_iterator InitListExpr::child_begin() { - return InitExprs.size() ? &InitExprs[0] : 0; -} -Stmt::child_iterator InitListExpr::child_end() { - return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0; -} - -// DesignatedInitExpr -Stmt::child_iterator DesignatedInitExpr::child_begin() { - char* Ptr = static_cast(static_cast(this)); - Ptr += sizeof(DesignatedInitExpr); - return reinterpret_cast(reinterpret_cast(Ptr)); -} -Stmt::child_iterator DesignatedInitExpr::child_end() { - return child_iterator(&*child_begin() + NumSubExprs); -} - -// ImplicitValueInitExpr -Stmt::child_iterator ImplicitValueInitExpr::child_begin() { - return child_iterator(); -} - -Stmt::child_iterator ImplicitValueInitExpr::child_end() { - return child_iterator(); -} - -// ParenListExpr -Stmt::child_iterator ParenListExpr::child_begin() { - return &Exprs[0]; -} -Stmt::child_iterator ParenListExpr::child_end() { - return &Exprs[0]+NumExprs; -} - -// ObjCStringLiteral -Stmt::child_iterator ObjCStringLiteral::child_begin() { - return &String; -} -Stmt::child_iterator ObjCStringLiteral::child_end() { - return &String+1; -} - -// ObjCEncodeExpr -Stmt::child_iterator ObjCEncodeExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator ObjCEncodeExpr::child_end() { return child_iterator(); } - -// ObjCSelectorExpr -Stmt::child_iterator ObjCSelectorExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator ObjCSelectorExpr::child_end() { - return child_iterator(); -} - -// ObjCProtocolExpr -Stmt::child_iterator ObjCProtocolExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator ObjCProtocolExpr::child_end() { - return child_iterator(); + return child_range(&Argument.Ex, &Argument.Ex + 1); } // ObjCMessageExpr -Stmt::child_iterator ObjCMessageExpr::child_begin() { +Stmt::child_range ObjCMessageExpr::children() { + Stmt **begin; if (getReceiverKind() == Instance) - return reinterpret_cast(this + 1); - return getArgs(); -} -Stmt::child_iterator ObjCMessageExpr::child_end() { - return getArgs() + getNumArgs(); + begin = reinterpret_cast(this + 1); + else + begin = reinterpret_cast(getArgs()); + return child_range(begin, + reinterpret_cast(getArgs() + getNumArgs())); } // Blocks -Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); } +BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, + SourceLocation l, bool ByRef, + bool constAdded) + : Expr(BlockDeclRefExprClass, t, VK, OK_Ordinary, false, false, + d->isParameterPack()), + D(d), Loc(l), IsByRef(ByRef), ConstQualAdded(constAdded) +{ + bool TypeDependent = false; + bool ValueDependent = false; + computeDeclRefDependence(D, getType(), TypeDependent, ValueDependent); + ExprBits.TypeDependent = TypeDependent; + ExprBits.ValueDependent = ValueDependent; +} -Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();} -Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 0a101300d8fa..28ff9fb57afc 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -29,57 +29,18 @@ QualType CXXTypeidExpr::getTypeOperand() const { .getUnqualifiedType(); } -// CXXTypeidExpr - has child iterators if the operand is an expression -Stmt::child_iterator CXXTypeidExpr::child_begin() { - return isTypeOperand() ? child_iterator() - : reinterpret_cast(&Operand); -} -Stmt::child_iterator CXXTypeidExpr::child_end() { - return isTypeOperand() ? child_iterator() - : reinterpret_cast(&Operand) + 1; -} - -// CXXBoolLiteralExpr -Stmt::child_iterator CXXBoolLiteralExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator CXXBoolLiteralExpr::child_end() { - return child_iterator(); -} - -// CXXNullPtrLiteralExpr -Stmt::child_iterator CXXNullPtrLiteralExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator CXXNullPtrLiteralExpr::child_end() { - return child_iterator(); -} - -// CXXThisExpr -Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); } -Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); } - -// CXXThrowExpr -Stmt::child_iterator CXXThrowExpr::child_begin() { return &Op; } -Stmt::child_iterator CXXThrowExpr::child_end() { - // If Op is 0, we are processing throw; which has no children. - return Op ? &Op+1 : &Op; -} - -// CXXDefaultArgExpr -Stmt::child_iterator CXXDefaultArgExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator CXXDefaultArgExpr::child_end() { - return child_iterator(); +QualType CXXUuidofExpr::getTypeOperand() const { + assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); + return Operand.get()->getType().getNonReferenceType() + .getUnqualifiedType(); } // CXXScalarValueInitExpr -Stmt::child_iterator CXXScalarValueInitExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator CXXScalarValueInitExpr::child_end() { - return child_iterator(); +SourceRange CXXScalarValueInitExpr::getSourceRange() const { + SourceLocation Start = RParenLoc; + if (TypeInfo) + Start = TypeInfo->getTypeLoc().getBeginLoc(); + return SourceRange(Start, RParenLoc); } // CXXNewExpr @@ -88,22 +49,44 @@ CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, - FunctionDecl *operatorDelete, QualType ty, - SourceLocation startLoc, SourceLocation endLoc) - : Expr(CXXNewExprClass, ty, ty->isDependentType(), ty->isDependentType()), - GlobalNew(globalNew), - Initializer(initializer), SubExprs(0), OperatorNew(operatorNew), + FunctionDecl *operatorDelete, + bool usualArrayDeleteWantsSize, QualType ty, + TypeSourceInfo *AllocatedTypeInfo, + SourceLocation startLoc, SourceLocation endLoc, + SourceLocation constructorLParen, + SourceLocation constructorRParen) + : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, + ty->isDependentType(), ty->isDependentType(), + ty->containsUnexpandedParameterPack()), + GlobalNew(globalNew), Initializer(initializer), + UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize), + SubExprs(0), OperatorNew(operatorNew), OperatorDelete(operatorDelete), Constructor(constructor), - TypeIdParens(TypeIdParens), StartLoc(startLoc), EndLoc(endLoc) { - + AllocatedTypeInfo(AllocatedTypeInfo), TypeIdParens(TypeIdParens), + StartLoc(startLoc), EndLoc(endLoc), ConstructorLParen(constructorLParen), + ConstructorRParen(constructorRParen) { AllocateArgsArray(C, arraySize != 0, numPlaceArgs, numConsArgs); unsigned i = 0; - if (Array) + if (Array) { + if (arraySize->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + SubExprs[i++] = arraySize; - for (unsigned j = 0; j < NumPlacementArgs; ++j) + } + + for (unsigned j = 0; j < NumPlacementArgs; ++j) { + if (placementArgs[j]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + SubExprs[i++] = placementArgs[j]; - for (unsigned j = 0; j < NumConstructorArgs; ++j) + } + + for (unsigned j = 0; j < NumConstructorArgs; ++j) { + if (constructorArgs[j]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + SubExprs[i++] = constructorArgs[j]; + } } void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, @@ -118,27 +101,59 @@ void CXXNewExpr::AllocateArgsArray(ASTContext &C, bool isArray, } -Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; } -Stmt::child_iterator CXXNewExpr::child_end() { - return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs(); -} - // CXXDeleteExpr -Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; } -Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; } +QualType CXXDeleteExpr::getDestroyedType() const { + const Expr *Arg = getArgument(); + while (const ImplicitCastExpr *ICE = dyn_cast(Arg)) { + if (ICE->getCastKind() != CK_UserDefinedConversion && + ICE->getType()->isVoidPointerType()) + Arg = ICE->getSubExpr(); + else + break; + } + // The type-to-delete may not be a pointer if it's a dependent type. + const QualType ArgType = Arg->getType(); -// CXXPseudoDestructorExpr -Stmt::child_iterator CXXPseudoDestructorExpr::child_begin() { return &Base; } -Stmt::child_iterator CXXPseudoDestructorExpr::child_end() { - return &Base + 1; + if (ArgType->isDependentType() && !ArgType->isPointerType()) + return QualType(); + + return ArgType->getAs()->getPointeeType(); } +// CXXPseudoDestructorExpr PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info) : Type(Info) { Location = Info->getTypeLoc().getLocalSourceRange().getBegin(); } +CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, + Expr *Base, bool isArrow, SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + TypeSourceInfo *ScopeType, SourceLocation ColonColonLoc, + SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) + : Expr(CXXPseudoDestructorExprClass, + Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, + FunctionProtoType::ExtProtoInfo())), + VK_RValue, OK_Ordinary, + /*isTypeDependent=*/(Base->isTypeDependent() || + (DestroyedType.getTypeSourceInfo() && + DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), + /*isValueDependent=*/Base->isValueDependent(), + // ContainsUnexpandedParameterPack + (Base->containsUnexpandedParameterPack() || + (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + (ScopeType && + ScopeType->getType()->containsUnexpandedParameterPack()) || + (DestroyedType.getTypeSourceInfo() && + DestroyedType.getTypeSourceInfo()->getType() + ->containsUnexpandedParameterPack()))), + Base(static_cast(Base)), IsArrow(isArrow), + OperatorLoc(OperatorLoc), Qualifier(Qualifier), + QualifierRange(QualifierRange), + ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), + DestroyedType(DestroyedType) { } + QualType CXXPseudoDestructorExpr::getDestroyedType() const { if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo()) return TInfo->getType(); @@ -156,7 +171,7 @@ SourceRange CXXPseudoDestructorExpr::getSourceRange() const { // UnresolvedLookupExpr UnresolvedLookupExpr * -UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, +UnresolvedLookupExpr::Create(ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -168,73 +183,94 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent, { void *Mem = C.Allocate(sizeof(UnresolvedLookupExpr) + ExplicitTemplateArgumentList::sizeFor(Args)); - UnresolvedLookupExpr *ULE - = new (Mem) UnresolvedLookupExpr(C, - Dependent ? C.DependentTy : C.OverloadTy, - Dependent, NamingClass, - Qualifier, QualifierRange, NameInfo, - ADL, - /*Overload*/ true, - /*ExplicitTemplateArgs*/ true, - Begin, End); - - reinterpret_cast(ULE+1)->initializeFrom(Args); - - return ULE; + return new (Mem) UnresolvedLookupExpr(C, NamingClass, + Qualifier, QualifierRange, NameInfo, + ADL, /*Overload*/ true, &Args, + Begin, End); } UnresolvedLookupExpr * -UnresolvedLookupExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { +UnresolvedLookupExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, + unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedLookupExpr); - if (NumTemplateArgs != 0) + if (HasExplicitTemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); - void *Mem = C.Allocate(size, llvm::alignof()); + void *Mem = C.Allocate(size, llvm::alignOf()); UnresolvedLookupExpr *E = new (Mem) UnresolvedLookupExpr(EmptyShell()); - E->HasExplicitTemplateArgs = NumTemplateArgs != 0; + E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; return E; } -OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, QualType T, - bool Dependent, NestedNameSpecifier *Qualifier, - SourceRange QRange, +OverloadExpr::OverloadExpr(StmtClass K, ASTContext &C, + NestedNameSpecifier *Qualifier, SourceRange QRange, const DeclarationNameInfo &NameInfo, - bool HasTemplateArgs, + const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) - : Expr(K, T, Dependent, Dependent), - Results(0), NumResults(0), NameInfo(NameInfo), Qualifier(Qualifier), - QualifierRange(QRange), HasExplicitTemplateArgs(HasTemplateArgs) + UnresolvedSetIterator End, + bool KnownDependent, + bool KnownContainsUnexpandedParameterPack) + : Expr(K, C.OverloadTy, VK_LValue, OK_Ordinary, KnownDependent, + KnownDependent, + (KnownContainsUnexpandedParameterPack || + NameInfo.containsUnexpandedParameterPack() || + (Qualifier && Qualifier->containsUnexpandedParameterPack()))), + Results(0), NumResults(End - Begin), NameInfo(NameInfo), + Qualifier(Qualifier), QualifierRange(QRange), + HasExplicitTemplateArgs(TemplateArgs != 0) { - initializeResults(C, Begin, End); -} - -void OverloadExpr::initializeResults(ASTContext &C, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - assert(Results == 0 && "Results already initialized!"); NumResults = End - Begin; if (NumResults) { + // Determine whether this expression is type-dependent. + for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) { + if ((*I)->getDeclContext()->isDependentContext() || + isa(*I)) { + ExprBits.TypeDependent = true; + ExprBits.ValueDependent = true; + } + } + Results = static_cast( C.Allocate(sizeof(DeclAccessPair) * NumResults, - llvm::alignof())); + llvm::alignOf())); memcpy(Results, &*Begin.getIterator(), NumResults * sizeof(DeclAccessPair)); } -} - -bool OverloadExpr::ComputeDependence(UnresolvedSetIterator Begin, - UnresolvedSetIterator End, - const TemplateArgumentListInfo *Args) { - for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I) - if ((*I)->getDeclContext()->isDependentContext()) - return true; + // If we have explicit template arguments, check for dependent + // template arguments and whether they contain any unexpanded pack + // expansions. + if (TemplateArgs) { + bool Dependent = false; + bool ContainsUnexpandedParameterPack = false; + getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent, + ContainsUnexpandedParameterPack); + + if (Dependent) { + ExprBits.TypeDependent = true; + ExprBits.ValueDependent = true; + } + if (ContainsUnexpandedParameterPack) + ExprBits.ContainsUnexpandedParameterPack = true; + } - if (Args && TemplateSpecializationType::anyDependentTemplateArguments(*Args)) - return true; + if (isTypeDependent()) + setType(C.DependentTy); +} - return false; +void OverloadExpr::initializeResults(ASTContext &C, + UnresolvedSetIterator Begin, + UnresolvedSetIterator End) { + assert(Results == 0 && "Results already initialized!"); + NumResults = End - Begin; + if (NumResults) { + Results = static_cast( + C.Allocate(sizeof(DeclAccessPair) * NumResults, + + llvm::alignOf())); + memcpy(Results, &*Begin.getIterator(), + NumResults * sizeof(DeclAccessPair)); + } } CXXRecordDecl *OverloadExpr::getNamingClass() const { @@ -244,21 +280,30 @@ CXXRecordDecl *OverloadExpr::getNamingClass() const { return cast(this)->getNamingClass(); } -Stmt::child_iterator UnresolvedLookupExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator UnresolvedLookupExpr::child_end() { - return child_iterator(); -} -// UnaryTypeTraitExpr -Stmt::child_iterator UnaryTypeTraitExpr::child_begin() { - return child_iterator(); -} -Stmt::child_iterator UnaryTypeTraitExpr::child_end() { - return child_iterator(); +// DependentScopeDeclRefExpr +DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *Args) + : Expr(DependentScopeDeclRefExprClass, T, VK_LValue, OK_Ordinary, + true, true, + (NameInfo.containsUnexpandedParameterPack() || + (Qualifier && Qualifier->containsUnexpandedParameterPack()))), + NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier), + HasExplicitTemplateArgs(Args != 0) +{ + if (Args) { + bool Dependent = true; + bool ContainsUnexpandedParameterPack + = ExprBits.ContainsUnexpandedParameterPack; + + reinterpret_cast(this+1) + ->initializeFrom(*Args, Dependent, ContainsUnexpandedParameterPack); + ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; + } } -// DependentScopeDeclRefExpr DependentScopeDeclRefExpr * DependentScopeDeclRefExpr::Create(ASTContext &C, NestedNameSpecifier *Qualifier, @@ -266,251 +311,46 @@ DependentScopeDeclRefExpr::Create(ASTContext &C, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args) { std::size_t size = sizeof(DependentScopeDeclRefExpr); - if (Args) size += ExplicitTemplateArgumentList::sizeFor(*Args); - void *Mem = C.Allocate(size); - - DependentScopeDeclRefExpr *DRE - = new (Mem) DependentScopeDeclRefExpr(C.DependentTy, - Qualifier, QualifierRange, - NameInfo, Args != 0); - if (Args) - reinterpret_cast(DRE+1) - ->initializeFrom(*Args); - - return DRE; + size += ExplicitTemplateArgumentList::sizeFor(*Args); + void *Mem = C.Allocate(size); + return new (Mem) DependentScopeDeclRefExpr(C.DependentTy, + Qualifier, QualifierRange, + NameInfo, Args); } DependentScopeDeclRefExpr * DependentScopeDeclRefExpr::CreateEmpty(ASTContext &C, + bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { std::size_t size = sizeof(DependentScopeDeclRefExpr); - if (NumTemplateArgs) + if (HasExplicitTemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); void *Mem = C.Allocate(size); - - return new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(), - DeclarationNameInfo(), - NumTemplateArgs != 0); -} - -StmtIterator DependentScopeDeclRefExpr::child_begin() { - return child_iterator(); + DependentScopeDeclRefExpr *E + = new (Mem) DependentScopeDeclRefExpr(QualType(), 0, SourceRange(), + DeclarationNameInfo(), 0); + E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; + return E; } -StmtIterator DependentScopeDeclRefExpr::child_end() { - return child_iterator(); -} +SourceRange CXXConstructExpr::getSourceRange() const { + if (ParenRange.isValid()) + return SourceRange(Loc, ParenRange.getEnd()); -bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const { - switch(UTT) { - default: assert(false && "Unknown type trait or not implemented"); - case UTT_IsPOD: return QueriedType->isPODType(); - case UTT_IsLiteral: return QueriedType->isLiteralType(); - case UTT_IsClass: // Fallthrough - case UTT_IsUnion: - if (const RecordType *Record = QueriedType->getAs()) { - bool Union = Record->getDecl()->isUnion(); - return UTT == UTT_IsUnion ? Union : !Union; - } - return false; - case UTT_IsEnum: return QueriedType->isEnumeralType(); - case UTT_IsPolymorphic: - if (const RecordType *Record = QueriedType->getAs()) { - // Type traits are only parsed in C++, so we've got CXXRecords. - return cast(Record->getDecl())->isPolymorphic(); - } - return false; - case UTT_IsAbstract: - if (const RecordType *RT = QueriedType->getAs()) - return cast(RT->getDecl())->isAbstract(); - return false; - case UTT_IsEmpty: - if (const RecordType *Record = QueriedType->getAs()) { - return !Record->getDecl()->isUnion() - && cast(Record->getDecl())->isEmpty(); - } - return false; - case UTT_HasTrivialConstructor: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If __is_pod (type) is true then the trait is true, else if type is - // a cv class or union type (or array thereof) with a trivial default - // constructor ([class.ctor]) then the trait is true, else it is false. - if (QueriedType->isPODType()) - return true; - if (const RecordType *RT = - C.getBaseElementType(QueriedType)->getAs()) - return cast(RT->getDecl())->hasTrivialConstructor(); - return false; - case UTT_HasTrivialCopy: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If __is_pod (type) is true or type is a reference type then - // the trait is true, else if type is a cv class or union type - // with a trivial copy constructor ([class.copy]) then the trait - // is true, else it is false. - if (QueriedType->isPODType() || QueriedType->isReferenceType()) - return true; - if (const RecordType *RT = QueriedType->getAs()) - return cast(RT->getDecl())->hasTrivialCopyConstructor(); - return false; - case UTT_HasTrivialAssign: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If type is const qualified or is a reference type then the - // trait is false. Otherwise if __is_pod (type) is true then the - // trait is true, else if type is a cv class or union type with - // a trivial copy assignment ([class.copy]) then the trait is - // true, else it is false. - // Note: the const and reference restrictions are interesting, - // given that const and reference members don't prevent a class - // from having a trivial copy assignment operator (but do cause - // errors if the copy assignment operator is actually used, q.v. - // [class.copy]p12). - - if (C.getBaseElementType(QueriedType).isConstQualified()) - return false; - if (QueriedType->isPODType()) - return true; - if (const RecordType *RT = QueriedType->getAs()) - return cast(RT->getDecl())->hasTrivialCopyAssignment(); - return false; - case UTT_HasTrivialDestructor: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If __is_pod (type) is true or type is a reference type - // then the trait is true, else if type is a cv class or union - // type (or array thereof) with a trivial destructor - // ([class.dtor]) then the trait is true, else it is - // false. - if (QueriedType->isPODType() || QueriedType->isReferenceType()) - return true; - if (const RecordType *RT = - C.getBaseElementType(QueriedType)->getAs()) - return cast(RT->getDecl())->hasTrivialDestructor(); - return false; - // TODO: Propagate nothrowness for implicitly declared special members. - case UTT_HasNothrowAssign: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If type is const qualified or is a reference type then the - // trait is false. Otherwise if __has_trivial_assign (type) - // is true then the trait is true, else if type is a cv class - // or union type with copy assignment operators that are known - // not to throw an exception then the trait is true, else it is - // false. - if (C.getBaseElementType(QueriedType).isConstQualified()) - return false; - if (QueriedType->isReferenceType()) - return false; - if (QueriedType->isPODType()) - return true; - if (const RecordType *RT = QueriedType->getAs()) { - CXXRecordDecl* RD = cast(RT->getDecl()); - if (RD->hasTrivialCopyAssignment()) - return true; - - bool FoundAssign = false; - bool AllNoThrow = true; - DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal); - DeclContext::lookup_const_iterator Op, OpEnd; - for (llvm::tie(Op, OpEnd) = RD->lookup(Name); - Op != OpEnd; ++Op) { - CXXMethodDecl *Operator = cast(*Op); - if (Operator->isCopyAssignmentOperator()) { - FoundAssign = true; - const FunctionProtoType *CPT - = Operator->getType()->getAs(); - if (!CPT->hasEmptyExceptionSpec()) { - AllNoThrow = false; - break; - } - } + SourceLocation End = Loc; + for (unsigned I = getNumArgs(); I > 0; --I) { + const Expr *Arg = getArg(I-1); + if (!Arg->isDefaultArgument()) { + SourceLocation NewEnd = Arg->getLocEnd(); + if (NewEnd.isValid()) { + End = NewEnd; + break; } - - return FoundAssign && AllNoThrow; } - return false; - case UTT_HasNothrowCopy: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If __has_trivial_copy (type) is true then the trait is true, else - // if type is a cv class or union type with copy constructors that are - // known not to throw an exception then the trait is true, else it is - // false. - if (QueriedType->isPODType() || QueriedType->isReferenceType()) - return true; - if (const RecordType *RT = QueriedType->getAs()) { - CXXRecordDecl *RD = cast(RT->getDecl()); - if (RD->hasTrivialCopyConstructor()) - return true; - - bool FoundConstructor = false; - bool AllNoThrow = true; - unsigned FoundTQs; - DeclarationName ConstructorName - = C.DeclarationNames.getCXXConstructorName( - C.getCanonicalType(QueriedType)); - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = RD->lookup(ConstructorName); - Con != ConEnd; ++Con) { - CXXConstructorDecl *Constructor = cast(*Con); - if (Constructor->isCopyConstructor(FoundTQs)) { - FoundConstructor = true; - const FunctionProtoType *CPT - = Constructor->getType()->getAs(); - if (!CPT->hasEmptyExceptionSpec()) { - AllNoThrow = false; - break; - } - } - } - - return FoundConstructor && AllNoThrow; - } - return false; - case UTT_HasNothrowConstructor: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If __has_trivial_constructor (type) is true then the trait is - // true, else if type is a cv class or union type (or array - // thereof) with a default constructor that is known not to - // throw an exception then the trait is true, else it is false. - if (QueriedType->isPODType()) - return true; - if (const RecordType *RT = - C.getBaseElementType(QueriedType)->getAs()) { - CXXRecordDecl *RD = cast(RT->getDecl()); - if (RD->hasTrivialConstructor()) - return true; - - if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) { - const FunctionProtoType *CPT - = Constructor->getType()->getAs(); - // TODO: check whether evaluating default arguments can throw. - // For now, we'll be conservative and assume that they can throw. - if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0) - return true; - } - } - return false; - case UTT_HasVirtualDestructor: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: - // If type is a class type with a virtual destructor ([class.dtor]) - // then the trait is true, else it is false. - if (const RecordType *Record = QueriedType->getAs()) { - CXXRecordDecl *RD = cast(Record->getDecl()); - if (CXXDestructorDecl *Destructor = RD->getDestructor()) - return Destructor->isVirtual(); - } - return false; } -} -SourceRange CXXConstructExpr::getSourceRange() const { - // FIXME: Should we know where the parentheses are, if there are any? - for (std::reverse_iterator I(&Args[NumArgs]), E(&Args[0]); I!=E;++I) { - // Ignore CXXDefaultExprs when computing the range, as they don't - // have a range. - if (!isa(*I)) - return SourceRange(Loc, (*I)->getLocEnd()); - } - - return SourceRange(Loc); + return SourceRange(Loc, End); } SourceRange CXXOperatorCallExpr::getSourceRange() const { @@ -546,6 +386,17 @@ Expr *CXXMemberCallExpr::getImplicitObjectArgument() { return 0; } +CXXRecordDecl *CXXMemberCallExpr::getRecordDecl() { + Expr* ThisArg = getImplicitObjectArgument(); + if (!ThisArg) + return 0; + + if (ThisArg->getType()->isAnyPointerType()) + return ThisArg->getType()->getPointeeType()->getAsCXXRecordDecl(); + + return ThisArg->getType()->getAsCXXRecordDecl(); +} + SourceRange CXXMemberCallExpr::getSourceRange() const { SourceLocation LocStart = getCallee()->getLocStart(); if (LocStart.isInvalid() && getNumArgs() > 0) @@ -572,15 +423,18 @@ const char *CXXNamedCastExpr::getCastName() const { } CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, - SourceLocation L) { + SourceLocation L, + SourceLocation RParenLoc) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXStaticCastExpr *E = - new (Buffer) CXXStaticCastExpr(T, K, Op, PathSize, WrittenTy, L); + new (Buffer) CXXStaticCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, + RParenLoc); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -593,15 +447,18 @@ CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C, } CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T, + ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, - SourceLocation L) { + SourceLocation L, + SourceLocation RParenLoc) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXDynamicCastExpr *E = - new (Buffer) CXXDynamicCastExpr(T, K, Op, PathSize, WrittenTy, L); + new (Buffer) CXXDynamicCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, + RParenLoc); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -614,14 +471,17 @@ CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C, } CXXReinterpretCastExpr * -CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, CastKind K, Expr *Op, +CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, + CastKind K, Expr *Op, const CXXCastPath *BasePath, - TypeSourceInfo *WrittenTy, SourceLocation L) { + TypeSourceInfo *WrittenTy, SourceLocation L, + SourceLocation RParenLoc) { unsigned PathSize = (BasePath ? BasePath->size() : 0); void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXReinterpretCastExpr *E = - new (Buffer) CXXReinterpretCastExpr(T, K, Op, PathSize, WrittenTy, L); + new (Buffer) CXXReinterpretCastExpr(T, VK, K, Op, PathSize, WrittenTy, L, + RParenLoc); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -633,10 +493,12 @@ CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) { return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize); } -CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, Expr *Op, +CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, + ExprValueKind VK, Expr *Op, TypeSourceInfo *WrittenTy, - SourceLocation L) { - return new (C) CXXConstCastExpr(T, Op, WrittenTy, L); + SourceLocation L, + SourceLocation RParenLoc) { + return new (C) CXXConstCastExpr(T, VK, Op, WrittenTy, L, RParenLoc); } CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) { @@ -644,7 +506,7 @@ CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) { } CXXFunctionalCastExpr * -CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, +CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, ExprValueKind VK, TypeSourceInfo *Written, SourceLocation L, CastKind K, Expr *Op, const CXXCastPath *BasePath, SourceLocation R) { @@ -652,7 +514,7 @@ CXXFunctionalCastExpr::Create(ASTContext &C, QualType T, void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr) + PathSize * sizeof(CXXBaseSpecifier*)); CXXFunctionalCastExpr *E = - new (Buffer) CXXFunctionalCastExpr(T, Written, L, K, Op, PathSize, R); + new (Buffer) CXXFunctionalCastExpr(T, VK, Written, L, K, Op, PathSize, R); if (PathSize) E->setCastPath(*BasePath); return E; } @@ -689,15 +551,22 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(ASTContext &C, CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, - QualType writtenTy, - SourceLocation tyBeginLoc, + TypeSourceInfo *Type, Expr **Args, unsigned NumArgs, - SourceLocation rParenLoc, + SourceRange parenRange, bool ZeroInitialization) - : CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, tyBeginLoc, - Cons, false, Args, NumArgs, ZeroInitialization), - TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) { + : CXXConstructExpr(C, CXXTemporaryObjectExprClass, + Type->getType().getNonReferenceType(), + Type->getTypeLoc().getBeginLoc(), + Cons, false, Args, NumArgs, ZeroInitialization, + CXXConstructExpr::CK_Complete, parenRange), + Type(Type) { +} + +SourceRange CXXTemporaryObjectExpr::getSourceRange() const { + return SourceRange(Type->getTypeLoc().getBeginLoc(), + getParenRange().getEnd()); } CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, @@ -705,10 +574,11 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool ZeroInitialization, - ConstructionKind ConstructKind) { + ConstructionKind ConstructKind, + SourceRange ParenRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, NumArgs, ZeroInitialization, - ConstructKind); + ConstructKind, ParenRange); } CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, @@ -716,31 +586,39 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, CXXConstructorDecl *D, bool elidable, Expr **args, unsigned numargs, bool ZeroInitialization, - ConstructionKind ConstructKind) -: Expr(SC, T, - T->isDependentType(), - (T->isDependentType() || - CallExpr::hasAnyValueDependentArguments(args, numargs))), - Constructor(D), Loc(Loc), Elidable(elidable), - ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), - Args(0), NumArgs(numargs) + ConstructionKind ConstructKind, + SourceRange ParenRange) + : Expr(SC, T, VK_RValue, OK_Ordinary, + T->isDependentType(), T->isDependentType(), + T->containsUnexpandedParameterPack()), + Constructor(D), Loc(Loc), ParenRange(ParenRange), Elidable(elidable), + ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), + Args(0), NumArgs(numargs) { if (NumArgs) { Args = new (C) Stmt*[NumArgs]; for (unsigned i = 0; i != NumArgs; ++i) { assert(args[i] && "NULL argument in CXXConstructExpr"); + + if (args[i]->isValueDependent()) + ExprBits.ValueDependent = true; + if (args[i]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + Args[i] = args[i]; } } } -CXXExprWithTemporaries::CXXExprWithTemporaries(ASTContext &C, - Expr *subexpr, - CXXTemporary **temps, - unsigned numtemps) - : Expr(CXXExprWithTemporariesClass, subexpr->getType(), - subexpr->isTypeDependent(), subexpr->isValueDependent()), +ExprWithCleanups::ExprWithCleanups(ASTContext &C, + Expr *subexpr, + CXXTemporary **temps, + unsigned numtemps) + : Expr(ExprWithCleanupsClass, subexpr->getType(), + subexpr->getValueKind(), subexpr->getObjectKind(), + subexpr->isTypeDependent(), subexpr->isValueDependent(), + subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr), Temps(0), NumTemps(0) { if (numtemps) { setNumTemporaries(C, numtemps); @@ -749,75 +627,53 @@ CXXExprWithTemporaries::CXXExprWithTemporaries(ASTContext &C, } } -void CXXExprWithTemporaries::setNumTemporaries(ASTContext &C, unsigned N) { +void ExprWithCleanups::setNumTemporaries(ASTContext &C, unsigned N) { assert(Temps == 0 && "Cannot resize with this"); NumTemps = N; Temps = new (C) CXXTemporary*[NumTemps]; } -CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C, - Expr *SubExpr, - CXXTemporary **Temps, - unsigned NumTemps) { - return new (C) CXXExprWithTemporaries(C, SubExpr, Temps, NumTemps); +ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, + Expr *SubExpr, + CXXTemporary **Temps, + unsigned NumTemps) { + return new (C) ExprWithCleanups(C, SubExpr, Temps, NumTemps); } -// CXXBindTemporaryExpr -Stmt::child_iterator CXXBindTemporaryExpr::child_begin() { - return &SubExpr; -} - -Stmt::child_iterator CXXBindTemporaryExpr::child_end() { - return &SubExpr + 1; -} - -// CXXConstructExpr -Stmt::child_iterator CXXConstructExpr::child_begin() { - return &Args[0]; -} -Stmt::child_iterator CXXConstructExpr::child_end() { - return &Args[0]+NumArgs; -} - -// CXXExprWithTemporaries -Stmt::child_iterator CXXExprWithTemporaries::child_begin() { - return &SubExpr; -} - -Stmt::child_iterator CXXExprWithTemporaries::child_end() { - return &SubExpr + 1; -} - -CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr( - SourceLocation TyBeginLoc, - QualType T, +CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) - : Expr(CXXUnresolvedConstructExprClass, T.getNonReferenceType(), - T->isDependentType(), true), - TyBeginLoc(TyBeginLoc), - Type(T), + : Expr(CXXUnresolvedConstructExprClass, + Type->getType().getNonReferenceType(), + VK_LValue, OK_Ordinary, + Type->getType()->isDependentType(), true, + Type->getType()->containsUnexpandedParameterPack()), + Type(Type), LParenLoc(LParenLoc), RParenLoc(RParenLoc), NumArgs(NumArgs) { Stmt **StoredArgs = reinterpret_cast(this + 1); - memcpy(StoredArgs, Args, sizeof(Expr *) * NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I]->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + StoredArgs[I] = Args[I]; + } } CXXUnresolvedConstructExpr * CXXUnresolvedConstructExpr::Create(ASTContext &C, - SourceLocation TyBegin, - QualType T, + TypeSourceInfo *Type, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc) { void *Mem = C.Allocate(sizeof(CXXUnresolvedConstructExpr) + sizeof(Expr *) * NumArgs); - return new (Mem) CXXUnresolvedConstructExpr(TyBegin, T, LParenLoc, + return new (Mem) CXXUnresolvedConstructExpr(Type, LParenLoc, Args, NumArgs, RParenLoc); } @@ -829,12 +685,8 @@ CXXUnresolvedConstructExpr::CreateEmpty(ASTContext &C, unsigned NumArgs) { return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs); } -Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() { - return child_iterator(reinterpret_cast(this + 1)); -} - -Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() { - return child_iterator(reinterpret_cast(this + 1) + NumArgs); +SourceRange CXXUnresolvedConstructExpr::getSourceRange() const { + return SourceRange(Type->getTypeLoc().getBeginLoc(), RParenLoc); } CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, @@ -846,17 +698,46 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs) - : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, + VK_LValue, OK_Ordinary, true, true, + ((Base && Base->containsUnexpandedParameterPack()) || + (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + MemberNameInfo.containsUnexpandedParameterPack())), Base(Base), BaseType(BaseType), IsArrow(IsArrow), HasExplicitTemplateArgs(TemplateArgs != 0), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), MemberNameInfo(MemberNameInfo) { - if (TemplateArgs) - getExplicitTemplateArgs().initializeFrom(*TemplateArgs); + if (TemplateArgs) { + bool Dependent = true; + bool ContainsUnexpandedParameterPack = false; + getExplicitTemplateArgs().initializeFrom(*TemplateArgs, Dependent, + ContainsUnexpandedParameterPack); + if (ContainsUnexpandedParameterPack) + ExprBits.ContainsUnexpandedParameterPack = true; + } } +CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C, + Expr *Base, QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo) + : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, + VK_LValue, OK_Ordinary, true, true, + ((Base && Base->containsUnexpandedParameterPack()) || + (Qualifier && Qualifier->containsUnexpandedParameterPack()) || + MemberNameInfo.containsUnexpandedParameterPack())), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), + Qualifier(Qualifier), QualifierRange(QualifierRange), + FirstQualifierFoundInScope(FirstQualifierFoundInScope), + MemberNameInfo(MemberNameInfo) { } + CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, @@ -877,7 +758,7 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, if (TemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); - void *Mem = C.Allocate(size, llvm::alignof()); + void *Mem = C.Allocate(size, llvm::alignOf()); return new (Mem) CXXDependentScopeMemberExpr(C, Base, BaseType, IsArrow, OperatorLoc, Qualifier, QualifierRange, @@ -887,8 +768,9 @@ CXXDependentScopeMemberExpr::Create(ASTContext &C, CXXDependentScopeMemberExpr * CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, + bool HasExplicitTemplateArgs, unsigned NumTemplateArgs) { - if (NumTemplateArgs == 0) + if (!HasExplicitTemplateArgs) return new (C) CXXDependentScopeMemberExpr(C, 0, QualType(), 0, SourceLocation(), 0, SourceRange(), 0, @@ -896,7 +778,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, std::size_t size = sizeof(CXXDependentScopeMemberExpr) + ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); - void *Mem = C.Allocate(size, llvm::alignof()); + void *Mem = C.Allocate(size, llvm::alignOf()); CXXDependentScopeMemberExpr *E = new (Mem) CXXDependentScopeMemberExpr(C, 0, QualType(), 0, SourceLocation(), 0, @@ -906,18 +788,7 @@ CXXDependentScopeMemberExpr::CreateEmpty(ASTContext &C, return E; } -Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() { - return child_iterator(&Base); -} - -Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() { - if (isImplicitAccess()) - return child_iterator(&Base); - return child_iterator(&Base + 1); -} - -UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, QualType T, - bool Dependent, +UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, @@ -928,17 +799,21 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C, QualType T, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedMemberExprClass, C, T, Dependent, + : OverloadExpr(UnresolvedMemberExprClass, C, Qualifier, QualifierRange, MemberNameInfo, - TemplateArgs != 0, Begin, End), + TemplateArgs, Begin, End, + // Dependent + ((Base && Base->isTypeDependent()) || + BaseType->isDependentType()), + // Contains unexpanded parameter pack + ((Base && Base->containsUnexpandedParameterPack()) || + BaseType->containsUnexpandedParameterPack())), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing), Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) { - if (TemplateArgs) - getExplicitTemplateArgs().initializeFrom(*TemplateArgs); } UnresolvedMemberExpr * -UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, +UnresolvedMemberExpr::Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -952,23 +827,23 @@ UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent, if (TemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs); - void *Mem = C.Allocate(size, llvm::alignof()); + void *Mem = C.Allocate(size, llvm::alignOf()); return new (Mem) UnresolvedMemberExpr(C, - Dependent ? C.DependentTy : C.OverloadTy, - Dependent, HasUnresolvedUsing, Base, BaseType, + HasUnresolvedUsing, Base, BaseType, IsArrow, OperatorLoc, Qualifier, QualifierRange, MemberNameInfo, TemplateArgs, Begin, End); } UnresolvedMemberExpr * -UnresolvedMemberExpr::CreateEmpty(ASTContext &C, unsigned NumTemplateArgs) { +UnresolvedMemberExpr::CreateEmpty(ASTContext &C, bool HasExplicitTemplateArgs, + unsigned NumTemplateArgs) { std::size_t size = sizeof(UnresolvedMemberExpr); - if (NumTemplateArgs != 0) + if (HasExplicitTemplateArgs) size += ExplicitTemplateArgumentList::sizeFor(NumTemplateArgs); - void *Mem = C.Allocate(size, llvm::alignof()); + void *Mem = C.Allocate(size, llvm::alignOf()); UnresolvedMemberExpr *E = new (Mem) UnresolvedMemberExpr(EmptyShell()); - E->HasExplicitTemplateArgs = NumTemplateArgs != 0; + E->HasExplicitTemplateArgs = HasExplicitTemplateArgs; return E; } @@ -980,7 +855,7 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { // lookup. CXXRecordDecl *Record = 0; if (getQualifier()) { - Type *T = getQualifier()->getAsType(); + const Type *T = getQualifier()->getAsType(); assert(T && "qualifier in member expression does not name type"); Record = T->getAsCXXRecordDecl(); assert(Record && "qualifier in member expression does not name record"); @@ -1001,12 +876,18 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const { return Record; } -Stmt::child_iterator UnresolvedMemberExpr::child_begin() { - return child_iterator(&Base); -} +SubstNonTypeTemplateParmPackExpr:: +SubstNonTypeTemplateParmPackExpr(QualType T, + NonTypeTemplateParmDecl *Param, + SourceLocation NameLoc, + const TemplateArgument &ArgPack) + : Expr(SubstNonTypeTemplateParmPackExprClass, T, VK_RValue, OK_Ordinary, + true, false, true), + Param(Param), Arguments(ArgPack.pack_begin()), + NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { } -Stmt::child_iterator UnresolvedMemberExpr::child_end() { - if (isImplicitAccess()) - return child_iterator(&Base); - return child_iterator(&Base + 1); +TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const { + return TemplateArgument(Arguments, NumArguments); } + + diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index d7e38ebbf5c9..890898a985e8 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -29,10 +29,27 @@ static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T); static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E); static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E); static Cl::Kinds ClassifyConditional(ASTContext &Ctx, - const ConditionalOperator *E); + const Expr *trueExpr, + const Expr *falseExpr); static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, Cl::Kinds Kind, SourceLocation &Loc); +static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang, + const Expr *E, + ExprValueKind Kind) { + switch (Kind) { + case VK_RValue: + return Lang.CPlusPlus && E->getType()->isRecordType() ? + Cl::CL_ClassTemporary : Cl::CL_PRValue; + case VK_LValue: + return Cl::CL_LValue; + case VK_XValue: + return Cl::CL_XValue; + } + llvm_unreachable("Invalid value category of implicit cast."); + return Cl::CL_PRValue; +} + Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { assert(!TR->isReferenceType() && "Expressions can't have reference type."); @@ -48,6 +65,19 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { kind = Cl::CL_Void; } + // Enable this assertion for testing. + switch (kind) { + case Cl::CL_LValue: assert(getValueKind() == VK_LValue); break; + case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break; + case Cl::CL_Function: + case Cl::CL_Void: + case Cl::CL_DuplicateVectorComponents: + case Cl::CL_MemberFunction: + case Cl::CL_SubObjCPropertySetting: + case Cl::CL_ClassTemporary: + case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break; + } + Cl::ModifiableType modifiable = Cl::CM_Untested; if (Loc) modifiable = IsModifiable(Ctx, this, kind, *Loc); @@ -60,7 +90,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { switch (E->getStmtClass()) { // First come the expressions that are always lvalues, unconditionally. - + case Stmt::NoStmtClass: +#define ABSTRACT_STMT(Kind) +#define STMT(Kind, Base) case Expr::Kind##Class: +#define EXPR(Kind, Base) +#include "clang/AST/StmtNodes.inc" + llvm_unreachable("cannot classify a statement"); + break; case Expr::ObjCIsaExprClass: // C++ [expr.prim.general]p1: A string literal is an lvalue. case Expr::StringLiteralClass: @@ -70,20 +106,56 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::PredefinedExprClass: // Property references are lvalues case Expr::ObjCPropertyRefExprClass: - case Expr::ObjCImplicitSetterGetterRefExprClass: // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of... case Expr::CXXTypeidExprClass: // Unresolved lookups get classified as lvalues. // FIXME: Is this wise? Should they get their own kind? case Expr::UnresolvedLookupExprClass: case Expr::UnresolvedMemberExprClass: + case Expr::CXXDependentScopeMemberExprClass: + case Expr::CXXUnresolvedConstructExprClass: + case Expr::DependentScopeDeclRefExprClass: // ObjC instance variables are lvalues // FIXME: ObjC++0x might have different rules case Expr::ObjCIvarRefExprClass: + return Cl::CL_LValue; // C99 6.5.2.5p5 says that compound literals are lvalues. - // FIXME: C++ might have a different opinion. + // In C++, they're class temporaries. case Expr::CompoundLiteralExprClass: - return Cl::CL_LValue; + return Ctx.getLangOptions().CPlusPlus? Cl::CL_ClassTemporary + : Cl::CL_LValue; + + // Expressions that are prvalues. + case Expr::CXXBoolLiteralExprClass: + case Expr::CXXPseudoDestructorExprClass: + case Expr::SizeOfAlignOfExprClass: + case Expr::CXXNewExprClass: + case Expr::CXXThisExprClass: + case Expr::CXXNullPtrLiteralExprClass: + case Expr::ImaginaryLiteralClass: + case Expr::GNUNullExprClass: + case Expr::OffsetOfExprClass: + case Expr::CXXThrowExprClass: + case Expr::ShuffleVectorExprClass: + case Expr::IntegerLiteralClass: + case Expr::CharacterLiteralClass: + case Expr::AddrLabelExprClass: + case Expr::CXXDeleteExprClass: + case Expr::ImplicitValueInitExprClass: + case Expr::BlockExprClass: + case Expr::FloatingLiteralClass: + case Expr::CXXNoexceptExprClass: + case Expr::CXXScalarValueInitExprClass: + case Expr::UnaryTypeTraitExprClass: + case Expr::BinaryTypeTraitExprClass: + case Expr::ObjCSelectorExprClass: + case Expr::ObjCProtocolExprClass: + case Expr::ObjCStringLiteralClass: + case Expr::ParenListExprClass: + case Expr::InitListExprClass: + case Expr::SizeOfPackExprClass: + case Expr::SubstNonTypeTemplateParmPackExprClass: + return Cl::CL_PRValue; // Next come the complicated cases. @@ -115,11 +187,22 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_LValue; // GNU extensions, simply look through them. - case UO_Real: - case UO_Imag: case UO_Extension: return ClassifyInternal(Ctx, cast(E)->getSubExpr()); + // Treat _Real and _Imag basically as if they were member + // expressions: l-value only if the operand is a true l-value. + case UO_Real: + case UO_Imag: { + const Expr *Op = cast(E)->getSubExpr()->IgnoreParens(); + Cl::Kinds K = ClassifyInternal(Ctx, Op); + if (K != Cl::CL_LValue) return K; + + if (isa(Op)) + return Cl::CL_SubObjCPropertySetting; + return Cl::CL_LValue; + } + // C++ [expr.pre.incr]p1: The result is the updated operand; it is an // lvalue, [...] // Not so in C. @@ -131,19 +214,15 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_PRValue; } + case Expr::OpaqueValueExprClass: + return ClassifyExprValueKind(Lang, E, + cast(E)->getValueKind()); + // Implicit casts are lvalues if they're lvalue casts. Other than that, we // only specifically record class temporaries. case Expr::ImplicitCastExprClass: - switch (cast(E)->getValueKind()) { - case VK_RValue: - return Lang.CPlusPlus && E->getType()->isRecordType() ? - Cl::CL_ClassTemporary : Cl::CL_PRValue; - case VK_LValue: - return Cl::CL_LValue; - case VK_XValue: - return Cl::CL_XValue; - } - llvm_unreachable("Invalid value category of implicit cast."); + return ClassifyExprValueKind(Lang, E, + cast(E)->getValueKind()); // C++ [expr.prim.general]p4: The presence of parentheses does not affect // whether the expression is an lvalue. @@ -160,6 +239,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: case Expr::CXXMemberCallExprClass: + case Expr::CUDAKernelCallExprClass: return ClassifyUnnamed(Ctx, cast(E)->getCallReturnType()); // __builtin_choose_expr is equivalent to the chosen expression. @@ -180,9 +260,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXBindTemporaryExprClass: return ClassifyInternal(Ctx, cast(E)->getSubExpr()); - // And the temporary lifetime guard. - case Expr::CXXExprWithTemporariesClass: - return ClassifyInternal(Ctx, cast(E)->getSubExpr()); + // And the cleanups guard. + case Expr::ExprWithCleanupsClass: + return ClassifyInternal(Ctx, cast(E)->getSubExpr()); // Casts depend completely on the target type. All casts work the same. case Expr::CStyleCastExprClass: @@ -195,10 +275,18 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { if (!Lang.CPlusPlus) return Cl::CL_PRValue; return ClassifyUnnamed(Ctx, cast(E)->getTypeAsWritten()); - case Expr::ConditionalOperatorClass: + case Expr::BinaryConditionalOperatorClass: { + if (!Lang.CPlusPlus) return Cl::CL_PRValue; + const BinaryConditionalOperator *co = cast(E); + return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); + } + + case Expr::ConditionalOperatorClass: { // Once again, only C++ is interesting. if (!Lang.CPlusPlus) return Cl::CL_PRValue; - return ClassifyConditional(Ctx, cast(E)); + const ConditionalOperator *co = cast(E); + return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); + } // ObjC message sends are effectively function calls, if the target function // is known. @@ -207,17 +295,35 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { cast(E)->getMethodDecl()) { return ClassifyUnnamed(Ctx, Method->getResultType()); } - + return Cl::CL_PRValue; + // Some C++ expressions are always class temporaries. case Expr::CXXConstructExprClass: case Expr::CXXTemporaryObjectExprClass: - case Expr::CXXScalarValueInitExprClass: return Cl::CL_ClassTemporary; - // Everything we haven't handled is a prvalue. - default: + case Expr::VAArgExprClass: + return ClassifyUnnamed(Ctx, E->getType()); + + case Expr::DesignatedInitExprClass: + return ClassifyInternal(Ctx, cast(E)->getInit()); + + case Expr::StmtExprClass: { + const CompoundStmt *S = cast(E)->getSubStmt(); + if (const Expr *LastExpr = dyn_cast_or_null(S->body_back())) + return ClassifyUnnamed(Ctx, LastExpr->getType()); return Cl::CL_PRValue; } + + case Expr::CXXUuidofExprClass: + return Cl::CL_LValue; + + case Expr::PackExpansionExprClass: + return ClassifyInternal(Ctx, cast(E)->getPattern()); + } + + llvm_unreachable("unhandled expression kind in classification"); + return Cl::CL_LValue; } /// ClassifyDecl - Return the classification of an expression referencing the @@ -239,6 +345,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { islvalue = NTTParm->getType()->isReferenceType(); else islvalue = isa(D) || isa(D) || + isa(D) || (Ctx.getLangOptions().CPlusPlus && (isa(D) || isa(D))); @@ -274,9 +381,8 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { if (E->isArrow()) return Cl::CL_LValue; // ObjC property accesses are not lvalues, but get special treatment. - Expr *Base = E->getBase(); - if (isa(Base) || - isa(Base)) + Expr *Base = E->getBase()->IgnoreParens(); + if (isa(Base)) return Cl::CL_SubObjCPropertySetting; return ClassifyInternal(Ctx, Base); } @@ -301,6 +407,9 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { // *E1 is an lvalue if (E->isArrow()) return Cl::CL_LValue; + Expr *Base = E->getBase()->IgnoreParenImpCasts(); + if (isa(Base)) + return Cl::CL_SubObjCPropertySetting; return ClassifyInternal(Ctx, E->getBase()); } @@ -320,8 +429,10 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { assert(Ctx.getLangOptions().CPlusPlus && "This is only relevant for C++."); // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand. + // Except we override this for writes to ObjC properties. if (E->isAssignmentOp()) - return Cl::CL_LValue; + return (E->getLHS()->getObjectKind() == OK_ObjCProperty + ? Cl::CL_PRValue : Cl::CL_LValue); // C++ [expr.comma]p1: the result is of the same value category as its right // operand, [...]. @@ -345,13 +456,11 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { return Cl::CL_PRValue; } -static Cl::Kinds ClassifyConditional(ASTContext &Ctx, - const ConditionalOperator *E) { +static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True, + const Expr *False) { assert(Ctx.getLangOptions().CPlusPlus && "This is only relevant for C++."); - Expr *True = E->getTrueExpr(); - Expr *False = E->getFalseExpr(); // C++ [expr.cond]p2 // If either the second or the third operand has type (cv) void, [...] // the result [...] is a prvalue. @@ -375,9 +484,10 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, if (Kind == Cl::CL_PRValue) { // For the sake of better diagnostics, we want to specifically recognize // use of the GCC cast-as-lvalue extension. - if (const CStyleCastExpr *CE = dyn_cast(E->IgnoreParens())){ - if (CE->getSubExpr()->Classify(Ctx).isLValue()) { - Loc = CE->getLParenLoc(); + if (const ExplicitCastExpr *CE = + dyn_cast(E->IgnoreParens())) { + if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) { + Loc = CE->getExprLoc(); return Cl::CM_LValueCast; } } @@ -401,9 +511,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Assignment to a property in ObjC is an implicit setter access. But a // setter might not exist. - if (const ObjCImplicitSetterGetterRefExpr *Expr = - dyn_cast(E)) { - if (Expr->getSetterMethod() == 0) + if (const ObjCPropertyRefExpr *Expr = dyn_cast(E)) { + if (Expr->isImplicitProperty() && Expr->getImplicitPropertySetter() == 0) return Cl::CM_NoSetterProperty; } @@ -420,7 +529,8 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, // Records with any const fields (recursively) are not modifiable. if (const RecordType *R = CT->getAs()) { - assert(!Ctx.getLangOptions().CPlusPlus && + assert((E->getObjectKind() == OK_ObjCProperty || + !Ctx.getLangOptions().CPlusPlus) && "C++ struct assignment should be resolved by the " "copy assignment operator."); if (R->hasConstFields()) @@ -430,7 +540,7 @@ static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, return Cl::CM_Modifiable; } -Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { +Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const { Classification VC = Classify(Ctx); switch (VC.getKind()) { case Cl::CL_LValue: return LV_Valid; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7347f5a43e17..656bb99df98e 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -43,12 +43,20 @@ using llvm::APFloat; /// evaluate the expression regardless of what the RHS is, but C only allows /// certain things in certain situations. struct EvalInfo { - ASTContext &Ctx; + const ASTContext &Ctx; /// EvalResult - Contains information about the evaluation. Expr::EvalResult &EvalResult; - EvalInfo(ASTContext &ctx, Expr::EvalResult& evalresult) + llvm::DenseMap OpaqueValues; + const APValue *getOpaqueValue(const OpaqueValueExpr *e) { + llvm::DenseMap::iterator + i = OpaqueValues.find(e); + if (i == OpaqueValues.end()) return 0; + return &i->second; + } + + EvalInfo(const ASTContext &ctx, Expr::EvalResult& evalresult) : Ctx(ctx), EvalResult(evalresult) {} }; @@ -73,12 +81,24 @@ namespace { APSInt &getComplexIntReal() { return IntReal; } APSInt &getComplexIntImag() { return IntImag; } - void moveInto(APValue &v) { + void moveInto(APValue &v) const { if (isComplexFloat()) v = APValue(FloatReal, FloatImag); else v = APValue(IntReal, IntImag); } + void setFrom(const APValue &v) { + assert(v.isComplexFloat() || v.isComplexInt()); + if (v.isComplexFloat()) { + makeComplexFloat(); + FloatReal = v.getComplexFloatReal(); + FloatImag = v.getComplexFloatImag(); + } else { + makeComplexInt(); + IntReal = v.getComplexIntReal(); + IntImag = v.getComplexIntImag(); + } + } }; struct LValue { @@ -88,12 +108,18 @@ namespace { Expr *getLValueBase() { return Base; } CharUnits getLValueOffset() { return Offset; } - void moveInto(APValue &v) { + void moveInto(APValue &v) const { v = APValue(Base, Offset); } + void setFrom(const APValue &v) { + assert(v.isLValue()); + Base = v.getLValueBase(); + Offset = v.getLValueOffset(); + } }; } +static bool Evaluate(EvalInfo &info, const Expr *E); static bool EvaluateLValue(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluatePointer(const Expr *E, LValue &Result, EvalInfo &Info); static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info); @@ -192,7 +218,7 @@ static bool HandleConversionToBool(const Expr* E, bool& Result, } static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, - APFloat &Value, ASTContext &Ctx) { + APFloat &Value, const ASTContext &Ctx) { unsigned DestWidth = Ctx.getIntWidth(DestType); // Determine whether we are converting to unsigned or signed. bool DestSigned = DestType->isSignedIntegerType(); @@ -206,7 +232,7 @@ static APSInt HandleFloatToIntCast(QualType DestType, QualType SrcType, } static APFloat HandleFloatToFloatCast(QualType DestType, QualType SrcType, - APFloat &Value, ASTContext &Ctx) { + APFloat &Value, const ASTContext &Ctx) { bool ignored; APFloat Result = Value; Result.convert(Ctx.getFloatTypeSemantics(DestType), @@ -215,18 +241,18 @@ static APFloat HandleFloatToFloatCast(QualType DestType, QualType SrcType, } static APSInt HandleIntToIntCast(QualType DestType, QualType SrcType, - APSInt &Value, ASTContext &Ctx) { + APSInt &Value, const ASTContext &Ctx) { unsigned DestWidth = Ctx.getIntWidth(DestType); APSInt Result = Value; // Figure out if this is a truncate, extend or noop cast. // If the input is signed, do a sign extend, noop, or truncate. - Result.extOrTrunc(DestWidth); + Result = Result.extOrTrunc(DestWidth); Result.setIsUnsigned(DestType->isUnsignedIntegerType()); return Result; } static APFloat HandleIntToFloatCast(QualType DestType, QualType SrcType, - APSInt &Value, ASTContext &Ctx) { + APSInt &Value, const ASTContext &Ctx) { APFloat Result(Ctx.getFloatTypeSemantics(DestType), 1); Result.convertFromAPInt(Value, Value.isSigned(), @@ -291,8 +317,34 @@ public: if (Visit(E->getInit(i))) return true; return false; } + + bool VisitSizeOfPackExpr(SizeOfPackExpr *) { return false; } }; +class OpaqueValueEvaluation { + EvalInfo &info; + OpaqueValueExpr *opaqueValue; + +public: + OpaqueValueEvaluation(EvalInfo &info, OpaqueValueExpr *opaqueValue, + Expr *value) + : info(info), opaqueValue(opaqueValue) { + + // If evaluation fails, fail immediately. + if (!Evaluate(info, value)) { + this->opaqueValue = 0; + return; + } + info.OpaqueValues[opaqueValue] = info.EvalResult.Val; + } + + bool hasError() const { return opaqueValue == 0; } + + ~OpaqueValueEvaluation() { + if (opaqueValue) info.OpaqueValues.erase(opaqueValue); + } +}; + } // end anonymous namespace //===----------------------------------------------------------------------===// @@ -402,7 +454,7 @@ bool LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { break; } - Result.Offset += CharUnits::fromQuantity(RL.getFieldOffset(i) / 8); + Result.Offset += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i)); return true; } @@ -460,17 +512,20 @@ public: { return Success(E); } bool VisitCallExpr(CallExpr *E); bool VisitBlockExpr(BlockExpr *E) { - if (!E->hasBlockDeclRefExprs()) + if (!E->getBlockDecl()->hasCaptures()) return Success(E); return false; } bool VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { return Success((Expr*)0); } + bool VisitBinaryConditionalOperator(BinaryConditionalOperator *E); bool VisitConditionalOperator(ConditionalOperator *E); bool VisitChooseExpr(ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } bool VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { return Success((Expr*)0); } + + bool VisitOpaqueValueExpr(OpaqueValueExpr *E); // FIXME: Missing: @protocol, @selector }; } // end anonymous namespace @@ -532,35 +587,6 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { default: break; - case CK_Unknown: { - // FIXME: The handling for CK_Unknown is ugly/shouldn't be necessary! - - // Check for pointer->pointer cast - if (SubExpr->getType()->isPointerType() || - SubExpr->getType()->isObjCObjectPointerType() || - SubExpr->getType()->isNullPtrType() || - SubExpr->getType()->isBlockPointerType()) - return Visit(SubExpr); - - if (SubExpr->getType()->isIntegralOrEnumerationType()) { - APValue Value; - if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) - break; - - if (Value.isInt()) { - Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); - Result.Base = 0; - Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue()); - return true; - } else { - Result.Base = Value.getLValueBase(); - Result.Offset = Value.getLValueOffset(); - return true; - } - } - break; - } - case CK_NoOp: case CK_BitCast: case CK_LValueBitCast: @@ -568,13 +594,54 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) { case CK_AnyPointerToBlockPointerCast: return Visit(SubExpr); + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: { + LValue BaseLV; + if (!EvaluatePointer(E->getSubExpr(), BaseLV, Info)) + return false; + + // Now figure out the necessary offset to add to the baseLV to get from + // the derived class to the base class. + CharUnits Offset = CharUnits::Zero(); + + QualType Ty = E->getSubExpr()->getType(); + const CXXRecordDecl *DerivedDecl = + Ty->getAs()->getPointeeType()->getAsCXXRecordDecl(); + + for (CastExpr::path_const_iterator PathI = E->path_begin(), + PathE = E->path_end(); PathI != PathE; ++PathI) { + const CXXBaseSpecifier *Base = *PathI; + + // FIXME: If the base is virtual, we'd need to determine the type of the + // most derived class and we don't support that right now. + if (Base->isVirtual()) + return false; + + const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl(); + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl); + + Offset += Layout.getBaseClassOffset(BaseDecl); + DerivedDecl = BaseDecl; + } + + Result.Base = BaseLV.getLValueBase(); + Result.Offset = BaseLV.getLValueOffset() + Offset; + return true; + } + + case CK_NullToPointer: { + Result.Base = 0; + Result.Offset = CharUnits::Zero(); + return true; + } + case CK_IntegralToPointer: { APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) break; if (Value.isInt()) { - Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); + Value.getInt() = Value.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType())); Result.Base = 0; Result.Offset = CharUnits::fromQuantity(Value.getInt().getZExtValue()); return true; @@ -602,6 +669,26 @@ bool PointerExprEvaluator::VisitCallExpr(CallExpr *E) { return false; } +bool PointerExprEvaluator::VisitOpaqueValueExpr(OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) + return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); + Result.setFrom(*value); + return true; +} + +bool PointerExprEvaluator:: +VisitBinaryConditionalOperator(BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool PointerExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { bool BoolResult; if (!HandleConversionToBool(E->getCond(), BoolResult, Info)) @@ -718,8 +805,7 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { llvm::SmallVector Elts; for (unsigned i = 0; i != NElts; ++i) { - APSInt Tmp = Init; - Tmp.extOrTrunc(EltWidth); + APSInt Tmp = Init.extOrTrunc(EltWidth); if (EltTy->isIntegerType()) Elts.push_back(APValue(Tmp)); @@ -898,15 +984,14 @@ public: bool VisitCharacterLiteral(const CharacterLiteral *E) { return Success(E->getValue(), E); } - bool VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) { - // Per gcc docs "this built-in function ignores top level - // qualifiers". We need to use the canonical version to properly - // be able to strip CRV qualifiers from the type. - QualType T0 = Info.Ctx.getCanonicalType(E->getArgType1()); - QualType T1 = Info.Ctx.getCanonicalType(E->getArgType2()); - return Success(Info.Ctx.typesAreCompatible(T0.getUnqualifiedType(), - T1.getUnqualifiedType()), - E); + + bool VisitOpaqueValueExpr(OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) { + if (e->getSourceExpr()) return Visit(e->getSourceExpr()); + return Error(e->getExprLoc(), diag::note_invalid_subexpr_in_ice, e); + } + return Success(value->getInt(), e); } bool CheckReferencedDecl(const Expr *E, const Decl *D); @@ -927,6 +1012,7 @@ public: bool VisitOffsetOfExpr(const OffsetOfExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); bool VisitConditionalOperator(const ConditionalOperator *E); + bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); bool VisitCastExpr(CastExpr* E); bool VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E); @@ -948,7 +1034,11 @@ public: } bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) { - return Success(E->EvaluateTrait(Info.Ctx), E); + return Success(E->getValue(), E); + } + + bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) { + return Success(E->getValue(), E); } bool VisitChooseExpr(const ChooseExpr *E) { @@ -958,6 +1048,9 @@ public: bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); + bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E); + bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); + private: CharUnits GetAlignOfExpr(const Expr *E); CharUnits GetAlignOfType(QualType T); @@ -1018,7 +1111,6 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { } VD->setEvaluatedValue(APValue()); - return false; } } } @@ -1160,6 +1252,24 @@ bool IntExprEvaluator::VisitCallExpr(CallExpr *E) { case Builtin::BI__builtin_expect: return Visit(E->getArg(0)); + + case Builtin::BIstrlen: + case Builtin::BI__builtin_strlen: + // As an extension, we support strlen() and __builtin_strlen() as constant + // expressions when the argument is a string literal. + if (StringLiteral *S + = dyn_cast(E->getArg(0)->IgnoreParenImpCasts())) { + // The string literal may have embedded null characters. Find the first + // one and truncate there. + llvm::StringRef Str = S->getString(); + llvm::StringRef::size_type Pos = Str.find(0); + if (Pos != llvm::StringRef::npos) + Str = Str.substr(0, Pos); + + return Success(Str.size(), E); + } + + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); } } @@ -1403,12 +1513,25 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { return Error(E->getOperatorLoc(), diag::note_expr_divide_by_zero, E); return Success(Result.getInt() % RHS, E); case BO_Shl: { - // FIXME: Warn about out of range shift amounts! - unsigned SA = - (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1); + // During constant-folding, a negative shift is an opposite shift. + if (RHS.isSigned() && RHS.isNegative()) { + RHS = -RHS; + goto shift_right; + } + + shift_left: + unsigned SA + = (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1); return Success(Result.getInt() << SA, E); } case BO_Shr: { + // During constant-folding, a negative shift is an opposite shift. + if (RHS.isSigned() && RHS.isNegative()) { + RHS = -RHS; + goto shift_left; + } + + shift_right: unsigned SA = (unsigned) RHS.getLimitedValue(Result.getInt().getBitWidth()-1); return Success(Result.getInt() >> SA, E); @@ -1423,6 +1546,18 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { } } +bool IntExprEvaluator:: +VisitBinaryConditionalOperator(const BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool IntExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { bool Cond; if (!HandleConversionToBool(E->getCond(), Cond, Info)) @@ -1439,12 +1574,9 @@ CharUnits IntExprEvaluator::GetAlignOfType(QualType T) { if (const ReferenceType *Ref = T->getAs()) T = Ref->getPointeeType(); - // Get information about the alignment. - unsigned CharSize = Info.Ctx.Target.getCharWidth(); - // __alignof is defined to return the preferred alignment. - return CharUnits::fromQuantity( - Info.Ctx.getPreferredTypeAlign(T.getTypePtr()) / CharSize); + return Info.Ctx.toCharUnitsFromBits( + Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); } CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) { @@ -1527,17 +1659,9 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { return false; RecordDecl *RD = RT->getDecl(); const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); - unsigned i = 0; - // FIXME: It would be nice if we didn't have to loop here! - for (RecordDecl::field_iterator Field = RD->field_begin(), - FieldEnd = RD->field_end(); - Field != FieldEnd; (void)++Field, ++i) { - if (*Field == MemberDecl) - break; - } + unsigned i = MemberDecl->getFieldIndex(); assert(i < RL.getFieldCount() && "offsetof field in wrong type"); - Result += CharUnits::fromQuantity( - RL.getFieldOffset(i) / Info.Ctx.getCharWidth()); + Result += Info.Ctx.toCharUnitsFromBits(RL.getFieldOffset(i)); CurrentType = MemberDecl->getType().getNonReferenceType(); break; } @@ -1565,9 +1689,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *E) { return false; // Add the offset to the base. - Result += CharUnits::fromQuantity( - RL.getBaseClassOffset(cast(BaseRT->getDecl())) - / Info.Ctx.getCharWidth()); + Result += RL.getBaseClassOffset(cast(BaseRT->getDecl())); break; } } @@ -1723,6 +1845,14 @@ bool IntExprEvaluator::VisitUnaryImag(const UnaryOperator *E) { return Success(0, E); } +bool IntExprEvaluator::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { + return Success(E->getPackLength(), E); +} + +bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { + return Success(E->getValue(), E); +} + //===----------------------------------------------------------------------===// // Float Evaluation //===----------------------------------------------------------------------===// @@ -1749,6 +1879,7 @@ public: bool VisitCastExpr(CastExpr *E); bool VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E); bool VisitConditionalOperator(ConditionalOperator *E); + bool VisitBinaryConditionalOperator(BinaryConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } @@ -1757,6 +1888,16 @@ public: bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); + bool VisitDeclRefExpr(const DeclRefExpr *E); + + bool VisitOpaqueValueExpr(const OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) + return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); + Result = value->getFloat(); + return true; + } + // FIXME: Missing: array subscript of vector, member of vector, // ImplicitValueInitExpr }; @@ -1767,7 +1908,7 @@ static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { return FloatExprEvaluator(Info, Result).Visit(const_cast(E)); } -static bool TryEvaluateBuiltinNaN(ASTContext &Context, +static bool TryEvaluateBuiltinNaN(const ASTContext &Context, QualType ResultTy, const Expr *Arg, bool SNaN, @@ -1844,6 +1985,45 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { } } +bool FloatExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { + const Decl *D = E->getDecl(); + if (!isa(D) || isa(D)) return false; + const VarDecl *VD = cast(D); + + // Require the qualifiers to be const and not volatile. + CanQualType T = Info.Ctx.getCanonicalType(E->getType()); + if (!T.isConstQualified() || T.isVolatileQualified()) + return false; + + const Expr *Init = VD->getAnyInitializer(); + if (!Init) return false; + + if (APValue *V = VD->getEvaluatedValue()) { + if (V->isFloat()) { + Result = V->getFloat(); + return true; + } + return false; + } + + if (VD->isEvaluatingValue()) + return false; + + VD->setEvaluatingValue(); + + Expr::EvalResult InitResult; + if (Init->Evaluate(InitResult, Info.Ctx) && !InitResult.HasSideEffects && + InitResult.Val.isFloat()) { + // Cache the evaluated value in the variable declaration. + Result = InitResult.Val.getFloat(); + VD->setEvaluatedValue(InitResult.Val); + return true; + } + + VD->setEvaluatedValue(APValue()); + return false; +} + bool FloatExprEvaluator::VisitUnaryReal(const UnaryOperator *E) { if (E->getSubExpr()->getType()->isAnyComplexType()) { ComplexValue CV; @@ -1902,6 +2082,10 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { return true; } + // We can't evaluate pointer-to-member operations. + if (E->isPtrMemOp()) + return false; + // FIXME: Diagnostics? I really don't understand how the warnings // and errors are supposed to work. APFloat RHS(0.0); @@ -1950,7 +2134,14 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) { Result, Info.Ctx); return true; } - // FIXME: Handle complex types + + if (E->getCastKind() == CK_FloatingComplexToReal) { + ComplexValue V; + if (!EvaluateComplex(SubExpr, V, Info)) + return false; + Result = V.getComplexFloatReal(); + return true; + } return false; } @@ -1960,6 +2151,18 @@ bool FloatExprEvaluator::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) return true; } +bool FloatExprEvaluator:: +VisitBinaryConditionalOperator(BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + bool FloatExprEvaluator::VisitConditionalOperator(ConditionalOperator *E) { bool Cond; if (!HandleConversionToBool(E->getCond(), Cond, Info)) @@ -1997,12 +2200,21 @@ public: bool VisitCastExpr(CastExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitUnaryOperator(const UnaryOperator *E); + bool VisitConditionalOperator(const ConditionalOperator *E); + bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E); bool VisitChooseExpr(const ChooseExpr *E) { return Visit(E->getChosenSubExpr(Info.Ctx)); } bool VisitUnaryExtension(const UnaryOperator *E) { return Visit(E->getSubExpr()); } - // FIXME Missing: unary +/-/~, binary div, ImplicitValueInitExpr, - // conditional ?:, comma + bool VisitOpaqueValueExpr(const OpaqueValueExpr *e) { + const APValue *value = Info.getOpaqueValue(e); + if (!value) + return (e->getSourceExpr() ? Visit(e->getSourceExpr()) : false); + Result.setFrom(*value); + return true; + } + // FIXME Missing: ImplicitValueInitExpr }; } // end anonymous namespace @@ -2038,99 +2250,143 @@ bool ComplexExprEvaluator::VisitImaginaryLiteral(ImaginaryLiteral *E) { } bool ComplexExprEvaluator::VisitCastExpr(CastExpr *E) { - Expr* SubExpr = E->getSubExpr(); - QualType EltType = E->getType()->getAs()->getElementType(); - QualType SubType = SubExpr->getType(); - if (SubType->isRealFloatingType()) { + switch (E->getCastKind()) { + case CK_BitCast: + case CK_LValueBitCast: + case CK_BaseToDerived: + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + case CK_Dynamic: + case CK_ToUnion: + case CK_ArrayToPointerDecay: + case CK_FunctionToPointerDecay: + case CK_NullToPointer: + case CK_NullToMemberPointer: + case CK_BaseToDerivedMemberPointer: + case CK_DerivedToBaseMemberPointer: + case CK_MemberPointerToBoolean: + case CK_ConstructorConversion: + case CK_IntegralToPointer: + case CK_PointerToIntegral: + case CK_PointerToBoolean: + case CK_ToVoid: + case CK_VectorSplat: + case CK_IntegralCast: + case CK_IntegralToBoolean: + case CK_IntegralToFloating: + case CK_FloatingToIntegral: + case CK_FloatingToBoolean: + case CK_FloatingCast: + case CK_AnyPointerToObjCPointerCast: + case CK_AnyPointerToBlockPointerCast: + case CK_ObjCObjectLValueCast: + case CK_FloatingComplexToReal: + case CK_FloatingComplexToBoolean: + case CK_IntegralComplexToReal: + case CK_IntegralComplexToBoolean: + llvm_unreachable("invalid cast kind for complex value"); + + case CK_LValueToRValue: + case CK_NoOp: + return Visit(E->getSubExpr()); + + case CK_Dependent: + case CK_GetObjCProperty: + case CK_UserDefinedConversion: + return false; + + case CK_FloatingRealToComplex: { APFloat &Real = Result.FloatReal; - if (!EvaluateFloat(SubExpr, Real, Info)) + if (!EvaluateFloat(E->getSubExpr(), Real, Info)) return false; - if (EltType->isRealFloatingType()) { - Result.makeComplexFloat(); - Real = HandleFloatToFloatCast(EltType, SubType, Real, Info.Ctx); - Result.FloatImag = APFloat(Real.getSemantics()); - return true; - } else { - Result.makeComplexInt(); - Result.IntReal = HandleFloatToIntCast(EltType, SubType, Real, Info.Ctx); - Result.IntImag = APSInt(Result.IntReal.getBitWidth(), - !Result.IntReal.isSigned()); - return true; - } - } else if (SubType->isIntegerType()) { + Result.makeComplexFloat(); + Result.FloatImag = APFloat(Real.getSemantics()); + return true; + } + + case CK_FloatingComplexCast: { + if (!Visit(E->getSubExpr())) + return false; + + QualType To = E->getType()->getAs()->getElementType(); + QualType From + = E->getSubExpr()->getType()->getAs()->getElementType(); + + Result.FloatReal + = HandleFloatToFloatCast(To, From, Result.FloatReal, Info.Ctx); + Result.FloatImag + = HandleFloatToFloatCast(To, From, Result.FloatImag, Info.Ctx); + return true; + } + + case CK_FloatingComplexToIntegralComplex: { + if (!Visit(E->getSubExpr())) + return false; + + QualType To = E->getType()->getAs()->getElementType(); + QualType From + = E->getSubExpr()->getType()->getAs()->getElementType(); + Result.makeComplexInt(); + Result.IntReal = HandleFloatToIntCast(To, From, Result.FloatReal, Info.Ctx); + Result.IntImag = HandleFloatToIntCast(To, From, Result.FloatImag, Info.Ctx); + return true; + } + + case CK_IntegralRealToComplex: { APSInt &Real = Result.IntReal; - if (!EvaluateInteger(SubExpr, Real, Info)) + if (!EvaluateInteger(E->getSubExpr(), Real, Info)) return false; - if (EltType->isRealFloatingType()) { - Result.makeComplexFloat(); - Result.FloatReal - = HandleIntToFloatCast(EltType, SubType, Real, Info.Ctx); - Result.FloatImag = APFloat(Result.FloatReal.getSemantics()); - return true; - } else { - Result.makeComplexInt(); - Real = HandleIntToIntCast(EltType, SubType, Real, Info.Ctx); - Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned()); - return true; - } - } else if (const ComplexType *CT = SubType->getAs()) { - if (!Visit(SubExpr)) + Result.makeComplexInt(); + Result.IntImag = APSInt(Real.getBitWidth(), !Real.isSigned()); + return true; + } + + case CK_IntegralComplexCast: { + if (!Visit(E->getSubExpr())) return false; - QualType SrcType = CT->getElementType(); + QualType To = E->getType()->getAs()->getElementType(); + QualType From + = E->getSubExpr()->getType()->getAs()->getElementType(); - if (Result.isComplexFloat()) { - if (EltType->isRealFloatingType()) { - Result.makeComplexFloat(); - Result.FloatReal = HandleFloatToFloatCast(EltType, SrcType, - Result.FloatReal, - Info.Ctx); - Result.FloatImag = HandleFloatToFloatCast(EltType, SrcType, - Result.FloatImag, - Info.Ctx); - return true; - } else { - Result.makeComplexInt(); - Result.IntReal = HandleFloatToIntCast(EltType, SrcType, - Result.FloatReal, - Info.Ctx); - Result.IntImag = HandleFloatToIntCast(EltType, SrcType, - Result.FloatImag, - Info.Ctx); - return true; - } - } else { - assert(Result.isComplexInt() && "Invalid evaluate result."); - if (EltType->isRealFloatingType()) { - Result.makeComplexFloat(); - Result.FloatReal = HandleIntToFloatCast(EltType, SrcType, - Result.IntReal, - Info.Ctx); - Result.FloatImag = HandleIntToFloatCast(EltType, SrcType, - Result.IntImag, - Info.Ctx); - return true; - } else { - Result.makeComplexInt(); - Result.IntReal = HandleIntToIntCast(EltType, SrcType, - Result.IntReal, - Info.Ctx); - Result.IntImag = HandleIntToIntCast(EltType, SrcType, - Result.IntImag, - Info.Ctx); - return true; - } - } + Result.IntReal = HandleIntToIntCast(To, From, Result.IntReal, Info.Ctx); + Result.IntImag = HandleIntToIntCast(To, From, Result.IntImag, Info.Ctx); + return true; + } + + case CK_IntegralComplexToFloatingComplex: { + if (!Visit(E->getSubExpr())) + return false; + + QualType To = E->getType()->getAs()->getElementType(); + QualType From + = E->getSubExpr()->getType()->getAs()->getElementType(); + Result.makeComplexFloat(); + Result.FloatReal = HandleIntToFloatCast(To, From, Result.IntReal, Info.Ctx); + Result.FloatImag = HandleIntToFloatCast(To, From, Result.IntImag, Info.Ctx); + return true; + } } - // FIXME: Handle more casts. + llvm_unreachable("unknown cast resulting in complex value"); return false; } bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { + if (E->getOpcode() == BO_Comma) { + if (!Visit(E->getRHS())) + return false; + + // If we can't evaluate the LHS, it might have side effects; + // conservatively mark it. + if (!E->getLHS()->isEvaluatable(Info.Ctx)) + Info.EvalResult.HasSideEffects = true; + + return true; + } if (!Visit(E->getLHS())) return false; @@ -2195,29 +2451,122 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { LHS.getComplexIntImag() * RHS.getComplexIntReal()); } break; + case BO_Div: + if (Result.isComplexFloat()) { + ComplexValue LHS = Result; + APFloat &LHS_r = LHS.getComplexFloatReal(); + APFloat &LHS_i = LHS.getComplexFloatImag(); + APFloat &RHS_r = RHS.getComplexFloatReal(); + APFloat &RHS_i = RHS.getComplexFloatImag(); + APFloat &Res_r = Result.getComplexFloatReal(); + APFloat &Res_i = Result.getComplexFloatImag(); + + APFloat Den = RHS_r; + Den.multiply(RHS_r, APFloat::rmNearestTiesToEven); + APFloat Tmp = RHS_i; + Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); + Den.add(Tmp, APFloat::rmNearestTiesToEven); + + Res_r = LHS_r; + Res_r.multiply(RHS_r, APFloat::rmNearestTiesToEven); + Tmp = LHS_i; + Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); + Res_r.add(Tmp, APFloat::rmNearestTiesToEven); + Res_r.divide(Den, APFloat::rmNearestTiesToEven); + + Res_i = LHS_i; + Res_i.multiply(RHS_r, APFloat::rmNearestTiesToEven); + Tmp = LHS_r; + Tmp.multiply(RHS_i, APFloat::rmNearestTiesToEven); + Res_i.subtract(Tmp, APFloat::rmNearestTiesToEven); + Res_i.divide(Den, APFloat::rmNearestTiesToEven); + } else { + if (RHS.getComplexIntReal() == 0 && RHS.getComplexIntImag() == 0) { + // FIXME: what about diagnostics? + return false; + } + ComplexValue LHS = Result; + APSInt Den = RHS.getComplexIntReal() * RHS.getComplexIntReal() + + RHS.getComplexIntImag() * RHS.getComplexIntImag(); + Result.getComplexIntReal() = + (LHS.getComplexIntReal() * RHS.getComplexIntReal() + + LHS.getComplexIntImag() * RHS.getComplexIntImag()) / Den; + Result.getComplexIntImag() = + (LHS.getComplexIntImag() * RHS.getComplexIntReal() - + LHS.getComplexIntReal() * RHS.getComplexIntImag()) / Den; + } + break; } return true; } +bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + // Get the operand value into 'Result'. + if (!Visit(E->getSubExpr())) + return false; + + switch (E->getOpcode()) { + default: + // FIXME: what about diagnostics? + return false; + case UO_Extension: + return true; + case UO_Plus: + // The result is always just the subexpr. + return true; + case UO_Minus: + if (Result.isComplexFloat()) { + Result.getComplexFloatReal().changeSign(); + Result.getComplexFloatImag().changeSign(); + } + else { + Result.getComplexIntReal() = -Result.getComplexIntReal(); + Result.getComplexIntImag() = -Result.getComplexIntImag(); + } + return true; + case UO_Not: + if (Result.isComplexFloat()) + Result.getComplexFloatImag().changeSign(); + else + Result.getComplexIntImag() = -Result.getComplexIntImag(); + return true; + } +} + +bool ComplexExprEvaluator:: +VisitBinaryConditionalOperator(const BinaryConditionalOperator *e) { + OpaqueValueEvaluation opaque(Info, e->getOpaqueValue(), e->getCommon()); + if (opaque.hasError()) return false; + + bool cond; + if (!HandleConversionToBool(e->getCond(), cond, Info)) + return false; + + return Visit(cond ? e->getTrueExpr() : e->getFalseExpr()); +} + +bool ComplexExprEvaluator::VisitConditionalOperator(const ConditionalOperator *E) { + bool Cond; + if (!HandleConversionToBool(E->getCond(), Cond, Info)) + return false; + + return Visit(Cond ? E->getTrueExpr() : E->getFalseExpr()); +} + //===----------------------------------------------------------------------===// // Top level Expr::Evaluate method. //===----------------------------------------------------------------------===// -/// Evaluate - Return true if this is a constant which we can fold using -/// any crazy technique (that has nothing to do with language standards) that -/// we want to. If this function returns true, it returns the folded constant -/// in Result. -bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { - const Expr *E = this; - EvalInfo Info(Ctx, Result); +static bool Evaluate(EvalInfo &Info, const Expr *E) { if (E->getType()->isVectorType()) { if (!EvaluateVector(E, Info.EvalResult.Val, Info)) return false; } else if (E->getType()->isIntegerType()) { if (!IntExprEvaluator(Info, Info.EvalResult.Val).Visit(const_cast(E))) return false; - if (Result.Val.isLValue() && !IsGlobalLValue(Result.Val.getLValueBase())) + if (Info.EvalResult.Val.isLValue() && + !IsGlobalLValue(Info.EvalResult.Val.getLValueBase())) return false; } else if (E->getType()->hasPointerRepresentation()) { LValue LV; @@ -2243,14 +2592,24 @@ bool Expr::Evaluate(EvalResult &Result, ASTContext &Ctx) const { return true; } -bool Expr::EvaluateAsBooleanCondition(bool &Result, ASTContext &Ctx) const { +/// Evaluate - Return true if this is a constant which we can fold using +/// any crazy technique (that has nothing to do with language standards) that +/// we want to. If this function returns true, it returns the folded constant +/// in Result. +bool Expr::Evaluate(EvalResult &Result, const ASTContext &Ctx) const { + EvalInfo Info(Ctx, Result); + return ::Evaluate(Info, this); +} + +bool Expr::EvaluateAsBooleanCondition(bool &Result, + const ASTContext &Ctx) const { EvalResult Scratch; EvalInfo Info(Ctx, Scratch); return HandleConversionToBool(this, Result, Info); } -bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const { +bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); LValue LV; @@ -2263,7 +2622,8 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, ASTContext &Ctx) const { return false; } -bool Expr::EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const { +bool Expr::EvaluateAsAnyLValue(EvalResult &Result, + const ASTContext &Ctx) const { EvalInfo Info(Ctx, Result); LValue LV; @@ -2276,21 +2636,21 @@ bool Expr::EvaluateAsAnyLValue(EvalResult &Result, ASTContext &Ctx) const { /// isEvaluatable - Call Evaluate to see if this expression can be constant /// folded, but discard the result. -bool Expr::isEvaluatable(ASTContext &Ctx) const { +bool Expr::isEvaluatable(const ASTContext &Ctx) const { EvalResult Result; return Evaluate(Result, Ctx) && !Result.HasSideEffects; } -bool Expr::HasSideEffects(ASTContext &Ctx) const { +bool Expr::HasSideEffects(const ASTContext &Ctx) const { Expr::EvalResult Result; EvalInfo Info(Ctx, Result); return HasSideEffect(Info).Visit(const_cast(this)); } -APSInt Expr::EvaluateAsInt(ASTContext &Ctx) const { +APSInt Expr::EvaluateAsInt(const ASTContext &Ctx) const { EvalResult EvalResult; bool Result = Evaluate(EvalResult, Ctx); - Result = Result; + (void)Result; assert(Result && "Could not evaluate expression"); assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); @@ -2358,6 +2718,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { } switch (E->getStmtClass()) { +#define ABSTRACT_STMT(Node) #define STMT(Node, Base) case Expr::Node##Class: #define EXPR(Node, Base) #include "clang/AST/StmtNodes.inc" @@ -2378,8 +2739,10 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AddrLabelExprClass: case Expr::StmtExprClass: case Expr::CXXMemberCallExprClass: + case Expr::CUDAKernelCallExprClass: case Expr::CXXDynamicCastExprClass: case Expr::CXXTypeidExprClass: + case Expr::CXXUuidofExprClass: case Expr::CXXNullPtrLiteralExprClass: case Expr::CXXThisExprClass: case Expr::CXXThrowExprClass: @@ -2390,7 +2753,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::DependentScopeDeclRefExprClass: case Expr::CXXConstructExprClass: case Expr::CXXBindTemporaryExprClass: - case Expr::CXXExprWithTemporariesClass: + case Expr::ExprWithCleanupsClass: case Expr::CXXTemporaryObjectExprClass: case Expr::CXXUnresolvedConstructExprClass: case Expr::CXXDependentScopeMemberExprClass: @@ -2402,15 +2765,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::ObjCProtocolExprClass: case Expr::ObjCIvarRefExprClass: case Expr::ObjCPropertyRefExprClass: - case Expr::ObjCImplicitSetterGetterRefExprClass: - case Expr::ObjCSuperExprClass: case Expr::ObjCIsaExprClass: case Expr::ShuffleVectorExprClass: case Expr::BlockExprClass: case Expr::BlockDeclRefExprClass: case Expr::NoStmtClass: + case Expr::OpaqueValueExprClass: + case Expr::PackExpansionExprClass: + case Expr::SubstNonTypeTemplateParmPackExprClass: return ICEDiag(2, E->getLocStart()); + case Expr::SizeOfPackExprClass: case Expr::GNUNullExprClass: // GCC considers the GNU __null value to be an integral constant expression. return NoDiag(); @@ -2421,8 +2786,9 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::CharacterLiteralClass: case Expr::CXXBoolLiteralExprClass: case Expr::CXXScalarValueInitExprClass: - case Expr::TypesCompatibleExprClass: case Expr::UnaryTypeTraitExprClass: + case Expr::BinaryTypeTraitExprClass: + case Expr::CXXNoexceptExprClass: return NoDiag(); case Expr::CallExprClass: case Expr::CXXOperatorCallExprClass: { @@ -2619,6 +2985,17 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { return NoDiag(); return ICEDiag(2, E->getLocStart()); } + case Expr::BinaryConditionalOperatorClass: { + const BinaryConditionalOperator *Exp = cast(E); + ICEDiag CommonResult = CheckICE(Exp->getCommon(), Ctx); + if (CommonResult.Val == 2) return CommonResult; + ICEDiag FalseResult = CheckICE(Exp->getFalseExpr(), Ctx); + if (FalseResult.Val == 2) return FalseResult; + if (CommonResult.Val == 1) return CommonResult; + if (FalseResult.Val == 1 && + Exp->getCommon()->EvaluateAsInt(Ctx) == 0) return NoDiag(); + return FalseResult; + } case Expr::ConditionalOperatorClass: { const ConditionalOperator *Exp = cast(E); // If the condition (ignoring parens) is a __builtin_constant_p call, diff --git a/lib/AST/FullExpr.cpp b/lib/AST/FullExpr.cpp deleted file mode 100644 index 93ee8d136000..000000000000 --- a/lib/AST/FullExpr.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//===--- FullExpr.cpp - C++ full expression class ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the FullExpr interface, to be used for type safe handling -// of full expressions. -// -// Full expressions are described in C++ [intro.execution]p12. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ASTContext.h" -#include "clang/AST/FullExpr.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "llvm/Support/AlignOf.h" -using namespace clang; - -FullExpr FullExpr::Create(ASTContext &Context, Expr *SubExpr, - CXXTemporary **Temporaries, unsigned NumTemporaries) { - FullExpr E; - - if (!NumTemporaries) { - E.SubExpr = SubExpr; - return E; - } - - unsigned Size = sizeof(FullExpr) - + sizeof(CXXTemporary *) * NumTemporaries; - - unsigned Align = llvm::AlignOf::Alignment; - ExprAndTemporaries *ET = - static_cast(Context.Allocate(Size, Align)); - - ET->SubExpr = SubExpr; - std::copy(Temporaries, Temporaries + NumTemporaries, ET->temps_begin()); - - return E; -} - diff --git a/lib/AST/InheritViz.cpp b/lib/AST/InheritViz.cpp index c47a9dadbadd..533a2329c583 100644 --- a/lib/AST/InheritViz.cpp +++ b/lib/AST/InheritViz.cpp @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/TypeOrdering.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/raw_ostream.h" #include @@ -135,34 +136,28 @@ InheritanceHierarchyWriter::WriteNodeReference(QualType Type, /// class using GraphViz. void CXXRecordDecl::viewInheritance(ASTContext& Context) const { QualType Self = Context.getTypeDeclType(const_cast(this)); - std::string ErrMsg; - sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); - if (Filename.isEmpty()) { - llvm::errs() << "Error: " << ErrMsg << "\n"; - return; - } - Filename.appendComponent(Self.getAsString() + ".dot"); - if (Filename.makeUnique(true,&ErrMsg)) { - llvm::errs() << "Error: " << ErrMsg << "\n"; + // Create temp directory + SmallString<128> Filename; + int FileFD = 0; + if (error_code ec = sys::fs::unique_file( + "clang-class-inheritance-hierarchy-%%-%%-%%-%%-" + + Self.getAsString() + ".dot", + FileFD, Filename)) { + errs() << "Error creating temporary output file: " << ec.message() << '\n'; return; } - llvm::errs() << "Writing '" << Filename.c_str() << "'... "; + llvm::errs() << "Writing '" << Filename << "'... "; - llvm::raw_fd_ostream O(Filename.c_str(), ErrMsg); + llvm::raw_fd_ostream O(FileFD, true); + InheritanceHierarchyWriter Writer(Context, O); + Writer.WriteGraph(Self); - if (ErrMsg.empty()) { - InheritanceHierarchyWriter Writer(Context, O); - Writer.WriteGraph(Self); - llvm::errs() << " done. \n"; + llvm::errs() << " done. \n"; + O.close(); - O.close(); - - // Display the graph - DisplayGraph(Filename); - } else { - llvm::errs() << "error opening file for writing!\n"; - } + // Display the graph + DisplayGraph(sys::Path(Filename)); } } diff --git a/lib/AST/ItaniumCXXABI.cpp b/lib/AST/ItaniumCXXABI.cpp index c3fa4666537b..bed02b4c0010 100644 --- a/lib/AST/ItaniumCXXABI.cpp +++ b/lib/AST/ItaniumCXXABI.cpp @@ -19,7 +19,10 @@ #include "CXXABI.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" +#include "clang/Basic/TargetInfo.h" using namespace clang; @@ -35,6 +38,24 @@ public: if (Pointee->isFunctionType()) return 2; return 1; } + + CallingConv getDefaultMethodCallConv() const { + return CC_C; + } + + // We cheat and just check that the class has a vtable pointer, and that it's + // only big enough to have a vtable pointer and nothing more (or less). + bool isNearlyEmpty(const CXXRecordDecl *RD) const { + + // Check that the class has a vtable pointer. + if (!RD->isDynamicClass()) + return false; + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + CharUnits PointerSize = + Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); + return Layout.getNonVirtualSize() == PointerSize; + } }; class ARMCXXABI : public ItaniumCXXABI { diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp new file mode 100644 index 000000000000..d66c374cbec0 --- /dev/null +++ b/lib/AST/ItaniumMangle.cpp @@ -0,0 +1,2705 @@ +//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements C++ name mangling according to the Itanium C++ ABI, +// which is used in GCC 3.2 and newer (and many compilers that are +// ABI-compatible with GCC): +// +// http://www.codesourcery.com/public/cxx-abi/abi.html +// +//===----------------------------------------------------------------------===// +#include "clang/AST/Mangle.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/ABI.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ErrorHandling.h" + +#define MANGLE_CHECKER 0 + +#if MANGLE_CHECKER +#include +#endif + +using namespace clang; + +namespace { + +static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) { + const DeclContext *DC = dyn_cast(ND); + if (!DC) + DC = ND->getDeclContext(); + while (!DC->isNamespace() && !DC->isTranslationUnit()) { + if (isa(DC->getParent())) + return dyn_cast(DC); + DC = DC->getParent(); + } + return 0; +} + +static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { + assert((isa(MD) || isa(MD)) && + "Passed in decl is not a ctor or dtor!"); + + if (const TemplateDecl *TD = MD->getPrimaryTemplate()) { + MD = cast(TD->getTemplatedDecl()); + + assert((isa(MD) || isa(MD)) && + "Templated decl is not a ctor or dtor!"); + } + + return MD; +} + +static const unsigned UnknownArity = ~0U; + +class ItaniumMangleContext : public MangleContext { + llvm::DenseMap AnonStructIds; + unsigned Discriminator; + llvm::DenseMap Uniquifier; + +public: + explicit ItaniumMangleContext(ASTContext &Context, + Diagnostic &Diags) + : MangleContext(Context, Diags) { } + + uint64_t getAnonymousStructId(const TagDecl *TD) { + std::pair::iterator, bool> Result = + AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); + return Result.first->second; + } + + void startNewFunction() { + MangleContext::startNewFunction(); + mangleInitDiscriminator(); + } + + /// @name Mangler Entry Points + /// @{ + + bool shouldMangleDeclName(const NamedDecl *D); + void mangleName(const NamedDecl *D, llvm::raw_ostream &); + void mangleThunk(const CXXMethodDecl *MD, + const ThunkInfo &Thunk, + llvm::raw_ostream &); + void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type, + const ThisAdjustment &ThisAdjustment, + llvm::raw_ostream &); + void mangleReferenceTemporary(const VarDecl *D, + llvm::raw_ostream &); + void mangleCXXVTable(const CXXRecordDecl *RD, + llvm::raw_ostream &); + void mangleCXXVTT(const CXXRecordDecl *RD, + llvm::raw_ostream &); + void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + llvm::raw_ostream &); + void mangleCXXRTTI(QualType T, llvm::raw_ostream &); + void mangleCXXRTTIName(QualType T, llvm::raw_ostream &); + void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, + llvm::raw_ostream &); + void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, + llvm::raw_ostream &); + + void mangleItaniumGuardVariable(const VarDecl *D, llvm::raw_ostream &); + + void mangleInitDiscriminator() { + Discriminator = 0; + } + + bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) { + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator; + if (discriminator == 1) + return false; + disc = discriminator-2; + return true; + } + /// @} +}; + +/// CXXNameMangler - Manage the mangling of a single name. +class CXXNameMangler { + ItaniumMangleContext &Context; + llvm::raw_ostream &Out; + + const CXXMethodDecl *Structor; + unsigned StructorType; + + /// SeqID - The next subsitution sequence number. + unsigned SeqID; + + llvm::DenseMap Substitutions; + + ASTContext &getASTContext() const { return Context.getASTContext(); } + +public: + CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_) + : Context(C), Out(Out_), Structor(0), StructorType(0), SeqID(0) { } + CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, + const CXXConstructorDecl *D, CXXCtorType Type) + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + SeqID(0) { } + CXXNameMangler(ItaniumMangleContext &C, llvm::raw_ostream &Out_, + const CXXDestructorDecl *D, CXXDtorType Type) + : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type), + SeqID(0) { } + +#if MANGLE_CHECKER + ~CXXNameMangler() { + if (Out.str()[0] == '\01') + return; + + int status = 0; + char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status); + assert(status == 0 && "Could not demangle mangled name!"); + free(result); + } +#endif + llvm::raw_ostream &getStream() { return Out; } + + void mangle(const NamedDecl *D, llvm::StringRef Prefix = "_Z"); + void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); + void mangleNumber(const llvm::APSInt &I); + void mangleNumber(int64_t Number); + void mangleFloat(const llvm::APFloat &F); + void mangleFunctionEncoding(const FunctionDecl *FD); + void mangleName(const NamedDecl *ND); + void mangleType(QualType T); + void mangleNameOrStandardSubstitution(const NamedDecl *ND); + +private: + bool mangleSubstitution(const NamedDecl *ND); + bool mangleSubstitution(QualType T); + bool mangleSubstitution(TemplateName Template); + bool mangleSubstitution(uintptr_t Ptr); + + bool mangleStandardSubstitution(const NamedDecl *ND); + + void addSubstitution(const NamedDecl *ND) { + ND = cast(ND->getCanonicalDecl()); + + addSubstitution(reinterpret_cast(ND)); + } + void addSubstitution(QualType T); + void addSubstitution(TemplateName Template); + void addSubstitution(uintptr_t Ptr); + + void mangleUnresolvedScope(NestedNameSpecifier *Qualifier); + void mangleUnresolvedName(NestedNameSpecifier *Qualifier, + DeclarationName Name, + unsigned KnownArity = UnknownArity); + + void mangleName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + void mangleUnqualifiedName(const NamedDecl *ND) { + mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity); + } + void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name, + unsigned KnownArity); + void mangleUnscopedName(const NamedDecl *ND); + void mangleUnscopedTemplateName(const TemplateDecl *ND); + void mangleUnscopedTemplateName(TemplateName); + void mangleSourceName(const IdentifierInfo *II); + void mangleLocalName(const NamedDecl *ND); + void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + bool NoFunction=false); + void mangleNestedName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + void manglePrefix(const DeclContext *DC, bool NoFunction=false); + void mangleTemplatePrefix(const TemplateDecl *ND); + void mangleTemplatePrefix(TemplateName Template); + void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); + void mangleQualifiers(Qualifiers Quals); + void mangleRefQualifier(RefQualifierKind RefQualifier); + + void mangleObjCMethodName(const ObjCMethodDecl *MD); + + // Declare manglers for every type class. +#define ABSTRACT_TYPE(CLASS, PARENT) +#define NON_CANONICAL_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T); +#include "clang/AST/TypeNodes.def" + + void mangleType(const TagType*); + void mangleType(TemplateName); + void mangleBareFunctionType(const FunctionType *T, + bool MangleReturnType); + void mangleNeonVectorType(const VectorType *T); + + void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value); + void mangleMemberExpr(const Expr *Base, bool IsArrow, + NestedNameSpecifier *Qualifier, + DeclarationName Name, + unsigned KnownArity); + void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); + void mangleCXXCtorType(CXXCtorType T); + void mangleCXXDtorType(CXXDtorType T); + + void mangleTemplateArgs(const ExplicitTemplateArgumentList &TemplateArgs); + void mangleTemplateArgs(TemplateName Template, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + void mangleTemplateArgs(const TemplateParameterList &PL, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + void mangleTemplateArgs(const TemplateParameterList &PL, + const TemplateArgumentList &AL); + void mangleTemplateArg(const NamedDecl *P, const TemplateArgument &A); + + void mangleTemplateParameter(unsigned Index); +}; + +} + +static bool isInCLinkageSpecification(const Decl *D) { + D = D->getCanonicalDecl(); + for (const DeclContext *DC = D->getDeclContext(); + !DC->isTranslationUnit(); DC = DC->getParent()) { + if (const LinkageSpecDecl *Linkage = dyn_cast(DC)) + return Linkage->getLanguage() == LinkageSpecDecl::lang_c; + } + + return false; +} + +bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) { + // In C, functions with no attributes never need to be mangled. Fastpath them. + if (!getASTContext().getLangOptions().CPlusPlus && !D->hasAttrs()) + return false; + + // Any decl can be declared with __asm("foo") on it, and this takes precedence + // over all other naming in the .o file. + if (D->hasAttr()) + return true; + + // Clang's "overloadable" attribute extension to C/C++ implies name mangling + // (always) as does passing a C++ member function and a function + // whose name is not a simple identifier. + const FunctionDecl *FD = dyn_cast(D); + if (FD && (FD->hasAttr() || isa(FD) || + !FD->getDeclName().isIdentifier())) + return true; + + // Otherwise, no mangling is done outside C++ mode. + if (!getASTContext().getLangOptions().CPlusPlus) + return false; + + // Variables at global scope with non-internal linkage are not mangled + if (!FD) { + const DeclContext *DC = D->getDeclContext(); + // Check for extern variable declared locally. + if (DC->isFunctionOrMethod() && D->hasLinkage()) + while (!DC->isNamespace() && !DC->isTranslationUnit()) + DC = DC->getParent(); + if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage) + return false; + } + + // Class members are always mangled. + if (D->getDeclContext()->isRecord()) + return true; + + // C functions and "main" are not mangled. + if ((FD && FD->isMain()) || isInCLinkageSpecification(D)) + return false; + + return true; +} + +void CXXNameMangler::mangle(const NamedDecl *D, llvm::StringRef Prefix) { + // Any decl can be declared with __asm("foo") on it, and this takes precedence + // over all other naming in the .o file. + if (const AsmLabelAttr *ALA = D->getAttr()) { + // If we have an asm name, then we use it as the mangling. + + // Adding the prefix can cause problems when one file has a "foo" and + // another has a "\01foo". That is known to happen on ELF with the + // tricks normally used for producing aliases (PR9177). Fortunately the + // llvm mangler on ELF is a nop, so we can just avoid adding the \01 + // marker. + llvm::StringRef UserLabelPrefix = + getASTContext().Target.getUserLabelPrefix(); + if (!UserLabelPrefix.empty()) + Out << '\01'; // LLVM IR Marker for __asm("foo") + + Out << ALA->getLabel(); + return; + } + + // ::= _Z + // ::= + // ::= + Out << Prefix; + if (const FunctionDecl *FD = dyn_cast(D)) + mangleFunctionEncoding(FD); + else if (const VarDecl *VD = dyn_cast(D)) + mangleName(VD); + else + mangleName(cast(D)); +} + +void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { + // ::= + mangleName(FD); + + // Don't mangle in the type if this isn't a decl we should typically mangle. + if (!Context.shouldMangleDeclName(FD)) + return; + + // Whether the mangling of a function type includes the return type depends on + // the context and the nature of the function. The rules for deciding whether + // the return type is included are: + // + // 1. Template functions (names or types) have return types encoded, with + // the exceptions listed below. + // 2. Function types not appearing as part of a function name mangling, + // e.g. parameters, pointer types, etc., have return type encoded, with the + // exceptions listed below. + // 3. Non-template function names do not have return types encoded. + // + // The exceptions mentioned in (1) and (2) above, for which the return type is + // never included, are + // 1. Constructors. + // 2. Destructors. + // 3. Conversion operator functions, e.g. operator int. + bool MangleReturnType = false; + if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) { + if (!(isa(FD) || isa(FD) || + isa(FD))) + MangleReturnType = true; + + // Mangle the type of the primary template. + FD = PrimaryTemplate->getTemplatedDecl(); + } + + // Do the canonicalization out here because parameter types can + // undergo additional canonicalization (e.g. array decay). + const FunctionType *FT + = cast(Context.getASTContext() + .getCanonicalType(FD->getType())); + + mangleBareFunctionType(FT, MangleReturnType); +} + +static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) { + while (isa(DC)) { + DC = DC->getParent(); + } + + return DC; +} + +/// isStd - Return whether a given namespace is the 'std' namespace. +static bool isStd(const NamespaceDecl *NS) { + if (!IgnoreLinkageSpecDecls(NS->getParent())->isTranslationUnit()) + return false; + + const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier(); + return II && II->isStr("std"); +} + +// isStdNamespace - Return whether a given decl context is a toplevel 'std' +// namespace. +static bool isStdNamespace(const DeclContext *DC) { + if (!DC->isNamespace()) + return false; + + return isStd(cast(DC)); +} + +static const TemplateDecl * +isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { + // Check if we have a function template. + if (const FunctionDecl *FD = dyn_cast(ND)){ + if (const TemplateDecl *TD = FD->getPrimaryTemplate()) { + TemplateArgs = FD->getTemplateSpecializationArgs(); + return TD; + } + } + + // Check if we have a class template. + if (const ClassTemplateSpecializationDecl *Spec = + dyn_cast(ND)) { + TemplateArgs = &Spec->getTemplateArgs(); + return Spec->getSpecializedTemplate(); + } + + return 0; +} + +void CXXNameMangler::mangleName(const NamedDecl *ND) { + // ::= + // ::= + // ::= + // ::= + // + const DeclContext *DC = ND->getDeclContext(); + + // If this is an extern variable declared locally, the relevant DeclContext + // is that of the containing namespace, or the translation unit. + if (isa(DC) && ND->hasLinkage()) + while (!DC->isNamespace() && !DC->isTranslationUnit()) + DC = DC->getParent(); + else if (GetLocalClassDecl(ND)) { + mangleLocalName(ND); + return; + } + + while (isa(DC)) + DC = DC->getParent(); + + if (DC->isTranslationUnit() || isStdNamespace(DC)) { + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { + mangleUnscopedTemplateName(TD); + TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); + mangleTemplateArgs(*TemplateParameters, *TemplateArgs); + return; + } + + mangleUnscopedName(ND); + return; + } + + if (isa(DC) || isa(DC)) { + mangleLocalName(ND); + return; + } + + mangleNestedName(ND, DC); +} +void CXXNameMangler::mangleName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + const DeclContext *DC = IgnoreLinkageSpecDecls(TD->getDeclContext()); + + if (DC->isTranslationUnit() || isStdNamespace(DC)) { + mangleUnscopedTemplateName(TD); + TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); + mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs); + } else { + mangleNestedName(TD, TemplateArgs, NumTemplateArgs); + } +} + +void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) { + // ::= + // ::= St # ::std:: + if (isStdNamespace(ND->getDeclContext())) + Out << "St"; + + mangleUnqualifiedName(ND); +} + +void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) { + // ::= + // ::= + if (mangleSubstitution(ND)) + return; + + // ::= + if (const TemplateTemplateParmDecl *TTP + = dyn_cast(ND)) { + mangleTemplateParameter(TTP->getIndex()); + return; + } + + mangleUnscopedName(ND->getTemplatedDecl()); + addSubstitution(ND); +} + +void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) { + // ::= + // ::= + if (TemplateDecl *TD = Template.getAsTemplateDecl()) + return mangleUnscopedTemplateName(TD); + + if (mangleSubstitution(Template)) + return; + + // FIXME: How to cope with operators here? + DependentTemplateName *Dependent = Template.getAsDependentTemplateName(); + assert(Dependent && "Not a dependent template name?"); + if (!Dependent->isIdentifier()) { + // FIXME: We can't possibly know the arity of the operator here! + Diagnostic &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error, + "cannot mangle dependent operator name"); + Diags.Report(DiagID); + return; + } + + mangleSourceName(Dependent->getIdentifier()); + addSubstitution(Template); +} + +void CXXNameMangler::mangleFloat(const llvm::APFloat &F) { + // TODO: avoid this copy with careful stream management. + llvm::SmallString<20> Buffer; + F.bitcastToAPInt().toString(Buffer, 16, false); + Out.write(Buffer.data(), Buffer.size()); +} + +void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) { + if (Value.isSigned() && Value.isNegative()) { + Out << 'n'; + Value.abs().print(Out, true); + } else + Value.print(Out, Value.isSigned()); +} + +void CXXNameMangler::mangleNumber(int64_t Number) { + // ::= [n] + if (Number < 0) { + Out << 'n'; + Number = -Number; + } + + Out << Number; +} + +void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { + // ::= h _ + // ::= v _ + // ::= # non-virtual base override + // ::= _ + // # virtual base override, with vcall offset + if (!Virtual) { + Out << 'h'; + mangleNumber(NonVirtual); + Out << '_'; + return; + } + + Out << 'v'; + mangleNumber(NonVirtual); + Out << '_'; + mangleNumber(Virtual); + Out << '_'; +} + +void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) { + Qualifier = getASTContext().getCanonicalNestedNameSpecifier(Qualifier); + switch (Qualifier->getKind()) { + case NestedNameSpecifier::Global: + // nothing + break; + case NestedNameSpecifier::Namespace: + mangleName(Qualifier->getAsNamespace()); + break; + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + const Type *QTy = Qualifier->getAsType(); + + if (const TemplateSpecializationType *TST = + dyn_cast(QTy)) { + if (!mangleSubstitution(QualType(TST, 0))) { + mangleTemplatePrefix(TST->getTemplateName()); + + // FIXME: GCC does not appear to mangle the template arguments when + // the template in question is a dependent template name. Should we + // emulate that badness? + mangleTemplateArgs(TST->getTemplateName(), TST->getArgs(), + TST->getNumArgs()); + addSubstitution(QualType(TST, 0)); + } + } else { + // We use the QualType mangle type variant here because it handles + // substitutions. + mangleType(QualType(QTy, 0)); + } + } + break; + case NestedNameSpecifier::Identifier: + // Member expressions can have these without prefixes. + if (Qualifier->getPrefix()) + mangleUnresolvedScope(Qualifier->getPrefix()); + mangleSourceName(Qualifier->getAsIdentifier()); + break; + } +} + +/// Mangles a name which was not resolved to a specific entity. +void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *Qualifier, + DeclarationName Name, + unsigned KnownArity) { + if (Qualifier) + mangleUnresolvedScope(Qualifier); + // FIXME: ambiguity of unqualified lookup with :: + + mangleUnqualifiedName(0, Name, KnownArity); +} + +static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) { + assert(RD->isAnonymousStructOrUnion() && + "Expected anonymous struct or union!"); + + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I) { + const FieldDecl *FD = *I; + + if (FD->getIdentifier()) + return FD; + + if (const RecordType *RT = FD->getType()->getAs()) { + if (const FieldDecl *NamedDataMember = + FindFirstNamedDataMember(RT->getDecl())) + return NamedDataMember; + } + } + + // We didn't find a named data member. + return 0; +} + +void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, + DeclarationName Name, + unsigned KnownArity) { + // ::= + // ::= + // ::= + switch (Name.getNameKind()) { + case DeclarationName::Identifier: { + if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { + // We must avoid conflicts between internally- and externally- + // linked variable declaration names in the same TU. + // This naming convention is the same as that followed by GCC, though it + // shouldn't actually matter. + if (ND && isa(ND) && ND->getLinkage() == InternalLinkage && + ND->getDeclContext()->isFileContext()) + Out << 'L'; + + mangleSourceName(II); + break; + } + + // Otherwise, an anonymous entity. We must have a declaration. + assert(ND && "mangling empty name without declaration"); + + if (const NamespaceDecl *NS = dyn_cast(ND)) { + if (NS->isAnonymousNamespace()) { + // This is how gcc mangles these names. + Out << "12_GLOBAL__N_1"; + break; + } + } + + if (const VarDecl *VD = dyn_cast(ND)) { + // We must have an anonymous union or struct declaration. + const RecordDecl *RD = + cast(VD->getType()->getAs()->getDecl()); + + // Itanium C++ ABI 5.1.2: + // + // For the purposes of mangling, the name of an anonymous union is + // considered to be the name of the first named data member found by a + // pre-order, depth-first, declaration-order walk of the data members of + // the anonymous union. If there is no such data member (i.e., if all of + // the data members in the union are unnamed), then there is no way for + // a program to refer to the anonymous union, and there is therefore no + // need to mangle its name. + const FieldDecl *FD = FindFirstNamedDataMember(RD); + + // It's actually possible for various reasons for us to get here + // with an empty anonymous struct / union. Fortunately, it + // doesn't really matter what name we generate. + if (!FD) break; + assert(FD->getIdentifier() && "Data member name isn't an identifier!"); + + mangleSourceName(FD->getIdentifier()); + break; + } + + // We must have an anonymous struct. + const TagDecl *TD = cast(ND); + if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + assert(TD->getDeclContext() == D->getDeclContext() && + "Typedef should not be in another decl context!"); + assert(D->getDeclName().getAsIdentifierInfo() && + "Typedef was not named!"); + mangleSourceName(D->getDeclName().getAsIdentifierInfo()); + break; + } + + // Get a unique id for the anonymous struct. + uint64_t AnonStructId = Context.getAnonymousStructId(TD); + + // Mangle it as a source name in the form + // [n] $_ + // where n is the length of the string. + llvm::SmallString<8> Str; + Str += "$_"; + Str += llvm::utostr(AnonStructId); + + Out << Str.size(); + Out << Str.str(); + break; + } + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + assert(false && "Can't mangle Objective-C selector names here!"); + break; + + case DeclarationName::CXXConstructorName: + if (ND == Structor) + // If the named decl is the C++ constructor we're mangling, use the type + // we were given. + mangleCXXCtorType(static_cast(StructorType)); + else + // Otherwise, use the complete constructor name. This is relevant if a + // class with a constructor is declared within a constructor. + mangleCXXCtorType(Ctor_Complete); + break; + + case DeclarationName::CXXDestructorName: + if (ND == Structor) + // If the named decl is the C++ destructor we're mangling, use the type we + // were given. + mangleCXXDtorType(static_cast(StructorType)); + else + // Otherwise, use the complete destructor name. This is relevant if a + // class with a destructor is declared within a destructor. + mangleCXXDtorType(Dtor_Complete); + break; + + case DeclarationName::CXXConversionFunctionName: + // ::= cv # (cast) + Out << "cv"; + mangleType(Context.getASTContext().getCanonicalType(Name.getCXXNameType())); + break; + + case DeclarationName::CXXOperatorName: { + unsigned Arity; + if (ND) { + Arity = cast(ND)->getNumParams(); + + // If we have a C++ member function, we need to include the 'this' pointer. + // FIXME: This does not make sense for operators that are static, but their + // names stay the same regardless of the arity (operator new for instance). + if (isa(ND)) + Arity++; + } else + Arity = KnownArity; + + mangleOperatorName(Name.getCXXOverloadedOperator(), Arity); + break; + } + + case DeclarationName::CXXLiteralOperatorName: + // FIXME: This mangling is not yet official. + Out << "li"; + mangleSourceName(Name.getCXXLiteralIdentifier()); + break; + + case DeclarationName::CXXUsingDirective: + assert(false && "Can't mangle a using directive name!"); + break; + } +} + +void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { + // ::= + // ::= [n] + // ::= + Out << II->getLength() << II->getName(); +} + +void CXXNameMangler::mangleNestedName(const NamedDecl *ND, + const DeclContext *DC, + bool NoFunction) { + // + // ::= N [] [] E + // ::= N [] [] + // E + + Out << 'N'; + if (const CXXMethodDecl *Method = dyn_cast(ND)) { + mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + mangleRefQualifier(Method->getRefQualifier()); + } + + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { + mangleTemplatePrefix(TD); + TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); + mangleTemplateArgs(*TemplateParameters, *TemplateArgs); + } + else { + manglePrefix(DC, NoFunction); + mangleUnqualifiedName(ND); + } + + Out << 'E'; +} +void CXXNameMangler::mangleNestedName(const TemplateDecl *TD, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + // ::= N [] E + + Out << 'N'; + + mangleTemplatePrefix(TD); + TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); + mangleTemplateArgs(*TemplateParameters, TemplateArgs, NumTemplateArgs); + + Out << 'E'; +} + +void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { + // := Z E [] + // := Z E s [] + // := _ + const DeclContext *DC = ND->getDeclContext(); + Out << 'Z'; + + if (const ObjCMethodDecl *MD = dyn_cast(DC)) { + mangleObjCMethodName(MD); + } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) { + mangleFunctionEncoding(cast(RD->getDeclContext())); + Out << 'E'; + + // Mangle the name relative to the closest enclosing function. + if (ND == RD) // equality ok because RD derived from ND above + mangleUnqualifiedName(ND); + else + mangleNestedName(ND, DC, true /*NoFunction*/); + + unsigned disc; + if (Context.getNextDiscriminator(RD, disc)) { + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + } + + return; + } + else + mangleFunctionEncoding(cast(DC)); + + Out << 'E'; + mangleUnqualifiedName(ND); +} + +void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { + // ::= + // ::= + // ::= + // ::= # empty + // ::= + + while (isa(DC)) + DC = DC->getParent(); + + if (DC->isTranslationUnit()) + return; + + if (const BlockDecl *Block = dyn_cast(DC)) { + manglePrefix(DC->getParent(), NoFunction); + llvm::SmallString<64> Name; + llvm::raw_svector_ostream NameStream(Name); + Context.mangleBlock(Block, NameStream); + NameStream.flush(); + Out << Name.size() << Name; + return; + } + + if (mangleSubstitution(cast(DC))) + return; + + // Check if we have a template. + const TemplateArgumentList *TemplateArgs = 0; + if (const TemplateDecl *TD = isTemplate(cast(DC), TemplateArgs)) { + mangleTemplatePrefix(TD); + TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); + mangleTemplateArgs(*TemplateParameters, *TemplateArgs); + } + else if(NoFunction && (isa(DC) || isa(DC))) + return; + else if (const ObjCMethodDecl *Method = dyn_cast(DC)) + mangleObjCMethodName(Method); + else { + manglePrefix(DC->getParent(), NoFunction); + mangleUnqualifiedName(cast(DC)); + } + + addSubstitution(cast(DC)); +} + +void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { + // ::=